OutOfMemory рдФрд░ GDI + рдХрднреА-рдХрднреА OutOfMemory рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ

рдХрд╛рдо рдкрд░ рдЕрдВрддрд┐рдо рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╕рдордп, рдореЗрд░реЗ рд╕рд╣рдХрд░реНрдореА рдФрд░ рдореИрдВрдиреЗ рдЗрд╕ рддрдереНрдп рдХрд╛ рд╕рд╛рдордирд╛ рдХрд┐рдпрд╛ рдХрд┐ System.Drawing рдореЗрдВ рдХреБрдЫ рддрд░реАрдХреЗ рдФрд░ рдирд┐рд░реНрдорд╛рддрд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ OutOfMemory рд╕реЗ рдЧрд┐рд░рддреЗ рд╣реИрдВ, рдФрд░ рдЬрдм рдЕрднреА рднреА рдмрд╣реБрдд, рдмрд╣реБрдд рдореБрдХреНрдд рд╕реНрдореГрддрд┐ рд╣реИред



рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рд░


рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ C # рдХреЛрдб рд▓реЗрдВ:

using System.Drawing; using System.Drawing.Drawing2D; namespace TempProject { static class Program { static void Main() { var point1 = new PointF(-3.367667E-16f, 0f); var point2 = new PointF(3.367667E-16f, 100f); var brush = new LinearGradientBrush(point1, point2, Color.White, Color.Black); } } } 

рдЬрдм рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ, рддреЛ рдПрдХ рдЖрдЙрдЯрдСрдлрд╝рдореЗрдореЛрд░реА рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХрдиреЗ рдХреА рдЧрд╛рд░рдВрдЯреА рджреА рдЬрд╛рддреА рд╣реИ, рднрд▓реЗ рд╣реА рдХрд┐рддрдиреА рдореБрдлреНрдд рдореЗрдореЛрд░реА рдЙрдкрд▓рдмреНрдз рд╣реЛред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдЖрдк 3.367667E-16f рдФрд░ -3.367667E-16f рдХреЛ 0 рд╕реЗ рдмрджрд▓рддреЗ рд╣реИрдВ, рдЬреЛ рд╕рддреНрдп рдХреЗ рдмрд╣реБрдд рдХрд░реАрдм рд╣реИ, рддреЛ рд╕рдм рдХреБрдЫ рдареАрдХ рдЪрд▓реЗрдЧрд╛ - рднрд░рдг рдХрд╛ рдирд┐рд░реНрдорд╛рдг рд╣реЛрдЧрд╛ред рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдЕрдЬреАрдм рд▓рдЧрддрд╛ рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреНрдпреЛрдВ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдФрд░ рдЗрд╕рд╕реЗ рдХреИрд╕реЗ рдирд┐рдкрдЯрдирд╛ рд╣реИред

рд░реЛрдЧ рдХреЗ рдХрд╛рд░рдгреЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдПрдВ


рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕реАрдЦрддреЗ рд╣реИрдВ рдХрд┐ LinearGradientBrush рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк referenceource.microsoft.com рдкрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реЛрдВрдЧреЗ:

 public LinearGradientBrush(PointF point1, PointF point2, Color color1, Color color2) { IntPtr brush = IntPtr.Zero; int status = SafeNativeMethods.Gdip.GdipCreateLineBrush( new GPPOINTF(point1), new GPPOINTF(point2), color1.ToArgb(), color2.ToArgb(), (int)WrapMode.Tile, out brush ); if (status != SafeNativeMethods.Gdip.Ok) throw SafeNativeMethods.Gdip.StatusException(status); SetNativeBrushInternal(brush); } 

рдпрд╣ рдиреЛрдЯрд┐рд╕ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд GdipCreateLineBrush рдкрджреНрдзрддрд┐ рдХрд╛ GDI + рдХреЙрд▓ рд╣реИред рддреЛ, рдЖрдкрдХреЛ рдпрд╣ рджреЗрдЦрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, IDA + HexRays рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЖрдИрдбреАрдП gdiplus.dll рдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВред рдпрджрд┐ рдЖрдкрдХреЛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдХрд┐рд╕ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдбреАрдмрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдк SysInternals рд╕реЗ рдкреНрд░реЛрд╕реЗрд╕ рдПрдХреНрд╕рдкреНрд▓реЛрд░рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдк рдЙрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдкрд░ рдЕрдиреБрдорддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рдЕрдиреБрднрд╡ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдБ gdiplus.dll рдирд┐рд╣рд┐рдд рд╣реИред рд╡реЗ рдЗрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдХреЗ рд╕реНрд╡рд╛рдореА рдХреЛ рдмрджрд▓рдХрд░ рд╣рд▓ рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рддреЛ, рдЖрдИрдбреАрдП рдореЗрдВ gdiplus.dll рдЦреЛрд▓реЗрдВред рдЪрд▓реЛ рдлрд╝рд╛рдЗрд▓ рд╕рдВрд╕рд╛рдзрд┐рдд рд╣реЛрдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рдореЗрдиреВ рдореЗрдВ рд╕реЗрд▓реЗрдХреНрдЯ рдХрд░реЗрдВ: рд╡реНрдпреВ тЖТ рдУрдкрди рд╕рдмреНрдЬреЗрдХреНрдЯреНрд╕ тЖТ рдЗрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдПрдХреНрд╕рдкреЛрд░реНрдЯ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдлрдВрдХреНрд╢рдиреНрд╕ рдХреЛ рдЦреЛрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХреНрд╕рдкреЛрд░реНрдЯ рдХрд░реЗрдВ рдФрд░ рд╡рд╣рд╛рдВ GdipCreateLineBrush рдвреВрдВрдвреЗрдВред

рдЕрдХреНрд╖рд░ рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, HexRays рдФрд░ рдкреНрд░рд▓реЗрдЦрди рдХреА рд╢рдХреНрддрд┐, рдЖрдк рдХреЛрдб рдХреЛрдб рд╕реЗ рд╡рд┐рдзрд┐ рдХреЛрдб рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдкрдврд╝рдиреЗ рдпреЛрдЧреНрдп ++ рдореЗрдВ рдЕрдиреБрд╡рд╛рдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

GdipCreateLineBrush
 GpStatus __userpurge GdipCreateLineBrush@<eax>(int a1@<edi>, GpPointF *point1, GpPointF *point2, int color1, int color2, int wrapMode, GpRectGradient **result) { GpStatus status; // esi MAPDST GpGradientBrush *v8; // eax GpRectGradient *v9; // eax int v12; // [esp+4h] [ebp-Ch] int vColor1; // [esp+8h] [ebp-8h] int vColor2; // [esp+Ch] [ebp-4h] FPUStateSaver::FPUStateSaver(&v12, 1); EnterCriticalSection(&GdiplusStartupCriticalSection::critSec); if ( Globals::LibraryInitRefCount > 0 ) { LeaveCriticalSection(&GdiplusStartupCriticalSection::critSec); if ( result && point1 && point2 && wrapMode != 4 ) { vColor1 = color1; vColor2 = color2; v8 = operator new(a1); status = 0; if ( v8 ) v9 = GpLineGradient::GpLineGradient(v8, point1, point2, &vColor1, &vColor2, wrapMode); else v9 = 0; *result = v9; if ( !CheckValid<GpHatch>(result) ) status = OutOfMemory; } else { status = InvalidParameter; } } else { LeaveCriticalSection(&GdiplusStartupCriticalSection::critSec); status = GdiplusNotInitialized; } __asm { fclex } return status; } 

рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдХреЛрдб рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╣реИред рдЗрд╕рдХрд╛ рд╕рд╛рд░ рд▓рд╛рдЗрдиреЛрдВ рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИ:

 if ( result && point1 && point2 && wrapMode != 4 ) { vColor1 = color1; vColor2 = color2; v8 = operator new(a1); status = 0; if ( v8 ) v9 = GpLineGradient::GpLineGradient(v8, point1, point2, &vColor1, &vColor2, wrapMode); else v9 = 0; *result = v9; if ( !CheckValid<GpHatch>(result) ) status = OutOfMemory } else { status = InvalidParameter; } 

рдпрджрд┐ рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд╕рд╣реА рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдпрд╣ рдирд╣реАрдВ рд╣реИ, рддреЛ GdiPlus рдЬрд╛рдБрдЪрддрд╛ рд╣реИ, рддреЛ рдПрдХ InvalidParameter рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛, рдПрдХ GpLineGradient рд╡реИрдзрддрд╛ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдФрд░ рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИред рдпрджрд┐ рд╕рддреНрдпрд╛рдкрди рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ, рддреЛ OutOfMemory рд▓реМрдЯрд╛ рджреА рдЬрд╛рддреА рд╣реИред рдЬрд╛рд╣рд┐рд░рд╛ рддреМрд░ рдкрд░, рдпрд╣ рд╣рдорд╛рд░рд╛ рдорд╛рдорд▓рд╛ рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ GpLineGradio рдирд┐рд░реНрдорд╛рдг рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ:

GpLineGradient :: GpLineGradient
 GpRectGradient *__thiscall GpLineGradient::GpLineGradient(GpGradientBrush *this, GpPointF *point1, GpPointF *point2, int color1, int color2, int wrapMode) { GpGradientBrush *v6; // esi float height; // ST2C_4 double v8; // st7 float width; // ST2C_4 float angle; // ST2C_4 GpRectF rect; // [esp+1Ch] [ebp-10h] v6 = this; GpGradientBrush::GpGradientBrush(this); GpRectGradient::DefaultBrush(v6); rect.Height = 0.0; rect.Width = 0.0; rect.Y = 0.0; rect.X = 0.0; *v6 = &GpLineGradient::`vftable; if ( LinearGradientRectFromPoints(point1, point2, &rect) ) { *(v6 + 1) = 1279869254; } else { height = point2->Y - point1->Y; v8 = height; width = point2->X - point1->X; angle = atan2(v8, width) * 180.0 / 3.141592653589793; GpLineGradient::SetLineGradient(v6, point1, point2, &rect, color1, color2, angle, 0, wrapMode); } return v6; } 

рдпрд╣рд╛рдБ рд╡реИрд░рд┐рдПрдмрд▓реНрд╕ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдлрд┐рд░ LinearGradientRectFromPoints рдФрд░ SetLineGradient рдореЗрдВ рднрд░реЗ рдЧрдП рд╣реИрдВред рдореИрдВ рдпрд╣ рдорд╛рдирдиреЗ рдХреА рд╣рд┐рдореНрдордд рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдмрд┐рдВрджреБ, рдмрд┐рдВрджреБ 1 рдФрд░ рдмрд┐рдВрджреБ 2 рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдПрдХ рднрд░рдг рдЖрдпрдд рд╣реИ, рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк LinearGradientRectFromPoints рдкрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:

LinearGradientRectFromPoints
 GpStatus __fastcall LinearGradientRectFromPoints(GpPointF *p1, GpPointF *p2, GpRectF *result) { double vP1X; // st7 float vLeft; // ST1C_4 MAPDST double vP1Y; // st7 float vTop; // ST1C_4 MAPDST float vWidth; // ST18_4 MAPDST double vWidth3; // st7 float vHeight; // ST18_4 MAPDST float vP2X; // [esp+18h] [ebp-8h] float vP2Y; // [esp+1Ch] [ebp-4h] if ( IsClosePointF(p1, p2) ) return InvalidParameter; vP2X = p2->X; vP1X = p1->X; if ( vP2X <= vP1X ) vP1X = vP2X; vLeft = vP1X; result->X = vLeft; vP2Y = p2->Y; vP1Y = p1->Y; if ( vP2Y <= vP1Y ) vP1Y = vP2Y; vTop = vP1Y; result->Y = vTop; vWidth = p1->X - p2->X; vWidth = fabs(vWidth); vWidth3 = vWidth; result->Width = vWidth; vHeight = p1->Y - p2->Y; vHeight = fabs(vHeight); result->Height = vHeight; vWidth = vWidth3; if ( IsCloseReal(p1->X, p2->X) ) { result->X = vLeft - 0.5 * vHeight; result->Width = vHeight; vWidth = vHeight; } if ( IsCloseReal(p1->Y, p2->Y) ) { result->Y = vTop - vWidth * 0.5; result->Height = vWidth; } return 0; } 

рдЬреИрд╕рд╛ рдХрд┐ рдЕрдкреЗрдХреНрд╖рд┐рдд рдерд╛, рдкреЙрдЗрдВрдЯ рдкреЙрдЗрдВрдЯ 1 рдФрд░ рдкреЙрдЗрдВрдЯ 2 рдХреА рдЖрдпрдд рд╣реИред

рдЕрдм рд╣рдо рдЕрдкрдиреА рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛ рдкрд░ рд╡рд╛рдкрд╕ рдЖрддреЗ рд╣реИрдВ рдФрд░ рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ SetLineGradient рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ:

SetLineGradient
 GpStatus __thiscall GpLineGradient::SetLineGradient(DpGradientBrush *this, GpPointF *p1, GpPointF *p2, GpRectF *rect, int color1, int color2, float angle, int zero, int wrapMode) { _DWORD *v10; // edi float *v11; // edi GpStatus v12; // esi _DWORD *v14; // edi this->wrapMode = wrapMode; v10 = &this->dword40; this->Color1 = *color1; this->Color2 = *color2; this->Color11 = *color1; this->Color21 = *color2; this->dwordB0 = 0; this->float98 = 1.0; this->dwordA4 = 1; this->dwordA0 = 1; this->float94 = 1.0; this->dwordAC = 0; if ( CalcLinearGradientXform(zero, rect, angle, &this->gap4[16]) ) { *this->gap4 = 1279869254; *v10 = 0; v14 = v10 + 1; *v14 = 0; ++v14; *v14 = 0; v14[1] = 0; *&this[1].gap4[12] = 0; *&this[1].gap4[16] = 0; *&this[1].gap4[20] = 0; *&this[1].gap4[24] = 0; *&this->gap44[28] = 0; v12 = InvalidParameter; } else { *this->gap4 = 1970422321; *v10 = LODWORD(rect->X); v11 = (v10 + 1); *v11 = rect->Y; ++v11; *v11 = rect->Width; v11[1] = rect->Height; *&this->gap44[28] = zero; v12 = 0; *&this[1].gap4[12] = *p1; *&this[1].gap4[20] = *p2; } return v12; } 

SetLineGradient рдореЗрдВ рднреА, рдХреЗрд╡рд▓ рдлрд╝реАрд▓реНрдб рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рд╣реЛрддрд╛ рд╣реИред рддреЛ, рд╣рдореЗрдВ рдЧрд╣рд░рд╛рдИ рддрдХ рдЬрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

 int __fastcall CalcLinearGradientXform(int zero, GpRectF *rect, float angle, int a4) { //... //... //... return GpMatrix::InferAffineMatrix(a4, points, rect) != OK ? InvalidParameter : OK; } 

рдФрд░ рдЕрдВрдд рдореЗрдВ:

 GpStatus __thiscall GpMatrix::InferAffineMatrix(int this, GpPointF *points, GpRectF *rect) { //... double height; // st6 double y; // st5 double width; // st4 double x; // st3 double bottom; // st2 float right; // ST3C_4 float rectArea; // ST3C_4 //... x = rect->X; y = rect->Y; width = rect->Width; height = rect->Height; right = x + width; bottom = height + y; rectArea = bottom * right - x * y - (y * width + x * height); rectArea = fabs(rectArea); if ( rectArea < 0.00000011920929 ) return InvalidParameter; //... } 

InferAffineMatrix рд╡рд┐рдзрд┐ рдмрд┐рд▓реНрдХреБрд▓ рд╡рд╣реА рд╣реИ рдЬреЛ рд╣рдореЗрдВ рд░реБрдЪрддреА рд╣реИред рдпрд╣рд╛рдВ рд░реЗрдХреНрдЯ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреА рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИ - рдЕрдВрдХреЛрдВ рдХреА рдореВрд▓ рдЖрдпрдд, рдФрд░ рдпрджрд┐ рдпрд╣ 0.00000011920929 рд╕реЗ рдХрдо рд╣реИ, рддреЛ InferAffineMatrix, InvalidParameter рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИред 0.00000011920929 рдлреНрд▓реЛрдЯ (FLT_EPSILON) рдХреЗ рд▓рд┐рдП рдорд╢реАрди рдПрдкреНрд╕рд┐рд▓реЙрди рд╣реИ ред рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ Microsoft рдЖрдпрдд рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдХрд┐рддрдирд╛ рджрд┐рд▓рдЪрд╕реНрдк рдорд╛рдирддрд╛ рд╣реИ:

 rectArea = bottom * right - x * y - (y * width + x * height); 

рдХреНрд╖реЗрддреНрд░ рд╕реЗ рдирд┐рдЪрд▓реЗ рджрд╛рдИрдВ рдУрд░, рдХреНрд╖реЗрддреНрд░ рдХреЛ рдКрдкрд░реА рдмрд╛рдИрдВ рдУрд░ рдШрдЯрд╛рдПрдВ, рдлрд┐рд░ рдЖрдпрдд рдХреЗ рдКрдкрд░ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдФрд░ рдЖрдпрдд рдХреЗ рдмрд╛рдИрдВ рдУрд░ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдШрдЯрд╛рдПрдВред рдРрд╕рд╛ рдХреНрдпреЛрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдореБрдЭреЗ рд╕рдордЭ рдирд╣реАрдВ рдЖрддрд╛; рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдХрд┐рд╕реА рджрд┐рди рдореБрдЭреЗ рдпрд╣ рдЧреБрдкреНрдд рд╡рд┐рдзрд┐ рдкрддрд╛ рдЪрд▓ рдЬрд╛рдПрдЧреАред

рддреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ:

  • рдЗрдирд░рдПрдлрд╝рд╛рдЗрдирдореИрдЯреНрд░рд┐рдХреНрд╕ рдиреЗ рдЗрдирд╡реИрд▓рд┐рдбрдкреИрд░реЗрдЯ рд░рд┐рдЯрд░реНрди рдХрд┐рдпрд╛;
  • CalcLinearGradientXForm рдЗрд╕ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдЕрдзрд┐рдХ рдлреЗрдВрдХрддрд╛ рд╣реИ;
  • SetLineGradient рдореЗрдВ, рдирд┐рд╖реНрдкрд╛рджрди рдпрджрд┐ рд╢рд╛рдЦрд╛ рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░реЗрдЧрд╛, рдФрд░ рд╡рд┐рдзрд┐ рднреА InvalidParameter рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧреА;
  • GpLineGradient рдирд┐рд░реНрдорд╛рддрд╛ InvalidParameter рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдЦреЛ рджреЗрдЧрд╛ рдФрд░ рдПрдХ GpLineGradient рдСрдмреНрдЬреЗрдХреНрдЯ рд▓реМрдЯрд╛рдПрдЧрд╛ рдЬреЛ рдЕрдВрдд рддрдХ рдЖрд░рдВрднреАрдХреГрдд рдирд╣реАрдВ рд╣реИ - рдпрд╣ рдмрд╣реБрдд рдмреБрд░рд╛ рд╣реИ!
  • GdipCreateLineBrush CheckValid (рд▓рд╛рдЗрди 26) рдореЗрдВ рдЬрд╛рдБрдЪ рдХрд░реЗрдЧрд╛ рдХрд┐ GpLineGradient рдСрдмреНрдЬреЗрдХреНрдЯ рдЙрди рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЗ рд╕рд╛рде рдорд╛рдиреНрдп рд╣реИ рдЬреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рднрд░реЗ рд╣реБрдП рдирд╣реАрдВ рд╣реИрдВ рдФрд░ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЧрд▓рдд рд╡рд╛рдкрд╕ рдЖрдПрдВрдЧреЗред
  • рдЙрд╕рдХреЗ рдмрд╛рдж, рд╕реНрдерд┐рддрд┐ OutOfMemory рдореЗрдВ рдмрджрд▓ рдЬрд╛рдПрдЧреА, рдЬрд┐рд╕реЗ GDI + рд╡рд┐рдзрд┐ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдкрд░ .NET рдорд┐рд▓реЗрдЧрд╛ред

рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ Microsoft рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдХреБрдЫ рддрд░реАрдХреЛрдВ рдХреА рд╡рд╛рдкрд╕реА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ рдЧрд▓рдд рдзрд╛рд░рдгрд╛ рдмрдирд╛рддрд╛ рд╣реИ, рдФрд░ рдЕрдиреНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдХрд╛рдо рдХреА рд╕рдордЭ рдХреЛ рдЬрдЯрд┐рд▓ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдмрд╕ рдЗрддрдирд╛ рдХрд░рдирд╛ рдерд╛ рдХрд┐ рд╕реНрдЯреЗрдЯ рдХреЛ GpLineGradient рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╕реЗ рдКрдБрдЪрд╛ рдлреЗрдВрдХрд╛ рдЬрд╛рдП, рдФрд░ GdipCreateLineBrush рдореЗрдВ рдУрдХреЗ рдореЗрдВ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рдЪреЗрдХ рдХрд░реЗрдВ рдФрд░ рдЕрдиреНрдпрдерд╛ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХрд╛ рд╕реНрдЯреЗрдЯрд╕ рд╡рд╛рдкрд╕ рдХрд░реЗрдВред рдлрд┐рд░, GDI + рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП, рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдЕрдВрджрд░ рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдЕрдзрд┐рдХ рддрд╛рд░реНрдХрд┐рдХ рд▓рдЧреЗрдЧрд╛ред

рд╢реВрдиреНрдп рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдХрдо рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк, рдЕрд░реНрдерд╛рддред рдКрд░реНрдзреНрд╡рд╛рдзрд░ рднрд░рдг рдХреЗ рд╕рд╛рде, рдпрд╣ рдЙрд╕ рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд┐рдирд╛ рдЪрд▓рддрд╛ рд╣реИ, рдЬрд┐рд╕ рдХрд╛рд░рдг Microsoft рд▓рд╛рдЗрдирд░рдЧреНрд░реИрдбрд┐рдПрдВрдЯRectFromPoints рдкрджреНрдзрддрд┐ рдореЗрдВ 45 рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ Microsoft рдХрд░рддрд╛ рд╣реИ:

рдЬрд╛рджреВ
 if ( IsCloseReal(p1->X, p2->X) ) { result->X = vLeft - 0.5 * vHeight; result->Width = vHeight; vWidth = vHeight; } if ( IsCloseReal(p1->Y, p2->Y) ) { result->Y = vTop - vWidth * 0.5; result->Height = vWidth; } 

рдХреИрд╕реЗ рдХрд░реЗрдВ рдЗрд▓рд╛рдЬ?


.NET рдХреЛрдб рдореЗрдВ рдЗрд╕ рдХреНрд░реИрд╢ рд╕реЗ рдХреИрд╕реЗ рдмрдЪреЗрдВ? рд╕рдмрд╕реЗ рд╕рд░рд▓ рдФрд░ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╡рд┐рдХрд▓реНрдк рдпрд╣ рд╣реИ рдХрд┐ рдЖрдпрдд рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреА рддреБрд▓рдирд╛ рдкреЙрдЗрдВрдЯ 1 рдФрд░ рдкреЙрдЗрдВрдЯ 2 рд╕реЗ FLT_EPSILON рд╕реЗ рдХреА рдЬрд╛рдП рдФрд░ рдХреНрд╖реЗрддреНрд░ рдЫреЛрдЯрд╛ рд╣реЛрдиреЗ рдкрд░ рдЧреНрд░реЗрдбрд┐рдПрдВрдЯ рди рдмрдирд╛рдпрд╛ рдЬрд╛рдПред рд▓реЗрдХрд┐рди рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде, рд╣рдо рдврд╛рд▓ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдЦреЛ рджреЗрдВрдЧреЗ, рдФрд░ рдПрдХ рдЕрдирдкреЗрдХреНрд╖рд┐рдд рдХреНрд╖реЗрддреНрд░ рдЦреАрдВрдЪрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реИред рдореБрдЭреЗ рдЧреНрд░реЗрдбрд┐рдПрдВрдЯ рдлрд┐рд▓ рдХреЗ рдХреЛрдг рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╕рдордп рдПрдХ рдЕрдзрд┐рдХ рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╡рд┐рдХрд▓реНрдк рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдпрд╣ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рднрд░рдг рдХреНрд╖реИрддрд┐рдЬ рдпрд╛ рдКрд░реНрдзреНрд╡рд╛рдзрд░ рдХреЗ рдХрд░реАрдм рд╣реИ, рддреЛ рдЕрдВрдХ рдХреЗ рд▓рд┐рдП рд╕рдВрдмрдВрдзрд┐рдд рдкреИрд░рд╛рдореАрдЯрд░ рд╕рдорд╛рди рд╕реЗрдЯ рдХрд░реЗрдВ:

C # рдореЗрдВ рдореЗрд░рд╛ рд╕рдорд╛рдзрд╛рди
 static LinearGradientBrush CreateBrushSafely(PointF p1, PointF p2) { if(IsShouldNormalizePoints(p1, p2)) { if(!NormalizePoints(ref p1, ref p2)) return null; } var brush = new LinearGradientBrush(p1, p2, Color.White, Color.Black); return brush; } static bool IsShouldNormalizePoints(PointF p1, PointF p2) { float width = Math.Abs(p1.X - p2.X); float height = Math.Abs(p1.Y - p2.Y); return width * height < FLT_EPSILON && !(IsCloseFloat(p1.X, p2.X) || IsCloseFloat(p1.Y, p2.Y)); } static bool IsCloseFloat(float v1, float v2) { var t = v2 == 0.0f ? 1.0f : v2; return Math.Abs((v1 - v2) / t) < FLT_EPSILON; } static bool NormalizePoints(ref PointF p1, ref PointF p2) { const double twoDegrees = 0.03490658503988659153847381536977d; float width = Math.Abs(p1.X - p2.X); float height = Math.Abs(p1.Y - p2.Y); var angle = Math.Atan2(height, width); if (Math.Abs(angle) < twoDegrees) { p1.Y = p2.Y; return true; } if (Math.Abs(angle - Math.PI / 2) < twoDegrees) { p1.X = p2.X; return true; } return false; } 

рдкреНрд░рддрд┐рдпреЛрдЧреА рдХреИрд╕реЗ рдХрд░ рд░рд╣реЗ рд╣реИрдВ?


рдЖрдЗрдП рдЬрд╛рдиреЗрдВ рд╢рд░рд╛рдм рдореЗрдВ рдХреНрдпрд╛ рдЪрд▓ рд░рд╣рд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП , рд╢рд░рд╛рдм рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦреЗрдВ , рд▓рд╛рдЗрди 306:

рд╢рд░рд╛рдм рдХрд╛ GdipCreateLineBrush
 /****************************************************************************** * GdipCreateLineBrush [GDIPLUS.@] */ GpStatus WINGDIPAPI GdipCreateLineBrush(GDIPCONST GpPointF* startpoint, GDIPCONST GpPointF* endpoint, ARGB startcolor, ARGB endcolor, GpWrapMode wrap, GpLineGradient **line) { TRACE("(%s, %s, %x, %x, %d, %p)\n", debugstr_pointf(startpoint), debugstr_pointf(endpoint), startcolor, endcolor, wrap, line); if(!line || !startpoint || !endpoint || wrap == WrapModeClamp) return InvalidParameter; if (startpoint->X == endpoint->X && startpoint->Y == endpoint->Y) return OutOfMemory; *line = heap_alloc_zero(sizeof(GpLineGradient)); if(!*line) return OutOfMemory; (*line)->brush.bt = BrushTypeLinearGradient; (*line)->startpoint.X = startpoint->X; (*line)->startpoint.Y = startpoint->Y; (*line)->endpoint.X = endpoint->X; (*line)->endpoint.Y = endpoint->Y; (*line)->startcolor = startcolor; (*line)->endcolor = endcolor; (*line)->wrap = wrap; (*line)->gamma = FALSE; (*line)->rect.X = (startpoint->X < endpoint->X ? startpoint->X: endpoint->X); (*line)->rect.Y = (startpoint->Y < endpoint->Y ? startpoint->Y: endpoint->Y); (*line)->rect.Width = fabs(startpoint->X - endpoint->X); (*line)->rect.Height = fabs(startpoint->Y - endpoint->Y); if ((*line)->rect.Width == 0) { (*line)->rect.X -= (*line)->rect.Height / 2.0f; (*line)->rect.Width = (*line)->rect.Height; } else if ((*line)->rect.Height == 0) { (*line)->rect.Y -= (*line)->rect.Width / 2.0f; (*line)->rect.Height = (*line)->rect.Width; } (*line)->blendcount = 1; (*line)->blendfac = heap_alloc_zero(sizeof(REAL)); (*line)->blendpos = heap_alloc_zero(sizeof(REAL)); if (!(*line)->blendfac || !(*line)->blendpos) { heap_free((*line)->blendfac); heap_free((*line)->blendpos); heap_free(*line); *line = NULL; return OutOfMemory; } (*line)->blendfac[0] = 1.0f; (*line)->blendpos[0] = 1.0f; (*line)->pblendcolor = NULL; (*line)->pblendpos = NULL; (*line)->pblendcount = 0; linegradient_init_transform(*line); TRACE("<-- %p\n", *line); return Ok; } 

рдпрд╣рд╛рдБ рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рд╕рддреНрдпрд╛рдкрди рд╣реИ:

 if(!line || !startpoint || !endpoint || wrap == WrapModeClamp) return InvalidParameter; 

рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рд╡рд┐рдВрдбреЛрдЬ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрддрддрд╛ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ:

 if (startpoint->X == endpoint->X && startpoint->Y == endpoint->Y) return OutOfMemory; 

рдФрд░ рдмрд╛рдХреА рдХреБрдЫ рднреА рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рд╣реИ - рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрди рдФрд░ рдЦреЗрддреЛрдВ рдореЗрдВ рднрд░рдирд╛ред рд╕реНрд░реЛрдд рдХреЛрдб рд╕реЗ, рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╡рд╛рдЗрди рдореЗрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдврд╛рд▓ рднрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ - рдпрджрд┐ рдЖрдк рд╡рд┐рдВрдбреЛрдЬ рдкрд░ рдирд┐рдореНрди рдкреНрд░реЛрдЧреНрд░рд╛рдо рдЪрд▓рд╛рддреЗ рд╣реИрдВ (рдореИрдВ Windows10x64 рдкрд░ рдЪрд▓рд╛)

рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдпрдХреНрд░рдо
 #include <Windows.h> #include "stdafx.h" #include <gdiplus.h> #include <iostream> #pragma comment(lib,"gdiplus.lib") void CreateBrush(float x1, float x2) { Gdiplus::LinearGradientBrush linGrBrush( Gdiplus::PointF(x1, -0.5f), Gdiplus::PointF(x2, 10.5f), Gdiplus::Color(255, 0, 0, 0), Gdiplus::Color(255, 255, 255, 255)); const int status = linGrBrush.GetLastStatus(); const char* result; if (status == 3) { result = "OutOfMemory"; } else { result = "Ok"; } std::cout << result << "\n"; } int main() { Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); Gdiplus::Graphics myGraphics(GetDC(0)); CreateBrush(-3.367667E-16f, 3.367667E-16f); CreateBrush(0, 0); return 0; } 

рд╡рд┐рдВрдбреЛрдЬ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдпрд╣ рд╣реЛрдЧрд╛:
OutOfMemory
рдареАрдХ рд╣реИ
рдФрд░ рд╢рд░рд╛рдм рдХреЗ рд╕рд╛рде рдЙрдмрдВрдЯреВ рдореЗрдВ:
рдареАрдХ рд╣реИ
рдареАрдХ рд╣реИ
рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдпрд╛ рддреЛ рдореИрдВ рдХреБрдЫ рдЧрд▓рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдпрд╛ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╡рд╛рдЗрди рд╡рд┐рдВрдбреЛрдЬ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рддрд╛рд░реНрдХрд┐рдХ рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдирд┐рд╖реНрдХрд░реНрд╖


рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╢рд╛ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдореБрдЭреЗ рдХреБрдЫ рд╕рдордЭ рдирд╣реАрдВ рдЖрдпрд╛ рдФрд░ GDI + рдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реИред рд╕рдЪ рд╣реИ, рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдорд╛рдЗрдХреНрд░реЛрд╕реЙрдлреНрдЯ рдиреЗ рдРрд╕рд╛ рдХреНрдпреЛрдВ рдХрд┐рдпрд╛ред рдореИрдВрдиреЗ рдЙрдирдХреЗ рдЕрдиреНрдп рдЙрддреНрдкрд╛рджреЛрдВ рдореЗрдВ рдмрд╣реБрдд рд╡рд┐рд▓рдореНрдм рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдРрд╕реА рдЪреАрдЬреЗрдВ рднреА рд╣реИрдВ рдЬреЛ рдПрдХ рд╕рднреНрдп рд╕рдорд╛рдЬ рдореЗрдВ рдХреЛрдб рд░рд┐рд╡реНрдпреВ рдХреЛ рдкрд╛рд░рд┐рдд рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред

Source: https://habr.com/ru/post/hi412851/


All Articles