7 SysUtils
, Classes
, Math
, e_log
, e_textures
, SDL2
, GL
, GLExt
, MAPDEF
;
10 TMirrorType
=(M_NONE
, M_HORIZONTAL
, M_VERTICAL
);
11 TBlending
=(B_NONE
, B_BLEND
, B_FILTER
, B_INVERT
);
17 TPoint
= MAPDEF
.TPoint
; // TODO: create an utiltypes.pas or something
18 // for other types like rect as well
25 Left
, Top
, Right
, Bottom
: Integer;
43 //------------------------------------------------------------------
45 //------------------------------------------------------------------
47 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
48 procedure e_ResizeWindow(Width
, Height
: Integer);
50 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
51 Blending
: Boolean; Mirror
: TMirrorType
= M_NONE
);
52 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
53 Blending
: Boolean; Angle
: Single; RC
: PPoint
; Mirror
: TMirrorType
= M_NONE
);
54 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
55 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
56 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
57 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
58 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
59 AlphaChannel
: Boolean; Blending
: Boolean);
60 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
61 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
62 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
63 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
64 Blending
: TBlending
= B_NONE
);
66 function e_CreateTexture(FileName
: string; var ID
: DWORD
): Boolean;
67 function e_CreateTextureEx(FileName
: string; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
68 function e_CreateTextureMem(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
): Boolean;
69 function e_CreateTextureMemEx(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
70 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
71 function e_GetTextureSize2(ID
: DWORD
): TRectWH
;
72 procedure e_DeleteTexture(ID
: DWORD
);
73 procedure e_RemoveAllTextures();
76 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
77 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
78 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
79 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
80 Color
: TRGB
; Scale
: Single = 1.0);
81 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
82 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
83 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
84 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
85 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
86 procedure e_CharFont_Remove(FontID
: DWORD
);
87 procedure e_CharFont_RemoveAll();
90 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
92 procedure e_TextureFontKill(FontID
: DWORD
);
93 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
94 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
95 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
96 procedure e_TextureFontPrintFmt(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Shadow
: Boolean = False);
97 procedure e_TextureFontGetSize(ID
: DWORD
; var CharWidth
, CharHeight
: Byte);
98 procedure e_RemoveAllTextureFont();
100 procedure e_ReleaseEngine();
101 procedure e_BeginRender();
102 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
103 procedure e_Clear(); overload
;
104 procedure e_EndRender();
106 function e_GetGamma(win
: PSDL_Window
): Byte;
107 procedure e_SetGamma(win
: PSDL_Window
;Gamma
: Byte);
109 procedure e_MakeScreenshot(st
: TStream
; Width
, Height
: Word);
111 function _RGB(Red
, Green
, Blue
: Byte): TRGB
;
112 function _Point(X
, Y
: Integer): TPoint2i
;
113 function _Rect(X
, Y
: Integer; Width
, Height
: Word): TRectWH
;
114 function _TRect(L
, T
, R
, B
: LongInt): TRect
;
119 e_NoGraphics
: Boolean = False;
136 TTextureFont
= record
146 Chars
: array[0..255] of
156 TSavedTexture
= record
163 e_Textures
: array of TTexture
= nil;
164 e_TextureFonts
: array of TTextureFont
= nil;
165 e_CharFonts
: array of TCharFont
;
166 //e_SavedTextures: array of TSavedTexture;
168 //------------------------------------------------------------------
169 // Èíèöèàëèçèðóåò OpenGL
170 //------------------------------------------------------------------
171 procedure e_InitGL();
175 e_DummyTextures
:= True;
181 glDisable(GL_DEPTH_TEST
);
182 glEnable(GL_SCISSOR_TEST
);
183 glClearColor(0, 0, 0, 0);
186 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
188 mat
: Array [0..15] of GLDouble
;
191 if e_NoGraphics
then Exit
;
193 glScissor(X
, Y
, Width
, Height
);
194 glViewport(X
, Y
, Width
, Height
);
195 //gluOrtho2D(0, Width, Height, 0);
197 glMatrixMode(GL_PROJECTION
);
199 mat
[ 0] := 2.0 / Width
;
205 mat
[ 5] := -2.0 / Height
;
219 glLoadMatrixd(@mat
[0]);
221 glMatrixMode(GL_MODELVIEW
);
225 //------------------------------------------------------------------
226 // Èùåò ñâîáîäíûé ýëåìåíò â ìàññèâå òåêñòóð
227 //------------------------------------------------------------------
228 function FindTexture(): DWORD
;
232 if e_Textures
<> nil then
233 for i
:= 0 to High(e_Textures
) do
234 if e_Textures
[i
].Width
= 0 then
240 if e_Textures
= nil then
242 SetLength(e_Textures
, 32);
247 Result
:= High(e_Textures
) + 1;
248 SetLength(e_Textures
, Length(e_Textures
) + 32);
252 //------------------------------------------------------------------
254 //------------------------------------------------------------------
255 function e_CreateTexture(FileName
: String; var ID
: DWORD
): Boolean;
262 e_WriteLog('Loading texture from '+FileName
, MSG_NOTIFY
);
264 find_id
:= FindTexture();
266 if not LoadTexture(FileName
, e_Textures
[find_id
].tx
, e_Textures
[find_id
].Width
,
267 e_Textures
[find_id
].Height
, @fmt
) then Exit
;
270 e_Textures
[ID
].Fmt
:= fmt
;
275 function e_CreateTextureEx(FileName
: String; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
282 find_id
:= FindTexture();
284 if not LoadTextureEx(FileName
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
286 e_Textures
[find_id
].Width
:= fWidth
;
287 e_Textures
[find_id
].Height
:= fHeight
;
288 e_Textures
[find_id
].Fmt
:= fmt
;
295 function e_CreateTextureMem(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
): Boolean;
302 find_id
:= FindTexture
;
304 if not LoadTextureMem(pData
, dataSize
, e_Textures
[find_id
].tx
, e_Textures
[find_id
].Width
, e_Textures
[find_id
].Height
, @fmt
) then exit
;
307 e_Textures
[id
].Fmt
:= fmt
;
312 function e_CreateTextureMemEx(pData
: Pointer; dataSize
: LongInt; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
319 find_id
:= FindTexture();
321 if not LoadTextureMemEx(pData
, dataSize
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
323 e_Textures
[find_id
].Width
:= fWidth
;
324 e_Textures
[find_id
].Height
:= fHeight
;
325 e_Textures
[find_id
].Fmt
:= fmt
;
332 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
334 if Width
<> nil then Width
^ := e_Textures
[ID
].Width
;
335 if Height
<> nil then Height
^ := e_Textures
[ID
].Height
;
338 function e_GetTextureSize2(ID
: DWORD
): TRectWH
;
346 w
:= e_Textures
[ID
].Width
;
347 h
:= e_Textures
[ID
].Height
;
354 if e_NoGraphics
then Exit
;
356 data
:= GetMemory(w
*h
*4);
357 glEnable(GL_TEXTURE_2D
);
358 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
359 glGetTexImage(GL_TEXTURE_2D
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
361 for y
:= h
-1 downto 0 do
368 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
374 Result
.Y
:= h
-lastline
;
386 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
392 Result
.Height
:= h
-lastline
-Result
.Y
;
404 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
410 Result
.X
:= lastline
+1;
415 for x
:= w
-1 downto 0 do
422 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
428 Result
.Width
:= lastline
-Result
.X
+1;
436 procedure e_ResizeWindow(Width
, Height
: Integer);
440 e_SetViewPort(0, 0, Width
, Height
);
443 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
444 Blending
: Boolean; Mirror
: TMirrorType
= M_NONE
);
448 if e_NoGraphics
then Exit
;
449 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
451 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
456 if (AlphaChannel
) or (Alpha
> 0) then
457 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
460 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
463 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
465 glEnable(GL_TEXTURE_2D
);
466 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
469 u
:= e_Textures
[ID
].tx
.u
;
470 v
:= e_Textures
[ID
].tx
.v
;
472 if Mirror
= M_NONE
then
474 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
475 glTexCoord2f(0, 0); glVertex2i(X
, Y
);
476 glTexCoord2f(0, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
477 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
480 if Mirror
= M_HORIZONTAL
then
482 glTexCoord2f(u
, 0); glVertex2i(X
, Y
);
483 glTexCoord2f(0, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
484 glTexCoord2f(0, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
485 glTexCoord2f(u
, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
488 if Mirror
= M_VERTICAL
then
490 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
491 glTexCoord2f(0, -v
); glVertex2i(X
, Y
);
492 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
493 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
501 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
502 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
506 if e_NoGraphics
then Exit
;
507 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
509 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
514 if (AlphaChannel
) or (Alpha
> 0) then
515 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
518 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
521 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
523 glEnable(GL_TEXTURE_2D
);
524 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
526 u
:= e_Textures
[ID
].tx
.u
;
527 v
:= e_Textures
[ID
].tx
.v
;
530 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
531 glTexCoord2f(u
, v
); glVertex2i(X
+ Width
, Y
);
532 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
+ Height
);
533 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ Height
);
539 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
540 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
544 if e_NoGraphics
then Exit
;
545 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
547 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
552 if (AlphaChannel
) or (Alpha
> 0) then
553 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
556 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
559 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
561 glEnable(GL_TEXTURE_2D
);
562 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
565 u
:= e_Textures
[ID
].tx
.u
;
566 v
:= e_Textures
[ID
].tx
.v
;
568 if Mirror
= M_NONE
then
570 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
);
571 glTexCoord2f(0, 0); glVertex2i(X
, Y
);
572 glTexCoord2f(0, -v
); glVertex2i(X
, Y
+ Height
);
573 glTexCoord2f(u
, -v
); glVertex2i(X
+ Width
, Y
+ Height
);
576 if Mirror
= M_HORIZONTAL
then
578 glTexCoord2f(u
, 0); glVertex2i(X
, Y
);
579 glTexCoord2f(0, 0); glVertex2i(X
+ Width
, Y
);
580 glTexCoord2f(0, -v
); glVertex2i(X
+ Width
, Y
+ Height
);
581 glTexCoord2f(u
, -v
); glVertex2i(X
, Y
+ Height
);
584 if Mirror
= M_VERTICAL
then
586 glTexCoord2f(u
, -v
); glVertex2i(X
+ Width
, Y
);
587 glTexCoord2f(0, -v
); glVertex2i(X
, Y
);
588 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ Height
);
589 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
+ Height
);
597 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
598 AlphaChannel
: Boolean; Blending
: Boolean);
600 X2
, Y2
, dx
, w
, h
: Integer;
603 if e_NoGraphics
then Exit
;
604 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
606 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
611 if (AlphaChannel
) or (Alpha
> 0) then
612 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
615 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
618 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
626 glEnable(GL_TEXTURE_2D
);
627 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
629 X2
:= X
+ e_Textures
[ID
].Width
* XCount
;
630 Y2
:= Y
+ e_Textures
[ID
].Height
* YCount
;
632 //k8: this SHOULD work... i hope
633 if (e_Textures
[ID
].tx
.width
= e_Textures
[ID
].tx
.glwidth
) and (e_Textures
[ID
].tx
.height
= e_Textures
[ID
].tx
.glheight
) then
636 glTexCoord2i(0, YCount
); glVertex2i(X
, Y
);
637 glTexCoord2i(XCount
, YCount
); glVertex2i(X2
, Y
);
638 glTexCoord2i(XCount
, 0); glVertex2i(X2
, Y2
);
639 glTexCoord2i(0, 0); glVertex2i(X
, Y2
);
646 u
:= e_Textures
[ID
].tx
.u
;
647 v
:= e_Textures
[ID
].tx
.v
;
648 w
:= e_Textures
[ID
].tx
.width
;
649 h
:= e_Textures
[ID
].tx
.height
;
656 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
657 glTexCoord2f(u
, v
); glVertex2i(X
+w
, Y
);
658 glTexCoord2f(u
, 0); glVertex2i(X
+w
, Y
+h
);
659 glTexCoord2f(0, 0); glVertex2i(X
, Y
+h
);
673 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
674 Blending
: Boolean; Angle
: Single; RC
: PPoint
; Mirror
: TMirrorType
= M_NONE
);
678 if e_NoGraphics
then Exit
;
679 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
681 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
686 if (AlphaChannel
) or (Alpha
> 0) then
687 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
690 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
693 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
695 if (Angle
<> 0) and (RC
<> nil) then
698 glTranslatef(X
+RC
.X
, Y
+RC
.Y
, 0);
699 glRotatef(Angle
, 0, 0, 1);
700 glTranslatef(-(X
+RC
.X
), -(Y
+RC
.Y
), 0);
703 glEnable(GL_TEXTURE_2D
);
704 glBindTexture(GL_TEXTURE_2D
, e_Textures
[id
].tx
.id
);
705 glBegin(GL_QUADS
); //0-1 1-1
708 u
:= e_Textures
[ID
].tx
.u
;
709 v
:= e_Textures
[ID
].tx
.v
;
711 if Mirror
= M_NONE
then
713 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
714 glTexCoord2f(0, 0); glVertex2i(X
, Y
);
715 glTexCoord2f(0, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
716 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
719 if Mirror
= M_HORIZONTAL
then
721 glTexCoord2f(u
, 0); glVertex2i(X
, Y
);
722 glTexCoord2f(0, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
723 glTexCoord2f(0, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
724 glTexCoord2f(u
, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
727 if Mirror
= M_VERTICAL
then
729 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
730 glTexCoord2f(0, -v
); glVertex2i(X
, Y
);
731 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
732 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
743 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
745 if e_NoGraphics
then Exit
;
746 glDisable(GL_TEXTURE_2D
);
747 glColor3ub(Red
, Green
, Blue
);
750 if (Size
= 2) or (Size
= 4) then
754 glVertex2f(X
+0.3, Y
+1.0);
757 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
760 procedure e_LineCorrection(var X1
, Y1
, X2
, Y2
: Integer);
762 // Make lines only top-left/bottom-right and top-right/bottom-left
774 // Pixel-perfect hack
782 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
784 nX1
, nY1
, nX2
, nY2
: Integer;
786 if e_NoGraphics
then Exit
;
787 // Only top-left/bottom-right quad
804 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
808 glDisable(GL_TEXTURE_2D
);
809 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
813 nX1
:= X1
; nY1
:= Y1
;
814 nX2
:= X2
; nY2
:= Y1
;
815 e_LineCorrection(nX1
, nY1
, nX2
, nY2
); // Pixel-perfect lines
816 glVertex2i(nX1
, nY1
);
817 glVertex2i(nX2
, nY2
);
819 nX1
:= X2
; nY1
:= Y1
;
820 nX2
:= X2
; nY2
:= Y2
;
821 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
822 glVertex2i(nX1
, nY1
);
823 glVertex2i(nX2
, nY2
);
825 nX1
:= X2
; nY1
:= Y2
;
826 nX2
:= X1
; nY2
:= Y2
;
827 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
828 glVertex2i(nX1
, nY1
);
829 glVertex2i(nX2
, nY2
);
831 nX1
:= X1
; nY1
:= Y2
;
832 nX2
:= X1
; nY2
:= Y1
;
833 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
834 glVertex2i(nX1
, nY1
);
835 glVertex2i(nX2
, nY2
);
838 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
843 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
844 Blending
: TBlending
= B_NONE
);
846 if e_NoGraphics
then Exit
;
847 if (Alpha
> 0) or (Blending
<> B_NONE
) then
852 if Blending
= B_BLEND
then
853 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
)
855 if Blending
= B_FILTER
then
856 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
)
858 if Blending
= B_INVERT
then
859 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
)
862 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
864 glDisable(GL_TEXTURE_2D
);
865 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
877 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
882 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
884 if e_NoGraphics
then Exit
;
885 // Pixel-perfect lines
887 e_LineCorrection(X1
, Y1
, X2
, Y2
);
892 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
896 glDisable(GL_TEXTURE_2D
);
897 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
905 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
910 //------------------------------------------------------------------
911 // Óäàëÿåò òåêñòóðó èç ìàññèâà
912 //------------------------------------------------------------------
913 procedure e_DeleteTexture(ID
: DWORD
);
915 if not e_NoGraphics
then
916 glDeleteTextures(1, @e_Textures
[ID
].tx
.id
);
917 e_Textures
[ID
].tx
.id
:= 0;
918 e_Textures
[ID
].Width
:= 0;
919 e_Textures
[ID
].Height
:= 0;
922 //------------------------------------------------------------------
923 // Óäàëÿåò âñå òåêñòóðû
924 //------------------------------------------------------------------
925 procedure e_RemoveAllTextures();
929 if e_Textures
= nil then Exit
;
931 for i
:= 0 to High(e_Textures
) do
932 if e_Textures
[i
].Width
<> 0 then e_DeleteTexture(i
);
936 //------------------------------------------------------------------
938 //------------------------------------------------------------------
939 procedure e_ReleaseEngine();
942 e_RemoveAllTextureFont
;
945 procedure e_BeginRender();
947 if e_NoGraphics
then Exit
;
948 glEnable(GL_ALPHA_TEST
);
949 glAlphaFunc(GL_GREATER
, 0.0);
952 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
954 if e_NoGraphics
then Exit
;
955 glClearColor(Red
, Green
, Blue
, 0);
959 procedure e_Clear(); overload
;
961 if e_NoGraphics
then Exit
;
962 glClearColor(0, 0, 0, 0);
963 glClear(GL_COLOR_BUFFER_BIT
);
966 procedure e_EndRender();
968 if e_NoGraphics
then Exit
;
972 function e_GetGamma(win
: PSDL_Window
): Byte;
974 ramp
: array [0..256*3-1] of Word;
975 rgb
: array [0..2] of Double;
984 if e_NoGraphics
then Exit
;
989 SDL_GetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
998 for j
:= min
to max
- 1 do
1001 B
:= (j
mod 256)/256;
1003 sum
:= sum
+ ln(A
)/ln(B
);
1006 rgb
[i
] := sum
/ count
;
1009 Result
:= 100 - Trunc(((rgb
[0] + rgb
[1] + rgb
[2])/3 - 0.23) * 100/(2.7 - 0.23));
1012 procedure e_SetGamma(win
: PSDL_Window
; Gamma
: Byte);
1014 ramp
: array [0..256*3-1] of Word;
1019 if e_NoGraphics
then Exit
;
1020 g
:= (100 - Gamma
)*(2.7 - 0.23)/100 + 0.23;
1022 for i
:= 0 to 255 do
1024 r
:= Exp(g
* ln(i
/256))*65536;
1025 if r
< 0 then r
:= 0
1026 else if r
> 65535 then r
:= 65535;
1027 ramp
[i
] := trunc(r
);
1028 ramp
[i
+ 256] := trunc(r
);
1029 ramp
[i
+ 512] := trunc(r
);
1032 SDL_SetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
1035 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
1039 e_WriteLog('Creating CharFont...', MSG_NOTIFY
);
1043 if e_CharFonts
<> nil then
1044 for i
:= 0 to High(e_CharFonts
) do
1045 if not e_CharFonts
[i
].Live
then
1051 if id
= DWORD(-1) then
1053 SetLength(e_CharFonts
, Length(e_CharFonts
) + 1);
1054 id
:= High(e_CharFonts
);
1057 with e_CharFonts
[id
] do
1059 for i
:= 0 to High(Chars
) do
1073 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
1075 with e_CharFonts
[FontID
].Chars
[Ord(c
)] do
1077 TextureID
:= Texture
;
1082 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1086 if e_NoGraphics
then Exit
;
1087 if Text = '' then Exit
;
1088 if e_CharFonts
= nil then Exit
;
1089 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1091 with e_CharFonts
[FontID
] do
1093 for a
:= 1 to Length(Text) do
1094 with Chars
[Ord(Text[a
])] do
1095 if TextureID
<> -1 then
1097 e_Draw(TextureID
, X
, Y
, 0, True, False);
1098 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1103 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
1104 Color
: TRGB
; Scale
: Single = 1.0);
1109 if e_NoGraphics
then Exit
;
1110 if Text = '' then Exit
;
1111 if e_CharFonts
= nil then Exit
;
1112 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1114 with e_CharFonts
[FontID
] do
1116 for a
:= 1 to Length(Text) do
1117 with Chars
[Ord(Text[a
])] do
1118 if TextureID
<> -1 then
1120 if Scale
<> 1.0 then
1123 glScalef(Scale
, Scale
, 0);
1128 e_Draw(TextureID
, X
, Y
, 0, True, False);
1131 if Scale
<> 1.0 then glPopMatrix
;
1133 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1138 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1140 a
, TX
, TY
, len
: Integer;
1144 if e_NoGraphics
then Exit
;
1145 if Text = '' then Exit
;
1146 if e_CharFonts
= nil then Exit
;
1147 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1155 len
:= Length(Text);
1157 e_CharFont_GetSize(FontID
, 'A', w
, h
);
1159 with e_CharFonts
[FontID
] do
1161 for a
:= 1 to len
do
1172 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1177 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1182 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1187 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1192 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1197 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1202 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1207 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1212 with Chars
[Ord(Text[a
])] do
1213 if TextureID
<> -1 then
1217 e_Draw(TextureID
, TX
, TY
, 0, True, False);
1220 TX
:= TX
+Width
+IfThen(a
= Length(Text), 0, Space
);
1226 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
1234 if Text = '' then Exit
;
1235 if e_CharFonts
= nil then Exit
;
1236 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1238 with e_CharFonts
[FontID
] do
1240 for a
:= 1 to Length(Text) do
1241 with Chars
[Ord(Text[a
])] do
1242 if TextureID
<> -1 then
1244 w
:= w
+Width
+IfThen(a
= Length(Text), 0, Space
);
1245 e_GetTextureSize(TextureID
, nil, @h2
);
1246 if h2
> h
then h
:= h2
;
1251 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
1253 a
, lines
, len
: Integer;
1260 if Text = '' then Exit
;
1261 if e_CharFonts
= nil then Exit
;
1262 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1265 len
:= Length(Text);
1267 with e_CharFonts
[FontID
] do
1269 for a
:= 1 to len
do
1271 if Text[a
] = #10 then
1281 else if Text[a
] in [#1, #2, #3, #4, #18, #19, #20, #21] then
1284 with Chars
[Ord(Text[a
])] do
1285 if TextureID
<> -1 then
1287 w2
:= w2
+ Width
+ IfThen(a
= len
, 0, Space
);
1288 e_GetTextureSize(TextureID
, nil, @h2
);
1289 if h2
> h
then h
:= h2
;
1299 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
1305 if e_CharFonts
= nil then Exit
;
1306 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1308 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1309 Result
:= Max(Result
, e_CharFonts
[FontID
].Chars
[a
].Width
);
1312 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
1319 if e_CharFonts
= nil then Exit
;
1320 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1322 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1324 if e_CharFonts
[FontID
].Chars
[a
].TextureID
<> -1 then
1325 e_GetTextureSize(e_CharFonts
[FontID
].Chars
[a
].TextureID
, nil, @h2
)
1327 if h2
> Result
then Result
:= h2
;
1331 procedure e_CharFont_Remove(FontID
: DWORD
);
1335 with e_CharFonts
[FontID
] do
1336 for a
:= 0 to High(Chars
) do
1337 if Chars
[a
].TextureID
<> -1 then e_DeleteTexture(Chars
[a
].TextureID
);
1339 e_CharFonts
[FontID
].Live
:= False;
1342 procedure e_CharFont_RemoveAll();
1346 if e_CharFonts
= nil then Exit
;
1348 for a
:= 0 to High(e_CharFonts
) do
1349 e_CharFont_Remove(a
);
1354 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
1361 if e_NoGraphics
then Exit
;
1362 e_WriteLog('Creating texture font...', MSG_NOTIFY
);
1366 if e_TextureFonts
<> nil then
1367 for i
:= 0 to High(e_TextureFonts
) do
1368 if e_TextureFonts
[i
].Base
= 0 then
1374 if id
= DWORD(-1) then
1376 SetLength(e_TextureFonts
, Length(e_TextureFonts
) + 1);
1377 id
:= High(e_TextureFonts
);
1380 with e_TextureFonts
[id
] do
1382 Base
:= glGenLists(XCount
*YCount
);
1383 TextureID
:= e_Textures
[Tex
].tx
.id
;
1384 CharWidth
:= (e_Textures
[Tex
].Width
div XCount
)+Space
;
1385 CharHeight
:= e_Textures
[Tex
].Height
div YCount
;
1392 glBindTexture(GL_TEXTURE_2D
, e_Textures
[Tex
].tx
.id
);
1393 for loop1
:= 0 to XCount
*YCount
-1 do
1395 cx
:= (loop1
mod XCount
)/XCount
;
1396 cy
:= (loop1
div YCount
)/YCount
;
1398 glNewList(e_TextureFonts
[id
].Base
+loop1
, GL_COMPILE
);
1400 glTexCoord2f(cx
, 1.0-cy
-1/YCount
);
1401 glVertex2d(0, e_Textures
[Tex
].Height
div YCount
);
1403 glTexCoord2f(cx
+1/XCount
, 1.0-cy
-1/YCount
);
1404 glVertex2i(e_Textures
[Tex
].Width
div XCount
, e_Textures
[Tex
].Height
div YCount
);
1406 glTexCoord2f(cx
+1/XCount
, 1.0-cy
);
1407 glVertex2i(e_Textures
[Tex
].Width
div XCount
, 0);
1409 glTexCoord2f(cx
, 1.0-cy
);
1412 glTranslated((e_Textures
[Tex
].Width
div XCount
)+Space
, 0, 0);
1419 procedure e_TextureFontKill(FontID
: DWORD
);
1421 if e_NoGraphics
then Exit
;
1422 glDeleteLists(e_TextureFonts
[FontID
].Base
, 256);
1423 e_TextureFonts
[FontID
].Base
:= 0;
1426 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
1428 if e_NoGraphics
then Exit
;
1429 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1430 if Text = '' then Exit
;
1432 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1435 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1438 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1439 glEnable(GL_TEXTURE_2D
);
1440 glTranslated(x
, y
, 0);
1441 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1442 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1443 glDisable(GL_TEXTURE_2D
);
1446 glDisable(GL_BLEND
);
1449 // god forgive me for this, but i cannot figure out how to do it without lists
1450 procedure e_TextureFontPrintChar(X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
1452 if e_NoGraphics
then Exit
;
1457 glColor4ub(0, 0, 0, 128);
1458 glTranslated(X
+1, Y
+1, 0);
1459 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1464 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1465 glTranslated(X
, Y
, 0);
1466 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1471 procedure e_TextureFontPrintFmt(X
, Y
: Integer; Text: string; FontID
: DWORD
; Shadow
: Boolean = False);
1473 a
, TX
, TY
, len
: Integer;
1477 if e_NoGraphics
then Exit
;
1478 if Text = '' then Exit
;
1479 if e_TextureFonts
= nil then Exit
;
1480 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1488 len
:= Length(Text);
1490 w
:= e_TextureFonts
[FontID
].CharWidth
;
1492 with e_TextureFonts
[FontID
] do
1494 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1495 glEnable(GL_TEXTURE_2D
);
1496 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1498 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1501 for a
:= 1 to len
do
1512 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1517 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1522 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1527 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1532 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1537 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1542 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1547 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1554 e_TextureFontPrintChar(TX
, TY
, Text[a
], FontID
, Shadow
);
1559 glDisable(GL_TEXTURE_2D
);
1560 glDisable(GL_BLEND
);
1564 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
1565 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
1567 if e_NoGraphics
then Exit
;
1568 if Text = '' then Exit
;
1571 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1572 glEnable(GL_TEXTURE_2D
);
1573 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1575 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1580 glColor4ub(0, 0, 0, 128);
1581 glTranslated(x
+1, y
+1, 0);
1582 glScalef(Scale
, Scale
, 0);
1583 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1588 glColor4ub(Red
, Green
, Blue
, 255);
1589 glTranslated(x
, y
, 0);
1590 glScalef(Scale
, Scale
, 0);
1591 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1593 glDisable(GL_TEXTURE_2D
);
1595 glColor3ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
);
1596 glDisable(GL_BLEND
);
1599 procedure e_TextureFontGetSize(ID
: DWORD
; var CharWidth
, CharHeight
: Byte);
1603 if e_NoGraphics
then Exit
;
1604 if Integer(ID
) > High(e_TextureFonts
) then
1606 CharWidth
:= e_TextureFonts
[ID
].CharWidth
;
1607 CharHeight
:= e_TextureFonts
[ID
].CharHeight
;
1610 procedure e_RemoveAllTextureFont();
1614 if e_NoGraphics
then Exit
;
1615 if e_TextureFonts
= nil then Exit
;
1617 for i
:= 0 to High(e_TextureFonts
) do
1618 if e_TextureFonts
[i
].Base
<> 0 then
1620 glDeleteLists(e_TextureFonts
[i
].Base
, 256);
1621 e_TextureFonts
[i
].Base
:= 0;
1624 e_TextureFonts
:= nil;
1627 function _RGB(Red
, Green
, Blue
: Byte): TRGB
;
1634 function _Point(X
, Y
: Integer): TPoint2i
;
1640 function _Rect(X
, Y
: Integer; Width
, Height
: Word): TRectWH
;
1644 Result
.Width
:= Width
;
1645 Result
.Height
:= Height
;
1648 function _TRect(L
, T
, R
, B
: LongInt): TRect
;
1657 procedure e_MakeScreenshot (st
: TStream
; Width
, Height
: Word);
1659 pixels
, obuf
, scln
, ps
, pd
: PByte;
1663 sign
: array [0..7] of Byte;
1664 hbuf
: array [0..12] of Byte;
1667 if e_NoGraphics
then Exit
;
1670 // first, extract and pack graphics data
1672 if (Width
mod 4) > 0 then Width
:= Width
+ 4 - (Width
mod 4);
1674 GetMem(pixels
, Width
*Height
*3);
1676 FillChar(pixels
^, Width
*Height
*3, 0);
1677 glReadPixels(0, 0, Width
, Height
, GL_RGB
, GL_UNSIGNED_BYTE
, pixels
);
1678 //e_WriteLog('PNG: pixels read', MSG_NOTIFY);
1681 GetMem(scln
, (Width
*3+1)*Height
);
1685 Inc(ps
, (Width
*3)*(Height
-1));
1686 for i
:= 0 to Height
-1 do
1690 Move(ps
^, pd
^, Width
*3);
1701 obufsize
:= (Width
*3+1)*Height
*2;
1702 GetMem(obuf
, obufsize
);
1707 res
:= compress2(Pointer(obuf
), dlen
, Pointer(pixels
), (Width
*3+1)*Height
, 9);
1708 if res
= Z_OK
then break
;
1709 if res
<> Z_BUF_ERROR
then raise Exception
.Create('can''t pack data for PNG');
1710 obufsize
:= obufsize
*2;
1713 GetMem(obuf
, obufsize
);
1715 //e_WriteLog(Format('PNG: pixels compressed from %d to %d', [Integer(Width*Height*3), Integer(dlen)]), MSG_NOTIFY);
1728 st
.writeBuffer(sign
, 8);
1729 //e_WriteLog('PNG: signature written', MSG_NOTIFY);
1732 writeIntBE(st
, LongWord(13));
1737 st
.writeBuffer(sign
, 4);
1738 crc
:= crc32(0, @sign
, 4);
1741 hbuf
[2] := (Width
shr 8) and $ff;
1742 hbuf
[3] := Width
and $ff;
1745 hbuf
[6] := (Height
shr 8) and $ff;
1746 hbuf
[7] := Height
and $ff;
1747 hbuf
[8] := 8; // bit depth
1748 hbuf
[9] := 2; // RGB
1749 hbuf
[10] := 0; // compression method
1750 hbuf
[11] := 0; // filter method
1751 hbuf
[12] := 0; // no interlace
1752 crc
:= crc32(crc
, @hbuf
, 13);
1753 st
.writeBuffer(hbuf
, 13);
1754 writeIntBE(st
, crc
);
1755 //e_WriteLog('PNG: header written', MSG_NOTIFY);
1758 writeIntBE(st
, LongWord(dlen
));
1763 st
.writeBuffer(sign
, 4);
1764 crc
:= crc32(0, @sign
, 4);
1765 crc
:= crc32(crc
, obuf
, dlen
);
1766 st
.writeBuffer(obuf
^, dlen
);
1767 writeIntBE(st
, crc
);
1768 //e_WriteLog('PNG: image data written', MSG_NOTIFY);
1771 writeIntBE(st
, LongWord(0));
1776 st
.writeBuffer(sign
, 4);
1777 crc
:= crc32(0, @sign
, 4);
1778 writeIntBE(st
, crc
);
1779 //e_WriteLog('PNG: end marker written', MSG_NOTIFY);
1781 if obuf
<> nil then FreeMem(obuf
);