From c3be56f2a3849cd22be39ce594498c7990e05606 Mon Sep 17 00:00:00 2001 From: FGSFDSFGS Date: Wed, 21 Dec 2016 04:06:32 +0300 Subject: [PATCH] hopefully no more windows --- src/editor/Editor.lpi | 13 +- src/editor/Editor.lpr | 13 +- src/editor/f_addresource_sound.pas | 7 +- src/editor/f_addresource_texture.pas | 8 +- src/editor/f_main.lfm | 5358 ++++--- src/editor/f_main.pas | 209 +- src/editor/f_mapoptions.lfm | 310 +- src/editor/f_options.lfm | 195 +- src/editor/g_language.pas | 13 +- src/editor/g_map.pas | 6 +- src/editor/g_textures.pas | 14 +- src/engine/e_graphics.pas | 717 +- src/engine/e_textures.pas | 636 +- src/lib/dgl/GL.pas | 2226 --- src/lib/dgl/dglOpenGL.pas | 15296 ------------------- src/lib/dgl/glExt.pas | 9483 ------------ src/lib/vampimg/Imaging.pas | 4252 ++++++ src/lib/vampimg/ImagingBitmap.pas | 855 ++ src/lib/vampimg/ImagingCanvases.pas | 2110 +++ src/lib/vampimg/ImagingClasses.pas | 1091 ++ src/lib/vampimg/ImagingColors.pas | 246 + src/lib/vampimg/ImagingComponents.pas | 1296 ++ src/lib/vampimg/ImagingDds.pas | 1144 ++ src/lib/vampimg/ImagingExtras.pas | 153 + src/lib/vampimg/ImagingFormats.pas | 4516 ++++++ src/lib/vampimg/ImagingGif.pas | 1291 ++ src/lib/vampimg/ImagingIO.pas | 646 + src/lib/vampimg/ImagingJpeg.pas | 768 + src/lib/vampimg/ImagingNetworkGraphics.pas | 2695 ++++ src/lib/vampimg/ImagingOptions.inc | 216 + src/lib/vampimg/ImagingPcx.pas | 375 + src/lib/vampimg/ImagingPortableMaps.pas | 977 ++ src/lib/vampimg/ImagingPsd.pas | 800 + src/lib/vampimg/ImagingRadiance.pas | 497 + src/lib/vampimg/ImagingTarga.pas | 619 + src/lib/vampimg/ImagingTypes.pas | 564 + src/lib/vampimg/ImagingUtility.pas | 1691 ++ src/lib/vampimg/ImagingXpm.pas | 580 + src/lib/vampimg/JpegLib/imjcapimin.pas | 401 + src/lib/vampimg/JpegLib/imjcapistd.pas | 222 + src/lib/vampimg/JpegLib/imjccoefct.pas | 521 + src/lib/vampimg/JpegLib/imjccolor.pas | 530 + src/lib/vampimg/JpegLib/imjcdctmgr.pas | 514 + src/lib/vampimg/JpegLib/imjchuff.pas | 1116 ++ src/lib/vampimg/JpegLib/imjcinit.pas | 95 + src/lib/vampimg/JpegLib/imjcmainct.pas | 343 + src/lib/vampimg/JpegLib/imjcmarker.pas | 724 + src/lib/vampimg/JpegLib/imjcmaster.pas | 701 + src/lib/vampimg/JpegLib/imjcomapi.pas | 130 + src/lib/vampimg/JpegLib/imjconfig.inc | 125 + src/lib/vampimg/JpegLib/imjcparam.pas | 701 + src/lib/vampimg/JpegLib/imjcphuff.pas | 962 ++ src/lib/vampimg/JpegLib/imjcprepct.pas | 406 + src/lib/vampimg/JpegLib/imjcsample.pas | 631 + src/lib/vampimg/JpegLib/imjdapimin.pas | 505 + src/lib/vampimg/JpegLib/imjdapistd.pas | 376 + src/lib/vampimg/JpegLib/imjdcoefct.pas | 895 ++ src/lib/vampimg/JpegLib/imjdcolor.pas | 501 + src/lib/vampimg/JpegLib/imjdct.pas | 109 + src/lib/vampimg/JpegLib/imjddctmgr.pas | 330 + src/lib/vampimg/JpegLib/imjdeferr.pas | 497 + src/lib/vampimg/JpegLib/imjdhuff.pas | 1204 ++ src/lib/vampimg/JpegLib/imjdinput.pas | 416 + src/lib/vampimg/JpegLib/imjdmainct.pas | 610 + src/lib/vampimg/JpegLib/imjdmarker.pas | 2648 ++++ src/lib/vampimg/JpegLib/imjdmaster.pas | 679 + src/lib/vampimg/JpegLib/imjdmerge.pas | 514 + src/lib/vampimg/JpegLib/imjdphuff.pas | 1061 ++ src/lib/vampimg/JpegLib/imjdpostct.pas | 341 + src/lib/vampimg/JpegLib/imjdsample.pas | 592 + src/lib/vampimg/JpegLib/imjerror.pas | 462 + src/lib/vampimg/JpegLib/imjfdctflt.pas | 176 + src/lib/vampimg/JpegLib/imjfdctfst.pas | 237 + src/lib/vampimg/JpegLib/imjfdctint.pas | 297 + src/lib/vampimg/JpegLib/imjidctasm.pas | 793 + src/lib/vampimg/JpegLib/imjidctflt.pas | 286 + src/lib/vampimg/JpegLib/imjidctfst.pas | 410 + src/lib/vampimg/JpegLib/imjidctint.pas | 440 + src/lib/vampimg/JpegLib/imjidctred.pas | 525 + src/lib/vampimg/JpegLib/imjinclude.pas | 126 + src/lib/vampimg/JpegLib/imjmemmgr.pas | 1283 ++ src/lib/vampimg/JpegLib/imjmemnobs.pas | 259 + src/lib/vampimg/JpegLib/imjmorecfg.pas | 219 + src/lib/vampimg/JpegLib/imjpeglib.pas | 1300 ++ src/lib/vampimg/JpegLib/imjquant1.pas | 1009 ++ src/lib/vampimg/JpegLib/imjquant2.pas | 1551 ++ src/lib/vampimg/JpegLib/imjutils.pas | 232 + src/lib/vampimg/JpegLib/readme.txt | 381 + src/lib/vampimg/ZLib/dzlib.pas | 523 + src/lib/vampimg/ZLib/imadler.pas | 113 + src/lib/vampimg/ZLib/iminfblock.pas | 951 ++ src/lib/vampimg/ZLib/iminfcodes.pas | 576 + src/lib/vampimg/ZLib/iminffast.pas | 318 + src/lib/vampimg/ZLib/iminftrees.pas | 781 + src/lib/vampimg/ZLib/iminfutil.pas | 222 + src/lib/vampimg/ZLib/impaszlib.pas | 520 + src/lib/vampimg/ZLib/imtrees.pas | 2249 +++ src/lib/vampimg/ZLib/imzconf.inc | 23 + src/lib/vampimg/ZLib/imzdeflate.pas | 2129 +++ src/lib/vampimg/ZLib/imzinflate.pas | 750 + src/lib/vampimg/ZLib/imzutil.pas | 190 + src/lib/vampimg/ZLib/readme.txt | 129 + src/shared/WADEDITOR.pas | 6 +- src/shared/WADSTRUCT.pas | 8 +- src/shared/mapstructio.inc | 685 + src/shared/mapstructsizes.inc | 25 + src/shared/utils.pas | 527 + 107 files changed, 71361 insertions(+), 30636 deletions(-) delete mode 100644 src/lib/dgl/GL.pas delete mode 100644 src/lib/dgl/dglOpenGL.pas delete mode 100644 src/lib/dgl/glExt.pas create mode 100644 src/lib/vampimg/Imaging.pas create mode 100644 src/lib/vampimg/ImagingBitmap.pas create mode 100644 src/lib/vampimg/ImagingCanvases.pas create mode 100644 src/lib/vampimg/ImagingClasses.pas create mode 100644 src/lib/vampimg/ImagingColors.pas create mode 100644 src/lib/vampimg/ImagingComponents.pas create mode 100644 src/lib/vampimg/ImagingDds.pas create mode 100644 src/lib/vampimg/ImagingExtras.pas create mode 100644 src/lib/vampimg/ImagingFormats.pas create mode 100644 src/lib/vampimg/ImagingGif.pas create mode 100644 src/lib/vampimg/ImagingIO.pas create mode 100644 src/lib/vampimg/ImagingJpeg.pas create mode 100644 src/lib/vampimg/ImagingNetworkGraphics.pas create mode 100644 src/lib/vampimg/ImagingOptions.inc create mode 100644 src/lib/vampimg/ImagingPcx.pas create mode 100644 src/lib/vampimg/ImagingPortableMaps.pas create mode 100644 src/lib/vampimg/ImagingPsd.pas create mode 100644 src/lib/vampimg/ImagingRadiance.pas create mode 100644 src/lib/vampimg/ImagingTarga.pas create mode 100644 src/lib/vampimg/ImagingTypes.pas create mode 100644 src/lib/vampimg/ImagingUtility.pas create mode 100644 src/lib/vampimg/ImagingXpm.pas create mode 100644 src/lib/vampimg/JpegLib/imjcapimin.pas create mode 100644 src/lib/vampimg/JpegLib/imjcapistd.pas create mode 100644 src/lib/vampimg/JpegLib/imjccoefct.pas create mode 100644 src/lib/vampimg/JpegLib/imjccolor.pas create mode 100644 src/lib/vampimg/JpegLib/imjcdctmgr.pas create mode 100644 src/lib/vampimg/JpegLib/imjchuff.pas create mode 100644 src/lib/vampimg/JpegLib/imjcinit.pas create mode 100644 src/lib/vampimg/JpegLib/imjcmainct.pas create mode 100644 src/lib/vampimg/JpegLib/imjcmarker.pas create mode 100644 src/lib/vampimg/JpegLib/imjcmaster.pas create mode 100644 src/lib/vampimg/JpegLib/imjcomapi.pas create mode 100644 src/lib/vampimg/JpegLib/imjconfig.inc create mode 100644 src/lib/vampimg/JpegLib/imjcparam.pas create mode 100644 src/lib/vampimg/JpegLib/imjcphuff.pas create mode 100644 src/lib/vampimg/JpegLib/imjcprepct.pas create mode 100644 src/lib/vampimg/JpegLib/imjcsample.pas create mode 100644 src/lib/vampimg/JpegLib/imjdapimin.pas create mode 100644 src/lib/vampimg/JpegLib/imjdapistd.pas create mode 100644 src/lib/vampimg/JpegLib/imjdcoefct.pas create mode 100644 src/lib/vampimg/JpegLib/imjdcolor.pas create mode 100644 src/lib/vampimg/JpegLib/imjdct.pas create mode 100644 src/lib/vampimg/JpegLib/imjddctmgr.pas create mode 100644 src/lib/vampimg/JpegLib/imjdeferr.pas create mode 100644 src/lib/vampimg/JpegLib/imjdhuff.pas create mode 100644 src/lib/vampimg/JpegLib/imjdinput.pas create mode 100644 src/lib/vampimg/JpegLib/imjdmainct.pas create mode 100644 src/lib/vampimg/JpegLib/imjdmarker.pas create mode 100644 src/lib/vampimg/JpegLib/imjdmaster.pas create mode 100644 src/lib/vampimg/JpegLib/imjdmerge.pas create mode 100644 src/lib/vampimg/JpegLib/imjdphuff.pas create mode 100644 src/lib/vampimg/JpegLib/imjdpostct.pas create mode 100644 src/lib/vampimg/JpegLib/imjdsample.pas create mode 100644 src/lib/vampimg/JpegLib/imjerror.pas create mode 100644 src/lib/vampimg/JpegLib/imjfdctflt.pas create mode 100644 src/lib/vampimg/JpegLib/imjfdctfst.pas create mode 100644 src/lib/vampimg/JpegLib/imjfdctint.pas create mode 100644 src/lib/vampimg/JpegLib/imjidctasm.pas create mode 100644 src/lib/vampimg/JpegLib/imjidctflt.pas create mode 100644 src/lib/vampimg/JpegLib/imjidctfst.pas create mode 100644 src/lib/vampimg/JpegLib/imjidctint.pas create mode 100644 src/lib/vampimg/JpegLib/imjidctred.pas create mode 100644 src/lib/vampimg/JpegLib/imjinclude.pas create mode 100644 src/lib/vampimg/JpegLib/imjmemmgr.pas create mode 100644 src/lib/vampimg/JpegLib/imjmemnobs.pas create mode 100644 src/lib/vampimg/JpegLib/imjmorecfg.pas create mode 100644 src/lib/vampimg/JpegLib/imjpeglib.pas create mode 100644 src/lib/vampimg/JpegLib/imjquant1.pas create mode 100644 src/lib/vampimg/JpegLib/imjquant2.pas create mode 100644 src/lib/vampimg/JpegLib/imjutils.pas create mode 100644 src/lib/vampimg/JpegLib/readme.txt create mode 100644 src/lib/vampimg/ZLib/dzlib.pas create mode 100644 src/lib/vampimg/ZLib/imadler.pas create mode 100644 src/lib/vampimg/ZLib/iminfblock.pas create mode 100644 src/lib/vampimg/ZLib/iminfcodes.pas create mode 100644 src/lib/vampimg/ZLib/iminffast.pas create mode 100644 src/lib/vampimg/ZLib/iminftrees.pas create mode 100644 src/lib/vampimg/ZLib/iminfutil.pas create mode 100644 src/lib/vampimg/ZLib/impaszlib.pas create mode 100644 src/lib/vampimg/ZLib/imtrees.pas create mode 100644 src/lib/vampimg/ZLib/imzconf.inc create mode 100644 src/lib/vampimg/ZLib/imzdeflate.pas create mode 100644 src/lib/vampimg/ZLib/imzinflate.pas create mode 100644 src/lib/vampimg/ZLib/imzutil.pas create mode 100644 src/lib/vampimg/ZLib/readme.txt create mode 100644 src/shared/mapstructio.inc create mode 100644 src/shared/mapstructsizes.inc create mode 100644 src/shared/utils.pas diff --git a/src/editor/Editor.lpi b/src/editor/Editor.lpi index 46e8ea6..6125b97 100644 --- a/src/editor/Editor.lpi +++ b/src/editor/Editor.lpi @@ -31,10 +31,13 @@ - + - + + + + @@ -98,7 +101,9 @@ + + @@ -224,8 +229,8 @@ - - + + diff --git a/src/editor/Editor.lpr b/src/editor/Editor.lpr index a0da9ce..647bfae 100644 --- a/src/editor/Editor.lpr +++ b/src/editor/Editor.lpr @@ -4,7 +4,7 @@ program Editor; uses Forms, Interfaces, - dglOpenGL in '../lib/dgl/dglOpenGL.pas', + GL, GLExt, e_graphics in '../engine/e_graphics.pas', e_log in '../engine/e_log.pas', e_textures in '../engine/e_textures.pas', @@ -37,10 +37,13 @@ uses f_packmap in 'f_packmap.pas' {PackMapForm}, f_maptest in 'f_maptest.pas' {MapTestForm}, f_choosetype in 'f_choosetype.pas' {ChooseTypeForm}, - fmod in '../lib/fmod/fmod.pas', - fmoderrors in '../lib/fmod/fmoderrors.pas', - fmodpresets in '../lib/fmod/fmodpresets.pas', - fmodtypes in '../lib/fmod/fmodtypes.pas', + fmod, + fmoderrors, + fmodpresets, + fmodtypes, + ImagingTypes, + Imaging, + ImagingUtility, g_language in 'g_language.pas', f_selectlang in 'f_selectlang.pas' {SelectLanguageForm}; diff --git a/src/editor/f_addresource_sound.pas b/src/editor/f_addresource_sound.pas index 4efa987..2dfc49d 100644 --- a/src/editor/f_addresource_sound.pas +++ b/src/editor/f_addresource_sound.pas @@ -105,7 +105,8 @@ function CreateSoundWAD(Resource: String): Boolean; var WAD: TWADEditor_1; FileName, SectionName, ResourceName: String; - ResLength, sz: Integer; + ResLength: Integer; + sz: LongWord; soundExInfo: FMOD_CREATESOUNDEXINFO; res: FMOD_RESULT; @@ -126,10 +127,10 @@ begin sz := SizeOf(FMOD_CREATESOUNDEXINFO); FillMemory(@soundExInfo, sz, 0); soundExInfo.cbsize := sz; - soundExInfo.length := ResLength; + soundExInfo.length := LongWord(ResLength); res := FMOD_System_CreateStream(F_System, SoundData, - FMOD_LOOP_OFF + FMOD_2D + FMOD_SOFTWARE + FMOD_OPENMEMORY, + FMOD_LOOP_OFF or FMOD_2D or FMOD_OPENMEMORY, @soundExInfo, Sound); if res <> FMOD_OK then diff --git a/src/editor/f_addresource_texture.pas b/src/editor/f_addresource_texture.pas index f9ebe0a..ce9a073 100644 --- a/src/editor/f_addresource_texture.pas +++ b/src/editor/f_addresource_texture.pas @@ -37,13 +37,13 @@ var AddTextureForm: TAddTextureForm; function IsAnim(Res: String): Boolean; -function GetFrame(Res: String; var Data: Pointer; +function GetFrame(Res: String; var Data: Pointer; var DataLen: Integer; var Width, Height: Word): Boolean; implementation uses - BinEditor, WADEDITOR, f_main, g_textures, WADSTRUCT, CONFIG, g_map, + BinEditor, WADEDITOR, WADSTRUCT, f_main, g_textures, CONFIG, g_map, g_language; type @@ -169,7 +169,7 @@ begin Result := ok; end; -function GetFrame(Res: String; var Data: Pointer; +function GetFrame(Res: String; var Data: Pointer; var DataLen: Integer; var Width, Height: Word): Boolean; var AnimWAD: Pointer; @@ -232,6 +232,8 @@ begin Exit; end; + DataLen := Len; + Height := config.ReadInt('', 'frameheight', 0); Width := config.ReadInt('', 'framewidth', 0); diff --git a/src/editor/f_main.lfm b/src/editor/f_main.lfm index 58c22a2..fcc7377 100644 --- a/src/editor/f_main.lfm +++ b/src/editor/f_main.lfm @@ -1,21 +1,19 @@ object MainForm: TMainForm Left = 434 + Height = 480 Top = 255 - AutoScroll = False + Width = 672 Caption = '2' - ClientHeight = 554 - ClientWidth = 792 + ClientHeight = 460 + ClientWidth = 672 Color = clBtnFace Constraints.MinHeight = 480 Constraints.MinWidth = 672 - Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' - Font.Style = [] KeyPreview = True Menu = MainMenu - Position = poDefault OnActivate = FormActivate OnCloseQuery = FormCloseQuery OnCreate = FormCreate @@ -23,303 +21,333 @@ object MainForm: TMainForm OnKeyDown = FormKeyDown OnKeyUp = FormKeyUp OnResize = FormResize - PixelsPerInch = 96 + Position = poDefault + LCLVersion = '1.6.0.4' object Splitter1: TSplitter - Left = 640 + Left = 518 + Height = 289 Top = 34 - Height = 387 + Width = 5 Align = alRight Beveled = True MinSize = 64 OnCanResize = Splitter1CanResize + ResizeAnchor = akRight end object Splitter2: TSplitter + Cursor = crVSplit Left = 0 - Top = 421 - Width = 792 Height = 3 - Cursor = crVSplit + Top = 323 + Width = 672 Align = alBottom MinSize = 64 OnCanResize = Splitter2CanResize + ResizeAnchor = akBottom end object PanelProps: TPanel - Left = 643 + Left = 523 + Height = 289 Top = 34 Width = 149 - Height = 387 Align = alRight BevelInner = bvRaised BevelOuter = bvLowered + ClientHeight = 289 + ClientWidth = 149 TabOrder = 0 object vleObjectProperty: TValueListEditor - Left = 0 - Top = 0 + Left = 2 + Height = 255 + Top = 2 Width = 145 - Height = 353 Align = alClient Constraints.MinWidth = 145 DefaultColWidth = 60 DefaultRowHeight = 16 - DisplayOptions = [doColumnTitles, doAutoColResize] - DropDownRows = 11 - FixedCols = 1 - Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -12 Font.Name = 'MS Sans Serif' - Font.Style = [] ParentFont = False + RowCount = 2 ScrollBars = ssVertical TabOrder = 0 - TitleCaptions.Strings = ( - 'Свойство' - 'Значение') + TitleFont.Color = clWindowText + TitleFont.Height = -12 + TitleFont.Name = 'MS Sans Serif' OnEditButtonClick = vleObjectPropertyEditButtonClick OnEnter = vleObjectPropertyEnter OnExit = vleObjectPropertyExit - OnGetPickList = vleObjectPropertyGetPickList OnKeyDown = vleObjectPropertyKeyDown + DisplayOptions = [doColumnTitles, doAutoColResize] + DropDownRows = 11 + Strings.Strings = ( + '' + ) + TitleCaptions.Strings = ( + 'Свойство' + 'Значение' + ) + OnGetPickList = vleObjectPropertyGetPickList ColWidths = ( - 70 - 71) + 62 + 62 + ) end object PanelPropApply: TPanel - Left = 0 - Top = 353 - Width = 145 + Left = 2 Height = 30 + Top = 257 + Width = 145 Align = alBottom BevelOuter = bvNone + ClientHeight = 30 + ClientWidth = 145 TabOrder = 1 object bApplyProperty: TButton Left = 6 + Height = 25 Top = 1 Width = 129 - Height = 25 Caption = 'Применить свойства' - TabOrder = 0 OnClick = bApplyPropertyClick + TabOrder = 0 end end end object PanelMap: TPanel Left = 0 + Height = 289 Top = 34 - Width = 640 - Height = 387 + Width = 518 Align = alClient BevelOuter = bvNone + ClientHeight = 289 + ClientWidth = 518 TabOrder = 1 - object RenderPanel: TPanel + object sbHorizontal: TScrollBar + Left = 0 + Height = 13 + Top = 276 + Width = 518 + Align = alBottom + LargeChange = 256 + Max = 0 + PageSize = 0 + SmallChange = 16 + TabOrder = 0 + TabStop = False + OnScroll = sbHorizontalScroll + end + object sbVertical: TScrollBar + Left = 504 + Height = 276 + Top = 0 + Width = 14 + Align = alRight + Kind = sbVertical + LargeChange = 256 + Max = 0 + PageSize = 0 + SmallChange = 16 + TabOrder = 1 + TabStop = False + OnScroll = sbVerticalScroll + end + object RenderPanel: TOpenGLControl Left = 0 + Height = 276 Top = 0 - Width = 626 - Height = 374 + Width = 504 Align = alClient - BevelInner = bvRaised - BevelOuter = bvLowered - TabOrder = 0 + AlphaBits = 8 OnMouseDown = RenderPanelMouseDown OnMouseMove = RenderPanelMouseMove OnMouseUp = RenderPanelMouseUp + OnPaint = RenderPanelPaint OnResize = RenderPanelResize object pLoadProgress: TPanel Left = 142 + Height = 49 Top = 94 Width = 185 - Height = 49 + ClientHeight = 49 + ClientWidth = 185 TabOrder = 0 Visible = False object lLoad: TLabel Left = 6 + Height = 13 Top = 30 Width = 169 - Height = 13 AutoSize = False + ParentColor = False end object pbLoad: TProgressBar Left = 6 + Height = 16 Top = 6 Width = 169 - Height = 16 Step = 1 TabOrder = 0 end end end - object sbHorizontal: TScrollBar - Left = 0 - Top = 372 - Width = 640 - Height = 13 - Align = alBottom - LargeChange = 256 - Max = 0 - PageSize = 0 - SmallChange = 16 - TabOrder = 1 - TabStop = False - OnScroll = sbHorizontalScroll - end - object sbVertical: TScrollBar - Left = 624 - Top = 0 - Width = 14 - Height = 374 - Align = alRight - Kind = sbVertical - LargeChange = 256 - Max = 0 - PageSize = 0 - SmallChange = 16 - TabOrder = 2 - TabStop = False - OnScroll = sbVerticalScroll - end end object StatusBar: TStatusBar Left = 0 - Top = 535 - Width = 792 - Height = 19 + Height = 23 + Top = 437 + Width = 672 AutoHint = True - Panels = < + Panels = < item Width = 600 - end + end item Width = 50 end> - SizeGrip = False SimplePanel = False + SizeGrip = False end object PanelObjs: TPanel Left = 0 - Top = 424 - Width = 792 Height = 111 + Top = 326 + Width = 672 Align = alBottom BevelInner = bvRaised BevelOuter = bvLowered + ClientHeight = 111 + ClientWidth = 672 Constraints.MinHeight = 111 TabOrder = 3 object pcObjects: TPageControl - Left = 0 - Top = 0 - Width = 788 + Left = 2 Height = 107 + Top = 2 + Width = 668 ActivePage = tsPanels Align = alClient Images = ImageList + TabIndex = 0 TabOrder = 0 object tsPanels: TTabSheet Caption = 'Панели' + ClientHeight = 80 + ClientWidth = 660 ImageIndex = 12 object lbTextureList: TListBox Left = 206 - Top = 0 - Width = 362 - Height = 78 + Height = 80 Hint = 'Список текстур' - Style = lbOwnerDrawFixed + Top = 0 + Width = 242 Align = alClient Constraints.MaxHeight = 600 Constraints.MinHeight = 70 ItemHeight = 13 - TabOrder = 0 OnClick = lbTextureListClick + Style = lbOwnerDrawFixed + TabOrder = 0 end object PanelTextures: TPanel - Left = 568 + Left = 448 + Height = 80 Top = 0 Width = 212 - Height = 78 Align = alRight BevelOuter = bvNone + ClientHeight = 80 + ClientWidth = 212 TabOrder = 1 object LabelTxH: TLabel Left = 33 + Height = 13 Top = 22 Width = 91 - Height = 13 Caption = 'Высота текстуры:' + ParentColor = False end object LabelTxW: TLabel Left = 33 + Height = 13 Top = 0 Width = 92 - Height = 13 Caption = 'Ширина текстуры:' + ParentColor = False end object lTextureHeight: TLabel Left = 139 + Height = 13 Top = 22 Width = 33 - Height = 13 AutoSize = False + ParentColor = False end object lTextureWidth: TLabel Left = 139 + Height = 13 Top = 0 Width = 33 - Height = 13 AutoSize = False + ParentColor = False end object cbPreview: TCheckBox Left = 35 + Height = 19 Top = 54 - Width = 169 - Height = 17 + Width = 165 Caption = 'Предварительный просмотр' TabOrder = 0 end object bbAddTexture: TBitBtn Left = 3 - Top = 0 - Width = 25 Height = 25 Hint = 'Добавить текстуру в список' + Top = 0 + Width = 25 Caption = '+' - TabOrder = 1 OnClick = bbAddTextureClick + TabOrder = 1 end object bbRemoveTexture: TBitBtn Left = 3 - Top = 24 - Width = 25 Height = 25 Hint = 'Удалить текстуру из списка' + Top = 24 + Width = 25 Caption = '-' - TabOrder = 2 OnClick = bbRemoveTextureClick + TabOrder = 2 end object bClearTexture: TButton Left = 3 - Top = 48 - Width = 25 Height = 25 Hint = 'Убрать выбор текстуры' - TabOrder = 3 + Top = 48 + Width = 25 OnClick = bClearTextureClick + TabOrder = 3 end end object PanelPanelType: TPanel Left = 0 + Height = 80 Top = 0 Width = 206 - Height = 78 Align = alLeft BevelOuter = bvNone + ClientHeight = 80 + ClientWidth = 206 TabOrder = 2 object lbPanelType: TListBox Left = 0 + Height = 80 + Hint = 'Тип панели' Top = 0 Width = 201 - Height = 78 - Hint = 'Тип панели' Align = alLeft - ItemHeight = 13 Items.Strings = ( 'Стена' 'Фон' @@ -332,22 +360,25 @@ object MainForm: TMainForm 'Кислота 2' 'Лифт вверх' 'Лифт вниз' - 'Блокиратор монстров') + 'Блокиратор монстров' + ) + ItemHeight = 13 TabOrder = 0 end end end object tsItems: TTabSheet Caption = 'Предметы' + ClientHeight = 0 + ClientWidth = 0 ImageIndex = 4 object lbItemList: TListBox Left = 0 - Top = 0 - Width = 201 Height = 78 Hint = 'Список предметов' + Top = 0 + Width = 201 Align = alLeft - ItemHeight = 13 Items.Strings = ( 'Аптечка' 'Большая аптечка' @@ -380,37 +411,40 @@ object MainForm: TMainForm 'Зеленый ключ' 'Синий ключ' 'Бутылек здоровья' - 'Часть брони') + 'Часть брони' + ) + ItemHeight = 13 TabOrder = 0 end object cbOnlyDM: TCheckBox Left = 208 + Height = 17 Top = 0 Width = 97 - Height = 17 Caption = 'Только в DM' TabOrder = 1 end object cbFall: TCheckBox Left = 208 + Height = 17 Top = 16 Width = 97 - Height = 17 Caption = 'Падает' TabOrder = 2 end end object tsMonsters: TTabSheet Caption = 'Монстры' + ClientHeight = 0 + ClientWidth = 0 ImageIndex = 15 object lbMonsterList: TListBox Left = 0 - Top = 0 - Width = 201 Height = 78 Hint = 'Список монстров' + Top = 0 + Width = 201 Align = alLeft - ItemHeight = 13 Items.Strings = ( 'Демон' 'Бес' @@ -431,14 +465,16 @@ object MainForm: TMainForm 'Рыба' 'Бочка' 'Робот' - 'Приколист') + 'Приколист' + ) + ItemHeight = 13 TabOrder = 0 end object rbMonsterLeft: TRadioButton Left = 208 + Height = 17 Top = 0 Width = 113 - Height = 17 Caption = 'Влево' Checked = True TabOrder = 1 @@ -446,24 +482,25 @@ object MainForm: TMainForm end object rbMonsterRight: TRadioButton Left = 208 + Height = 17 Top = 16 Width = 113 - Height = 17 Caption = 'Вправо' TabOrder = 2 end end object tsAreas: TTabSheet Caption = 'Области' + ClientHeight = 0 + ClientWidth = 0 ImageIndex = 3 object lbAreasList: TListBox Left = 0 - Top = 0 - Width = 201 Height = 78 Hint = 'Список областей' + Top = 0 + Width = 201 Align = alLeft - ItemHeight = 13 Items.Strings = ( '1ый игрок' '2ой игрок' @@ -472,14 +509,16 @@ object MainForm: TMainForm 'Синий флаг' 'DOM флаг' 'Красная команда' - 'Синяя команда') + 'Синяя команда' + ) + ItemHeight = 13 TabOrder = 0 end object rbAreaLeft: TRadioButton Left = 208 + Height = 17 Top = 0 Width = 113 - Height = 17 Caption = 'Влево' Checked = True TabOrder = 1 @@ -487,24 +526,25 @@ object MainForm: TMainForm end object rbAreaRight: TRadioButton Left = 208 + Height = 17 Top = 16 Width = 113 - Height = 17 Caption = 'Вправо' TabOrder = 2 end end object tsTriggers: TTabSheet Caption = 'Триггеры' + ClientHeight = 0 + ClientWidth = 0 ImageIndex = 6 object lbTriggersList: TListBox Left = 0 - Top = 0 - Width = 201 Height = 78 Hint = 'Список триггеров' + Top = 0 + Width = 201 Align = alLeft - ItemHeight = 13 Items.Strings = ( 'Выход' 'Телепортация' @@ -526,125 +566,137 @@ object MainForm: TMainForm 'Звук' 'Создать монстра' 'Создать предмет' - 'Музыка') + 'Музыка' + ) + ItemHeight = 13 TabOrder = 0 end object clbActivationType: TCheckListBox Left = 201 - Top = 0 - Width = 128 Height = 78 Hint = 'Тип активации триггера' + Top = 0 + Width = 128 Align = alLeft - ItemHeight = 13 Items.Strings = ( 'Игрок близко' 'Монстр близко' 'Игрок нажал' 'Монстр нажал' 'Выстрел' - 'Монстров нет') + 'Монстров нет' + ) + ItemHeight = 17 TabOrder = 1 + Data = { + 06000000000000000000 + } end object clbKeys: TCheckListBox Left = 329 - Top = 0 - Width = 128 Height = 78 Hint = 'Ключи для активации' + Top = 0 + Width = 128 Align = alLeft - ItemHeight = 13 Items.Strings = ( 'Красный ключ' 'Зеленый ключ' 'Синий ключ' 'Красная команда' - 'Синяя команда') + 'Синяя команда' + ) + ItemHeight = 17 TabOrder = 2 + Data = { + 050000000000000000 + } end end end end object MainToolBar: TToolBar Left = 0 - Top = 0 - Width = 792 Height = 34 + Top = 0 + Width = 672 ButtonHeight = 31 ButtonWidth = 31 Caption = 'MainToolBar' - Flat = True Images = ilToolbar TabOrder = 4 object tbNewMap: TToolButton - Left = 0 - Top = 0 + Left = 1 Hint = 'Очистить карту' + Top = 2 Caption = 'tbNewMap' ImageIndex = 0 OnClick = aNewMapExecute end object tbOpenMap: TToolButton - Left = 31 - Top = 0 + Left = 32 Hint = 'Открыть карту' + Top = 2 Caption = 'tbOpenMap' ImageIndex = 1 OnClick = aOpenMapExecute end object tbSaveMap: TToolButton - Left = 62 - Top = 0 + Left = 63 Hint = 'Сохранить карту' + Top = 2 Caption = 'tbSaveMap' ImageIndex = 2 OnClick = aSaveMapExecute end object tbOpenWadMap: TToolButton - Left = 93 - Top = 0 + Left = 94 Hint = 'Открыть другую карты из этого же WAD''а' + Top = 2 Caption = 'tbOpenWadMap' ImageIndex = 8 OnClick = miOpenWadMapClick end object tbLine1: TToolButton - Left = 124 - Top = 0 + Left = 125 + Height = 31 + Top = 2 Width = 8 Caption = 'tbLine1' ImageIndex = 3 Style = tbsSeparator end object tbShowMap: TToolButton - Left = 132 - Top = 0 + Left = 133 Hint = 'Показать мини-карту' + Top = 2 Caption = 'tbShowMap' ImageIndex = 3 OnClick = miMiniMapClick end object tbLine2: TToolButton - Left = 163 - Top = 0 + Left = 164 + Height = 31 + Top = 2 Width = 8 Caption = 'tbLine2' ImageIndex = 6 Style = tbsSeparator end object tbShow: TToolButton - Left = 171 - Top = 0 + Left = 172 Hint = 'Отрисовка панелей/объектов' + Top = 2 Caption = 'tbShow' DropdownMenu = pmShow ImageIndex = 4 - Style = tbsDropDown OnClick = tbShowClick + Style = tbsDropDown end object tbLine3: TToolButton Left = 215 - Top = 0 + Height = 31 + Top = 2 Width = 8 Caption = 'tbLine3' ImageIndex = 7 @@ -652,23 +704,24 @@ object MainForm: TMainForm end object tbGridOn: TToolButton Left = 223 - Top = 0 Hint = 'Включить/Отключить отображение сетки' + Top = 2 Caption = 'tbGridOn' ImageIndex = 6 OnClick = tbGridOnClick end object tbGrid: TToolButton Left = 254 - Top = 0 Hint = 'Изменить шаг сетки' + Top = 2 Caption = 'tbGrid' ImageIndex = 5 OnClick = miSwitchGridClick end object tbLine4: TToolButton Left = 285 - Top = 0 + Height = 31 + Top = 2 Width = 8 Caption = 'tbLine4' ImageIndex = 7 @@ -676,97 +729,598 @@ object MainForm: TMainForm end object tbTestMap: TToolButton Left = 293 - Top = 0 Hint = 'Тест карты в игре' + Top = 2 Caption = 'tbTestMap' DropdownMenu = pmMapTest ImageIndex = 7 - Style = tbsDropDown OnClick = miTestMapClick + Style = tbsDropDown end end object OpenDialog: TOpenDialog - DefaultExt = 'wad' - Filter = - 'Карты Doom 2D: Forever (*.wad)|*.wad|Старые карты Doom 2D: Forev' + - 'er (*.ini)|*.ini|Все файлы (*.*)|*.*' + DefaultExt = '.wad' + Filter = 'Карты Doom 2D: Forever (*.wad)|*.wad|Старые карты Doom 2D: Forever (*.ini)|*.ini|Все файлы (*.*)|*.*' Options = [ofHideReadOnly, ofNoChangeDir, ofPathMustExist, ofFileMustExist, ofEnableSizing, ofDontAddToRecent] - Left = 32 - Top = 64 + left = 32 + top = 64 end object ImageList: TImageList - Left = 32 - Top = 101 + left = 32 + top = 101 Bitmap = { - 494C01011E002200040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 - 0000000000003600000028000000400000009000000001002000000000000090 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 + 4C691E000000100000001000000000000000737373FF737373FF737373FF7373 + 73FF7B7B7BFF7B7B7BFF7B7B7BFF848484FF848484FF848484FF848484FF8484 + 84FF000000000000000000000000000000006B6B6BFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCECECEFFFFFFFFFFB5D6 + CEFF737373FF0000000000000000000000006B6B6BFFFFFFFFFFE7FFF7FFE7FF + F7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7F7FFB5B5B5FFFFFFFFFFD6F7 + EFFFB5D6CEFF6B6B6BFF00000000000000006B6B6BFFFFFFFFFFE7FFF7FFE7FF + F7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7F7FFA5A5A5FFFFFFFFFFFFFF + FFFFFFFFFFFF5A5A5AFF00000000000000006B6B6BFFFFFFFFFFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFF7F7F7FF949494FF8C8C8CFF7373 + 73FF5A5A5AFF5A5A5AFF00000000000000006B6B6BFFFFFFFFFFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFF7F7F7FFD6D6D6FFC6C6C6FFB5B5 + B5FF9C9C9CFF525252FF00000000000000006B6B6BFFFFFFFFFFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFCEEFE7FFC6DE + DEFFDEDEDEFF525252FF0000000000000000636363FFFFFFFFFFD6EFEFFFD6EF + EFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EF + EFFFFFFFFFFF4A4A4AFF00000000000000005A5A5AFFFFFFFFFFD6EFE7FFD6EF + E7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EF + E7FFFFFFFFFF424242FF00000000000000005A5A5AFFFFFFFFFFD6EFE7FFD6EF + E7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EF + E7FFFFFFFFFF424242FF00000000000000004A4A4AFFFFFFFFFFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7 + E7FFFFFFFFFF393939FF00000000000000004A4A4AFFFFFFFFFFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7 + E7FFFFFFFFFF313131FF00000000000000004A4A4AFFFFFFFFFFBDDED6FFBDDE + D6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDE + D6FFFFFFFFFF313131FF0000000000000000424242FFFFFFFFFFC6DEDEFFC6DE + DEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFFFFFFFFFF313131FF0000000000000000424242FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF292929FF00000000000000006B6B6BFF292929FF212121FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF4A4A4AFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000008C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF00000000000000000000000000000000000000000000 + 000000000000000000000000000000000000949494FF9C9C9CFF9C9C9CFF9C9C + 9CFF9C9C9CFF9C9C9CFF949494FF000000000000000000000000000000000000 + 0000000000000000000000000000000000008C8C8CFF949494FF8C948CFF8C94 + 94FF949494FF949494FF8C8C8CFF7B7B7BFF7B7B7BFF737373FF737373FF7373 + 73FF737373FF000000000000000000000000848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF848484FF848C84FF848C + 84FF848C84FF848484FF00000000000000007B7B7BFF848484FF848484FF8484 + 84FF848484FF848484FF848484FF7B7B7BFF848C84FFD6EFE7FFDEF7F7FFDEF7 + F7FFDEF7F7FFE7F7F7FF7B9494FF00000000737373FF847B7BFF7B7B7BFF6B6B + 6BFF737373FF737373FF737373FF6B736BFFADC6BDFFCEE7E7FFC6DED6FFC6DE + D6FFC6DED6FFC6E7DEFF7B9494FF000000006B6B6BFF7B7373FF6B6B6BFF7B84 + 84FFB5CECEFFB5CECEFFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6 + D6FFBDDED6FFCEE7DEFF7B9494FF00000000636363FF6B6B6BFF636363FFA5B5 + B5FFBDD6D6FFBDD6D6FFB5D6CEFFB5D6CEFFB5CECEFFB5CECEFFB5CECEFFB5D6 + CEFFBDD6D6FFC6DEDEFF7B9494FF000000005A5A5AFF5A5A5AFF737B7BFFB5CE + C6FFADC6BDFFADC6BDFFADC6BDFFADC6C6FFADC6BDFFADC6BDFFB5CEC6FFB5CE + CEFFBDDED6FF7B9494FF0000000000000000525252FF5A5A5AFF7B8C8CFFADC6 + C6FFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFADC6 + C6FFBDD6CEFF7B9494FF00000000000000004A4A4AFF5A5A5AFF94B5ADFFA5BD + B5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BD + BDFFADCEC6FF7B9494FF0000000000000000424242FF5A6363FF9CB5ADFF94AD + ADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF9CB5B5FF9CBD + B5FFA5BDBDFF7B9494FF0000000000000000393939FF7B9494FF94ADADFF94AD + A5FF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94ADADFF94B5ADFF94B5 + B5FF7B9494FF000000000000000000000000393939FF7B8C8CFF849C94FF7B94 + 94FF7B9494FF7B9494FF7B9494FF7B9494FF7B9494FF7B9494FF7B9494FF7B94 + 94FF7B9494FF0000000000000000000000004A4A52FF4A4A52FF4A4A52FF4A4A + 52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A + 52FF7B9494FF000000000000000000000000848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF00000000848484FFDEF7F7FFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7 + F7FF9CB5ADFFB5CECEFF737373FF7B7B7BFFD6F7EFFFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFF94ADA5FFADCEC6FF6B6B6BFF7B7B7BFFD6EFE7FFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFF94ADADFFADC6C6FF636363FF7B7B7BFFCEE7DEFFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFF8CA5A5FFADC6C6FF5A5A5AFF6B6B6BFFADCEC6FF9CB5ADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7 + F7FF7B9C94FF9CB5B5FF525252FF636363FFADC6C6FF94ADADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7 + F7FF7B9494FF94ADADFF4A4A4AFF5A5A5AFFADC6BDFF94ADA5FFE7E7E7FFF7F7 + F7FFF7F7F7FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFF7F7F7FFEFEFEFFFDEDE + DEFF73948CFF94ADADFF4A4A4AFF5A5A5AFFA5C6BDFF8CA59CFF8CA5A5FF849C + 9CFF7B948CFF738C84FF738C84FF738C84FF738C8CFF738C8CFF738C8CFF738C + 8CFF6B8484FF8CADA5FF424242FF525252FFA5BDB5FFA5BDB5FFA5BDB5FF94B5 + ADFF8CADA5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF424242FF525252FF9CB5B5FF9CB5ADFF9C9C9CFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF7B7B + 7BFF849C9CFF849C9CFF393939FF4A4A4AFF94ADA5FF8CA5A5FF7B7B7BFFFFFF + FFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF6B6B + 6BFF849C9CFF849C9CFF393939FF4A4A4AFF94ADA5FF8CA5A5FF7B7B7BFFFFFF + FFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF6B6B + 6BFF849C9CFF849C9CFF393939FF424242FF7B9494FF7B9494FF6B6B6BFFFFFF + FFFFE7E7E7FFA5BDB5FFFFFFFFFFFFFFFFFFEFEFEFFFE7E7E7FFE7E7E7FF6B6B + 6BFF7B9494FF7B9494FF292929FF393939FF7B9494FF7B9494FF636363FFE7E7 + E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FFD6D6D6FFE7E7E7FF5A5A + 5AFF7B9494FF7B9494FF292929FF00000000292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000849CB5FF849CB5FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000849CB5FF315284FF000052FF0000 + 52FF000052FF000052FF000052FF000000000000000000000000000000000000 + 000000000000000000000000000000000000849CB5FF315284FF0800A5FF0800 + A5FF0800A5FF08008CFF0800C6FF000052FF000052FF000052FF000052FF0000 + 52FF000052FF000000000000000000000000849CB5FF315284FF0800A5FF0800 + A5FF08008CFF0800C6FF0800C6FF08008CFF0800A5FF0800A5FF0800A5FF0000 + 52FF00000000000000000000000000000000849CB5FF315284FF0800A5FF0800 + A5FF0800A5FF08008CFF0800C6FF08008CFF08008CFF0800A5FF000052FF0000 + 000000000000000000000000000000000000849CB5FF315284FF0800A5FF0800 + A5FF08008CFF0800C6FF0800C6FF08008CFF0800A5FF000052FF000000000000 + 000000000000000000000000000000000000849CB5FF315284FF0800A5FF0800 + A5FF0800A5FF08008CFF0800C6FF08008CFF08008CFF000052FF000000000000 + 000000000000000000000000000000000000849CB5FF315284FF08008CFF0800 + 8CFF08008CFF0800C6FF0800C6FF08008CFF0800A5FF0800A5FF000052FF0000 + 000000000000000000000000000000000000849CB5FF315284FF000052FF0000 + 52FF000052FF000052FF000052FF08008CFF08008CFF08008CFF08008CFF0000 + 52FF00000000000000000000000000000000849CB5FF315284FF000000000000 + 0000000000000000000000000000000052FF000052FF000052FF000052FF0000 + 52FF000052FF000000000000000000000000849CB5FF315284FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000849CB5FF315284FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000849CB5FF315284FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000849CB5FF315284FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000315284FF315284FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00004A3939FF4A3939FF4A3939FF4A3939FF4A3939FF4A3939FF000000000000 + 0000000000000000000000000000000000000000000000000000080000FF2118 + 18FF000000FF180000FF180000FF210000FF210000FF100000FF210808FF0800 + 00FF0000000000000000000000000000000000000000080000FF080000FF1000 + 00FF520000FF9C0000FF9C0000FF9C0000FF9C0000FF730000FF4A0000FF1800 + 00FF080000FF000000000000000000000000080000FF080000FF180000FFBD18 + 18FFF74A4AFFF73939FFF74242FFF74242FFFF3939FFF70808FFC60000FF5200 + 00FF210000FF080000FF0000000000000000000000FF840000FF840000FFFF4A + 4AFFFF9C9CFFFF5252FFFF4A4AFFFF6363FFFF3131FFE70000FFDE0000FFAD00 + 00FF940000FF000000FF000000004A3939FF100000FF840000FFA50000FFDE10 + 10FFFF4A4AFFC61818FFCE0000FFDE0000FF940000FF8C0000FFC60808FFBD00 + 00FF940000FF420000FF421010FF423131FF840000FF840000FFCE0000FFCE10 + 10FFF73939FFA50808FF840000FF8C0000FF630000FFD64242FFF73131FFAD00 + 00FF940000FF730000FF290808FF4A3939FF9C0000FFA50000FFBD0000FFA500 + 00FFCE1010FFE70000FFE70808FFE71010FFC60000FFDE0808FFC60808FF9400 + 00FFA50000FF9C0000FF421010FF523131FF940000FF9C0000FFE70000FFF721 + 21FFF71818FFEF0000FFB50000FF9C0808FFE70000FFF71010FFF72929FFDE00 + 00FFB50000FF940000FF421010FF4A3131FF840000FF9C0000FFCE0000FFE700 + 00FFEF0000FFDE0000FFAD1010FFA51818FFCE0000FFD60000FFEF0000FFDE00 + 00FFB50000FF840000FF310808FF4A3131FF290000FFCE0000FFCE0000FFDE00 + 00FFCE0000FFCE0000FFB51010FFB51010FFCE0000FFBD0000FFDE0000FFBD00 + 00FFAD0000FF630000FF310808FF00000000000000FF000000FFAD0000FFF710 + 10FFC61010FF5A0000FF080000FF080000FF420000FFB50000FFF70808FFC600 + 00FF6B0000FF421818FF0000000000000000080000FF210000FF630000FFCE00 + 00FFAD0000FF630000FF420000FF420000FF5A0000FF9C0000FFBD0000FF9400 + 00FF290000FF080000FF000000000000000000000000080000FF100000FF6B00 + 00FF840000FFAD0000FFEF1010FFEF1818FFBD0000FF8C0000FF730000FF3100 + 00FF080000FF0000000000000000000000000000000000000000080000FF3921 + 21FF210000FF520000FF6B0808FF6B0808FF5A0000FF290000FF291010FF0800 + 00FF000000000000000000000000000000000000000000000000000000000000 + 00004A3939FF4A3939FF4A3939FF4A3939FF4A3939FF4A3939FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000006B8484FF6B8484FF6B8484FF6B8484FF6B8484FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000006B8484FF42635AFF42635AFF42635AFF42635AFF42635AFF6B84 + 84FF000000000000000000000000000000000000000000000000000000000000 + 00006B8484FF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF6B8484FF0000000000000000000000000000000000000000000000000000 + 000042635AFF42635AFF294A4AFF294A4AFF294A4AFF294A4AFF294A4AFF4263 + 5AFF42635AFF000000000000000000000000000000006B8484FF000000006B84 + 84FF42635AFF294A4AFF294A4AFF00000000000000000000000000000000294A + 4AFF42635AFF6B8484FF0000000000000000000000006B8484FF6B8484FF4263 + 5AFF294A4AFF294A4AFF00000000000000000000000000000000000000000000 + 000042635AFF294A4AFF0000000000000000000000006B8484FF42635AFF4263 + 5AFF294A4AFF0000000000000000000000000000000000000000000000000000 + 0000294A4AFF000000000000000000000000000000006B8484FF42635AFF294A + 4AFF294A4AFF0000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000294A4AFF294A4AFF294A + 4AFF294A4AFF294A4AFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000949494FF848484FF7B7B7BFF9C9C + 9CFF9C9C9CFF9C9C9CFF7B7B7BFF8C8C8CFF9C9C9CFFA5A5A5FF8C8C8CFF7B7B + 7BFF7B7B7BFF5A5A5AFF00000000000000007B7B7BFF6B6B6BFF636363FF7373 + 73FF737373FF737373FF636363FF6B6B6BFF737373FF848484FF6B6B6BFF6363 + 63FF636363FF424242FF0000000000000000848484FF6B6B6BFF6B6B6BFF7B7B + 7BFF7B7B7BFF7B7B7BFF424242FF424242FF7B7B7BFF8C8C8CFF737373FF6363 + 63FF6B6B6BFF4A4A4AFF0000000000000000949494FF737373FF6B6B6BFF8484 + 84FF848484FF848484FF292929FF212121FF7B7B7BFF8C8C8CFF7B7B7BFF6B6B + 6BFF6B6B6BFF4A4A4AFF0000000000000000949494FF737373FF6B6B6BFF8C8C + 8CFF8C8C8CFF8C8C8CFF212121FF101010FF848484FF949494FF7B7B7BFF6B6B + 6BFF6B6B6BFF4A4A4AFF00000000000000009C9C9CFF7B7B7BFF6B6B6BFF5252 + 52FF4A4A4AFF636363FF212121FF101010FF636363FF525252FF525252FF6B6B + 6BFF737373FF525252FF0000000000000000A5A5A5FF848484FF4A6B63FF3939 + 39FF636363FF4A4A4AFF393939FF313131FF424242FF5A5A5AFF212121FF4A6B + 63FF7B7B7BFF5A5A5AFF00000000000000009C9C9CFF7B7B7BFF8C8C8CFF4242 + 42FF8C8C8CFF8C8C8CFF737373FF737373FF8C8C8CFF949494FF313131FF7373 + 73FF737373FF5A5A5AFF00000000000000009C9C9CFF7B7B7BFF636363FF4242 + 42FF6B6B6BFF8C8C8CFF737373FF7B7B7BFF8C8C8CFF6B6B6BFF393939FF5A5A + 5AFF737373FF525252FF0000000000000000949494FF737373FF7B7B7BFF8484 + 84FF848484FF848484FF6B6B6BFF737373FF848484FF949494FF7B7B7BFF7373 + 73FF6B6B6BFF4A4A4AFF00000000000000008C8C8CFF6B6B6BFF6B6B6BFF7B7B + 7BFF7B7B7BFF7B7B7BFF6B6B6BFF6B6B6BFF7B7B7BFF848484FF737373FF6363 + 63FF636363FF4A4A4AFF0000000000000000848484FF6B6B6BFF636363FF7373 + 73FF737373FF737373FF636363FF6B6B6BFF737373FF848484FF6B6B6BFF6363 + 63FF636363FF424242FF00000000000000007B7B7BFF636363FF636363FF6B6B + 6BFF6B6B6BFF6B6B6BFF5A5A5AFF636363FF6B6B6BFF7B7B7BFF6B6B6BFF5A5A + 5AFF5A5A5AFF424242FF0000000000000000424242FF393939FF393939FF4242 + 42FF424242FF424242FF313131FF393939FF424242FF424242FF393939FF3939 + 39FF292929FF393939FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000000000000000000A5A5 + A5FFA5A5A5FF000000000000000000000000A5A5A5FFA5A5A5FF000000000000 + 0000000000000000000000000000000000000000000000000000000000008484 + 84FFA5A5A5FF000000000000000000000000A5A5A5FF848484FF000000000000 + 0000000000000000000000000000000000000000000000000000000000008484 + 84FFA5A5A5FF000000000000000000000000A5A5A5FF848484FF000000000000 + 0000000000000000000000000000000000000000000000000000000000006B6B + 6BFF848484FFA5A5A5FF00000000A5A5A5FF848484FF6B6B6BFF000000000000 + 0000000000000000000000000000000000000000000000000000000000004A4A + 4AFF6B6B6BFFA5A5A5FF00000000A5A5A5FF6B6B6BFF4A4A4AFF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00006B6B6BFF848484FF4A4A4AFF848484FF6B6B6BFF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00004A4A4AFF6B6B6BFF4A4A4AFF6B6B6BFF4A4A4AFF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000004A4A4AFF4A4A4AFF4A4A4AFF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000004A6B + 5AFF6B8C7BFF52846BFF6B9C8CFF6B9C8CFF527363FF526B63FF000000000000 + 00000000000000000000000000000000000000000000000000004A6B5AFF5273 + 63FF00000000315A4AFF4A7B6BFF295A4AFF000000004A7363FF4A6B5AFF0000 + 00000000000000000000000000000000000000000000000000004A6B5AFF0000 + 00000000000000000000426B5AFF000000000000000000000000527B63FF0000 + 00000000000000000000000000000000000000000000294231FF4A7B63FF0000 + 000000000000637B73FF396352FF5A7B6BFF0000000000000000527B63FF395A + 42FF0000000000000000000000000000000000000000315242FF52846BFF528C + 6BFF5A8C73FF4A6B5AFF00000000426B5AFF5A8473FF5A9473FF639473FF214A + 31FF000000000000000000000000000000000000000000000000295239FF315A + 4AFF295239FF000000000000000000000000295239FF31634AFF214A31FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000737373FF737373FF737373FF737373FF7B7B + 7BFF848484FF848484FF848484FF000000000000000000000000000000000000 + 00000000000000000000000000006B6B6BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFCECECEFFB5D6CEFF737373FF0000000000000000000000000000 + 00000000000000000000000000006B6B6BFFFFFFFFFFE7FFF7FFE7FFF7FFE7FF + F7FFF7F7F7FF737373FF737373FF737373FF737373FF7B7B7BFF848484FF8484 + 84FF848484FF00000000000000006B6B6BFFFFFFFFFFDEF7F7FFDEF7F7FFDEF7 + F7FFF7F7F7FF6B6B6BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCECE + CEFFDEB5BDFF737373FF000000006B6B6BFFFFFFFFFFDEF7F7FFDEF7F7FFDEF7 + F7FFF7F7F7FF6B6B6BFFFFFFFFFFFFE7EFFFFFE7EFFFFFE7EFFFF7F7F7FFA5A5 + A5FFFFFFFFFFFFFFFFFF5A5A5AFF6B6B6BFFFFFFFFFFDEF7F7FFDEF7F7FFDEF7 + F7FFDEF7F7FF6B6B6BFFFFFFFFFFFFDEDEFFFFDEDEFFFFDEDEFFF7F7F7FF9494 + 94FF737373FF5A5A5AFF5A5A5AFF5A5A5AFFFFFFFFFFD6EFE7FFD6EFE7FFD6EF + E7FFD6EFE7FF6B6B6BFFFFFFFFFFFFDEDEFFFFDEDEFFFFDEDEFFF7F7F7FFD6D6 + D6FFB5B5B5FF9C9C9CFF525252FF5A5A5AFFFFFFFFFFD6EFE7FFD6EFE7FFD6EF + E7FFD6EFE7FF6B6B6BFFFFFFFFFFFFDEDEFFFFDEDEFFFFDEDEFFFFDEDEFFFFDE + DEFFE7C6C6FFDEDEDEFF525252FF4A4A4AFFFFFFFFFFCEE7E7FFCEE7E7FFCEE7 + E7FFCEE7E7FF5A5A5AFFFFFFFFFFF7D6DEFFF7D6DEFFF7D6DEFFF7D6DEFFF7D6 + DEFFF7D6DEFFFFFFFFFF424242FF424242FFFFFFFFFFC6DEDEFFC6DEDEFFC6DE + DEFFC6DEDEFF5A5A5AFFFFFFFFFFF7D6DEFFF7D6DEFFF7D6DEFFF7D6DEFFF7D6 + DEFFF7D6DEFFFFFFFFFF424242FF424242FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF4A4A4AFFFFFFFFFFEFCECEFFEFCECEFFEFCECEFFEFCECEFFEFCE + CEFFEFCECEFFFFFFFFFF313131FF6B6B6BFF292929FF212121FF181818FF1818 + 18FF181818FF424242FFFFFFFFFFE7C6C6FFE7C6C6FFE7C6C6FFE7C6C6FFE7C6 + C6FFE7C6C6FFFFFFFFFF313131FF000000000000000000000000000000000000 + 000000000000424242FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF292929FF000000000000000000000000000000000000 + 0000000000006B6B6BFF292929FF212121FF181818FF181818FF181818FF1818 + 18FF181818FF181818FF4A4A4AFF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000737373FF737373FF737373FF848484FF8484 + 84FF848484FF0000000000000000000000000000000000000000000000000000 + 00000000000000000000000000006B6B6BFFFFFFFFFFFFFFFFFFFFFFFFFFCECE + CEFFDEB5BDFF737373FF00000000848484FF848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF6B6B6BFFFFFFFFFFFFE7EFFFF7F7F7FFA5A5 + A5FFFFFFFFFFFFFFFFFF5A5A5AFF848484FF525A5AFF4A5A52FF525A5AFF525A + 5AFF525A5AFF525A5AFF525A5AFF6B6B6BFFFFFFFFFFFFFFFFFFFFFFFFFF9494 + 94FF737373FF5A5A5AFF5A5A5AFF7B7B7BFF394242FF394242FF394242FF3942 + 42FF394242FF394242FF394242FF6B6B6BFFFFFFFFFF6B8484FFFFFFFFFFFFFF + FFFFB5B5B5FF9C9C9CFF525252FF5A5A5AFF313939FF313939FF313939FF3139 + 39FF313939FF313939FF313939FFFFFFFFFF6B8484FF6B8484FF42635AFFFFFF + FFFFFFFFFFFFDEDEDEFF525252FF7B7B7BFF212929FF212929FFF7F7F7FFF7F7 + F7FFF7F7F7FF212929FFF7F7F7FF6B8484FF6B8484FF5A7373FF42635AFF4263 + 5AFFFFFFFFFFFFFFFFFF313131FF5A5A5AFF080808FF212929FFDEE7E7FF6B84 + 84FFDEE7E7FFF7F7F7FF6B8484FF6B8484FF5A7373FF42635AFF42635AFFFFFF + FFFFFFFFFFFFFFFFFFFF292929FF5A5A5AFF080808FF080808FFDEDEDEFF6B84 + 84FF6B8484FF6B8484FF6B8484FF5A7373FF42635AFF42635AFFEFEFEFFF1818 + 18FF181818FF181818FF4A4A4AFF525252FFFFFFFFFFFFFFFFFFFFFFFFFF6B84 + 84FF5A7373FF6B8484FF5A7373FF42635AFF42635AFFDEDEDEFF080808FF4242 + 42FF000000000000000000000000525252FFFFFFFFFFEF0000FFFFDEDEFF6B84 + 84FF5A7373FF5A7373FF42635AFF42635AFFFFFFFFFF000000FF000000FF3939 + 39FF0000000000000000000000004A4A4AFFFFFFFFFFD60000FFFFDEDEFF6B84 + 84FF5A7373FF5A7373FF5A7373FF42635AFFFFFFFFFF000000FF000000FF3939 + 39FF0000000000000000000000004A4A4AFFFFFFFFFFBD0000FFFFDEDEFF4A63 + 52FF42635AFF42635AFF42635AFF42635AFF42635AFFDEDEDEFF000000FF3939 + 39FF000000000000000000000000424242FFFFFFFFFF8C0000FFFFDEDEFFFFDE + DEFFFFDEDEFFFFDEDEFFFFDEDEFFFFDEDEFFFFFFFFFFDEDEDEFF000000FF2929 + 29FF000000000000000000000000393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF000000FF2929 + 29FF000000000000000000000000292929FF292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF292929FF292929FF2121 + 21FF00000000000000000000000000000000000000007B7B7BFF848484FF8484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF737373FF00000000000000000000000000000000848484FFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FF737373FF000000000000000000000000000000007B7B7BFFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FF6B6B6BFF000000000000000000000000000000007B7B7BFFD6EFEFFFD6EF + EFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EF + EFFF636363FF000000000000000000000000000000007B7B7BFFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7 + E7FF5A5A5AFF000000000000000000000000000000006B6B6BFFC6DEDEFFC6DE + DEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFF525252FF00000000000000000000000000000000636363FFBDD6D6FFBDD6 + D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6 + D6FF4A4A4AFF000000000000000000000000000000005A5A5AFFB5CECEFFB5CE + CEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CE + CEFF4A4A4AFF000000000000000000000000000000005A5A5AFFADC6C6FFADC6 + C6FFADC6C6FFADC6C6FFADC6C6FFADC6C6FFADC6C6FFDEF7F7FF7B9C9CFFADC6 + C6FF424242FF00000000000000000000000000000000525252FFA5BDBDFFA5BD + BDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFF7B9C9CFF6B8484FFA5BD + BDFF424242FF00000000000000000000000000000000525252FF9CB5B5FF9CB5 + B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5 + B5FF393939FF000000000000000000000000000000004A4A4AFF94ADADFF94AD + ADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94AD + ADFF393939FF000000000000000000000000000000004A4A4AFF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF393939FF00000000000000000000000000000000424242FF849C9CFF849C + 9CFF849C9CFF849C9CFF849C9CFF849C9CFF849C9CFF849C9CFF849C9CFF849C + 9CFF292929FF00000000000000000000000000000000393939FF7B9C9CFF7B9C + 9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C + 9CFF292929FF00000000000000000000000000000000292929FF292929FF2929 + 29FF292929FF292929FF292929FF292929FF292929FF292929FF292929FF2121 + 21FF292929FF000000000000000000000000737373FF737373FF737373FF7373 + 73FF7B7B7BFF7B7B7BFF7B7B7BFF848484FF848484FF848484FF848484FF8484 + 84FF000000000000000000000000000000006B6B6BFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCECECEFFFFFFFFFFB5D6 + CEFF737373FF0000000000000000000000006B6B6BFFFFFFFFFFE7FFF7FFE7FF + F7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7F7FFB5B5B5FFFFFFFFFFD6F7 + EFFFB5D6CEFF6B6B6BFF00000000000000006B6B6BFFFFFFFFFFE7FFF7FF4A4A + FFFF4A4AFFFFE7FFF7FFE7FFF7FFE7FFF7FFF7F7F7FFA5A5A5FFFFFFFFFFFFFF + FFFFFFFFFFFF5A5A5AFF4A4AFFFF000000006B6B6BFFFFFFFFFF4A4AFFFF4A4A + FFFF4A4AFFFFDEF7F7FFDEF7F7FFDEF7F7FFF7F7F7FF949494FF8C8C8CFF7373 + 73FF5A5A5AFF4A4AFFFF4A4AFFFF000000006B6B6BFFFFFFFFFFB5B5B5FF4A4A + FFFF4A4AFFFF4A4AFFFFDEF7F7FFDEF7F7FFF7F7F7FFD6D6D6FFC6C6C6FFB5B5 + B5FF4A4AFFFF4A4AFFFF4A4AFFFF000000006B6B6BFFFFFFFFFFDEF7F7FFB5B5 + B5FF4A4AFFFF4A4AFFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFCEEFE7FF4A4A + FFFF4A4AFFFF4A4AFFFF0000000000000000636363FFFFFFFFFFD6EFEFFFD6EF + EFFFB5B5B5FF4A4AFFFF4A4AFFFFD6EFEFFFD6EFEFFFD6EFEFFF4A4AFFFF4A4A + FFFF4A4AFFFF4A4A4AFF00000000000000005A5A5AFFFFFFFFFFD6EFE7FFD6EF + E7FFD6EFE7FF4A4AFFFF4A4AFFFF4A4AFFFFD6EFE7FF4A4AFFFF4A4AFFFF4A4A + FFFFB5B5B5FF424242FF00000000000000005A5A5AFFFFFFFFFFD6EFE7FFD6EF + E7FFD6EFE7FFB5B5B5FF4A4AFFFF4A4AFFFF4A4AFFFF4A4AFFFFB5B5B5FFB5B5 + B5FFFFFFFFFF424242FF00000000000000004A4A4AFFFFFFFFFFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FF4A4AFFFF4A4AFFFF4A4AFFFFB5B5B5FFCEE7E7FFCEE7 + E7FFFFFFFFFF393939FF00000000000000004A4A4AFFFFFFFFFFCEE7E7FFCEE7 + E7FFCEE7E7FF4A4AFFFF4A4AFFFFB5B5B5FF4A4AFFFF4A4AFFFFCEE7E7FFCEE7 + E7FFFFFFFFFF313131FF00000000000000004A4A4AFFFFFFFFFFBDDED6FFBDDE + D6FF4A4AFFFFB5B5B5FFB5B5B5FFBDDED6FFB5B5B5FF4A4AFFFF4A4AFFFFBDDE + D6FFFFFFFFFF313131FF0000000000000000424242FFFFFFFFFFC6DEDEFFC6DE + DEFFB5B5B5FFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFB5B5B5FF4A4AFFFF4A4A + FFFFFFFFFFFF313131FF0000000000000000424242FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5B5B5FF4A4A + FFFF4A4AFFFF292929FF00000000000000006B6B6BFF292929FF212121FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF4A4AFFFF4A4AFFFF00000000949494FF949494FF949494FF949494FF9494 + 94FF949494FF949494FF949494FF949494FF949494FF949494FF8C8C8CFF0000 + 0000000000000000000000000000949494FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF7B7B7BFF0000 + 0000000000000000000000000000949494FF8C8C8CFFD6D6D6FF949494FF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFFD6D6D6FF949494FF8C8C8CFF7B7B7BFF0000 + 0000000000000000000000000000949494FF8C8C8CFF949494FF424242FF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF949494FF424242FF8C8C8CFF7B7B7BFF0000 + 0000000000000000000000000000949494FF8C8C8CFF8C8C8CFF8C8C8CFF394A + 7BFF394A7BFF394A7BFF394A7BFF394A7BFF213173FF213173FF394A7BFF394A + 7BFF394A7BFF394A7BFF213173FF949494FF8C8C8CFF8C8C8CFF8C8C8CFF394A + 7BFF213173FF213173FF213173FF213173FF10186BFF394A7BFF213173FF2131 + 73FF213173FF213173FF10186BFF949494FF8C8C8CFF8C8C8CFF8C8C8CFF394A + 7BFF213173FF213173FF213173FF213173FF10186BFF394A7BFF213173FF2131 + 73FF213173FF213173FF10186BFF949494FF8C8C8CFF8C8C8CFF8C8C8CFF2131 + 73FF10186BFF10186BFF10186BFF10186BFF10186BFF10186BFF10186BFF1018 + 6BFF10186BFF10186BFF10186BFF949494FF8C8C8CFFD6D6D6FF949494FF2131 + 73FF394A7BFF394A7BFF394A7BFF394A7BFF394A7BFF394A7BFF394A7BFF394A + 7BFF394A7BFF394A7BFF10186BFF949494FF8C8C8CFF949494FF424242FF394A + 7BFF213173FF213173FF213173FF213173FF213173FF213173FF213173FF2131 + 73FF213173FF213173FF10186BFF949494FF8C8C8CFF8C8C8CFF8C8C8CFF394A + 7BFF213173FF213173FF213173FF213173FF213173FF213173FF213173FF2131 + 73FF213173FF213173FF10186BFF8C8C8CFF7B7B7BFF7B7B7BFF7B7B7BFF2131 + 73FF10186BFF10186BFF10186BFF10186BFF10186BFF10186BFF10186BFF1018 + 6BFF10186BFF10186BFF10186BFF000000000000000000000000000000002131 + 73FF394A7BFF394A7BFF394A7BFF394A7BFF394A7BFF10186BFF394A7BFF394A + 7BFF394A7BFF394A7BFF10186BFF00000000000000000000000000000000394A + 7BFF213173FF213173FF213173FF213173FF213173FF10186BFF394A7BFF2131 + 73FF213173FF213173FF10186BFF00000000000000000000000000000000394A + 7BFF213173FF213173FF213173FF213173FF213173FF10186BFF394A7BFF2131 + 73FF213173FF213173FF10186BFF000000000000000000000000000000002131 + 73FF10186BFF10186BFF10186BFF10186BFF10186BFF10186BFF10186BFF1018 + 6BFF10186BFF10186BFF10186BFF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5A + B5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF3139ADFF00000000000000000000 + 00000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF00000000000000000000 + 00000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF00000000000000000000 + 00000000000000000000000000004A5AB5FF3139ADFF3139ADFF5A736BFF5A73 + 6BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF4263 + 5AFF0000000000000000000000004A5AB5FF3139ADFF3139ADFF5A736BFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF294A + 4AFF0000000000000000000000004A5AB5FF3139ADFF3139ADFF5A736BFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF294A + 4AFF0000000000000000000000004A5AB5FF3139ADFF3139ADFF5A736BFF4263 + 5AFF42635AFF6B8484FF6B8484FF6B8484FF6B8484FF6B8484FF6B8484FF6B84 + 84FF6B8484FF6B8484FF5A7373FF4A5AB5FF3139ADFF3139ADFF5A736BFF4263 + 5AFF42635AFF6B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF4A5AB5FF3139ADFF3139ADFF5A736BFF4263 + 5AFF42635AFF6B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF3139ADFF10219CFF10219CFF5A736BFF4263 + 5AFF42635AFF6B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF0000000000000000000000005A736BFF4263 + 5AFF42635AFF6B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF0000000000000000000000005A736BFF4263 + 5AFF42635AFF6B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF00000000000000000000000042635AFF294A + 4AFF294A4AFF6B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF000000000000000000000000000000000000 + 0000000000006B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF000000000000000000000000000000000000 + 0000000000006B8484FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF42635AFF000000000000000000000000000000000000 + 0000000000005A7373FF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF42635AFF848484FF848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF848484FF848484FF525A5AFF4A5A52FF525A5AFF525A + 5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A + 5AFF4A5A52FF4A5A52FF737373FF7B7B7BFF394242FF394242FF394242FF3942 + 42FF394242FF394242FF394242FF394242FF394242FF394242FF394242FF3942 + 42FF394242FF394242FF6B6B6BFF7B7B7BFF313939FF313939FF313939FF3139 + 39FF313939FF313939FF313939FF313939FF313939FF313939FF313939FF3139 + 39FFC6C6C6FFC6C6C6FF636363FF7B7B7BFF212929FF212929FF212929FF2129 + 29FF212929FF212929FF212929FFFFFFFFFF212929FF212929FF212929FF2129 + 29FF212929FF212929FF5A5A5AFF6B6B6BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF182118FF182118FF182118FF1821 + 18FF182118FF182118FF525252FF636363FF081810FF081810FF081810FF0818 + 10FF081810FF081810FF081810FF081810FF081810FF081810FF081810FF0818 + 10FFC6C6C6FFC6C6C6FF4A4A4AFF5A5A5AFF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF4A4A4AFF5A5A5AFF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF424242FF525252FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFF0000FFFFFFFFFF080808FF0808 + 08FFC6C6C6FFC6C6C6FF424242FF525252FFFFFFFFFFEF0000FFEF0000FFEF00 + 00FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFFFFFFFFF000000FF0000 + 00FF000000FF000000FF393939FF4A4A4AFFFFFFFFFFD60000FFD60000FFD600 + 00FFD60000FFD60000FFD60000FFD60000FFD60000FFFFFFFFFF000000FF0000 + 00FF000000FF000000FF393939FF4A4A4AFFFFFFFFFFBD0000FFBD0000FFBD00 + 00FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFFFFFFFFF000000FF0000 + 00FFC6C6C6FFC6C6C6FF393939FF424242FFFFFFFFFF8C0000FF8C0000FF8C00 + 00FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FFFFFFFFFF000000FF0000 + 00FF000000FF000000FF292929FF393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF0000 + 00FF000000FF000000FF292929FF292929FF292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF212121FF000000000000000000000000000000000000 + 00000000000031319CFF5A5ABDFF5A5ABDFF31319CFF00000000000000000000 + 0000000000000000000000000000000000004A4A4AFF5A5ABDFF6B6BCEFF6B6B + CEFF5252BDFF6B6BCEFF8C8CE7FF8C8CE7FF8C8CE7FF6B6BCEFF31319CFF7B7B + DEFF5A5ABDFF4A4A4AFF00000000212121FF6B6B6BFF5A5A5AFF8C8CE7FF9494 + EFFF6B6BCEFF8C8CE7FFA5A5F7FFB5B5FFFFA5A5F7FF8C8CE7FF8C8CE7FF2929 + 8CFF5A5A5AFF6B6B6BFF212121FF212121FF5A5A5AFF212121FF5252BDFF6B6B + CEFF31319CFF6B6BCEFF8C8CE7FF8C8CE7FF8C8CE7FF6B6BCEFF6B6BCEFF0000 + 52FF212121FF5A5A5AFF212121FF212121FF4A4A4AFF212121FF181884FF6B6B + CEFF5252BDFF7373D6FF5A5ABDFF4A4AB5FF5A5ABDFF6B6BCEFF7373D6FF1818 + 7BFF212121FF4A4A4AFF212121FF00000000212121FF00005AFF101073FF8484 + DEFF7B7BDEFF6B6BCEFF8484DEFF6B6BCEFF8484DEFF7B7BDEFF8C8CE7FF5252 + BDFF212121FF212121FF00000000000000000000000031319CFF18187BFF3939 + A5FFA5A5F7FFA5A5F7FF8C8CE7FF3939A5FF8C8CE7FFA5A5F7FF8C8CE7FF0000 + 5AFF31319CFF00000000000000000000000031319CFF6B6BCEFF31319CFF1818 + 7BFF00005AFF00005AFF00005AFF00004AFF18187BFF00005AFF000042FF6363 + C6FF6B6BCEFF7B7BDEFF000000000000000021218CFF6B6BCEFF7B7BDEFF1010 + 73FF5A5ABDFF31319CFF6B6BCEFF5252BDFF6B6BCEFF31319CFF29298CFF3939 + A5FF8C8CE7FF292994FF0000000000000000101073FF080863FF080863FF0000 + 42FF6B6BCEFF4A4AB5FF9494EFFF7B7BDEFF9494EFFF4A4AB5FF6B6BCEFF0000 + 00FF00005AFF000052FF0000000000000000000000000000000031319CFF0000 + 42FF7B7BDEFF6363C6FF31319CFF5A5ABDFF31319CFF6363C6FF7B7BDEFF0000 + 00FF31319CFF0000000000000000000000000000000000000000000000003131 + 9CFF29298CFF31319CFF000052FF000052FF000042FF4242ADFF31319CFF3131 + 9CFF000000000000000000000000000000000000000000000000000000000000 + 42FF9494EFFF000042FF31319CFF181884FF21218CFF00005AFF8484DEFF0000 + 42FF000000000000000000000000000000000000000000000000000000000000 + 42FF6B6B6BFF5A5ABDFF4A4AB5FF3939A5FF3939A5FF4A4AB5FF424242FF0000 + 42FF000000000000000000000000000000000000000000000000000000000000 + 42FF292994FF21218CFF393939FF393939FF292929FF292929FF4A4AB5FF0000 + 42FF000000000000000000000000000000000000000000000000000000000000 + 00000000000000005AFF00005AFF000042FF00004AFF292994FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00007BB5B5FF7BB5B5FF7BB5B5FF7BB5B5FF7BB5B5FF7BB5B5FF7BB5B5FF7BB5 + B5FF5A8C8CFF0000000000000000000000000000000000000000000000000000 + 00007BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF216B5AFF000000000000000000000000000000006BA59CFF6BA59CFF6BA5 + 9CFF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF216B5AFF000000000000000000000000000000006BA59CFF427B73FF427B + 73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF216B5AFF000000000000000000000000000000006BA59CFF427B73FF427B + 73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF000000FF000000FF5A8C8CFF5A8C + 8CFF216B5AFF00000000000000005A8C84FF5A8C84FF6BA59CFF427B73FF427B + 73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF000000FFF7F7F7FF000000FF5A8C + 8CFF216B5AFF00000000000000005A8C84FF316B63FF6BA59CFF427B73FF427B + 73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF000000FFF7F7EFFFFFFFFFFF0000 + 00FF216B5AFF00000000000000005A8C84FF316B63FF6BA59CFF427B73FF427B + 73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF000000FFE7E7E7FFF7F7F7FFFFFF + FFFF000000FF00000000000000005A8C84FF316B63FF6BA59CFF427B73FF427B + 73FF5A8C8CFF216B5AFF216B5AFF216B5AFF000000FFDEDEDEFFEFEFEFFFF7F7 + F7FFFFFFFFFF000000FF000000005A8C84FF316B63FF6BA59CFF427B73FF427B + 73FF427B73FF427B73FF427B73FF427B73FF000000FFCECECEFFDEDEDEFFEFEF + EFFFFFFFFFFFFFFFFFFF000000FF5A8C84FF316B63FF427B73FF10524AFF1052 + 4AFF10524AFF10524AFF10524AFF10524AFF000000FFC6C6C6FFD6D6D6FFE7E7 + E7FF8C8C8CFF000000FF000000FF5A8C84FF316B63FF316B63FF316B63FF316B + 63FF316B63FF316B63FF316B63FF004239FF000000FF9C9C9CFF8C8C8CFFCECE + CEFFDEDEDEFF000000FF000000005A8C84FF316B63FF316B63FF316B63FF316B + 63FF316B63FF316B63FF316B63FF004239FF000000FF8C8C8CFF000000FFC6C6 + C6FFD6D6D6FF000000FF00000000316B63FF004239FF004239FF004239FF0042 + 39FF004239FF004239FF004239FF004239FF000000FF000000FF000000000000 + 00FFB5B5B5FFCEC6CEFF000000FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00FFADADADFFBDBDBDFF000000FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000FF000000FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000006B8484FF6B8484FF6B8484FF6B8484FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00006B8484FF5A7373FF42635AFF42635AFF5A7373FF6B8484FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000042635AFF42635AFF000000000000000042635AFF5A7373FF6B8484FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000006B8484FF5A7373FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000005A7373FF42635AFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000006B8484FF6B8484FF42635AFF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000006B8484FF5A7373FF42635AFF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000042635AFF42635AFF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000006B8484FF6B8484FF0000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000042635AFF42635AFF0000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -778,1159 +1332,604 @@ object MainForm: TMainForm 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000002929290029292900292929002929 - 2900292929002929290029292900292929002929290029292900292929002929 - 2900292929002929290029292900292929002929290029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100212121000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000029292900FFFFFF00DEDEDE00C7C7 - C700FFFFFF00FFFFFF00A2A2A200FFFFFF00DEDEDE00DEDEDE00FFFFFF00A2A2 - A200A2A2A200BBBBBB00FFFFFF0029292900393939006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F543800292929000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000029292900FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF0029292900424242006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F543800292929000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000039393900FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00393939004A4A4A00372E2400372E2400372E - 2400372E2400372E2400372E2400372E2400372E2400372E2400372E2400372E - 24006F5438006F5438006F543800393939000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000039393900C2975C00C2975C00C297 - 5C00C2975C00C2975C00C2975C00C2975C00C2975C00C2975C00C2975C00C297 - 5C00C2975C00C2975C00C2975C00393939004A4A4A006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F543800372E - 24006F5438006F5438006F543800393939000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000039393900C2975C00CAA67600CAA6 - 7600C2975C00C2975C00D2B48E00D2B48E00C2975C00C2975C00D2B48E00D2B4 - 8E00C2975C00C2975C00C2975C0039393900525252006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F543800372E - 24006F5438006F5438006F543800393939000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000042424200C2975C00D2B48E00D2B4 - 8E00D2B48E00C2975C00E1CEB700DAC2A300E5D5C100E5D5C100DAC2A300E1CE - B700C2975C00C2975C00C2975C0042424200525252006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F543800372E - 24006F5438006F5438006F543800424242000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000042424200C2975C00D2B48E00D6BB - 9900E9DBCA00DEC8AE00E1CEB700C2975C00E1CEB700E1CEB700C2975C00E9DB - CA00E1CEB700E1CEB700C2975C00424242005A5A5A0071573C0071573C007157 - 3C0071573C0071573C0071573C0071573C0071573C0071573C0071573C00382F - 250071573C0071573C0071573C00424242000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000004A4A4A00C2975C00D2B48E00F4ED - E500C69E6A00DAC2A300E5D5C100C2975C00DEC8AE00E1CEB700C2975C00E1CE - B700C2975C00E5D5C100C2975C004A4A4A005A5A5A00745B4000745B4000745B - 4000745B4000745B4000745B4000745B4000745B4000745B4000745B40003930 - 2600745B4000745B4000745B40004A4A4A000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000004A4A4A00C2975C00CEAD8200D6BB - 9900C2975C00C2975C00E1CEB700C2975C00CEAD8200CEAD8200C2975C00E1CE - B700E1CEB700DAC2A300C2975C004A4A4A0063636300775F4400775F4400775F - 4400775F4400775F4400775F4400775F4400775F4400775F4400775F44003A32 - 2800775F4400775F4400775F44004A4A4A000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000052525200C2975C00C2975C00C297 - 5C00C2975C00C2975C00C2975C00C2975C00C2975C00C2975C00C2975C00C297 - 5C00C2975C00C2975C00C2975C00525252006B6B6B007A644A007A644A007A64 - 4A007A644A007A644A007A644A007A644A007A644A007A644A007A644A003B33 - 2A007A644A007A644A007A644A00525252000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000005A5A5A00C2975C00C2975C00C297 - 5C00C2975C00C2975C00C2975C00C2975C00C2975C00C2975C00C2975C00C297 - 5C00C2975C00C2975C00C2975C005A5A5A007B7B7B007E6950007E6950007E69 - 50007E6950007E6950007E6950007E6950007E6950007E6950007E6950003D35 - 2C007E6950007E6950007E6950005A5A5A000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000063636300FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00636363007B7B7B00826F5700826F5700826F - 5700826F5700826F5700826F5700826F5700826F5700826F5700826F57003E37 - 2F00826F5700826F5700826F5700636363000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000006B6B6B00FFFFFF00E9E9E900E9E9 - E900FFFFFF00FFFFFF00D3D3D300D3D3D300FFFFFF00FFFFFF00D3D3D300D3D3 - D300FFFFFF00FFFFFF00FFFFFF006B6B6B007B7B7B0086765E0086765E008676 - 5E0086765E0086765E0086765E0086765E0086765E0086765E0086765E00403A - 310086765E0086765E0086765E006B6B6B000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000073737300FFFFFF00D3D3D300D3D3 - D300D3D3D300FFFFFF00A2A2A200BBBBBB009494940094949400BBBBBB00A2A2 - A200FFFFFF00FFFFFF00FFFFFF0073737300848484008B7C65008B7C65008B7C - 65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C6500413C - 34008B7C65008B7C65008B7C6500737373000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C0084848400848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C0084848400848484000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000002929290029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100212121000000000000000000000000000000 - 000000000000000000003139AD0010219C0010219C0010219C0010219C001021 - 9C0010219C0010219C0010219C0010219C00000000006B6B6B00292929002121 - 2100181818001818180018181800181818001818180018181800181818001818 - 180018181800181818004A4A4A00000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000003939390000006300000063000000 - 63000000630000006B0000006300000063000000630000006B00000063000000 - 0000000000000000000000000000292929000000000000000000000000000000 - 000000000000000000004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C000000000042424200FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF0029292900000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000004242420000007300000073000000 - 7300000073000000730000007300000073000000730000007300000073000000 - 0000000000000000000000000000292929000000000000000000000000000000 - 000000000000000000004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C000000000042424200FFFFFF00C8E0 - E000C8E0DF00C8E0E000C8E0E000C8E0DF00B5B5B500C8DFDF00C7DFDF00C8DF - E000C8E0DF00FFFFFF0031313100000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000004A4A4A0000008400000084000000 - 8400000084000000840000008400000084000000840000008400000084000000 - 0000000000000000840000008400393939000000000000000000000000004263 - 5A00294A4A00294A4A004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C00000000004A4A4A00FFFFFF00CAE2 - E100CAE2E100CAE2E100CAE2E100B5B5B50072282800B5B5B500B5B5B500B5B5 - B500B5B5B500B5B5B50018181800B5B5B5000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000004A4A4A0000009400000094000000 - 9400000094000000940000009400000094000000940000009400000094000000 - 0000000000000000000000000000393939000000000000000000000000005A73 - 6B0042635A0042635A004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C00000000004A4A4A00FFFFFF00CDE5 - E300CCE5E300CDE5E300B5B5B500812D2D00812D2D00812D2D00812D2D00812D - 2D00812D2D00812D2D00812D2D00812D2D004E63630042555500364545000000 - 0000000000004E636300425555003645450000000000000000004E6363004255 - 550036454500000000000000000000000000525252000000A5000000A5000000 - A50000009C0000009C0000009C000000A5000000A5000000A5000000A5000000 - 0000000000000000000000000000393939000000000000000000000000005A73 - 6B0042635A0042635A004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C00000000004A4A4A00FFFFFF00D0E8 - E500D0E8E600CFE8E50092333300923333009233330092333300923333009233 - 33009233330092333300923333009233330000000000788C8C005A7373004254 - 54000000000000000000788C8C005A737300425454000000000000000000788C - 8C005A737300425454000000000000000000525252000000AD000000AD000000 - AD000000AD000000AD000000AD000000AD000000AD000000AD000000AD000808 - 0800000000000000AD000000AD004242420039524A0029423900294239005A73 - 6B0042635A0042635A004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C00000000005A5A5A00FFFFFF00D3EB - E800D3EBE800A3393900A3393900A3393900A3393900A3393900A3393900A339 - 3900A3393900A3393900A3393900A33939000000000000000000788C8C005A73 - 7300425454000000000000000000788C8C005A73730042545400000000000000 - 0000788C8C005A73730042545400000000005A5A5A0008080800080808000808 - 0800080808000808080008080800080808000808080008080800080808000808 - 080000000000000000000000000042424200425A520039524A0039524A005A73 - 6B0042635A0042635A004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C00000000005A5A5A00FFFFFF00D7EE - EA00D7EEEB00D6EEEB00B23E3E00B23E3E00B23E3E00B23E3E00B33F3F00B23E - 3E00B23E3E00B23E3E00B23E3E00B23E3E00000000000000000000000000788C - 8C005A737300425454000000000000000000788C8C005A737300425454000000 - 000000000000788C8C005A737300425454005A5A5A0000080800000808000008 - 0800000808000008080000080800000808000008080000080800000808000008 - 08000008080000080800000808004A4A4A00425A520039524A0039524A005A73 - 6B0042635A0042635A004A5AB5003139AD003139AD003139AD003139AD003139 - AD003139AD003139AD003139AD0010219C000000000063636300FFFFFF00DAF2 - ED00DAF2ED00DAF2ED00DAF2ED00BD424200BD424200BD424200BD424200BD42 - 4200BD424200BD424200BD424200BD4242000000000000000000000000004254 - 54005A737300788C8C000000000000000000425454005A737300788C8C000000 - 000000000000425454005A737300788C8C006363630008100800081008000810 - 0800081008000810080008100800081008000810080008100800081008000810 - 0800081008002929AD002929AD004A4A4A00425A520039524A0039524A005A73 - 6B0042635A0042635A004A5AB5004A5AB5004A5AB5004A5AB5004A5AB5004A5A - B5004A5AB5004A5AB5004A5AB5003139AD00000000006B6B6B00FFFFFF00DEF6 - F000DEF6F000DDF5F000DDF5EF00DDF5F000BD424200DDF5EF00DDF5F000DEF5 - F000C6DEDE00DEDEDE0052525200000000000000000000000000425454005A73 - 7300788C8C000000000000000000425454005A737300788C8C00000000000000 - 0000425454005A737300788C8C00000000006B6B6B003939AD003939AD003939 - AD003939AD003939AD003939AD003939AD003939AD0010181000101810001018 - 100010181000101810001018100052525200425A520039524A0039524A005A73 - 6B0042635A0042635A0042635A0042635A0042635A0042635A0042635A004263 - 5A00294A4A00000000000000000000000000000000006B6B6B00FFFFFF00E0F9 - F200E1F9F200E0F8F200E0F8F200E0F8F200E1F9F200F7F7F700D6D6D600C6C6 - C600B5B5B5009C9C9C00525252000000000000000000425454005A737300788C - 8C000000000000000000425454005A737300788C8C0000000000000000004254 - 54005A737300788C8C0000000000000000007B7B7B0018212100182121001821 - 2100182121001821210018212100182121004A4AAD0018212100182121001821 - 21001821210018212100182121005A5A5A00425A520039524A0039524A005A73 - 6B0042635A0042635A0042635A0042635A0042635A0042635A0042635A004263 - 5A00294A4A00000000000000000000000000000000006B6B6B00FFFFFF00E3FB - F400E3FBF400E3FBF300E3FBF400E3FCF400E3FBF400F7F7F700949494008C8C - 8C00737373005A5A5A005A5A5A0000000000687F7F00798D8D00879999000000 - 000000000000687F7F00798D8D00879999000000000000000000687F7F00798D - 8D00879999000000000000000000000000007B7B7B0021292900212929002129 - 2900212929002129290021292900212929002129290021292900212929002129 - 2900212929005252AD005252AD0063636300425A520039524A0039524A005A73 - 6B005A736B005A736B005A736B005A736B005A736B005A736B005A736B005A73 - 6B0042635A00000000000000000000000000000000006B6B6B00FFFFFF00E5FE - F600E5FDF600E5FDF600E5FEF600E6FEF600E5FDF600F7F7F700A5A5A500FFFF - FF00FFFFFF00FFFFFF005A5A5A00000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000007B7B7B0029293100292931002929 - 3100292931002929310029293100292931002929310029293100292931002929 - 31002929310029293100292931006B6B6B00425A520039524A0039524A003952 - 4A0039524A0039524A0039524A0039524A0039524A0029423900000000000000 - 000000000000000000000000000000000000000000006B6B6B00FFFFFF00E7FF - F700E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700F7F7F700B5B5B500FFFF - FF00D6F7EF00B5D6CE006B6B6B00000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000084848400525A5A004A5A5200525A - 5A00525A5A00525A5A00525A5A00525A5A00525A5A00525A5A00525A5A00525A - 5A00525A5A004A5A52004A5A520073737300425A520039524A0039524A003952 - 4A0039524A0039524A0039524A0039524A0039524A0029423900000000000000 - 000000000000000000000000000000000000000000006B6B6B00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CECECE00FFFF - FF00B5D6CE007373730000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000084848400848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C008484840084848400425A5200425A5200425A5200425A - 5200425A5200425A5200425A5200425A5200425A520039524A00000000000000 - 0000000000000000000000000000000000000000000073737300737373007373 - 7300737373007B7B7B007B7B7B007B7B7B008484840084848400848484008484 - 8400848484000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000002929290029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100212121000000000029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100000000000000000029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000393939006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F54380029292900393939007B9494007B9494006363 - 6300E7E7E700FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7E700D6D6D600E7E7 - E7005A5A5A007B9494007B94940029292900393939007B9494007B9494006363 - 6300E7E7E700FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7E700D6D6D600E7E7 - E7005A5A5A007B9494007B949400292929000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000424242006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F54380029292900424242007B9494007B9494006B6B - 6B00FFFFFF00E7E7E700A5BDB500FFFFFF00FFFFFF00EFEFEF00E7E7E700E7E7 - E7006B6B6B007B9494007B94940029292900424242007B9494007B9494006B6B - 6B00FFFFFF00E7E7E700A5BDB500FFFFFF00FFFFFF00EFEFEF00E7E7E700E7E7 - E7006B6B6B007B9494007B949400292929000000000000000000000000000000 - 0000C6CED600ADB5B500ADB5B500ADB5B500ADB5B500C6CED600000000000000 - 0000000000000000000000000000000000004A4A4A006F5438006F5438006F54 - 3800393939006F5438006F5438006F543800393939006F5438006F5438006F54 - 3800393939006F5438006F543800393939004A4A4A0094ADA5008CA5A5007B7B - 7B00FFFFFF005A736B008CA5A500FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7006B6B6B00849C9C00849C9C00393939004A4A4A0094ADA5008CA5A5007B7B - 7B00FFFFFF005A736B008CA5A500FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7006B6B6B00849C9C00849C9C0039393900000000000000000000000000BDC6 - C600848C8C00424242003939390039393900394242007B848400BDC6CE00C6CE - D600000000000000000000000000000000004A4A4A006F5438006F543800FFFF - FF006F5438006F5438006F543800FFFFFF006F5438006F5438006F543800FFFF - FF006F5438006F5438006F543800393939004A4A4A0094ADA5008CA5A5007B7B - 7B00FFFFFF005A736B008CA5A500FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7006B6B6B00849C9C00849C9C00393939004A4A4A0094ADA5008CA5A5007B7B - 7B00FFFFFF005A736B008CA5A500FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7006B6B6B00849C9C00849C9C00393939000000000000000000C6CED6002929 - 2900636B6B009C9CA500ADB5B500ADB5B500BDC6C600737B7B0018181800848C - 8C00C6CED600000000000000000000000000525252006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F54380039393900525252009CB5B5009CB5AD009C9C - 9C00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7007B7B7B00849C9C00849C9C0039393900525252009CB5B5009CB5AD009C9C - 9C00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7007B7B7B00849C9C00849C9C00393939000000000000000000C6CECE00ADB5 - BD00C6CED60039424200000000000000000018181800ADB5B500ADB5B5001010 - 10007B7B8400000000000000000000000000525252006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F5438004242420052525200A5BDB500A5BDB500A5BD - B50094B5AD008CADA5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5 - A5008CA5A5008CA5A5008CA5A5004242420052525200A5BDB500A5BDB500A5BD - B50094B5AD008CADA5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5 - A5008CA5A5008CA5A5008CA5A5004242420000000000000000009CA5AD009CA5 - AD0021292900000000000000000000000000000000000000000094949C00848C - 8C00182121000000000000000000000000005A5A5A0071573C0071573C007157 - 3C003939390071573C0071573C0071573C003939390071573C0071573C007157 - 3C003939390071573C0071573C00424242005A5A5A00A5C6BD008CA59C008CA5 - A500849C9C007B948C00738C8400738C8400738C8400738C8C00738C8C00738C - 8C00738C8C006B8484008CADA500424242005A5A5A00A5C6BD008CA59C008CA5 - A500849C9C007B948C00738C8400738C8400738C8400738C8C00738C8C00738C - 8C00738C8C006B8484008CADA5004242420000000000000000005A5A6300848C - 8C000000000042424200C6CECE0000000000000000000000000084848C003139 - 390029313100B5BDBD0000000000000000005A5A5A00745B4000745B4000FFFF - FF00745B4000745B4000745B4000FFFFFF00745B4000745B4000745B4000FFFF - FF00745B4000745B4000745B40004A4A4A005A5A5A00ADC6BD0094ADA500E7E7 - E700F7F7F700F7F7F700EFEFEF00EFEFEF00EFEFEF00EFEFEF00F7F7F700EFEF - EF00DEDEDE0073948C0094ADAD004A4A4A005A5A5A00ADC6BD0094ADA500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000000000 - 00000000000073948C0094ADAD004A4A4A000000000000000000949C9C002121 - 2100000000000000000029292900080808000000000000000000393939002129 - 29007B8484008C8C8C00000000000000000063636300775F4400775F4400775F - 4400775F4400775F4400775F4400775F4400775F4400775F4400775F4400775F - 4400775F4400775F4400775F44004A4A4A0063636300ADC6C60094ADAD00FFFF - FF00FFFFFF00FFFFFF00FFFFFF006B6B6B006B6B6B00FFFFFF00FFFFFF00FFFF - FF00F7F7F7007B94940094ADAD004A4A4A0063636300ADC6C60094ADAD00FFFF - FF008C0000008C0000008C0000008C0000008C000000FFFFFF00000000000000 - 0000C6C6C6007B94940094ADAD004A4A4A0000000000000000004A5252008484 - 8C0073737B0042424A00101010001818180010101000525252005A6363008C8C - 940042424200949C9C0000000000000000006B6B6B007A644A007A644A007A64 - 4A007A644A007A644A007A644A007A644A007A644A007A644A007A644A007A64 - 4A007A644A007A644A007A644A00525252006B6B6B00ADCEC6009CB5AD00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00DEDEDE00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00F7F7F7007B9C94009CB5B500525252006B6B6B00ADCEC6009CB5AD00FFFF - FF00EF000000EF000000EF000000EF000000EF000000FFFFFF00000000000000 - 0000000000007B9C94009CB5B500525252000000000000000000949C9C004A4A - 4A00737B7B00737B7B00949C9C0094949C0094949C007B8484006B6B73005252 - 5200A5A5AD000000000000000000000000007B7B7B007E6950007E6950007E69 - 5000393939007E6950007E6950007E695000393939007E6950007E6950007E69 - 5000393939007E6950007E6950005A5A5A007B7B7B00CEE7DE00A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF006B6B6B006B6B6B00DEDEDE00FFFFFF00FFFF - FF00FFFFFF008CA5A500ADC6C6005A5A5A007B7B7B00CEE7DE00A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FF000000FF000000FFFFFF00080808000808 - 0800C6C6C6008CA5A500ADC6C6005A5A5A000000000000000000C6CED600BDC6 - C60084848C00737B7B005252520052525200525252006B737300848C8C00BDBD - C600000000000000000000000000000000007B7B7B00826F5700826F5700FFFF - FF00826F5700826F5700826F5700FFFFFF00826F5700826F5700826F5700FFFF - FF00826F5700826F5700826F5700636363007B7B7B00D6EFE700A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DEDEDE006B6B6B00FFFFFF00FFFF - FF00FFFFFF0094ADAD00ADC6C600636363007B7B7B00D6EFE700A5BDB5000818 - 1000081810000818100008181000081810000818100008181000081810000818 - 10000818100094ADAD00ADC6C600636363000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000007B7B7B0086765E0086765E008676 - 5E0086765E0086765E0086765E0086765E0086765E0086765E0086765E008676 - 5E0086765E0086765E0086765E006B6B6B007B7B7B00D6F7EF00A5BDB500FFFF - FF00FFFFFF00FFFFFF008C8C8C006B6B6B006B6B6B00DEDEDE00FFFFFF00FFFF - FF00FFFFFF0094ADA500ADCEC6006B6B6B007B7B7B00D6F7EF00A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0018211800182118001821 - 1800C6C6C60094ADA500ADCEC6006B6B6B000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000848484008B7C65008B7C65008B7C - 65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C - 65008B7C65008B7C65008B7C65007373730084848400DEF7F700A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00F7F7F7009CB5AD00B5CECE007373730084848400DEF7F700A5BDB5002129 - 290021292900212929002129290021292900FFFFFF0021292900212929002129 - 2900212929009CB5AD00B5CECE00737373000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000084848400848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C00848484008484840000000000848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C00848484000000000000000000848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C0084848400000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000002929290029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100212121000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000ADADAD00BDBDBD00000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000393939006F5438006F5438006F54 - 38006F5438006F5438006F5438006F543800393939006F5438006F5438006F54 - 38006F5438006F5438003939390029292900316B630000423900004239000042 - 3900004239000042390000423900004239000042390000000000000000000000 - 000000000000B5B5B500CEC6CE00000000000000000000000000000000000000 - 000000000000000000000000000042635A0042635A0000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000010219C00000000000000000000000000000000000000 - 000000000000000000000000000000000000424242006F5438006F5438006F54 - 38006F5438006F5438006F543800FFFFFF006F5438006F5438006F5438006F54 - 38006F543800FFFFFF006F543800292929005A8C8400316B6300316B6300316B - 6300316B6300316B6300316B6300316B630000423900000000008C8C8C000000 - 0000C6C6C600D6D6D60000000000000000000000000000000000000000000000 - 00000000000000000000000000006B8484006B84840000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000010219C003139AD0010219C000000000000000000000000000000 - 0000000000000000000000000000000000004A4A4A006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F543800393939005A8C8400316B6300316B6300316B - 6300316B6300316B6300316B6300316B630000423900000000009C9C9C008C8C - 8C00CECECE00DEDEDE0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000003139AD004A5AB5003139AD000000000000000000000000000000 - 0000000000000000000000000000000000004A4A4A006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F543800393939005A8C8400316B6300427B73001052 - 4A0010524A0010524A0010524A0010524A0010524A0000000000C6C6C600D6D6 - D600E7E7E7008C8C8C0000000000000000000000000000000000000000000000 - 000000000000000000000000000042635A0042635A0000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000010219C003139AD00000000003139AD0010219C0000000000000000000000 - 000000000000000000000000000000000000525252006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F543800393939005A8C8400316B63006BA59C00427B - 7300427B7300427B7300427B7300427B7300427B730000000000CECECE00DEDE - DE00EFEFEF00FFFFFF00FFFFFF00000000000000000000000000000000000000 - 00000000000000000000000000006B8484005A73730042635A00000000000000 + 0000000000000000000000000000000000000000000000000000000000004A5A + B5FF4A5AB5FF0000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000004A5AB5FF4A5AB5FF3139 + ADFF3139ADFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF1021 + 9CFF10219CFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000003139ADFF10219CFF10219CFF0000 + 00000000000000000000000000000000000000000000000000004A5AB5FF0000 + 00000000000000000000000000004A5AB5FF3139ADFF00000000000000000000 + 00000000000000000000000000000000000000000000000000003139ADFF4A5A + B5FF0000000000000000000000003139ADFF10219CFF00000000000000000000 + 000000000000000000000000000000000000000000000000000010219CFF3139 + ADFF4A5AB5FF000000004A5AB5FF3139ADFF0000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000001021 - 9C003139AD004A5AB500000000004A5AB5003139AD0000000000000000000000 - 000000000000000000000000000000000000525252006F5438006F5438006F54 - 38006F5438006F5438006F5438006F5438006F5438006F5438006F5438006F54 - 38006F5438006F5438006F543800424242005A8C8400316B63006BA59C00427B - 7300427B73005A8C8C00216B5A00216B5A00216B5A0000000000DEDEDE00EFEF - EF00F7F7F700FFFFFF0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000006B8484006B84840042635A000000 - 0000000000000000000000000000000000000000000000000000000000003139 - AD004A5AB5000000000000000000000000003139AD0010219C00000000000000 - 0000000000000000000000000000000000005A5A5A0071573C0071573C007157 - 3C0071573C0071573C0071573C0071573C003939390071573C0071573C007157 - 3C0071573C0071573C0039393900424242005A8C8400316B63006BA59C00427B - 7300427B73007BB5B5005A8C8C005A8C8C005A8C8C0000000000E7E7E700F7F7 - F700FFFFFF000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000005A7373004263 - 5A00000000000000000000000000000000000000000000000000000000004A5A - B500000000000000000000000000000000004A5AB5003139AD00000000000000 - 0000000000000000000000000000000000005A5A5A00745B4000745B4000745B - 4000745B4000745B4000745B4000FFFFFF00745B4000745B4000745B4000745B - 4000745B4000FFFFFF00745B40004A4A4A005A8C8400316B63006BA59C00427B - 7300427B73007BB5B5005A8C8C005A8C8C005A8C8C0000000000F7F7EF00FFFF - FF0000000000216B5A0000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000006B8484005A73 - 7300000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000003139AD0010219C001021 - 9C000000000000000000000000000000000063636300775F4400775F44003939 - 3900775F4400775F440039393900775F4400775F4400775F4400775F4400775F - 4400775F4400775F4400775F44004A4A4A005A8C84005A8C84006BA59C00427B - 7300427B73007BB5B5005A8C8C005A8C8C005A8C8C0000000000F7F7F7000000 - 00005A8C8C00216B5A0000000000000000000000000000000000000000000000 - 00000000000042635A0042635A00000000000000000042635A005A7373006B84 - 8400000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD0010219C0010219C0000000000000000006B6B6B007A644A00FFFFFF007A64 - 4A007A644A00FFFFFF007A644A007A644A007A644A007A644A007A644A007A64 - 4A007A644A007A644A007A644A005252520000000000000000006BA59C00427B - 7300427B73007BB5B5005A8C8C005A8C8C005A8C8C0000000000000000005A8C - 8C005A8C8C00216B5A0000000000000000000000000000000000000000000000 - 0000000000006B8484005A73730042635A0042635A005A7373006B8484000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000004A5AB5004A5A - B5003139AD003139AD0000000000000000007B7B7B007E6950007E6950007E69 - 50007E6950007E6950007E6950007E6950007E6950007E6950007E6950007E69 - 50007E6950007E6950007E6950005A5A5A0000000000000000006BA59C00427B - 7300427B73007BB5B5005A8C8C005A8C8C005A8C8C005A8C8C005A8C8C005A8C - 8C005A8C8C00216B5A0000000000000000000000000000000000000000000000 - 000000000000000000006B8484006B8484006B8484006B848400000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00004A5AB5004A5AB50000000000000000007B7B7B00826F5700826F57003939 - 3900826F5700826F570039393900826F5700826F5700826F5700826F5700826F - 5700826F5700826F5700826F57006363630000000000000000006BA59C006BA5 - 9C006BA59C007BB5B5005A8C8C005A8C8C005A8C8C005A8C8C005A8C8C005A8C - 8C005A8C8C00216B5A0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000007B7B7B0086765E00FFFFFF008676 - 5E0086765E00FFFFFF0086765E0086765E0086765E0086765E0086765E008676 - 5E0086765E0086765E0086765E006B6B6B000000000000000000000000000000 - 0000000000007BB5B5005A8C8C005A8C8C005A8C8C005A8C8C005A8C8C005A8C - 8C005A8C8C00216B5A0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000848484008B7C65008B7C65008B7C - 65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C65008B7C - 65008B7C65008B7C65008B7C6500737373000000000000000000000000000000 - 0000000000007BB5B5007BB5B5007BB5B5007BB5B5007BB5B5007BB5B5007BB5 - B5007BB5B5005A8C8C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000084848400848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C0084848400848484000000000000000000000000000000 - 00002131730010186B0010186B0010186B0010186B0010186B0010186B001018 - 6B0010186B0010186B0010186B0010186B000000000000000000000000000000 - 000000000000000000005A73730042635A0042635A0042635A0042635A004263 - 5A0042635A0042635A0042635A0042635A002929290029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100212121000000000000000000000000000000 - 0000000000000000000000005A0000005A000000420000004A00292994000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000394A7B00213173002131730021317300213173002131730010186B00394A - 7B0021317300213173002131730010186B000000000000000000000000000000 - 000000000000000000006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A0039393900FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 - 0000000000000000000000000000292929000000000000000000000000000000 - 0000000042002929940021218C00393939003939390029292900292929004A4A - B500000042000000000000000000000000000000000000000000000000000000 - 0000394A7B00213173002131730021317300213173002131730010186B00394A - 7B0021317300213173002131730010186B000000000000000000000000000000 - 000000000000000000006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A0042424200FFFFFF008C0000008C00 - 00008C0000008C0000008C0000008C0000008C0000008C000000FFFFFF000000 - 0000000000000000000000000000292929000000000000000000000000000000 - 0000000042006B6B6B005A5ABD004A4AB5003939A5003939A5004A4AB5004242 - 4200000042000000000000000000000000000000000000000000000000000000 - 000021317300394A7B00394A7B00394A7B00394A7B00394A7B0010186B00394A - 7B00394A7B00394A7B00394A7B0010186B000000000000000000000000004263 - 5A00294A4A00294A4A006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A004A4A4A00FFFFFF00BD000000BD00 - 0000BD000000BD000000BD000000BD000000BD000000BD000000FFFFFF000000 - 000000000000C6C6C600C6C6C600393939000000000000000000000000000000 - 0000000042009494EF000000420031319C001818840021218C0000005A008484 - DE00000042000000000000000000000000008C8C8C007B7B7B007B7B7B007B7B - 7B002131730010186B0010186B0010186B0010186B0010186B0010186B001018 - 6B0010186B0010186B0010186B0010186B000000000000000000000000005A73 - 6B0042635A0042635A006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A004A4A4A00FFFFFF00D6000000D600 - 0000D6000000D6000000D6000000D6000000D6000000D6000000FFFFFF000000 - 0000000000000000000000000000393939000000000000000000000000000000 - 000031319C0029298C0031319C000000520000005200000042004242AD003131 - 9C0031319C00000000000000000000000000949494008C8C8C008C8C8C008C8C - 8C00394A7B002131730021317300213173002131730021317300213173002131 - 730021317300213173002131730010186B000000000000000000000000005A73 - 6B0042635A0042635A006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A0052525200FFFFFF00EF000000EF00 - 0000EF000000EF000000EF000000EF000000EF000000EF000000FFFFFF000000 - 0000000000000000000000000000393939000000000000000000000000003131 - 9C00000042007B7BDE006363C60031319C005A5ABD0031319C006363C6007B7B - DE000000000031319C000000000000000000949494008C8C8C00949494004242 - 4200394A7B002131730021317300213173002131730021317300213173002131 - 730021317300213173002131730010186B003139AD0010219C0010219C005A73 - 6B0042635A0042635A006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A0052525200FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FF000000FF000000FF000000FFFFFF000808 - 080008080800C6C6C600C6C6C600424242000000000010107300080863000808 - 6300000042006B6BCE004A4AB5009494EF007B7BDE009494EF004A4AB5006B6B - CE000000000000005A000000520000000000949494008C8C8C00D6D6D6009494 - 940021317300394A7B00394A7B00394A7B00394A7B00394A7B00394A7B00394A - 7B00394A7B00394A7B00394A7B0010186B004A5AB5003139AD003139AD005A73 - 6B0042635A0042635A006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A005A5A5A0008080800080808000808 - 0800080808000808080008080800080808000808080008080800080808000808 - 0800080808000808080008080800424242000000000021218C006B6BCE007B7B - DE00101073005A5ABD0031319C006B6BCE005252BD006B6BCE0031319C002929 - 8C003939A5008C8CE7002929940000000000949494008C8C8C008C8C8C008C8C - 8C002131730010186B0010186B0010186B0010186B0010186B0010186B001018 - 6B0010186B0010186B0010186B0010186B004A5AB5003139AD003139AD005A73 - 6B0042635A0042635A006B8484005A7373005A7373005A7373005A7373005A73 - 73005A7373005A7373005A73730042635A005A5A5A0008080800080808000808 - 0800080808000808080008080800080808000808080008080800080808000808 - 08000808080008080800080808004A4A4A000000000031319C006B6BCE003131 - 9C0018187B0000005A0000005A0000005A0000004A0018187B0000005A000000 - 42006363C6006B6BCE007B7BDE0000000000949494008C8C8C008C8C8C008C8C - 8C00394A7B002131730021317300213173002131730010186B00394A7B002131 - 730021317300213173002131730010186B004A5AB5003139AD003139AD005A73 - 6B0042635A0042635A006B8484006B8484006B8484006B8484006B8484006B84 - 84006B8484006B8484006B8484005A7373006363630008181000081810000818 - 1000081810000818100008181000081810000818100008181000081810000818 - 100008181000C6C6C600C6C6C6004A4A4A00000000000000000031319C001818 - 7B003939A500A5A5F700A5A5F7008C8CE7003939A5008C8CE700A5A5F7008C8C - E70000005A0031319C000000000000000000949494008C8C8C008C8C8C008C8C - 8C00394A7B002131730021317300213173002131730010186B00394A7B002131 - 730021317300213173002131730010186B004A5AB5003139AD003139AD005A73 - 6B0042635A0042635A0042635A0042635A0042635A0042635A0042635A004263 - 5A00294A4A000000000000000000000000006B6B6B00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0018211800182118001821 - 180018211800182118001821180052525200000000002121210000005A001010 - 73008484DE007B7BDE006B6BCE008484DE006B6BCE008484DE007B7BDE008C8C - E7005252BD00212121002121210000000000949494008C8C8C008C8C8C008C8C - 8C00394A7B00394A7B00394A7B00394A7B00394A7B002131730021317300394A - 7B00394A7B00394A7B00394A7B00213173004A5AB5003139AD003139AD005A73 - 6B0042635A0042635A0042635A0042635A0042635A0042635A0042635A004263 - 5A00294A4A000000000000000000000000007B7B7B0021292900212929002129 - 290021292900212929002129290021292900FFFFFF0021292900212929002129 - 29002129290021292900212929005A5A5A00212121004A4A4A00212121001818 - 84006B6BCE005252BD007373D6005A5ABD004A4AB5005A5ABD006B6BCE007373 - D60018187B00212121004A4A4A0021212100949494008C8C8C00949494004242 - 42008C8C8C008C8C8C008C8C8C008C8C8C0094949400424242008C8C8C007B7B - 7B00000000000000000000000000000000004A5AB5003139AD003139AD005A73 - 6B005A736B005A736B005A736B005A736B005A736B005A736B005A736B005A73 - 6B0042635A000000000000000000000000007B7B7B0031393900313939003139 - 3900313939003139390031393900313939003139390031393900313939003139 - 390031393900C6C6C600C6C6C60063636300212121005A5A5A00212121005252 - BD006B6BCE0031319C006B6BCE008C8CE7008C8CE7008C8CE7006B6BCE006B6B - CE0000005200212121005A5A5A0021212100949494008C8C8C00D6D6D6009494 - 94008C8C8C008C8C8C008C8C8C008C8C8C00D6D6D600949494008C8C8C007B7B - 7B00000000000000000000000000000000004A5AB5003139AD003139AD003139 - AD003139AD003139AD003139AD003139AD003139AD0010219C00000000000000 - 0000000000000000000000000000000000007B7B7B0039424200394242003942 - 4200394242003942420039424200394242003942420039424200394242003942 - 42003942420039424200394242006B6B6B00212121006B6B6B005A5A5A008C8C - E7009494EF006B6BCE008C8CE700A5A5F700B5B5FF00A5A5F7008C8CE7008C8C - E70029298C005A5A5A006B6B6B0021212100949494008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C007B7B - 7B00000000000000000000000000000000004A5AB5003139AD003139AD003139 - AD003139AD003139AD003139AD003139AD003139AD0010219C00000000000000 - 00000000000000000000000000000000000084848400525A5A004A5A5200525A - 5A00525A5A00525A5A00525A5A00525A5A00525A5A00525A5A00525A5A00525A - 5A00525A5A004A5A52004A5A520073737300000000004A4A4A005A5ABD006B6B - CE006B6BCE005252BD006B6BCE008C8CE7008C8CE7008C8CE7006B6BCE003131 - 9C007B7BDE005A5ABD004A4A4A00000000009494940094949400949494009494 - 9400949494009494940094949400949494009494940094949400949494008C8C - 8C00000000000000000000000000000000004A5AB5004A5AB5004A5AB5004A5A - B5004A5AB5004A5AB5004A5AB5004A5AB5004A5AB5003139AD00000000000000 - 00000000000000000000000000000000000084848400848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C0084848400848484000000000000000000000000000000 - 0000000000000000000031319C005A5ABD005A5ABD0031319C00000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000002929290029292900212121001818 - 1800181818001818180018181800181818001818180018181800292929002929 - 2900212121000000000000000000000000000000000000000000292929002929 - 2900292929002929290029292900292929002929290029292900292929002929 - 290021212100292929000000000000000000000000006B6B6B00292929002121 - 2100181818001818180018181800181818001818180018181800181818001818 - 1800181818004A4AFF004A4AFF00000000000000000000000000000000000000 - 000000000000000000006B6B6B00292929002121210018181800181818001818 - 18001818180018181800181818004A4A4A0039393900FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000000000 - 0000292929000000000000000000000000000000000000000000393939007B9C - 9C007B9C9C007B9C9C007B9C9C007B9C9C007B9C9C007B9C9C007B9C9C007B9C - 9C007B9C9C002929290000000000000000000000000042424200FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00B5B5 - B5004A4AFF004A4AFF0029292900000000000000000000000000000000000000 - 0000000000000000000042424200FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF002929290042424200FFFFFF008C000000FFDE - DE00FFDEDE00FFDEDE00FFDEDE00FFDEDE00FFDEDE00FFFFFF00DEDEDE000000 - 000029292900000000000000000000000000000000000000000042424200849C - 9C00849C9C00849C9C00849C9C00849C9C00849C9C00849C9C00849C9C00849C - 9C00849C9C002929290000000000000000000000000042424200FFFFFF00C6DE - DE00C6DEDE00B5B5B500C6DEDE00C6DEDE00C6DEDE00C6DEDE00B5B5B5004A4A - FF004A4AFF00FFFFFF0031313100000000006B6B6B0029292900212121001818 - 1800181818001818180042424200FFFFFF00E7C6C600E7C6C600E7C6C600E7C6 - C600E7C6C600E7C6C600FFFFFF00313131004A4A4A00FFFFFF00BD000000FFDE - DE004A63520042635A0042635A0042635A0042635A0042635A00DEDEDE000000 - 00003939390000000000000000000000000000000000000000004A4A4A008CA5 - A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5 - A5008CA5A500393939000000000000000000000000004A4A4A00FFFFFF00BDDE - D600BDDED6004A4AFF00B5B5B500B5B5B500BDDED600B5B5B5004A4AFF004A4A - FF00BDDED600FFFFFF00313131000000000042424200FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF004A4A4A00FFFFFF00EFCECE00EFCECE00EFCECE00EFCE - CE00EFCECE00EFCECE00FFFFFF00313131004A4A4A00FFFFFF00D6000000FFDE - DE006B8484005A7373005A7373005A73730042635A00FFFFFF00000000000000 - 00003939390000000000000000000000000000000000000000004A4A4A0094AD - AD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094AD - AD0094ADAD00393939000000000000000000000000004A4A4A00FFFFFF00CEE7 - E700CEE7E700CEE7E7004A4AFF004A4AFF00B5B5B5004A4AFF004A4AFF00CEE7 - E700CEE7E700FFFFFF00313131000000000042424200FFFFFF00C6DEDE00C6DE - DE00C6DEDE00C6DEDE005A5A5A00FFFFFF00F7D6DE00F7D6DE00F7D6DE00F7D6 - DE00F7D6DE00F7D6DE00FFFFFF004242420052525200FFFFFF00EF000000FFDE - DE006B8484005A7373005A73730042635A0042635A00FFFFFF00000000000000 - 0000393939000000000000000000000000000000000000000000525252009CB5 - B5009CB5B5009CB5B5009CB5B5009CB5B5009CB5B5009CB5B5009CB5B5009CB5 - B5009CB5B500393939000000000000000000000000004A4A4A00FFFFFF00CEE7 - E700CEE7E700CEE7E700CEE7E7004A4AFF004A4AFF004A4AFF00B5B5B500CEE7 - E700CEE7E700FFFFFF0039393900000000004A4A4A00FFFFFF00CEE7E700CEE7 - E700CEE7E700CEE7E7005A5A5A00FFFFFF00F7D6DE00F7D6DE00F7D6DE00F7D6 - DE00F7D6DE00F7D6DE00FFFFFF004242420052525200FFFFFF00FFFFFF00FFFF - FF006B8484005A7373006B8484005A73730042635A0042635A00DEDEDE000808 - 080042424200000000000000000000000000000000000000000052525200A5BD - BD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BDBD007B9C9C006B84 - 8400A5BDBD00424242000000000000000000000000005A5A5A00FFFFFF00D6EF - E700D6EFE700D6EFE700B5B5B5004A4AFF004A4AFF004A4AFF004A4AFF00B5B5 - B500B5B5B500FFFFFF0042424200000000005A5A5A00FFFFFF00D6EFE700D6EF - E700D6EFE700D6EFE7006B6B6B00FFFFFF00FFDEDE00FFDEDE00FFDEDE00FFDE - DE00FFDEDE00E7C6C600DEDEDE00525252005A5A5A000808080008080800DEDE - DE006B8484006B8484006B8484006B8484005A73730042635A0042635A00EFEF - EF001818180018181800181818004A4A4A0000000000000000005A5A5A00ADC6 - C600ADC6C600ADC6C600ADC6C600ADC6C600ADC6C600ADC6C600DEF7F7007B9C - 9C00ADC6C600424242000000000000000000000000005A5A5A00FFFFFF00D6EF - E700D6EFE700D6EFE7004A4AFF004A4AFF004A4AFF00D6EFE7004A4AFF004A4A - FF004A4AFF00B5B5B50042424200000000005A5A5A00FFFFFF00D6EFE700D6EF - E700D6EFE700D6EFE7006B6B6B00FFFFFF00FFDEDE00FFDEDE00FFDEDE00F7F7 - F700D6D6D600B5B5B5009C9C9C00525252005A5A5A000808080021292900DEE7 - E7006B848400DEE7E700F7F7F7006B8484006B8484005A73730042635A004263 - 5A00FFFFFF00FFFFFF00FFFFFF002929290000000000000000005A5A5A00B5CE - CE00B5CECE00B5CECE00B5CECE00B5CECE00B5CECE00B5CECE00B5CECE00B5CE - CE00B5CECE004A4A4A0000000000000000000000000063636300FFFFFF00D6EF - EF00D6EFEF00B5B5B5004A4AFF004A4AFF00D6EFEF00D6EFEF00D6EFEF004A4A - FF004A4AFF004A4AFF004A4A4A00000000006B6B6B00FFFFFF00DEF7F700DEF7 - F700DEF7F700DEF7F7006B6B6B00FFFFFF00FFDEDE00FFDEDE00FFDEDE00F7F7 - F70094949400737373005A5A5A005A5A5A007B7B7B002129290021292900F7F7 - F700F7F7F700F7F7F70021292900F7F7F7006B8484006B8484005A7373004263 - 5A0042635A00FFFFFF00FFFFFF0031313100000000000000000063636300BDD6 - D600BDD6D600BDD6D600BDD6D600BDD6D600BDD6D600BDD6D600BDD6D600BDD6 - D600BDD6D6004A4A4A000000000000000000000000006B6B6B00FFFFFF00DEF7 - F700B5B5B5004A4AFF004A4AFF00DEF7F700DEF7F700DEF7F700DEF7F700CEEF - E7004A4AFF004A4AFF004A4AFF00000000006B6B6B00FFFFFF00DEF7F700DEF7 - F700DEF7F700F7F7F7006B6B6B00FFFFFF00FFE7EF00FFE7EF00FFE7EF00F7F7 - F700A5A5A500FFFFFF00FFFFFF005A5A5A005A5A5A0031393900313939003139 - 390031393900313939003139390031393900FFFFFF006B8484006B8484004263 - 5A00FFFFFF00FFFFFF00DEDEDE005252520000000000000000006B6B6B00C6DE - DE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DE - DE00C6DEDE00525252000000000000000000000000006B6B6B00FFFFFF00B5B5 - B5004A4AFF004A4AFF004A4AFF00DEF7F700DEF7F700F7F7F700D6D6D600C6C6 - C600B5B5B5004A4AFF004A4AFF004A4AFF006B6B6B00FFFFFF00DEF7F700DEF7 - F700DEF7F700F7F7F7006B6B6B00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00CECECE00DEB5BD0073737300000000007B7B7B0039424200394242003942 - 4200394242003942420039424200394242006B6B6B00FFFFFF006B848400FFFF - FF00FFFFFF00B5B5B5009C9C9C005252520000000000000000007B7B7B00CEE7 - E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7 - E700CEE7E7005A5A5A000000000000000000000000006B6B6B00FFFFFF004A4A - FF004A4AFF004A4AFF00DEF7F700DEF7F700DEF7F700F7F7F700949494008C8C - 8C00737373005A5A5A004A4AFF004A4AFF006B6B6B00FFFFFF00E7FFF700E7FF - F700E7FFF700F7F7F700737373007373730073737300737373007B7B7B008484 - 84008484840084848400000000000000000084848400525A5A004A5A5200525A - 5A00525A5A00525A5A00525A5A00525A5A006B6B6B00FFFFFF00FFFFFF00FFFF - FF0094949400737373005A5A5A005A5A5A0000000000000000007B7B7B00D6EF - EF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EF - EF00D6EFEF00636363000000000000000000000000006B6B6B00FFFFFF00E7FF - F7004A4AFF004A4AFF00E7FFF700E7FFF700E7FFF700F7F7F700A5A5A500FFFF - FF00FFFFFF00FFFFFF005A5A5A004A4AFF006B6B6B00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00CECECE00B5D6CE007373730000000000000000000000 - 00000000000000000000000000000000000084848400848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C006B6B6B00FFFFFF00FFE7EF00F7F7 - F700A5A5A500FFFFFF00FFFFFF005A5A5A0000000000000000007B7B7B00DEF7 - F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7 - F700DEF7F7006B6B6B000000000000000000000000006B6B6B00FFFFFF00E7FF - F700E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700F7F7F700B5B5B500FFFF - FF00D6F7EF00B5D6CE006B6B6B00000000007373730073737300737373007373 - 73007B7B7B008484840084848400848484000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000006B6B6B00FFFFFF00FFFFFF00FFFF - FF00CECECE00DEB5BD007373730000000000000000000000000084848400DEF7 - F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7 - F700DEF7F700737373000000000000000000000000006B6B6B00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CECECE00FFFF - FF00B5D6CE007373730000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000007373730073737300737373008484 - 84008484840084848400000000000000000000000000000000007B7B7B008484 - 8400848484008484840084848400848484008484840084848400848484008484 - 8400848484007373730000000000000000000000000073737300737373007373 - 7300737373007B7B7B007B7B7B007B7B7B008484840084848400848484008484 - 8400848484000000000000000000000000000000000000000000000000000000 - 0000000000004A3939004A3939004A3939004A3939004A3939004A3939000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000800 - 00003921210021000000520000006B0808006B0808005A000000290000002910 - 1000080000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000042424200393939003939 - 3900424242004242420042424200313131003939390042424200424242003939 - 3900393939002929290039393900000000000000000000000000000000002952 - 3900315A4A00295239000000000000000000000000002952390031634A00214A - 3100000000000000000000000000000000000000000000000000080000001000 - 00006B00000084000000AD000000EF101000EF181800BD0000008C0000007300 - 0000310000000800000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007B7B7B00636363006363 - 63006B6B6B006B6B6B006B6B6B005A5A5A00636363006B6B6B007B7B7B006B6B - 6B005A5A5A005A5A5A0042424200000000000000000000000000315242005284 - 6B00528C6B005A8C73004A6B5A0000000000426B5A005A8473005A9473006394 - 7300214A31000000000000000000000000000000000008000000210000006300 - 0000CE000000AD0000006300000042000000420000005A0000009C000000BD00 - 0000940000002900000008000000000000000000000000000000294A4A00294A - 4A00294A4A00294A4A00294A4A00000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000848484006B6B6B006363 - 6300737373007373730073737300636363006B6B6B0073737300848484006B6B - 6B00636363006363630042424200000000000000000000000000294231004A7B - 63000000000000000000637B7300396352005A7B6B000000000000000000527B - 6300395A4200000000000000000000000000000000000000000000000000AD00 - 0000F7101000C61010005A000000080000000800000042000000B5000000F708 - 0800C60000006B000000421818000000000000000000000000006B8484004263 - 5A00294A4A00294A4A0000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000008C8C8C006B6B6B006B6B - 6B007B7B7B007B7B7B007B7B7B006B6B6B006B6B6B007B7B7B00848484007373 - 730063636300636363004A4A4A00000000000000000000000000000000004A6B - 5A00000000000000000000000000426B5A00000000000000000000000000527B - 6300000000000000000000000000000000004A31310029000000CE000000CE00 - 0000DE000000CE000000CE000000B5101000B5101000CE000000BD000000DE00 - 0000BD000000AD000000630000003108080000000000000000006B8484004263 - 5A0042635A00294A4A0000000000000000000000000000000000000000000000 - 000000000000294A4A0000000000000000000000000094949400737373007B7B - 7B008484840084848400848484006B6B6B007373730084848400949494007B7B - 7B00737373006B6B6B004A4A4A00000000000000000000000000000000004A6B - 5A005273630000000000315A4A004A7B6B00295A4A00000000004A7363004A6B - 5A00000000000000000000000000000000004A313100840000009C000000CE00 - 0000E7000000EF000000DE000000AD101000A5181800CE000000D6000000EF00 - 0000DE000000B5000000840000003108080000000000000000006B8484006B84 - 840042635A00294A4A00294A4A00000000000000000000000000000000000000 - 00000000000042635A00294A4A0000000000000000009C9C9C007B7B7B006363 - 6300424242006B6B6B008C8C8C00737373007B7B7B008C8C8C006B6B6B003939 - 39005A5A5A007373730052525200000000000000000000000000000000000000 - 00004A6B5A006B8C7B0052846B006B9C8C006B9C8C0052736300526B63000000 - 00000000000000000000000000000000000052313100940000009C000000E700 - 0000F7212100F7181800EF000000B50000009C080800E7000000F7101000F729 - 2900DE000000B5000000940000004210100000000000000000006B8484000000 - 00006B84840042635A00294A4A00294A4A000000000000000000000000000000 - 0000294A4A0042635A006B84840000000000000000009C9C9C007B7B7B008C8C - 8C00424242008C8C8C008C8C8C0073737300737373008C8C8C00949494003131 - 310073737300737373005A5A5A00000000000000000000000000000000000000 - 000000000000000000004A4A4A004A4A4A004A4A4A0000000000000000000000 - 0000000000000000000000000000000000004A3939009C000000A5000000BD00 - 0000A5000000CE101000E7000000E7080800E7101000C6000000DE080800C608 - 080094000000A50000009C000000421010000000000000000000000000000000 - 00000000000042635A0042635A00294A4A00294A4A00294A4A00294A4A00294A - 4A0042635A0042635A00000000000000000000000000A5A5A500848484004A6B - 630039393900636363004A4A4A003939390031313100424242005A5A5A002121 - 21004A6B63007B7B7B005A5A5A00000000000000000000000000000000000000 - 0000000000004A4A4A006B6B6B004A4A4A006B6B6B004A4A4A00000000000000 - 000000000000000000000000000000000000423131008400000084000000CE00 - 0000CE101000F7393900A5080800840000008C00000063000000D6424200F731 - 3100AD0000009400000073000000290808000000000000000000000000000000 - 0000000000006B84840042635A0042635A0042635A0042635A0042635A004263 - 5A0042635A006B8484000000000000000000000000009C9C9C007B7B7B006B6B - 6B00525252004A4A4A0063636300212121001010100063636300525252005252 - 52006B6B6B007373730052525200000000000000000000000000000000000000 - 0000000000006B6B6B00848484004A4A4A00848484006B6B6B00000000000000 - 0000000000000000000000000000000000004A3939001000000084000000A500 - 0000DE101000FF4A4A00C6181800CE000000DE000000940000008C000000C608 - 0800BD0000009400000042000000421010000000000000000000000000000000 - 000000000000000000006B84840042635A0042635A0042635A0042635A004263 - 5A006B8484000000000000000000000000000000000094949400737373006B6B - 6B008C8C8C008C8C8C008C8C8C00212121001010100084848400949494007B7B - 7B006B6B6B006B6B6B004A4A4A00000000000000000000000000000000000000 - 00004A4A4A006B6B6B00A5A5A50000000000A5A5A5006B6B6B004A4A4A000000 - 0000000000000000000000000000000000000000000000000000840000008400 - 0000FF4A4A00FF9C9C00FF525200FF4A4A00FF636300FF313100E7000000DE00 - 0000AD0000009400000000000000000000000000000000000000000000000000 - 00000000000000000000000000006B8484006B8484006B8484006B8484006B84 - 8400000000000000000000000000000000000000000094949400737373006B6B - 6B0084848400848484008484840029292900212121007B7B7B008C8C8C007B7B - 7B006B6B6B006B6B6B004A4A4A00000000000000000000000000000000000000 - 00006B6B6B0084848400A5A5A50000000000A5A5A500848484006B6B6B000000 - 0000000000000000000000000000000000000000000008000000080000001800 - 0000BD181800F74A4A00F7393900F7424200F7424200FF393900F7080800C600 - 0000520000002100000008000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000848484006B6B6B006B6B - 6B007B7B7B007B7B7B007B7B7B0042424200424242007B7B7B008C8C8C007373 - 7300636363006B6B6B004A4A4A00000000000000000000000000000000000000 - 000084848400A5A5A500000000000000000000000000A5A5A500848484000000 - 0000000000000000000000000000000000000000000000000000080000000800 - 000010000000520000009C0000009C0000009C0000009C000000730000004A00 - 0000180000000800000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007B7B7B006B6B6B006363 - 6300737373007373730073737300636363006B6B6B0073737300848484006B6B - 6B00636363006363630042424200000000000000000000000000000000000000 - 000084848400A5A5A500000000000000000000000000A5A5A500848484000000 - 0000000000000000000000000000000000000000000000000000000000000800 - 0000211818000000000018000000180000002100000021000000100000002108 - 0800080000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000094949400848484007B7B - 7B009C9C9C009C9C9C009C9C9C007B7B7B008C8C8C009C9C9C00A5A5A5008C8C - 8C007B7B7B007B7B7B005A5A5A00000000000000000000000000000000000000 - 0000A5A5A500A5A5A500000000000000000000000000A5A5A500A5A5A5000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000004A3939004A3939004A3939004A3939004A3939004A3939000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000006B6B6B00292929002121 - 2100181818001818180018181800181818001818180018181800181818001818 - 180018181800181818004A4A4A0000000000000000004A4A52004A4A52004A4A - 52004A4A52004A4A52004A4A52004A4A52004A4A52004A4A52004A4A52004A4A - 52004A4A52007B94940000000000000000000000000029292900212121001818 - 1800181818001818180018181800181818001818180018181800181818002929 - 2900292929002121210021212100000000000000000031528400315284000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000042424200FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00292929000000000000000000393939007B8C8C00849C - 94007B9494007B9494007B9494007B9494007B9494007B9494007B9494007B94 - 94007B9494007B9494000000000000000000393939007B9494007B9494006363 - 6300E7E7E700FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7E700D6D6D600E7E7 - E7005A5A5A007B9494007B9494002929290000000000849CB500315284000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000042424200FFFFFF00C6DE - DE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DE - DE00C6DEDE00FFFFFF00313131000000000000000000393939007B94940094AD - AD0094ADA50094ADA50094ADA50094ADA50094ADA50094ADA50094ADAD0094B5 - AD0094B5B5007B9494000000000000000000424242007B9494007B9494006B6B - 6B00FFFFFF00E7E7E700A5BDB500FFFFFF00FFFFFF00EFEFEF00E7E7E700E7E7 - E7006B6B6B007B9494007B9494002929290000000000849CB500315284000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004A4A4A00FFFFFF00BDDE - D600BDDED600BDDED600BDDED600BDDED600BDDED600BDDED600BDDED600BDDE - D600BDDED600FFFFFF00313131000000000000000000424242005A6363009CB5 - AD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD009CB5 - B5009CBDB500A5BDBD007B949400000000004A4A4A0094ADA5008CA5A5007B7B - 7B00FFFFFF005A736B008CA5A500FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7006B6B6B00849C9C00849C9C003939390000000000849CB500315284000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004A4A4A00FFFFFF00CEE7 - E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7 - E700CEE7E700FFFFFF003131310000000000000000004A4A4A005A5A5A0094B5 - AD00A5BDB500A5BDB500A5BDB500A5BDB500A5BDB500A5BDB500A5BDB500A5BD - B500A5BDBD00ADCEC6007B949400000000004A4A4A0094ADA5008CA5A5007B7B - 7B00FFFFFF005A736B008CA5A500FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7006B6B6B00849C9C00849C9C003939390000000000849CB500315284000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004A4A4A00FFFFFF00CEE7 - E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7 - E700CEE7E700FFFFFF00393939000000000000000000525252005A5A5A007B8C - 8C00ADC6C600A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BD - BD00ADC6C600BDD6CE007B94940000000000525252009CB5B5009CB5AD009C9C - 9C00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E7E7 - E7007B7B7B00849C9C00849C9C003939390000000000849CB500315284000000 - 0000000000000000000000000000000000000000520000005200000052000000 - 520000005200000052000000000000000000000000005A5A5A00FFFFFF00D6EF - E700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EF - E700D6EFE700FFFFFF004242420000000000000000005A5A5A005A5A5A00737B - 7B00B5CEC600ADC6BD00ADC6BD00ADC6BD00ADC6C600ADC6BD00ADC6BD00B5CE - C600B5CECE00BDDED6007B9494000000000052525200A5BDB500A5BDB500A5BD - B50094B5AD008CADA5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5 - A5008CA5A5008CA5A5008CA5A5004242420000000000849CB500315284000000 - 52000000520000005200000052000000520008008C0008008C0008008C000800 - 8C0000005200000000000000000000000000000000005A5A5A00FFFFFF00D6EF - E700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EF - E700D6EFE700FFFFFF00424242000000000000000000636363006B6B6B006363 - 6300A5B5B500BDD6D600BDD6D600B5D6CE00B5D6CE00B5CECE00B5CECE00B5CE - CE00B5D6CE00BDD6D600C6DEDE007B9494005A5A5A00A5C6BD008CA59C008CA5 - A500849C9C007B948C00738C8400738C8400738C8400738C8C00738C8C00738C - 8C00738C8C006B8484008CADA5004242420000000000849CB500315284000800 - 8C0008008C0008008C000800C6000800C60008008C000800A5000800A5000000 - 5200000000000000000000000000000000000000000063636300FFFFFF00D6EF - EF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EF - EF00D6EFEF00FFFFFF004A4A4A0000000000000000006B6B6B007B7373006B6B - 6B007B848400B5CECE00B5CECE00BDD6D600BDD6D600BDD6D600BDD6D600BDD6 - D600BDD6D600BDDED600CEE7DE007B9494005A5A5A00ADC6BD0094ADA500E7E7 - E700F7F7F700F7F7F700EFEFEF00EFEFEF00EFEFEF00EFEFEF00F7F7F700EFEF - EF00DEDEDE0073948C0094ADAD004A4A4A0000000000849CB500315284000800 - A5000800A5000800A50008008C000800C60008008C0008008C00000052000000 - 000000000000000000000000000000000000000000006B6B6B00FFFFFF00DEF7 - F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700CEEF - E700C6DEDE00DEDEDE0052525200000000000000000073737300847B7B007B7B - 7B006B6B6B007373730073737300737373006B736B00ADC6BD00CEE7E700C6DE - D600C6DED600C6DED600C6E7DE007B94940063636300ADC6C60094ADAD00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00F7F7F7007B94940094ADAD004A4A4A0000000000849CB500315284000800 - A5000800A50008008C000800C6000800C60008008C000800A500000052000000 - 000000000000000000000000000000000000000000006B6B6B00FFFFFF00DEF7 - F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700F7F7F700D6D6D600C6C6 - C600B5B5B5009C9C9C005252520000000000000000007B7B7B00848484008484 - 8400848484008484840084848400848484007B7B7B00848C8400D6EFE700DEF7 - F700DEF7F700DEF7F700E7F7F7007B9494006B6B6B00ADCEC6009CB5AD00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00F7F7F7007B9C94009CB5B5005252520000000000849CB500315284000800 - A5000800A5000800A50008008C000800C60008008C0008008C000800A5000000 - 520000000000000000000000000000000000000000006B6B6B00FFFFFF00DEF7 - F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700F7F7F700949494008C8C - 8C00737373005A5A5A005A5A5A000000000000000000848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008484840084848400848C - 8400848C8400848C840084848400000000007B7B7B00CEE7DE00A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF008CA5A500ADC6C6005A5A5A0000000000849CB500315284000800 - A5000800A50008008C000800C6000800C60008008C000800A5000800A5000800 - A50000005200000000000000000000000000000000006B6B6B00FFFFFF00E7FF - F700E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700F7F7F700A5A5A500FFFF - FF00FFFFFF00FFFFFF005A5A5A0000000000000000008C8C8C00949494008C94 - 8C008C94940094949400949494008C8C8C007B7B7B007B7B7B00737373007373 - 7300737373007373730000000000000000007B7B7B00D6EFE700A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0094ADAD00ADC6C6006363630000000000849CB500315284000800 - A5000800A5000800A50008008C000800C6000000520000005200000052000000 - 520000005200000052000000000000000000000000006B6B6B00FFFFFF00E7FF - F700E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700F7F7F700B5B5B500FFFF - FF00D6F7EF00B5D6CE006B6B6B000000000000000000949494009C9C9C009C9C - 9C009C9C9C009C9C9C009C9C9C00949494000000000000000000000000000000 - 0000000000000000000000000000000000007B7B7B00D6F7EF00A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF0094ADA500ADCEC6006B6B6B0000000000849CB500315284000000 - 5200000052000000520000005200000052000000000000000000000000000000 - 000000000000000000000000000000000000000000006B6B6B00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00CECECE00FFFF - FF00B5D6CE0073737300000000000000000000000000000000008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C00000000000000000000000000000000000000 - 00000000000000000000000000000000000084848400DEF7F700A5BDB500FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00F7F7F7009CB5AD00B5CECE007373730000000000849CB500849CB5000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000073737300737373007373 - 7300737373007B7B7B007B7B7B007B7B7B008484840084848400848484008484 - 8400848484000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000848484008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C0084848400000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000424D3E000000000000003E000000 - 2800000040000000900000000100010000000000800400000000000000000000 - 000000000000000000000000FFFFFF0000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000FC008001FFFF0000FC008001FFFF - 0000FC008001FFFF0000E0008000FFFF0000E000800018C70000E00080008C63 - 000000008000C631000000008000E318000000008000E318000000008001C631 - 0000000780018C6300000007800118C7000000078001FFFF0000003F8001FFFF - 0000003F8003FFFF0000003F8007FFFF000080018001FFFF000000000000FFFF - 000000000000F03F000000000000E00F000000000000C007000000000000C007 - 000000000000C007000000000000C003000000000000C003000000000000C003 - 000000000000C007000000000000C00F000000000000FFFF000000000000FFFF - 000000000000FFFF000080018001FFFFFFF9FFFFFFFF0000FFF0FFFFFFFF0000 - 0010FE7FFDFF00000001FE7FF8FF00000001FFFFF8FF00000000FE7FF27F0000 - 0000FE3FE27F00000001FF1FE73F00000003FFCFEF3F00000003FFCFFF8F0000 - 0003F98FFF830000C003F81FFFC30000C003FC3FFFF30000C003FFFFFFFF0000 - F803FFFFFFFF0000F803FFFFFFFF0000F000FC000000FC1FF000FC000000F007 - F000FC000000F007F000E0000000F0070000E0000000F0070000E0000000E003 - 000000000000800100000000000080010000000000008001000000000000C003 - 00000007000080010000000700000000000F000700000000000F003F00000000 - 000F003F00008001000F003F0000FC3FFFFF0007C0038001FC000007C0038001 - FC000007C003800100000007C003800100000007C003800100000007C0038001 - 00000007C003800100000000C003800100000000C003800100000000C0038001 - 00000000C003800000010000C003800000030000C0038000007F0000C0038001 - 00FFFF01C0038003FFFFFF03C0038007F81FFFFFFFFFFFFFE007FFFF8001E38F - C003FFFF8001C1078001C1FF8001CC678001C3FF8001EEEF0000C3FB8001E44F - 0000C1F98001F01F0000D0F18001FC7F0000F8038001F83F0000F8038001F83F - 0000FC078001F11F8001FE0F8001F11F8001FFFF8001F39FC003FFFF8001F39F - E007FFFF8001F39FF81FFFFFFFFFFFFF8001800380019FFF8001800300009FFF - 8001800300009FFF8001800100009FFF8001800100009FFF8001800100009F03 - 8001800100008007800180000000800F800180000000801F800180000000801F - 800180000000800F80018001000080078001800300008003800180FF000080FF - 8003C1FF00009FFF8007FFFF8001FFFF00000000000000000000000000000000 - 000000000000} + 9CFF3139ADFF000000003139ADFF10219CFF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00003139ADFF4A5AB5FF3139ADFF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000010219CFF3139ADFF10219CFF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000010219CFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000848484FF848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF848484FF848484FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF8B7C65FF737373FF7B7B7BFF86765EFFFFFFFFFF86765EFF8676 + 5EFFFFFFFFFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF8676 + 5EFF86765EFF86765EFF6B6B6BFF7B7B7BFF826F57FF826F57FF393939FF826F + 57FF826F57FF393939FF826F57FF826F57FF826F57FF826F57FF826F57FF826F + 57FF826F57FF826F57FF636363FF7B7B7BFF7E6950FF7E6950FF7E6950FF7E69 + 50FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E69 + 50FF7E6950FF7E6950FF5A5A5AFF6B6B6BFF7A644AFFFFFFFFFF7A644AFF7A64 + 4AFFFFFFFFFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A64 + 4AFF7A644AFF7A644AFF525252FF636363FF775F44FF775F44FF393939FF775F + 44FF775F44FF393939FF775F44FF775F44FF775F44FF775F44FF775F44FF775F + 44FF775F44FF775F44FF4A4A4AFF5A5A5AFF745B40FF745B40FF745B40FF745B + 40FF745B40FF745B40FFFFFFFFFF745B40FF745B40FF745B40FF745B40FF745B + 40FFFFFFFFFF745B40FF4A4A4AFF5A5A5AFF71573CFF71573CFF71573CFF7157 + 3CFF71573CFF71573CFF71573CFF393939FF71573CFF71573CFF71573CFF7157 + 3CFF71573CFF393939FF424242FF525252FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF424242FF525252FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF393939FF4A4A4AFF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF393939FF4A4A4AFF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF393939FF424242FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FFFFFFFFFF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FFFFFFFFFF6F5438FF292929FF393939FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF393939FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF393939FF292929FF292929FF292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF212121FF848484FF848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF848484FF848484FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF8B7C65FF737373FF7B7B7BFF86765EFF86765EFF86765EFF8676 + 5EFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF8676 + 5EFF86765EFF86765EFF6B6B6BFF7B7B7BFF826F57FF826F57FFFFFFFFFF826F + 57FF826F57FF826F57FFFFFFFFFF826F57FF826F57FF826F57FFFFFFFFFF826F + 57FF826F57FF826F57FF636363FF7B7B7BFF7E6950FF7E6950FF7E6950FF3939 + 39FF7E6950FF7E6950FF7E6950FF393939FF7E6950FF7E6950FF7E6950FF3939 + 39FF7E6950FF7E6950FF5A5A5AFF6B6B6BFF7A644AFF7A644AFF7A644AFF7A64 + 4AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A64 + 4AFF7A644AFF7A644AFF525252FF636363FF775F44FF775F44FF775F44FF775F + 44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F + 44FF775F44FF775F44FF4A4A4AFF5A5A5AFF745B40FF745B40FFFFFFFFFF745B + 40FF745B40FF745B40FFFFFFFFFF745B40FF745B40FF745B40FFFFFFFFFF745B + 40FF745B40FF745B40FF4A4A4AFF5A5A5AFF71573CFF71573CFF71573CFF3939 + 39FF71573CFF71573CFF71573CFF393939FF71573CFF71573CFF71573CFF3939 + 39FF71573CFF71573CFF424242FF525252FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF424242FF525252FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF393939FF4A4A4AFF6F5438FF6F5438FFFFFFFFFF6F54 + 38FF6F5438FF6F5438FFFFFFFFFF6F5438FF6F5438FF6F5438FFFFFFFFFF6F54 + 38FF6F5438FF6F5438FF393939FF4A4A4AFF6F5438FF6F5438FF6F5438FF3939 + 39FF6F5438FF6F5438FF6F5438FF393939FF6F5438FF6F5438FF6F5438FF3939 + 39FF6F5438FF6F5438FF393939FF424242FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF292929FF393939FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF292929FF292929FF292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF212121FF00000000848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF00000000848484FFDEF7F7FFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7 + F7FF9CB5ADFFB5CECEFF737373FF7B7B7BFFD6F7EFFFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFF8C8C8CFF6B6B6BFF6B6B6BFFDEDEDEFFFFFFFFFFFFFFFFFFFFFF + FFFF94ADA5FFADCEC6FF6B6B6BFF7B7B7BFFD6EFE7FFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFDEDEDEFF6B6B6BFFFFFFFFFFFFFFFFFFFFFF + FFFF94ADADFFADC6C6FF636363FF7B7B7BFFCEE7DEFFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF6B6B6BFF6B6B6BFFDEDEDEFFFFFFFFFFFFFFFFFFFFFF + FFFF8CA5A5FFADC6C6FF5A5A5AFF6B6B6BFFADCEC6FF9CB5ADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFDEDEDEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7 + F7FF7B9C94FF9CB5B5FF525252FF636363FFADC6C6FF94ADADFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF6B6B6BFF6B6B6BFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7 + F7FF7B9494FF94ADADFF4A4A4AFF5A5A5AFFADC6BDFF94ADA5FFE7E7E7FFF7F7 + F7FFF7F7F7FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFF7F7F7FFEFEFEFFFDEDE + DEFF73948CFF94ADADFF4A4A4AFF5A5A5AFFA5C6BDFF8CA59CFF8CA5A5FF849C + 9CFF7B948CFF738C84FF738C84FF738C84FF738C8CFF738C8CFF738C8CFF738C + 8CFF6B8484FF8CADA5FF424242FF525252FFA5BDB5FFA5BDB5FFA5BDB5FF94B5 + ADFF8CADA5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF424242FF525252FF9CB5B5FF9CB5ADFF9C9C9CFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF7B7B + 7BFF849C9CFF849C9CFF393939FF4A4A4AFF94ADA5FF8CA5A5FF7B7B7BFFFFFF + FFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF6B6B + 6BFF849C9CFF849C9CFF393939FF4A4A4AFF94ADA5FF8CA5A5FF7B7B7BFFFFFF + FFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF6B6B + 6BFF849C9CFF849C9CFF393939FF424242FF7B9494FF7B9494FF6B6B6BFFFFFF + FFFFE7E7E7FFA5BDB5FFFFFFFFFFFFFFFFFFEFEFEFFFE7E7E7FFE7E7E7FF6B6B + 6BFF7B9494FF7B9494FF292929FF393939FF7B9494FF7B9494FF636363FFE7E7 + E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FFD6D6D6FFE7E7E7FF5A5A + 5AFF7B9494FF7B9494FF292929FF00000000292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF0000000000000000848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF00000000848484FFDEF7F7FFA5BDB5FF212929FF2129 + 29FF212929FF212929FF212929FFFFFFFFFF212929FF212929FF212929FF2129 + 29FF9CB5ADFFB5CECEFF737373FF7B7B7BFFD6F7EFFFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF182118FF182118FF182118FFC6C6 + C6FF94ADA5FFADCEC6FF6B6B6BFF7B7B7BFFD6EFE7FFA5BDB5FF081810FF0818 + 10FF081810FF081810FF081810FF081810FF081810FF081810FF081810FF0818 + 10FF94ADADFFADC6C6FF636363FF7B7B7BFFCEE7DEFFA5BDB5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFFFFFFFF080808FF080808FFC6C6 + C6FF8CA5A5FFADC6C6FF5A5A5AFF6B6B6BFFADCEC6FF9CB5ADFFFFFFFFFFEF00 + 00FFEF0000FFEF0000FFEF0000FFEF0000FFFFFFFFFF000000FF000000FF0000 + 00FF7B9C94FF9CB5B5FF525252FF636363FFADC6C6FF94ADADFFFFFFFFFF8C00 + 00FF8C0000FF8C0000FF8C0000FF8C0000FFFFFFFFFF000000FF000000FFC6C6 + C6FF7B9494FF94ADADFF4A4A4AFF5A5A5AFFADC6BDFF94ADA5FFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF000000FF0000 + 00FF73948CFF94ADADFF4A4A4AFF5A5A5AFFA5C6BDFF8CA59CFF8CA5A5FF849C + 9CFF7B948CFF738C84FF738C84FF738C84FF738C8CFF738C8CFF738C8CFF738C + 8CFF6B8484FF8CADA5FF424242FF525252FFA5BDB5FFA5BDB5FFA5BDB5FF94B5 + ADFF8CADA5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF424242FF525252FF9CB5B5FF9CB5ADFF9C9C9CFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF7B7B + 7BFF849C9CFF849C9CFF393939FF4A4A4AFF94ADA5FF8CA5A5FF7B7B7BFFFFFF + FFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF6B6B + 6BFF849C9CFF849C9CFF393939FF4A4A4AFF94ADA5FF8CA5A5FF7B7B7BFFFFFF + FFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FF6B6B + 6BFF849C9CFF849C9CFF393939FF424242FF7B9494FF7B9494FF6B6B6BFFFFFF + FFFFE7E7E7FFA5BDB5FFFFFFFFFFFFFFFFFFEFEFEFFFE7E7E7FFE7E7E7FF6B6B + 6BFF7B9494FF7B9494FF292929FF393939FF7B9494FF7B9494FF636363FFE7E7 + E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7E7FFD6D6D6FFE7E7E7FF5A5A + 5AFF7B9494FF7B9494FF292929FF00000000292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000C6CED6FFBDC6C6FF8484 + 8CFF737B7BFF525252FF525252FF525252FF6B7373FF848C8CFFBDBDC6FF0000 + 00000000000000000000000000000000000000000000949C9CFF4A4A4AFF737B + 7BFF737B7BFF949C9CFF94949CFF94949CFF7B8484FF6B6B73FF525252FFA5A5 + ADFF00000000000000000000000000000000000000004A5252FF84848CFF7373 + 7BFF42424AFF101010FF181818FF101010FF525252FF5A6363FF8C8C94FF4242 + 42FF949C9CFF00000000000000000000000000000000949C9CFF212121FF0000 + 00FF000000FF292929FF080808FF000000FF000000FF393939FF212929FF7B84 + 84FF8C8C8CFF000000000000000000000000000000005A5A63FF848C8CFF0000 + 00FF424242FFC6CECEFF000000FF000000FF000000FF84848CFF313939FF2931 + 31FFB5BDBDFF000000000000000000000000000000009CA5ADFF9CA5ADFF2129 + 29FF000000FF000000FF000000FF000000FF000000FF94949CFF848C8CFF1821 + 21FF0000000000000000000000000000000000000000C6CECEFFADB5BDFFC6CE + D6FF394242FF000000FF000000FF181818FFADB5B5FFADB5B5FF101010FF7B7B + 84FF0000000000000000000000000000000000000000C6CED6FF292929FF636B + 6BFF9C9CA5FFADB5B5FFADB5B5FFBDC6C6FF737B7BFF181818FF848C8CFFC6CE + D6FF000000000000000000000000000000000000000000000000BDC6C6FF848C + 8CFF424242FF393939FF393939FF394242FF7B8484FFBDC6CEFFC6CED6FF0000 + 000000000000000000000000000000000000000000000000000000000000C6CE + D6FFADB5B5FFADB5B5FFADB5B5FFADB5B5FFC6CED6FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000848484FF848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF848484FF848484FF525A5AFF4A5A52FF525A5AFF525A + 5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A + 5AFF4A5A52FF4A5A52FF737373FF7B7B7BFF292931FF292931FF292931FF2929 + 31FF292931FF292931FF292931FF292931FF292931FF292931FF292931FF2929 + 31FF292931FF292931FF6B6B6BFF7B7B7BFF212929FF212929FF212929FF2129 + 29FF212929FF212929FF212929FF212929FF212929FF212929FF212929FF2129 + 29FF5252ADFF5252ADFF636363FF7B7B7BFF182121FF182121FF182121FF1821 + 21FF182121FF182121FF182121FF4A4AADFF182121FF182121FF182121FF1821 + 21FF182121FF182121FF5A5A5AFF6B6B6BFF3939ADFF3939ADFF3939ADFF3939 + ADFF3939ADFF3939ADFF3939ADFF3939ADFF101810FF101810FF101810FF1018 + 10FF101810FF101810FF525252FF636363FF081008FF081008FF081008FF0810 + 08FF081008FF081008FF081008FF081008FF081008FF081008FF081008FF0810 + 08FF2929ADFF2929ADFF4A4A4AFF5A5A5AFF000808FF000808FF000808FF0008 + 08FF000808FF000808FF000808FF000808FF000808FF000808FF000808FF0008 + 08FF000808FF000808FF4A4A4AFF5A5A5AFF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0000 + 00FF000000FF000000FF424242FF525252FF0000ADFF0000ADFF0000ADFF0000 + ADFF0000ADFF0000ADFF0000ADFF0000ADFF0000ADFF0000ADFF080808FF0000 + 00FF0000ADFF0000ADFF424242FF525252FF0000A5FF0000A5FF0000A5FF0000 + 9CFF00009CFF00009CFF0000A5FF0000A5FF0000A5FF0000A5FF000000FF0000 + 00FF000000FF000000FF393939FF4A4A4AFF000094FF000094FF000094FF0000 + 94FF000094FF000094FF000094FF000094FF000094FF000094FF000000FF0000 + 00FF000000FF000000FF393939FF4A4A4AFF000084FF000084FF000084FF0000 + 84FF000084FF000084FF000084FF000084FF000084FF000084FF000000FF0000 + 00FF000084FF000084FF393939FF424242FF000073FF000073FF000073FF0000 + 73FF000073FF000073FF000073FF000073FF000073FF000073FF000000FF0000 + 00FF000000FF000000FF292929FF393939FF000063FF000063FF000063FF0000 + 63FF00006BFF000063FF000063FF000063FF00006BFF000063FF000000FF0000 + 00FF000000FF000000FF292929FF292929FF292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF212121FF425A52FF425A52FF425A52FF425A52FF425A + 52FF425A52FF425A52FF425A52FF425A52FF39524AFF00000000000000000000 + 0000000000000000000000000000425A52FF39524AFF39524AFF39524AFF3952 + 4AFF39524AFF39524AFF39524AFF39524AFF294239FF00000000000000000000 + 0000000000000000000000000000425A52FF39524AFF39524AFF39524AFF3952 + 4AFF39524AFF39524AFF39524AFF39524AFF294239FF00000000000000000000 + 0000000000000000000000000000425A52FF39524AFF39524AFF5A736BFF5A73 + 6BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF4263 + 5AFF000000000000000000000000425A52FF39524AFF39524AFF5A736BFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF294A + 4AFF000000000000000000000000425A52FF39524AFF39524AFF5A736BFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF294A + 4AFF000000000000000000000000425A52FF39524AFF39524AFF5A736BFF4263 + 5AFF42635AFF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5A + B5FF4A5AB5FF4A5AB5FF3139ADFF425A52FF39524AFF39524AFF5A736BFF4263 + 5AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF425A52FF39524AFF39524AFF5A736BFF4263 + 5AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF39524AFF294239FF294239FF5A736BFF4263 + 5AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF0000000000000000000000005A736BFF4263 + 5AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF0000000000000000000000005A736BFF4263 + 5AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF00000000000000000000000042635AFF294A + 4AFF294A4AFF4A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF000000000000000000000000000000000000 + 0000000000004A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF000000000000000000000000000000000000 + 0000000000004A5AB5FF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF10219CFF000000000000000000000000000000000000 + 0000000000003139ADFF10219CFF10219CFF10219CFF10219CFF10219CFF1021 + 9CFF10219CFF10219CFF10219CFF00000000737373FF737373FF737373FF7373 + 73FF7B7B7BFF7B7B7BFF7B7B7BFF848484FF848484FF848484FF848484FF8484 + 84FF000000000000000000000000000000006B6B6BFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCECECEFFFFFFFFFFB5D6 + CEFF737373FF0000000000000000000000006B6B6BFFFFFFFFFFE7FFF7FFE7FF + F7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7F7FFB5B5B5FFFFFFFFFFD6F7 + EFFFB5D6CEFF6B6B6BFF00000000000000006B6B6BFFFFFFFFFFE5FEF6FFE5FD + F6FFE5FDF6FFE5FEF6FFE6FEF6FFE5FDF6FFF7F7F7FFA5A5A5FFFFFFFFFFFFFF + FFFFFFFFFFFF5A5A5AFF00000000000000006B6B6BFFFFFFFFFFE3FBF4FFE3FB + F4FFE3FBF3FFE3FBF4FFE3FCF4FFE3FBF4FFF7F7F7FF949494FF8C8C8CFF7373 + 73FF5A5A5AFF5A5A5AFF00000000000000006B6B6BFFFFFFFFFFE0F9F2FFE1F9 + F2FFE0F8F2FFE0F8F2FFE0F8F2FFE1F9F2FFF7F7F7FFD6D6D6FFC6C6C6FFB5B5 + B5FF9C9C9CFF525252FF00000000000000006B6B6BFFFFFFFFFFDEF6F0FFDEF6 + F0FFDDF5F0FFDDF5EFFFDDF5F0FFBD4242FFDDF5EFFFDDF5F0FFDEF5F0FFC6DE + DEFFDEDEDEFF525252FF0000000000000000636363FFFFFFFFFFDAF2EDFFDAF2 + EDFFDAF2EDFFDAF2EDFFBD4242FFBD4242FFBD4242FFBD4242FFBD4242FFBD42 + 42FFBD4242FFBD4242FFBD4242FF000000005A5A5AFFFFFFFFFFD7EEEAFFD7EE + EBFFD6EEEBFFB23E3EFFB23E3EFFB23E3EFFB23E3EFFB33F3FFFB23E3EFFB23E + 3EFFB23E3EFFB23E3EFFB23E3EFF000000005A5A5AFFFFFFFFFFD3EBE8FFD3EB + E8FFA33939FFA33939FFA33939FFA33939FFA33939FFA33939FFA33939FFA339 + 39FFA33939FFA33939FFA33939FF000000004A4A4AFFFFFFFFFFD0E8E5FFD0E8 + E6FFCFE8E5FF923333FF923333FF923333FF923333FF923333FF923333FF9233 + 33FF923333FF923333FF923333FF000000004A4A4AFFFFFFFFFFCDE5E3FFCCE5 + E3FFCDE5E3FFB5B5B5FF812D2DFF812D2DFF812D2DFF812D2DFF812D2DFF812D + 2DFF812D2DFF812D2DFF812D2DFF000000004A4A4AFFFFFFFFFFCAE2E1FFCAE2 + E1FFCAE2E1FFCAE2E1FFB5B5B5FF722828FFB5B5B5FFB5B5B5FFB5B5B5FFB5B5 + B5FFB5B5B5FF181818FFB5B5B5FF00000000424242FFFFFFFFFFC8E0E0FFC8E0 + DFFFC8E0E0FFC8E0E0FFC8E0DFFFB5B5B5FFC8DFDFFFC7DFDFFFC8DFE0FFC8E0 + DFFFFFFFFFFF313131FF0000000000000000424242FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF292929FF00000000000000006B6B6BFF292929FF212121FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF4A4A4AFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000687F7FFF798D8DFF879999FF000000000000 + 0000687F7FFF798D8DFF879999FF0000000000000000687F7FFF798D8DFF8799 + 99FF00000000000000000000000000000000425454FF5A7373FF788C8CFF0000 + 000000000000425454FF5A7373FF788C8CFF0000000000000000425454FF5A73 + 73FF788C8CFF00000000000000000000000000000000425454FF5A7373FF788C + 8CFF0000000000000000425454FF5A7373FF788C8CFF00000000000000004254 + 54FF5A7373FF788C8CFF00000000000000000000000000000000425454FF5A73 + 73FF788C8CFF0000000000000000425454FF5A7373FF788C8CFF000000000000 + 0000425454FF5A7373FF788C8CFF000000000000000000000000788C8CFF5A73 + 73FF425454FF0000000000000000788C8CFF5A7373FF425454FF000000000000 + 0000788C8CFF5A7373FF425454FF0000000000000000788C8CFF5A7373FF4254 + 54FF0000000000000000788C8CFF5A7373FF425454FF0000000000000000788C + 8CFF5A7373FF425454FF0000000000000000788C8CFF5A7373FF425454FF0000 + 000000000000788C8CFF5A7373FF425454FF0000000000000000788C8CFF5A73 + 73FF425454FF00000000000000004E6363FF425555FF364545FF000000000000 + 00004E6363FF425555FF364545FF00000000000000004E6363FF425555FF3645 + 45FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000008C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF737373FFFFFFFFFFD3D3D3FFD3D3D3FFD3D3 + D3FFFFFFFFFFA2A2A2FFBBBBBBFF949494FF949494FFBBBBBBFFA2A2A2FFFFFF + FFFFFFFFFFFFFFFFFFFF737373FF6B6B6BFFFFFFFFFFE9E9E9FFE9E9E9FFFFFF + FFFFFFFFFFFFD3D3D3FFD3D3D3FFFFFFFFFFFFFFFFFFD3D3D3FFD3D3D3FFFFFF + FFFFFFFFFFFFFFFFFFFF6B6B6BFF636363FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF636363FF5A5A5AFFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFF5A5A5AFF525252FFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFF525252FF4A4A4AFFC2975CFFCEAD82FFD6BB99FFC297 + 5CFFC2975CFFE1CEB7FFC2975CFFCEAD82FFCEAD82FFC2975CFFE1CEB7FFE1CE + B7FFDAC2A3FFC2975CFF4A4A4AFF4A4A4AFFC2975CFFD2B48EFFF4EDE5FFC69E + 6AFFDAC2A3FFE5D5C1FFC2975CFFDEC8AEFFE1CEB7FFC2975CFFE1CEB7FFC297 + 5CFFE5D5C1FFC2975CFF4A4A4AFF424242FFC2975CFFD2B48EFFD6BB99FFE9DB + CAFFDEC8AEFFE1CEB7FFC2975CFFE1CEB7FFE1CEB7FFC2975CFFE9DBCAFFE1CE + B7FFE1CEB7FFC2975CFF424242FF424242FFC2975CFFD2B48EFFD2B48EFFD2B4 + 8EFFC2975CFFE1CEB7FFDAC2A3FFE5D5C1FFE5D5C1FFDAC2A3FFE1CEB7FFC297 + 5CFFC2975CFFC2975CFF424242FF393939FFC2975CFFCAA676FFCAA676FFC297 + 5CFFC2975CFFD2B48EFFD2B48EFFC2975CFFC2975CFFD2B48EFFD2B48EFFC297 + 5CFFC2975CFFC2975CFF393939FF393939FFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFF393939FF393939FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF393939FF292929FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFF292929FF292929FFFFFFFFFFDEDEDEFFC7C7C7FFFFFF + FFFFFFFFFFFFA2A2A2FFFFFFFFFFDEDEDEFFDEDEDEFFFFFFFFFFA2A2A2FFA2A2 + A2FFBBBBBBFFFFFFFFFF292929FF292929FF292929FF292929FF292929FF2929 + 29FF292929FF292929FF292929FF292929FF292929FF292929FF292929FF2929 + 29FF292929FF292929FF292929FF848484FF848484FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF848484FF848484FF848484FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF413C34FF8B7C + 65FF8B7C65FF8B7C65FF737373FF7B7B7BFF86765EFF86765EFF86765EFF8676 + 5EFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF403A31FF8676 + 5EFF86765EFF86765EFF6B6B6BFF7B7B7BFF826F57FF826F57FF826F57FF826F + 57FF826F57FF826F57FF826F57FF826F57FF826F57FF826F57FF3E372FFF826F + 57FF826F57FF826F57FF636363FF7B7B7BFF7E6950FF7E6950FF7E6950FF7E69 + 50FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF3D352CFF7E69 + 50FF7E6950FF7E6950FF5A5A5AFF6B6B6BFF7A644AFF7A644AFF7A644AFF7A64 + 4AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF3B332AFF7A64 + 4AFF7A644AFF7A644AFF525252FF636363FF775F44FF775F44FF775F44FF775F + 44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F44FF3A3228FF775F + 44FF775F44FF775F44FF4A4A4AFF5A5A5AFF745B40FF745B40FF745B40FF745B + 40FF745B40FF745B40FF745B40FF745B40FF745B40FF745B40FF393026FF745B + 40FF745B40FF745B40FF4A4A4AFF5A5A5AFF71573CFF71573CFF71573CFF7157 + 3CFF71573CFF71573CFF71573CFF71573CFF71573CFF71573CFF382F25FF7157 + 3CFF71573CFF71573CFF424242FF525252FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF372E24FF6F54 + 38FF6F5438FF6F5438FF424242FF525252FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF372E24FF6F54 + 38FF6F5438FF6F5438FF393939FF4A4A4AFF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF372E24FF6F54 + 38FF6F5438FF6F5438FF393939FF4A4A4AFF372E24FF372E24FF372E24FF372E + 24FF372E24FF372E24FF372E24FF372E24FF372E24FF372E24FF372E24FF6F54 + 38FF6F5438FF6F5438FF393939FF424242FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF292929FF393939FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF292929FF292929FF292929FF212121FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF292929FF2929 + 29FF212121FF212121FF212121FF + } end object SaveDialog: TSaveDialog - DefaultExt = 'wad' + DefaultExt = '.wad' Filter = 'Карты Doom 2D: Forever (*.wad)|*.wad|Все файлы (*.*)|*.*' Options = [ofHideReadOnly, ofNoChangeDir, ofPathMustExist, ofNoReadOnlyReturn, ofEnableSizing, ofDontAddToRecent] - Left = 64 - Top = 64 + left = 64 + top = 64 end object MainMenu: TMainMenu Images = ImageList - Left = 96 - Top = 64 + left = 96 + top = 64 object miMenuFile: TMenuItem Caption = 'Файл' object miNewMap: TMenuItem Caption = 'Новая карта' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000006B6B + 6BFF292929FF212121FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF4A4A4AFF00000000000000004242 + 42FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF292929FF00000000000000004242 + 42FFFFFFFFFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFFC6DEDEFFC6DEDEFFC6DEDEFFFFFFFFFF313131FF00000000000000004A4A + 4AFFFFFFFFFFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDE + D6FFBDDED6FFBDDED6FFBDDED6FFFFFFFFFF313131FF00000000000000004A4A + 4AFFFFFFFFFFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FFCEE7E7FFFFFFFFFF313131FF00000000000000004A4A + 4AFFFFFFFFFFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FFCEE7E7FFFFFFFFFF393939FF00000000000000005A5A + 5AFFFFFFFFFFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EF + E7FFD6EFE7FFD6EFE7FFD6EFE7FFFFFFFFFF424242FF00000000000000005A5A + 5AFFFFFFFFFFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EF + E7FFD6EFE7FFD6EFE7FFD6EFE7FFFFFFFFFF424242FF00000000000000006363 + 63FFFFFFFFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EF + EFFFD6EFEFFFD6EFEFFFD6EFEFFFFFFFFFFF4A4A4AFF00000000000000006B6B + 6BFFFFFFFFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FFDEF7F7FFCEEFE7FFC6DEDEFFDEDEDEFF525252FF00000000000000006B6B + 6BFFFFFFFFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFF7F7 + F7FFD6D6D6FFC6C6C6FFB5B5B5FF9C9C9CFF525252FF00000000000000006B6B + 6BFFFFFFFFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFF7F7 + F7FF949494FF8C8C8CFF737373FF5A5A5AFF5A5A5AFF00000000000000006B6B + 6BFFFFFFFFFFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7 + F7FFA5A5A5FFFFFFFFFFFFFFFFFFFFFFFFFF5A5A5AFF00000000000000006B6B + 6BFFFFFFFFFFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7 + F7FFB5B5B5FFFFFFFFFFD6F7EFFFB5D6CEFF6B6B6BFF00000000000000006B6B + 6BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFCECECEFFFFFFFFFFB5D6CEFF737373FF0000000000000000000000007373 + 73FF737373FF737373FF737373FF7B7B7BFF7B7B7BFF7B7B7BFF848484FF8484 + 84FF848484FF848484FF848484FF000000000000000000000000 + } ImageIndex = 0 ShortCut = 16462 OnClick = aNewMapExecute end object miOpenMap: TMenuItem Caption = 'Открыть карту' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000004A4A + 52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A52FF4A4A + 52FF4A4A52FF4A4A52FF4A4A52FF7B9494FF0000000000000000000000003939 + 39FF7B8C8CFF849C94FF7B9494FF7B9494FF7B9494FF7B9494FF7B9494FF7B94 + 94FF7B9494FF7B9494FF7B9494FF7B9494FF0000000000000000000000003939 + 39FF7B9494FF94ADADFF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94AD + A5FF94ADADFF94B5ADFF94B5B5FF7B9494FF0000000000000000000000004242 + 42FF5A6363FF9CB5ADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94AD + ADFF94ADADFF9CB5B5FF9CBDB5FFA5BDBDFF7B9494FF00000000000000004A4A + 4AFF5A5A5AFF94B5ADFFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BD + B5FFA5BDB5FFA5BDB5FFA5BDBDFFADCEC6FF7B9494FF00000000000000005252 + 52FF5A5A5AFF7B8C8CFFADC6C6FFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BD + BDFFA5BDBDFFA5BDBDFFADC6C6FFBDD6CEFF7B9494FF00000000000000005A5A + 5AFF5A5A5AFF737B7BFFB5CEC6FFADC6BDFFADC6BDFFADC6BDFFADC6C6FFADC6 + BDFFADC6BDFFB5CEC6FFB5CECEFFBDDED6FF7B9494FF00000000000000006363 + 63FF6B6B6BFF636363FFA5B5B5FFBDD6D6FFBDD6D6FFB5D6CEFFB5D6CEFFB5CE + CEFFB5CECEFFB5CECEFFB5D6CEFFBDD6D6FFC6DEDEFF7B9494FF000000006B6B + 6BFF7B7373FF6B6B6BFF7B8484FFB5CECEFFB5CECEFFBDD6D6FFBDD6D6FFBDD6 + D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDDED6FFCEE7DEFF7B9494FF000000007373 + 73FF847B7BFF7B7B7BFF6B6B6BFF737373FF737373FF737373FF6B736BFFADC6 + BDFFCEE7E7FFC6DED6FFC6DED6FFC6DED6FFC6E7DEFF7B9494FF000000007B7B + 7BFF848484FF848484FF848484FF848484FF848484FF848484FF7B7B7BFF848C + 84FFD6EFE7FFDEF7F7FFDEF7F7FFDEF7F7FFE7F7F7FF7B9494FF000000008484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8484 + 84FF848484FF848C84FF848C84FF848C84FF848484FF00000000000000008C8C + 8CFF949494FF8C948CFF8C9494FF949494FF949494FF8C8C8CFF7B7B7BFF7B7B + 7BFF737373FF737373FF737373FF737373FF0000000000000000000000009494 + 94FF9C9C9CFF9C9C9CFF9C9C9CFF9C9C9CFF9C9C9CFF949494FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00008C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 1 ShortCut = 16463 OnClick = aOpenMapExecute end object miSaveMap: TMenuItem Caption = 'Сохранить карту' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000002929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF00000000393939FF7B94 + 94FF7B9494FF636363FFE7E7E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7 + E7FFD6D6D6FFE7E7E7FF5A5A5AFF7B9494FF7B9494FF292929FF424242FF7B94 + 94FF7B9494FF6B6B6BFFFFFFFFFFE7E7E7FFA5BDB5FFFFFFFFFFFFFFFFFFEFEF + EFFFE7E7E7FFE7E7E7FF6B6B6BFF7B9494FF7B9494FF292929FF4A4A4AFF94AD + A5FF8CA5A5FF7B7B7BFFFFFFFFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF6B6B6BFF849C9CFF849C9CFF393939FF4A4A4AFF94AD + A5FF8CA5A5FF7B7B7BFFFFFFFFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF6B6B6BFF849C9CFF849C9CFF393939FF525252FF9CB5 + B5FF9CB5ADFF9C9C9CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF7B7B7BFF849C9CFF849C9CFF393939FF525252FFA5BD + B5FFA5BDB5FFA5BDB5FF94B5ADFF8CADA5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF424242FF5A5A5AFFA5C6 + BDFF8CA59CFF8CA5A5FF849C9CFF7B948CFF738C84FF738C84FF738C84FF738C + 8CFF738C8CFF738C8CFF738C8CFF6B8484FF8CADA5FF424242FF5A5A5AFFADC6 + BDFF94ADA5FFE7E7E7FFF7F7F7FFF7F7F7FFEFEFEFFFEFEFEFFFEFEFEFFFEFEF + EFFFF7F7F7FFEFEFEFFFDEDEDEFF73948CFF94ADADFF4A4A4AFF636363FFADC6 + C6FF94ADADFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFF7F7F7FF7B9494FF94ADADFF4A4A4AFF6B6B6BFFADCE + C6FF9CB5ADFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFF7F7F7FF7B9C94FF9CB5B5FF525252FF7B7B7BFFCEE7 + DEFFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFF8CA5A5FFADC6C6FF5A5A5AFF7B7B7BFFD6EF + E7FFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFF94ADADFFADC6C6FF636363FF7B7B7BFFD6F7 + EFFFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFF94ADA5FFADCEC6FF6B6B6BFF848484FFDEF7 + F7FFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFF7F7F7FF9CB5ADFFB5CECEFF737373FF000000008484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF00000000 + } ImageIndex = 2 ShortCut = 16467 OnClick = aSaveMapExecute end object miSaveMapAs: TMenuItem Caption = 'Сохранить карту как...' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000002929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF00000000393939FF7B94 + 94FF7B9494FF636363FFE7E7E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7 + E7FFD6D6D6FFE7E7E7FF5A5A5AFF7B9494FF7B9494FF292929FF424242FF7B94 + 94FF7B9494FF6B6B6BFFFFFFFFFFE7E7E7FFA5BDB5FFFFFFFFFFFFFFFFFFEFEF + EFFFE7E7E7FFE7E7E7FF6B6B6BFF7B9494FF7B9494FF292929FF4A4A4AFF94AD + A5FF8CA5A5FF7B7B7BFFFFFFFFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF6B6B6BFF849C9CFF849C9CFF393939FF4A4A4AFF94AD + A5FF8CA5A5FF7B7B7BFFFFFFFFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF6B6B6BFF849C9CFF849C9CFF393939FF525252FF9CB5 + B5FF9CB5ADFF9C9C9CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF7B7B7BFF849C9CFF849C9CFF393939FF525252FFA5BD + B5FFA5BDB5FFA5BDB5FF94B5ADFF8CADA5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF424242FF5A5A5AFFA5C6 + BDFF8CA59CFF8CA5A5FF849C9CFF7B948CFF738C84FF738C84FF738C84FF738C + 8CFF738C8CFF738C8CFF738C8CFF6B8484FF8CADA5FF424242FF5A5A5AFFADC6 + BDFF94ADA5FFE7E7E7FFF7F7F7FFF7F7F7FFEFEFEFFFEFEFEFFFEFEFEFFFEFEF + EFFFF7F7F7FFEFEFEFFFDEDEDEFF73948CFF94ADADFF4A4A4AFF636363FFADC6 + C6FF94ADADFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B6B6BFF6B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFFF7F7F7FF7B9494FF94ADADFF4A4A4AFF6B6B6BFFADCE + C6FF9CB5ADFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDEDEDEFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFF7F7F7FF7B9C94FF9CB5B5FF525252FF7B7B7BFFCEE7 + DEFFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B6B6BFF6B6B6BFFDEDE + DEFFFFFFFFFFFFFFFFFFFFFFFFFF8CA5A5FFADC6C6FF5A5A5AFF7B7B7BFFD6EF + E7FFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDEDEDEFF6B6B + 6BFFFFFFFFFFFFFFFFFFFFFFFFFF94ADADFFADC6C6FF636363FF7B7B7BFFD6F7 + EFFFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFF8C8C8CFF6B6B6BFF6B6B6BFFDEDE + DEFFFFFFFFFFFFFFFFFFFFFFFFFF94ADA5FFADCEC6FF6B6B6BFF848484FFDEF7 + F7FFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFF7F7F7FF9CB5ADFFB5CECEFF737373FF000000008484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF00000000 + } ImageIndex = 21 OnClick = aSaveMapAsExecute end object miOpenWadMap: TMenuItem Caption = 'Выбрать карту' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF292929FF292929FF292929FF292929FF292929FF292929FF292929FF2929 + 29FF292929FF292929FF292929FF292929FF292929FF292929FF292929FFFFFF + FFFFDEDEDEFFC7C7C7FFFFFFFFFFFFFFFFFFA2A2A2FFFFFFFFFFDEDEDEFFDEDE + DEFFFFFFFFFFA2A2A2FFA2A2A2FFBBBBBBFFFFFFFFFF292929FF292929FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF292929FF393939FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF393939FF393939FFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFF393939FF393939FFC297 + 5CFFCAA676FFCAA676FFC2975CFFC2975CFFD2B48EFFD2B48EFFC2975CFFC297 + 5CFFD2B48EFFD2B48EFFC2975CFFC2975CFFC2975CFF393939FF424242FFC297 + 5CFFD2B48EFFD2B48EFFD2B48EFFC2975CFFE1CEB7FFDAC2A3FFE5D5C1FFE5D5 + C1FFDAC2A3FFE1CEB7FFC2975CFFC2975CFFC2975CFF424242FF424242FFC297 + 5CFFD2B48EFFD6BB99FFE9DBCAFFDEC8AEFFE1CEB7FFC2975CFFE1CEB7FFE1CE + B7FFC2975CFFE9DBCAFFE1CEB7FFE1CEB7FFC2975CFF424242FF4A4A4AFFC297 + 5CFFD2B48EFFF4EDE5FFC69E6AFFDAC2A3FFE5D5C1FFC2975CFFDEC8AEFFE1CE + B7FFC2975CFFE1CEB7FFC2975CFFE5D5C1FFC2975CFF4A4A4AFF4A4A4AFFC297 + 5CFFCEAD82FFD6BB99FFC2975CFFC2975CFFE1CEB7FFC2975CFFCEAD82FFCEAD + 82FFC2975CFFE1CEB7FFE1CEB7FFDAC2A3FFC2975CFF4A4A4AFF525252FFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFF525252FF5A5A5AFFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFFC297 + 5CFFC2975CFFC2975CFFC2975CFFC2975CFFC2975CFF5A5A5AFF636363FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF636363FF6B6B6BFFFFFF + FFFFE9E9E9FFE9E9E9FFFFFFFFFFFFFFFFFFD3D3D3FFD3D3D3FFFFFFFFFFFFFF + FFFFD3D3D3FFD3D3D3FFFFFFFFFFFFFFFFFFFFFFFFFF6B6B6BFF737373FFFFFF + FFFFD3D3D3FFD3D3D3FFD3D3D3FFFFFFFFFFA2A2A2FFBBBBBBFF949494FF9494 + 94FFBBBBBBFFA2A2A2FFFFFFFFFFFFFFFFFFFFFFFFFF737373FF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF + } ImageIndex = 28 OnClick = miOpenWadMapClick end @@ -1939,16 +1938,124 @@ object MainForm: TMainForm end object miSaveMiniMap: TMenuItem Caption = 'Сохранить мини-карту' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000002929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF00000000393939FF7B94 + 94FF7B9494FF636363FFE7E7E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7E7 + E7FFD6D6D6FFE7E7E7FF5A5A5AFF7B9494FF7B9494FF292929FF424242FF7B94 + 94FF7B9494FF6B6B6BFFFFFFFFFFE7E7E7FFA5BDB5FFFFFFFFFFFFFFFFFFEFEF + EFFFE7E7E7FFE7E7E7FF6B6B6BFF7B9494FF7B9494FF292929FF4A4A4AFF94AD + A5FF8CA5A5FF7B7B7BFFFFFFFFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF6B6B6BFF849C9CFF849C9CFF393939FF4A4A4AFF94AD + A5FF8CA5A5FF7B7B7BFFFFFFFFFF5A736BFF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF6B6B6BFF849C9CFF849C9CFF393939FF525252FF9CB5 + B5FF9CB5ADFF9C9C9CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFE7E7E7FF7B7B7BFF849C9CFF849C9CFF393939FF525252FFA5BD + B5FFA5BDB5FFA5BDB5FF94B5ADFF8CADA5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF424242FF5A5A5AFFA5C6 + BDFF8CA59CFF8CA5A5FF849C9CFF7B948CFF738C84FF738C84FF738C84FF738C + 8CFF738C8CFF738C8CFF738C8CFF6B8484FF8CADA5FF424242FF5A5A5AFFADC6 + BDFF94ADA5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFF000000FF000000FF000000FF73948CFF94ADADFF4A4A4AFF636363FFADC6 + C6FF94ADADFFFFFFFFFF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FFFFFF + FFFF000000FF000000FFC6C6C6FF7B9494FF94ADADFF4A4A4AFF6B6B6BFFADCE + C6FF9CB5ADFFFFFFFFFFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFFFFF + FFFF000000FF000000FF000000FF7B9C94FF9CB5B5FF525252FF7B7B7BFFCEE7 + DEFFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFFFF + FFFF080808FF080808FFC6C6C6FF8CA5A5FFADC6C6FF5A5A5AFF7B7B7BFFD6EF + E7FFA5BDB5FF081810FF081810FF081810FF081810FF081810FF081810FF0818 + 10FF081810FF081810FF081810FF94ADADFFADC6C6FF636363FF7B7B7BFFD6F7 + EFFFA5BDB5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1821 + 18FF182118FF182118FFC6C6C6FF94ADA5FFADCEC6FF6B6B6BFF848484FFDEF7 + F7FFA5BDB5FF212929FF212929FF212929FF212929FF212929FFFFFFFFFF2129 + 29FF212929FF212929FF212929FF9CB5ADFFB5CECEFF737373FF000000008484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF00000000 + } ImageIndex = 22 OnClick = miSaveMiniMapClick end object miDeleteMap: TMenuItem Caption = 'Удалить карту из WAD...' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000006B6B + 6BFF292929FF212121FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF181818FF181818FF4A4AFFFF4A4AFFFF00000000000000004242 + 42FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFB5B5B5FF4A4AFFFF4A4AFFFF292929FF00000000000000004242 + 42FFFFFFFFFFC6DEDEFFC6DEDEFFB5B5B5FFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFFB5B5B5FF4A4AFFFF4A4AFFFFFFFFFFFF313131FF00000000000000004A4A + 4AFFFFFFFFFFBDDED6FFBDDED6FF4A4AFFFFB5B5B5FFB5B5B5FFBDDED6FFB5B5 + B5FF4A4AFFFF4A4AFFFFBDDED6FFFFFFFFFF313131FF00000000000000004A4A + 4AFFFFFFFFFFCEE7E7FFCEE7E7FFCEE7E7FF4A4AFFFF4A4AFFFFB5B5B5FF4A4A + FFFF4A4AFFFFCEE7E7FFCEE7E7FFFFFFFFFF313131FF00000000000000004A4A + 4AFFFFFFFFFFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FF4A4AFFFF4A4AFFFF4A4A + FFFFB5B5B5FFCEE7E7FFCEE7E7FFFFFFFFFF393939FF00000000000000005A5A + 5AFFFFFFFFFFD6EFE7FFD6EFE7FFD6EFE7FFB5B5B5FF4A4AFFFF4A4AFFFF4A4A + FFFF4A4AFFFFB5B5B5FFB5B5B5FFFFFFFFFF424242FF00000000000000005A5A + 5AFFFFFFFFFFD6EFE7FFD6EFE7FFD6EFE7FF4A4AFFFF4A4AFFFF4A4AFFFFD6EF + E7FF4A4AFFFF4A4AFFFF4A4AFFFFB5B5B5FF424242FF00000000000000006363 + 63FFFFFFFFFFD6EFEFFFD6EFEFFFB5B5B5FF4A4AFFFF4A4AFFFFD6EFEFFFD6EF + EFFFD6EFEFFF4A4AFFFF4A4AFFFF4A4AFFFF4A4A4AFF00000000000000006B6B + 6BFFFFFFFFFFDEF7F7FFB5B5B5FF4A4AFFFF4A4AFFFFDEF7F7FFDEF7F7FFDEF7 + F7FFDEF7F7FFCEEFE7FF4A4AFFFF4A4AFFFF4A4AFFFF00000000000000006B6B + 6BFFFFFFFFFFB5B5B5FF4A4AFFFF4A4AFFFF4A4AFFFFDEF7F7FFDEF7F7FFF7F7 + F7FFD6D6D6FFC6C6C6FFB5B5B5FF4A4AFFFF4A4AFFFF4A4AFFFF000000006B6B + 6BFFFFFFFFFF4A4AFFFF4A4AFFFF4A4AFFFFDEF7F7FFDEF7F7FFDEF7F7FFF7F7 + F7FF949494FF8C8C8CFF737373FF5A5A5AFF4A4AFFFF4A4AFFFF000000006B6B + 6BFFFFFFFFFFE7FFF7FF4A4AFFFF4A4AFFFFE7FFF7FFE7FFF7FFE7FFF7FFF7F7 + F7FFA5A5A5FFFFFFFFFFFFFFFFFFFFFFFFFF5A5A5AFF4A4AFFFF000000006B6B + 6BFFFFFFFFFFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7 + F7FFB5B5B5FFFFFFFFFFD6F7EFFFB5D6CEFF6B6B6BFF00000000000000006B6B + 6BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFCECECEFFFFFFFFFFB5D6CEFF737373FF0000000000000000000000007373 + 73FF737373FF737373FF737373FF7B7B7BFF7B7B7BFF7B7B7BFF848484FF8484 + 84FF848484FF848484FF848484FF000000000000000000000000 + } ImageIndex = 11 OnClick = aDeleteMap end object miPackMap: TMenuItem Caption = 'Упаковать карту' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000006B6B + 6BFF292929FF212121FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF4A4A4AFF00000000000000004242 + 42FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF292929FF00000000000000004242 + 42FFFFFFFFFFC8E0E0FFC8E0DFFFC8E0E0FFC8E0E0FFC8E0DFFFB5B5B5FFC8DF + DFFFC7DFDFFFC8DFE0FFC8E0DFFFFFFFFFFF313131FF00000000000000004A4A + 4AFFFFFFFFFFCAE2E1FFCAE2E1FFCAE2E1FFCAE2E1FFB5B5B5FF722828FFB5B5 + B5FFB5B5B5FFB5B5B5FFB5B5B5FFB5B5B5FF181818FFB5B5B5FF000000004A4A + 4AFFFFFFFFFFCDE5E3FFCCE5E3FFCDE5E3FFB5B5B5FF812D2DFF812D2DFF812D + 2DFF812D2DFF812D2DFF812D2DFF812D2DFF812D2DFF812D2DFF000000004A4A + 4AFFFFFFFFFFD0E8E5FFD0E8E6FFCFE8E5FF923333FF923333FF923333FF9233 + 33FF923333FF923333FF923333FF923333FF923333FF923333FF000000005A5A + 5AFFFFFFFFFFD3EBE8FFD3EBE8FFA33939FFA33939FFA33939FFA33939FFA339 + 39FFA33939FFA33939FFA33939FFA33939FFA33939FFA33939FF000000005A5A + 5AFFFFFFFFFFD7EEEAFFD7EEEBFFD6EEEBFFB23E3EFFB23E3EFFB23E3EFFB23E + 3EFFB33F3FFFB23E3EFFB23E3EFFB23E3EFFB23E3EFFB23E3EFF000000006363 + 63FFFFFFFFFFDAF2EDFFDAF2EDFFDAF2EDFFDAF2EDFFBD4242FFBD4242FFBD42 + 42FFBD4242FFBD4242FFBD4242FFBD4242FFBD4242FFBD4242FF000000006B6B + 6BFFFFFFFFFFDEF6F0FFDEF6F0FFDDF5F0FFDDF5EFFFDDF5F0FFBD4242FFDDF5 + EFFFDDF5F0FFDEF5F0FFC6DEDEFFDEDEDEFF525252FF00000000000000006B6B + 6BFFFFFFFFFFE0F9F2FFE1F9F2FFE0F8F2FFE0F8F2FFE0F8F2FFE1F9F2FFF7F7 + F7FFD6D6D6FFC6C6C6FFB5B5B5FF9C9C9CFF525252FF00000000000000006B6B + 6BFFFFFFFFFFE3FBF4FFE3FBF4FFE3FBF3FFE3FBF4FFE3FCF4FFE3FBF4FFF7F7 + F7FF949494FF8C8C8CFF737373FF5A5A5AFF5A5A5AFF00000000000000006B6B + 6BFFFFFFFFFFE5FEF6FFE5FDF6FFE5FDF6FFE5FEF6FFE6FEF6FFE5FDF6FFF7F7 + F7FFA5A5A5FFFFFFFFFFFFFFFFFFFFFFFFFF5A5A5AFF00000000000000006B6B + 6BFFFFFFFFFFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7F7 + F7FFB5B5B5FFFFFFFFFFD6F7EFFFB5D6CEFF6B6B6BFF00000000000000006B6B + 6BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFCECECEFFFFFFFFFFB5D6CEFF737373FF0000000000000000000000007373 + 73FF737373FF737373FF737373FF7B7B7BFF7B7B7BFF7B7B7BFF848484FF8484 + 84FF848484FF848484FF848484FF000000000000000000000000 + } ImageIndex = 26 OnClick = miPackMapClick end @@ -1957,6 +2064,42 @@ object MainForm: TMainForm end object miExit: TMenuItem Caption = 'Выход' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000292929FF292929FF292929FF292929FF292929FF292929FF292929FF2929 + 29FF292929FF292929FF212121FF292929FF0000000000000000000000000000 + 0000393939FF7B9C9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C9CFF7B9C + 9CFF7B9C9CFF7B9C9CFF7B9C9CFF292929FF0000000000000000000000000000 + 0000424242FF849C9CFF849C9CFF849C9CFF849C9CFF849C9CFF849C9CFF849C + 9CFF849C9CFF849C9CFF849C9CFF292929FF0000000000000000000000000000 + 00004A4A4AFF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF8CA5A5FF393939FF0000000000000000000000000000 + 00004A4A4AFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94AD + ADFF94ADADFF94ADADFF94ADADFF393939FF0000000000000000000000000000 + 0000525252FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5B5FF9CB5 + B5FF9CB5B5FF9CB5B5FF9CB5B5FF393939FF0000000000000000000000000000 + 0000525252FFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BD + BDFF7B9C9CFF6B8484FFA5BDBDFF424242FF0000000000000000000000000000 + 00005A5A5AFFADC6C6FFADC6C6FFADC6C6FFADC6C6FFADC6C6FFADC6C6FFADC6 + C6FFDEF7F7FF7B9C9CFFADC6C6FF424242FF0000000000000000000000000000 + 00005A5A5AFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CE + CEFFB5CECEFFB5CECEFFB5CECEFF4A4A4AFF0000000000000000000000000000 + 0000636363FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6 + D6FFBDD6D6FFBDD6D6FFBDD6D6FF4A4A4AFF0000000000000000000000000000 + 00006B6B6BFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFFC6DEDEFFC6DEDEFFC6DEDEFF525252FF0000000000000000000000000000 + 00007B7B7BFFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FFCEE7E7FF5A5A5AFF0000000000000000000000000000 + 00007B7B7BFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EF + EFFFD6EFEFFFD6EFEFFFD6EFEFFF636363FF0000000000000000000000000000 + 00007B7B7BFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFDEF7F7FF6B6B6BFF0000000000000000000000000000 + 0000848484FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFDEF7F7FF737373FF0000000000000000000000000000 + 00007B7B7BFF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF848484FF848484FF848484FF737373FF0000000000000000 + } ImageIndex = 10 ShortCut = 121 OnClick = aExitExecute @@ -1967,6 +2110,42 @@ object MainForm: TMainForm object miUndo: TMenuItem Caption = 'Отменить' Enabled = False + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000294A4AFF294A4AFF294A4AFF294A4AFF294A4AFF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00006B8484FF42635AFF294A4AFF294A4AFF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00006B8484FF42635AFF42635AFF294A4AFF0000000000000000000000000000 + 0000000000000000000000000000294A4AFF0000000000000000000000000000 + 00006B8484FF6B8484FF42635AFF294A4AFF294A4AFF00000000000000000000 + 000000000000000000000000000042635AFF294A4AFF00000000000000000000 + 00006B8484FF000000006B8484FF42635AFF294A4AFF294A4AFF000000000000 + 00000000000000000000294A4AFF42635AFF6B8484FF00000000000000000000 + 000000000000000000000000000042635AFF42635AFF294A4AFF294A4AFF294A + 4AFF294A4AFF294A4AFF42635AFF42635AFF0000000000000000000000000000 + 00000000000000000000000000006B8484FF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF42635AFF6B8484FF0000000000000000000000000000 + 0000000000000000000000000000000000006B8484FF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF6B8484FF000000000000000000000000000000000000 + 000000000000000000000000000000000000000000006B8484FF6B8484FF6B84 + 84FF6B8484FF6B8484FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 5 ShortCut = 16474 OnClick = aUndoExecute @@ -1977,6 +2156,42 @@ object MainForm: TMainForm object miCopy: TMenuItem Caption = 'Копировать объект' Enabled = False + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006B6B6BFF292929FF212121FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF4A4A4AFF000000000000 + 000000000000000000000000000000000000424242FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF292929FF6B6B6BFF2929 + 29FF212121FF181818FF181818FF181818FF424242FFFFFFFFFFE7C6C6FFE7C6 + C6FFE7C6C6FFE7C6C6FFE7C6C6FFE7C6C6FFFFFFFFFF313131FF424242FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A4A4AFFFFFFFFFFEFCECEFFEFCE + CEFFEFCECEFFEFCECEFFEFCECEFFEFCECEFFFFFFFFFF313131FF424242FFFFFF + FFFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFF5A5A5AFFFFFFFFFFF7D6DEFFF7D6 + DEFFF7D6DEFFF7D6DEFFF7D6DEFFF7D6DEFFFFFFFFFF424242FF4A4A4AFFFFFF + FFFFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FF5A5A5AFFFFFFFFFFF7D6DEFFF7D6 + DEFFF7D6DEFFF7D6DEFFF7D6DEFFF7D6DEFFFFFFFFFF424242FF5A5A5AFFFFFF + FFFFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FF6B6B6BFFFFFFFFFFFFDEDEFFFFDE + DEFFFFDEDEFFFFDEDEFFFFDEDEFFE7C6C6FFDEDEDEFF525252FF5A5A5AFFFFFF + FFFFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FF6B6B6BFFFFFFFFFFFFDEDEFFFFDE + DEFFFFDEDEFFF7F7F7FFD6D6D6FFB5B5B5FF9C9C9CFF525252FF6B6B6BFFFFFF + FFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FF6B6B6BFFFFFFFFFFFFDEDEFFFFDE + DEFFFFDEDEFFF7F7F7FF949494FF737373FF5A5A5AFF5A5A5AFF6B6B6BFFFFFF + FFFFDEF7F7FFDEF7F7FFDEF7F7FFF7F7F7FF6B6B6BFFFFFFFFFFFFE7EFFFFFE7 + EFFFFFE7EFFFF7F7F7FFA5A5A5FFFFFFFFFFFFFFFFFF5A5A5AFF6B6B6BFFFFFF + FFFFDEF7F7FFDEF7F7FFDEF7F7FFF7F7F7FF6B6B6BFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFCECECEFFDEB5BDFF737373FF000000006B6B6BFFFFFF + FFFFE7FFF7FFE7FFF7FFE7FFF7FFF7F7F7FF737373FF737373FF737373FF7373 + 73FF7B7B7BFF848484FF848484FF848484FF00000000000000006B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCECECEFFB5D6CEFF737373FF0000 + 0000000000000000000000000000000000000000000000000000737373FF7373 + 73FF737373FF737373FF7B7B7BFF848484FF848484FF848484FF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 8 ShortCut = 16451 OnClick = aCopyObjectExecute @@ -1984,12 +2199,84 @@ object MainForm: TMainForm object miCut: TMenuItem Caption = 'Вырезать объект' Enabled = False + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000295239FF315A4AFF295239FF0000000000000000000000002952 + 39FF31634AFF214A31FF00000000000000000000000000000000000000000000 + 0000315242FF52846BFF528C6BFF5A8C73FF4A6B5AFF00000000426B5AFF5A84 + 73FF5A9473FF639473FF214A31FF000000000000000000000000000000000000 + 0000294231FF4A7B63FF0000000000000000637B73FF396352FF5A7B6BFF0000 + 000000000000527B63FF395A42FF000000000000000000000000000000000000 + 0000000000004A6B5AFF000000000000000000000000426B5AFF000000000000 + 000000000000527B63FF00000000000000000000000000000000000000000000 + 0000000000004A6B5AFF527363FF00000000315A4AFF4A7B6BFF295A4AFF0000 + 00004A7363FF4A6B5AFF00000000000000000000000000000000000000000000 + 000000000000000000004A6B5AFF6B8C7BFF52846BFF6B9C8CFF6B9C8CFF5273 + 63FF526B63FF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000004A4A4AFF4A4A4AFF4A4A4AFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000004A4A4AFF6B6B6BFF4A4A4AFF6B6B6BFF4A4A + 4AFF000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000006B6B6BFF848484FF4A4A4AFF848484FF6B6B + 6BFF000000000000000000000000000000000000000000000000000000000000 + 000000000000000000004A4A4AFF6B6B6BFFA5A5A5FF00000000A5A5A5FF6B6B + 6BFF4A4A4AFF0000000000000000000000000000000000000000000000000000 + 000000000000000000006B6B6BFF848484FFA5A5A5FF00000000A5A5A5FF8484 + 84FF6B6B6BFF0000000000000000000000000000000000000000000000000000 + 00000000000000000000848484FFA5A5A5FF000000000000000000000000A5A5 + A5FF848484FF0000000000000000000000000000000000000000000000000000 + 00000000000000000000848484FFA5A5A5FF000000000000000000000000A5A5 + A5FF848484FF0000000000000000000000000000000000000000000000000000 + 00000000000000000000A5A5A5FFA5A5A5FF000000000000000000000000A5A5 + A5FFA5A5A5FF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 7 ShortCut = 16472 OnClick = aCutObjectExecute end object miPaste: TMenuItem Caption = 'Вставить объект' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF292929FF292929FF212121FF000000000000000000000000393939FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFF000000FF000000FF292929FF000000000000000000000000424242FFFFFF + FFFF8C0000FFFFDEDEFFFFDEDEFFFFDEDEFFFFDEDEFFFFDEDEFFFFDEDEFFFFFF + FFFFDEDEDEFF000000FF292929FF0000000000000000000000004A4A4AFFFFFF + FFFFBD0000FFFFDEDEFF4A6352FF42635AFF42635AFF42635AFF42635AFF4263 + 5AFFDEDEDEFF000000FF393939FF0000000000000000000000004A4A4AFFFFFF + FFFFD60000FFFFDEDEFF6B8484FF5A7373FF5A7373FF5A7373FF42635AFFFFFF + FFFF000000FF000000FF393939FF000000000000000000000000525252FFFFFF + FFFFEF0000FFFFDEDEFF6B8484FF5A7373FF5A7373FF42635AFF42635AFFFFFF + FFFF000000FF000000FF393939FF000000000000000000000000525252FFFFFF + FFFFFFFFFFFFFFFFFFFF6B8484FF5A7373FF6B8484FF5A7373FF42635AFF4263 + 5AFFDEDEDEFF080808FF424242FF0000000000000000000000005A5A5AFF0808 + 08FF080808FFDEDEDEFF6B8484FF6B8484FF6B8484FF6B8484FF5A7373FF4263 + 5AFF42635AFFEFEFEFFF181818FF181818FF181818FF4A4A4AFF5A5A5AFF0808 + 08FF212929FFDEE7E7FF6B8484FFDEE7E7FFF7F7F7FF6B8484FF6B8484FF5A73 + 73FF42635AFF42635AFFFFFFFFFFFFFFFFFFFFFFFFFF292929FF7B7B7BFF2129 + 29FF212929FFF7F7F7FFF7F7F7FFF7F7F7FF212929FFF7F7F7FF6B8484FF6B84 + 84FF5A7373FF42635AFF42635AFFFFFFFFFFFFFFFFFF313131FF5A5A5AFF3139 + 39FF313939FF313939FF313939FF313939FF313939FF313939FFFFFFFFFF6B84 + 84FF6B8484FF42635AFFFFFFFFFFFFFFFFFFDEDEDEFF525252FF7B7B7BFF3942 + 42FF394242FF394242FF394242FF394242FF394242FF394242FF6B6B6BFFFFFF + FFFF6B8484FFFFFFFFFFFFFFFFFFB5B5B5FF9C9C9CFF525252FF848484FF525A + 5AFF4A5A52FF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF6B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFF949494FF737373FF5A5A5AFF5A5A5AFF848484FF8484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF6B6B6BFFFFFF + FFFFFFE7EFFFF7F7F7FFA5A5A5FFFFFFFFFFFFFFFFFF5A5A5AFF000000000000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFFCECECEFFDEB5BDFF737373FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000737373FF7373 + 73FF737373FF848484FF848484FF848484FF0000000000000000 + } ImageIndex = 9 ShortCut = 16470 OnClick = aPasteObjectExecute @@ -1999,6 +2286,42 @@ object MainForm: TMainForm end object miSelectAll: TMenuItem Caption = 'Выделить все объекты' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF212121FF393939FF0000 + 63FF000063FF000063FF000063FF00006BFF000063FF000063FF000063FF0000 + 6BFF000063FF000000FF000000FF000000FF000000FF292929FF424242FF0000 + 73FF000073FF000073FF000073FF000073FF000073FF000073FF000073FF0000 + 73FF000073FF000000FF000000FF000000FF000000FF292929FF4A4A4AFF0000 + 84FF000084FF000084FF000084FF000084FF000084FF000084FF000084FF0000 + 84FF000084FF000000FF000000FF000084FF000084FF393939FF4A4A4AFF0000 + 94FF000094FF000094FF000094FF000094FF000094FF000094FF000094FF0000 + 94FF000094FF000000FF000000FF000000FF000000FF393939FF525252FF0000 + A5FF0000A5FF0000A5FF00009CFF00009CFF00009CFF0000A5FF0000A5FF0000 + A5FF0000A5FF000000FF000000FF000000FF000000FF393939FF525252FF0000 + ADFF0000ADFF0000ADFF0000ADFF0000ADFF0000ADFF0000ADFF0000ADFF0000 + ADFF0000ADFF080808FF000000FF0000ADFF0000ADFF424242FF5A5A5AFF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF000000FF000000FF000000FF424242FF5A5A5AFF0008 + 08FF000808FF000808FF000808FF000808FF000808FF000808FF000808FF0008 + 08FF000808FF000808FF000808FF000808FF000808FF4A4A4AFF636363FF0810 + 08FF081008FF081008FF081008FF081008FF081008FF081008FF081008FF0810 + 08FF081008FF081008FF081008FF2929ADFF2929ADFF4A4A4AFF6B6B6BFF3939 + ADFF3939ADFF3939ADFF3939ADFF3939ADFF3939ADFF3939ADFF3939ADFF1018 + 10FF101810FF101810FF101810FF101810FF101810FF525252FF7B7B7BFF1821 + 21FF182121FF182121FF182121FF182121FF182121FF182121FF4A4AADFF1821 + 21FF182121FF182121FF182121FF182121FF182121FF5A5A5AFF7B7B7BFF2129 + 29FF212929FF212929FF212929FF212929FF212929FF212929FF212929FF2129 + 29FF212929FF212929FF212929FF5252ADFF5252ADFF636363FF7B7B7BFF2929 + 31FF292931FF292931FF292931FF292931FF292931FF292931FF292931FF2929 + 31FF292931FF292931FF292931FF292931FF292931FF6B6B6BFF848484FF525A + 5AFF4A5A52FF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A + 5AFF525A5AFF525A5AFF525A5AFF4A5A52FF4A5A52FF737373FF848484FF8484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF848484FF + } ImageIndex = 24 ShortCut = 16449 OnClick = aSelectAllExecute @@ -2009,6 +2332,42 @@ object MainForm: TMainForm object miToFore: TMenuItem Caption = 'Передвинуть вперед' Enabled = False + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000003139ADFF10219CFF10219CFF1021 + 9CFF10219CFF10219CFF10219CFF10219CFF10219CFF10219CFF000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 00000000000042635AFF294A4AFF294A4AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 0000000000005A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 0000000000005A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF39524AFF2942 + 39FF294239FF5A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF4A5AB5FF4A5AB5FF4A5AB5FF4A5A + B5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF3139ADFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF294A4AFF000000000000000000000000425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF294A4AFF000000000000000000000000425A52FF3952 + 4AFF39524AFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A73 + 6BFF5A736BFF5A736BFF42635AFF000000000000000000000000425A52FF3952 + 4AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF2942 + 39FF000000000000000000000000000000000000000000000000425A52FF3952 + 4AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF2942 + 39FF000000000000000000000000000000000000000000000000425A52FF425A + 52FF425A52FF425A52FF425A52FF425A52FF425A52FF425A52FF425A52FF3952 + 4AFF000000000000000000000000000000000000000000000000 + } ImageIndex = 25 ShortCut = 16605 OnClick = aMoveToFore @@ -2016,6 +2375,42 @@ object MainForm: TMainForm object miToBack: TMenuItem Caption = 'Передвинуть назад' Enabled = False + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000005A7373FF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF000000000000 + 0000000000000000000000000000000000006B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF000000000000 + 0000000000000000000000000000000000006B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF000000000000 + 00000000000042635AFF294A4AFF294A4AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF000000000000 + 0000000000005A736BFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF000000000000 + 0000000000005A736BFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF3139ADFF1021 + 9CFF10219CFF5A736BFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF4A5AB5FF3139 + ADFF3139ADFF5A736BFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF4A5AB5FF3139 + ADFF3139ADFF5A736BFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF42635AFF4A5AB5FF3139 + ADFF3139ADFF5A736BFF42635AFF42635AFF6B8484FF6B8484FF6B8484FF6B84 + 84FF6B8484FF6B8484FF6B8484FF6B8484FF6B8484FF5A7373FF4A5AB5FF3139 + ADFF3139ADFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF294A4AFF0000000000000000000000004A5AB5FF3139 + ADFF3139ADFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF294A4AFF0000000000000000000000004A5AB5FF3139 + ADFF3139ADFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A73 + 6BFF5A736BFF5A736BFF42635AFF0000000000000000000000004A5AB5FF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF1021 + 9CFF0000000000000000000000000000000000000000000000004A5AB5FF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF1021 + 9CFF0000000000000000000000000000000000000000000000004A5AB5FF4A5A + B5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF3139 + ADFF000000000000000000000000000000000000000000000000 + } ImageIndex = 13 ShortCut = 16603 OnClick = aMoveToBack @@ -2025,29 +2420,209 @@ object MainForm: TMainForm Caption = 'Инструменты' object miSnapToGrid: TMenuItem Caption = 'Привязка к сетке' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF212121FF393939FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF292929FF424242FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF292929FF4A4A4AFF6F54 + 38FF6F5438FF6F5438FF393939FF6F5438FF6F5438FF6F5438FF393939FF6F54 + 38FF6F5438FF6F5438FF393939FF6F5438FF6F5438FF393939FF4A4A4AFF6F54 + 38FF6F5438FFFFFFFFFF6F5438FF6F5438FF6F5438FFFFFFFFFF6F5438FF6F54 + 38FF6F5438FFFFFFFFFF6F5438FF6F5438FF6F5438FF393939FF525252FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF393939FF525252FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF424242FF5A5A5AFF7157 + 3CFF71573CFF71573CFF393939FF71573CFF71573CFF71573CFF393939FF7157 + 3CFF71573CFF71573CFF393939FF71573CFF71573CFF424242FF5A5A5AFF745B + 40FF745B40FFFFFFFFFF745B40FF745B40FF745B40FFFFFFFFFF745B40FF745B + 40FF745B40FFFFFFFFFF745B40FF745B40FF745B40FF4A4A4AFF636363FF775F + 44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F + 44FF775F44FF775F44FF775F44FF775F44FF775F44FF4A4A4AFF6B6B6BFF7A64 + 4AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A64 + 4AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF525252FF7B7B7BFF7E69 + 50FF7E6950FF7E6950FF393939FF7E6950FF7E6950FF7E6950FF393939FF7E69 + 50FF7E6950FF7E6950FF393939FF7E6950FF7E6950FF5A5A5AFF7B7B7BFF826F + 57FF826F57FFFFFFFFFF826F57FF826F57FF826F57FFFFFFFFFF826F57FF826F + 57FF826F57FFFFFFFFFF826F57FF826F57FF826F57FF636363FF7B7B7BFF8676 + 5EFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF8676 + 5EFF86765EFF86765EFF86765EFF86765EFF86765EFF6B6B6BFF848484FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF737373FF848484FF8484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF848484FF + } ImageIndex = 20 ShortCut = 16465 OnClick = miSnapToGridClick end object miMiniMap: TMenuItem Caption = 'Мини-карта' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF212121FF393939FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF000000FF000000FF000000FF000000FF292929FF424242FFFFFF + FFFF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C00 + 00FFFFFFFFFF000000FF000000FF000000FF000000FF292929FF4A4A4AFFFFFF + FFFFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD00 + 00FFFFFFFFFF000000FF000000FFC6C6C6FFC6C6C6FF393939FF4A4A4AFFFFFF + FFFFD60000FFD60000FFD60000FFD60000FFD60000FFD60000FFD60000FFD600 + 00FFFFFFFFFF000000FF000000FF000000FF000000FF393939FF525252FFFFFF + FFFFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF00 + 00FFFFFFFFFF000000FF000000FF000000FF000000FF393939FF525252FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFF00 + 00FFFFFFFFFF080808FF080808FFC6C6C6FFC6C6C6FF424242FF5A5A5AFF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF424242FF5A5A5AFF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF4A4A4AFF636363FF0818 + 10FF081810FF081810FF081810FF081810FF081810FF081810FF081810FF0818 + 10FF081810FF081810FF081810FFC6C6C6FFC6C6C6FF4A4A4AFF6B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1821 + 18FF182118FF182118FF182118FF182118FF182118FF525252FF7B7B7BFF2129 + 29FF212929FF212929FF212929FF212929FF212929FF212929FFFFFFFFFF2129 + 29FF212929FF212929FF212929FF212929FF212929FF5A5A5AFF7B7B7BFF3139 + 39FF313939FF313939FF313939FF313939FF313939FF313939FF313939FF3139 + 39FF313939FF313939FF313939FFC6C6C6FFC6C6C6FF636363FF7B7B7BFF3942 + 42FF394242FF394242FF394242FF394242FF394242FF394242FF394242FF3942 + 42FF394242FF394242FF394242FF394242FF394242FF6B6B6BFF848484FF525A + 5AFF4A5A52FF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A + 5AFF525A5AFF525A5AFF525A5AFF4A5A52FF4A5A52FF737373FF848484FF8484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF848484FF + } ImageIndex = 14 ShortCut = 16471 OnClick = miMiniMapClick end object miSwitchGrid: TMenuItem Caption = 'Переключить сетку' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF212121FF393939FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF393939FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF393939FF292929FF424242FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FFFFFFFFFF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FFFFFFFFFF6F5438FF292929FF4A4A4AFF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF393939FF4A4A4AFF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF393939FF525252FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF393939FF525252FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF424242FF5A5A5AFF7157 + 3CFF71573CFF71573CFF71573CFF71573CFF71573CFF71573CFF393939FF7157 + 3CFF71573CFF71573CFF71573CFF71573CFF393939FF424242FF5A5A5AFF745B + 40FF745B40FF745B40FF745B40FF745B40FF745B40FFFFFFFFFF745B40FF745B + 40FF745B40FF745B40FF745B40FFFFFFFFFF745B40FF4A4A4AFF636363FF775F + 44FF775F44FF393939FF775F44FF775F44FF393939FF775F44FF775F44FF775F + 44FF775F44FF775F44FF775F44FF775F44FF775F44FF4A4A4AFF6B6B6BFF7A64 + 4AFFFFFFFFFF7A644AFF7A644AFFFFFFFFFF7A644AFF7A644AFF7A644AFF7A64 + 4AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF525252FF7B7B7BFF7E69 + 50FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E69 + 50FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF5A5A5AFF7B7B7BFF826F + 57FF826F57FF393939FF826F57FF826F57FF393939FF826F57FF826F57FF826F + 57FF826F57FF826F57FF826F57FF826F57FF826F57FF636363FF7B7B7BFF8676 + 5EFFFFFFFFFF86765EFF86765EFFFFFFFFFF86765EFF86765EFF86765EFF8676 + 5EFF86765EFF86765EFF86765EFF86765EFF86765EFF6B6B6BFF848484FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF737373FF848484FF8484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF848484FF + } ImageIndex = 19 ShortCut = 16453 OnClick = miSwitchGridClick end object miShowEdges: TMenuItem Caption = 'Границы карты' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF212121FF393939FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF292929FF424242FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF292929FF4A4A4AFF372E + 24FF372E24FF372E24FF372E24FF372E24FF372E24FF372E24FF372E24FF372E + 24FF372E24FF372E24FF6F5438FF6F5438FF6F5438FF393939FF4A4A4AFF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF372E24FF6F5438FF6F5438FF6F5438FF393939FF525252FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF372E24FF6F5438FF6F5438FF6F5438FF393939FF525252FF6F54 + 38FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F5438FF6F54 + 38FF6F5438FF372E24FF6F5438FF6F5438FF6F5438FF424242FF5A5A5AFF7157 + 3CFF71573CFF71573CFF71573CFF71573CFF71573CFF71573CFF71573CFF7157 + 3CFF71573CFF382F25FF71573CFF71573CFF71573CFF424242FF5A5A5AFF745B + 40FF745B40FF745B40FF745B40FF745B40FF745B40FF745B40FF745B40FF745B + 40FF745B40FF393026FF745B40FF745B40FF745B40FF4A4A4AFF636363FF775F + 44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F44FF775F + 44FF775F44FF3A3228FF775F44FF775F44FF775F44FF4A4A4AFF6B6B6BFF7A64 + 4AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A644AFF7A64 + 4AFF7A644AFF3B332AFF7A644AFF7A644AFF7A644AFF525252FF7B7B7BFF7E69 + 50FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E6950FF7E69 + 50FF7E6950FF3D352CFF7E6950FF7E6950FF7E6950FF5A5A5AFF7B7B7BFF826F + 57FF826F57FF826F57FF826F57FF826F57FF826F57FF826F57FF826F57FF826F + 57FF826F57FF3E372FFF826F57FF826F57FF826F57FF636363FF7B7B7BFF8676 + 5EFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF86765EFF8676 + 5EFF86765EFF403A31FF86765EFF86765EFF86765EFF6B6B6BFF848484FF8B7C + 65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C65FF8B7C + 65FF8B7C65FF413C34FF8B7C65FF8B7C65FF8B7C65FF737373FF848484FF8484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF848484FF + } ImageIndex = 29 OnClick = miShowEdgesClick end object miLayers: TMenuItem Caption = 'Слои' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000003139ADFF10219CFF10219CFF1021 + 9CFF10219CFF10219CFF10219CFF10219CFF10219CFF10219CFF000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 00000000000042635AFF294A4AFF294A4AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 0000000000005A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF000000000000 + 0000000000005A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF39524AFF2942 + 39FF294239FF5A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF4A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF10219CFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF4A5AB5FF4A5AB5FF4A5AB5FF4A5A + B5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF3139ADFF425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF294A4AFF000000000000000000000000425A52FF3952 + 4AFF39524AFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF294A4AFF000000000000000000000000425A52FF3952 + 4AFF39524AFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A73 + 6BFF5A736BFF5A736BFF42635AFF000000000000000000000000425A52FF3952 + 4AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF2942 + 39FF000000000000000000000000000000000000000000000000425A52FF3952 + 4AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF39524AFF2942 + 39FF000000000000000000000000000000000000000000000000425A52FF425A + 52FF425A52FF425A52FF425A52FF425A52FF425A52FF425A52FF425A52FF3952 + 4AFF000000000000000000000000000000000000000000000000 + } ImageIndex = 25 object miLayer1: TMenuItem Caption = 'Фон' @@ -2101,22 +2676,166 @@ object MainForm: TMainForm Caption = 'Сервис' object miCheckMap: TMenuItem Caption = 'Проверка карты' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000042635AFF42635AFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000006B8484FF6B8484FF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000042635AFF42635AFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000006B8484FF5A7373FF4263 + 5AFF000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000006B8484FF6B84 + 84FF42635AFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00005A7373FF42635AFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00006B8484FF5A7373FF00000000000000000000000000000000000000000000 + 000000000000000000000000000042635AFF42635AFF00000000000000004263 + 5AFF5A7373FF6B8484FF00000000000000000000000000000000000000000000 + 00000000000000000000000000006B8484FF5A7373FF42635AFF42635AFF5A73 + 73FF6B8484FF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006B8484FF6B8484FF6B8484FF6B84 + 84FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 17 OnClick = aCheckMapExecute end object miOptimmization: TMenuItem Caption = 'Оптимизация карты' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000010219CFF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000010219CFF3139ADFF10219CFF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000003139ADFF4A5AB5FF3139ADFF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000010219CFF3139ADFF000000003139ADFF10219CFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000010219CFF3139ADFF4A5AB5FF000000004A5AB5FF3139ADFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000003139ADFF4A5AB5FF0000000000000000000000003139ADFF1021 + 9CFF000000000000000000000000000000000000000000000000000000000000 + 0000000000004A5AB5FF000000000000000000000000000000004A5AB5FF3139 + ADFF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000003139 + ADFF10219CFF10219CFF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000004A5A + B5FF3139ADFF3139ADFF10219CFF10219CFF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00004A5AB5FF4A5AB5FF3139ADFF3139ADFF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000004A5AB5FF4A5AB5FF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 18 OnClick = aOptimizeExecute end object miMapPreview: TMenuItem Caption = 'Предварительный просмотр' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000C6CED6FFADB5B5FFADB5B5FFADB5B5FFADB5B5FFC6CE + D6FF000000000000000000000000000000000000000000000000000000000000 + 000000000000BDC6C6FF848C8CFF424242FF393939FF393939FF394242FF7B84 + 84FFBDC6CEFFC6CED6FF00000000000000000000000000000000000000000000 + 0000C6CED6FF292929FF636B6BFF9C9CA5FFADB5B5FFADB5B5FFBDC6C6FF737B + 7BFF181818FF848C8CFFC6CED6FF000000000000000000000000000000000000 + 0000C6CECEFFADB5BDFFC6CED6FF394242FF000000FF000000FF181818FFADB5 + B5FFADB5B5FF101010FF7B7B84FF000000000000000000000000000000000000 + 00009CA5ADFF9CA5ADFF212929FF000000FF000000FF000000FF000000FF0000 + 00FF94949CFF848C8CFF182121FF000000000000000000000000000000000000 + 00005A5A63FF848C8CFF000000FF424242FFC6CECEFF000000FF000000FF0000 + 00FF84848CFF313939FF293131FFB5BDBDFF0000000000000000000000000000 + 0000949C9CFF212121FF000000FF000000FF292929FF080808FF000000FF0000 + 00FF393939FF212929FF7B8484FF8C8C8CFF0000000000000000000000000000 + 00004A5252FF84848CFF73737BFF42424AFF101010FF181818FF101010FF5252 + 52FF5A6363FF8C8C94FF424242FF949C9CFF0000000000000000000000000000 + 0000949C9CFF4A4A4AFF737B7BFF737B7BFF949C9CFF94949CFF94949CFF7B84 + 84FF6B6B73FF525252FFA5A5ADFF000000000000000000000000000000000000 + 0000C6CED6FFBDC6C6FF84848CFF737B7BFF525252FF525252FF525252FF6B73 + 73FF848C8CFFBDBDC6FF00000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 23 ShortCut = 9 OnClick = miMapPreviewClick end object miTestMap: TMenuItem Caption = 'Тест карты в игре' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000004E6363FF4255 + 55FF364545FF00000000000000004E6363FF425555FF364545FF000000000000 + 00004E6363FF425555FF364545FF00000000000000000000000000000000788C + 8CFF5A7373FF425454FF0000000000000000788C8CFF5A7373FF425454FF0000 + 000000000000788C8CFF5A7373FF425454FF0000000000000000000000000000 + 0000788C8CFF5A7373FF425454FF0000000000000000788C8CFF5A7373FF4254 + 54FF0000000000000000788C8CFF5A7373FF425454FF00000000000000000000 + 000000000000788C8CFF5A7373FF425454FF0000000000000000788C8CFF5A73 + 73FF425454FF0000000000000000788C8CFF5A7373FF425454FF000000000000 + 000000000000425454FF5A7373FF788C8CFF0000000000000000425454FF5A73 + 73FF788C8CFF0000000000000000425454FF5A7373FF788C8CFF000000000000 + 0000425454FF5A7373FF788C8CFF0000000000000000425454FF5A7373FF788C + 8CFF0000000000000000425454FF5A7373FF788C8CFF00000000000000004254 + 54FF5A7373FF788C8CFF0000000000000000425454FF5A7373FF788C8CFF0000 + 000000000000425454FF5A7373FF788C8CFF0000000000000000687F7FFF798D + 8DFF879999FF0000000000000000687F7FFF798D8DFF879999FF000000000000 + 0000687F7FFF798D8DFF879999FF000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000 + } ImageIndex = 27 OnClick = miTestMapClick end @@ -2125,6 +2844,42 @@ object MainForm: TMainForm Caption = 'Настройка' object miMapOptions: TMenuItem Caption = 'Карта' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000292929FF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF292929FF292929FF212121FF212121FF212121FF393939FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF000000FF000000FF000000FF000000FF292929FF424242FFFFFF + FFFF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C00 + 00FFFFFFFFFF000000FF000000FF000000FF000000FF292929FF4A4A4AFFFFFF + FFFFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD00 + 00FFFFFFFFFF000000FF000000FFC6C6C6FFC6C6C6FF393939FF4A4A4AFFFFFF + FFFFD60000FFD60000FFD60000FFD60000FFD60000FFD60000FFD60000FFD600 + 00FFFFFFFFFF000000FF000000FF000000FF000000FF393939FF525252FFFFFF + FFFFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF00 + 00FFFFFFFFFF000000FF000000FF000000FF000000FF393939FF525252FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFF00 + 00FFFFFFFFFF080808FF080808FFC6C6C6FFC6C6C6FF424242FF5A5A5AFF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF424242FF5A5A5AFF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF4A4A4AFF636363FF0818 + 10FF081810FF081810FF081810FF081810FF081810FF081810FF081810FF0818 + 10FF081810FF081810FF081810FFC6C6C6FFC6C6C6FF4A4A4AFF6B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1821 + 18FF182118FF182118FF182118FF182118FF182118FF525252FF7B7B7BFF2129 + 29FF212929FF212929FF212929FF212929FF212929FF212929FFFFFFFFFF2129 + 29FF212929FF212929FF212929FF212929FF212929FF5A5A5AFF7B7B7BFF3139 + 39FF313939FF313939FF313939FF313939FF313939FF313939FF313939FF3139 + 39FF313939FF313939FF313939FFC6C6C6FFC6C6C6FF636363FF7B7B7BFF3942 + 42FF394242FF394242FF394242FF394242FF394242FF394242FF394242FF3942 + 42FF394242FF394242FF394242FF394242FF394242FF6B6B6BFF848484FF525A + 5AFF4A5A52FF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A5AFF525A + 5AFF525A5AFF525A5AFF525A5AFF4A5A52FF4A5A52FF737373FF848484FF8484 + 84FF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF848484FF848484FF + } ImageIndex = 14 ShortCut = 16461 OnClick = aMapOptionsExecute @@ -2134,6 +2889,42 @@ object MainForm: TMainForm end object miOptions: TMenuItem Caption = 'Редактор' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000FF000000FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000FFADADADFFBDBDBDFF000000FF316B63FF0042 + 39FF004239FF004239FF004239FF004239FF004239FF004239FF004239FF0000 + 00FF000000FF00000000000000FFB5B5B5FFCEC6CEFF000000FF5A8C84FF316B + 63FF316B63FF316B63FF316B63FF316B63FF316B63FF316B63FF004239FF0000 + 00FF8C8C8CFF000000FFC6C6C6FFD6D6D6FF000000FF000000005A8C84FF316B + 63FF316B63FF316B63FF316B63FF316B63FF316B63FF316B63FF004239FF0000 + 00FF9C9C9CFF8C8C8CFFCECECEFFDEDEDEFF000000FF000000005A8C84FF316B + 63FF427B73FF10524AFF10524AFF10524AFF10524AFF10524AFF10524AFF0000 + 00FFC6C6C6FFD6D6D6FFE7E7E7FF8C8C8CFF000000FF000000FF5A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF427B73FF427B73FF427B73FF427B73FF0000 + 00FFCECECEFFDEDEDEFFEFEFEFFFFFFFFFFFFFFFFFFF000000FF5A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF5A8C8CFF216B5AFF216B5AFF216B5AFF0000 + 00FFDEDEDEFFEFEFEFFFF7F7F7FFFFFFFFFF000000FF000000005A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FFE7E7E7FFF7F7F7FFFFFFFFFF000000FF00000000000000005A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FFF7F7EFFFFFFFFFFF000000FF216B5AFF00000000000000005A8C84FF5A8C + 84FF6BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FFF7F7F7FF000000FF5A8C8CFF216B5AFF0000000000000000000000000000 + 00006BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FF000000FF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00006BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF5A8C8CFF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00006BA59CFF6BA59CFF6BA59CFF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF5A8C8CFF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00000000000000000000000000007BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF5A8C8CFF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00000000000000000000000000007BB5B5FF7BB5B5FF7BB5B5FF7BB5B5FF7BB5 + B5FF7BB5B5FF7BB5B5FF7BB5B5FF5A8C8CFF0000000000000000 + } ImageIndex = 16 OnClick = aEditorOptionsExecute end @@ -2149,6 +2940,42 @@ object MainForm: TMainForm Caption = 'Справка' object miAbout: TMenuItem Caption = 'О программе' + Bitmap.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000FF000000FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000FFADADADFFBDBDBDFF000000FF316B63FF0042 + 39FF004239FF004239FF004239FF004239FF004239FF004239FF004239FF0000 + 00FF000000FF00000000000000FFB5B5B5FFCEC6CEFF000000FF5A8C84FF316B + 63FF316B63FF316B63FF316B63FF316B63FF316B63FF316B63FF004239FF0000 + 00FF8C8C8CFF000000FFC6C6C6FFD6D6D6FF000000FF000000005A8C84FF316B + 63FF316B63FF316B63FF316B63FF316B63FF316B63FF316B63FF004239FF0000 + 00FF9C9C9CFF8C8C8CFFCECECEFFDEDEDEFF000000FF000000005A8C84FF316B + 63FF427B73FF10524AFF10524AFF10524AFF10524AFF10524AFF10524AFF0000 + 00FFC6C6C6FFD6D6D6FFE7E7E7FF8C8C8CFF000000FF000000FF5A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF427B73FF427B73FF427B73FF427B73FF0000 + 00FFCECECEFFDEDEDEFFEFEFEFFFFFFFFFFFFFFFFFFF000000FF5A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF5A8C8CFF216B5AFF216B5AFF216B5AFF0000 + 00FFDEDEDEFFEFEFEFFFF7F7F7FFFFFFFFFF000000FF000000005A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FFE7E7E7FFF7F7F7FFFFFFFFFF000000FF00000000000000005A8C84FF316B + 63FF6BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FFF7F7EFFFFFFFFFFF000000FF216B5AFF00000000000000005A8C84FF5A8C + 84FF6BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FFF7F7F7FF000000FF5A8C8CFF216B5AFF0000000000000000000000000000 + 00006BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF0000 + 00FF000000FF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00006BA59CFF427B73FF427B73FF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF5A8C8CFF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00006BA59CFF6BA59CFF6BA59CFF7BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF5A8C8CFF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00000000000000000000000000007BB5B5FF5A8C8CFF5A8C8CFF5A8C8CFF5A8C + 8CFF5A8C8CFF5A8C8CFF5A8C8CFF216B5AFF0000000000000000000000000000 + 00000000000000000000000000007BB5B5FF7BB5B5FF7BB5B5FF7BB5B5FF7BB5 + B5FF7BB5B5FF7BB5B5FF7BB5B5FF5A8C8CFF0000000000000000 + } ImageIndex = 16 OnClick = aAboutExecute end @@ -2170,8 +2997,8 @@ object MainForm: TMainForm end object pmShow: TPopupMenu Images = ImageList - Left = 128 - Top = 64 + left = 128 + top = 64 object miLayerP1: TMenuItem Caption = 'Фон' Checked = True @@ -2221,178 +3048,508 @@ object MainForm: TMainForm object ilToolbar: TImageList Height = 24 Width = 24 - Left = 64 - Top = 101 + left = 64 + top = 101 Bitmap = { - 494C010109000E00040018001800FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 - 0000000000003600000028000000600000006000000001002000000000000090 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 + 4C69090000001800000018000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000737373FF7373 + 73FF737373FF737373FF7B7B7BFF7B7B7BFF848484FF848484FF848484FF8484 + 84FF848484FF848484FF848484FF848484FF0000000000000000000000000000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFCECECEFFFFFFFFFFB5D6CEFF737373FF00000000000000000000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFC6C6C6FFFFFFFFFFD6F7EFFFB5D6CEFF6B6B6BFF000000000000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FF + F7FFF7F7F7FFB5B5B5FFFFFFFFFFD6F7EFFFD6F7EFFFB5D6CEFF6B6B6BFF0000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FF + F7FFF7F7F7FFA5A5A5FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A5A5AFF0000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FFF7F7F7FF949494FF8C8C8CFF737373FF737373FF5A5A5AFF5A5A5AFF0000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FFF7F7F7FFD6D6D6FFC6C6C6FFB5B5B5FFADADADFF9C9C9CFF525252FF0000 + 00000000000000000000000000000000000000000000000000006B6B6BFFFFFF + FFFFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7F7FFDEF7 + F7FFDEF7F7FFDEF7F7FFCEEFE7FFC6DEDEFFC6DEDEFFDEDEDEFF525252FF0000 + 0000000000000000000000000000000000000000000000000000636363FFFFFF + FFFFD6F7EFFFD6F7EFFFD6F7EFFFD6F7EFFFD6F7EFFFD6F7EFFFD6F7EFFFD6F7 + EFFFD6F7EFFFD6F7EFFFD6F7EFFFD6F7EFFFDEFFF7FFFFFFFFFF4A4A4AFF0000 + 0000000000000000000000000000000000000000000000000000636363FFFFFF + FFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EF + EFFFD6EFEFFFD6EFEFFFD6EFEFFFD6EFEFFFDEF7F7FFFFFFFFFF4A4A4AFF0000 + 00000000000000000000000000000000000000000000000000005A5A5AFFFFFF + FFFFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EF + E7FFD6EFE7FFD6EFE7FFD6EFE7FFD6EFE7FFDEF7F7FFFFFFFFFF424242FF0000 + 00000000000000000000000000000000000000000000000000005A5A5AFFFFFF + FFFFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7 + E7FFCEE7E7FFCEE7E7FFCEE7E7FFCEE7E7FFDEF7F7FFFFFFFFFF424242FF0000 + 0000000000000000000000000000000000000000000000000000525252FFFFFF + FFFFC6E7DEFFC6E7DEFFC6E7DEFFC6E7DEFFC6E7DEFFC6E7DEFFC6E7DEFFC6E7 + DEFFC6E7DEFFC6E7DEFFC6E7DEFFC6E7DEFFD6F7EFFFFFFFFFFF393939FF0000 + 00000000000000000000000000000000000000000000000000004A4A4AFFFFFF + FFFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFD6EFEFFFFFFFFFFF393939FF0000 + 00000000000000000000000000000000000000000000000000004A4A4AFFFFFF + FFFFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DE + D6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFD6EFE7FFFFFFFFFF393939FF0000 + 00000000000000000000000000000000000000000000000000004A4A4AFFFFFF + FFFFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DE + D6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFD6EFE7FFFFFFFFFF393939FF0000 + 00000000000000000000000000000000000000000000000000004A4A4AFFFFFF + FFFFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDE + D6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFCEE7E7FFFFFFFFFF313131FF0000 + 00000000000000000000000000000000000000000000000000004A4A4AFFFFFF + FFFFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFBDDE + D6FFBDDED6FFBDDED6FFBDDED6FFBDDED6FFCEE7E7FFFFFFFFFF313131FF0000 + 0000000000000000000000000000000000000000000000000000424242FFFFFF + FFFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFFC6DEDEFFC6DEDEFFC6E7DEFFC6DEDEFFC6E7DEFFFFFFFFFF313131FF0000 + 0000000000000000000000000000000000000000000000000000424242FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF292929FF0000 + 00000000000000000000000000000000000000000000000000006B6B6BFF2929 + 29FF212121FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF4A4A4AFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000848484FF848484FF8484 + 84FF848484FF848484FF848484FF848484FF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000848484FF9C9C9CFF9C9C9CFF9C9C + 9CFF9C9C9CFF9C9C9CFF9C9C9CFF9C9C9CFF848484FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000848484FF949494FF949494FF9494 + 94FF949494FF949494FF949494FF949494FF848484FF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000007B7B7BFF948C8CFF948C94FF8C8C + 8CFF8C948CFF8C8C94FF8C948CFF8C9494FF7B7B7BFF7B7B7BFF7B7B7BFF7B7B + 7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF7B7B7BFF000000000000 + 000000000000000000000000000000000000737373FF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF6B6B6BFF6B6B6BFF6B6B6BFF6B6B6BFF6B6B6BFF6B6B6BFF6B6B + 6BFF6B6B6BFF000000000000000000000000737373FF848484FF848484FF8484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF6B6B63FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFE7FFF7FFF7FF + FFFFEFFFFFFF8CA5A5FF00000000000000006B6B6BFF848484FF848484FF8484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF6B6B + 63FFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DE + DEFFD6EFE7FF8CA5A5FF0000000000000000636363FF7B7B7BFF7B7B7BFF7B7B + 7BFF737373FF636363FF636363FF636363FF636363FF636363FF636363FF7B94 + 8CFFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFC6DED6FFCEE7 + E7FFBDD6D6FF8CA5A5FF0000000000000000636363FF7B7373FF737373FF7373 + 73FF636363FF7B948CFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFC6DEDEFFBDD6 + D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFBDD6D6FFCEE7DEFFBDD6 + D6FF8CA5A5FF0000000000000000000000005A5A5AFF737373FF737373FF7373 + 73FF636363FFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CE + CEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFB5CECEFFBDD6D6FFC6DE + D6FF8CA5A5FF000000000000000000000000525252FF6B6B6BFF6B6B6BFF5A5A + 5AFF7B948CFFB5CEC6FFB5CEC6FFB5CEC6FFB5CEC6FFB5CEC6FFB5CEC6FFB5CE + C6FFB5CEC6FFB5CEC6FFB5CEC6FFB5CEC6FFBDD6D6FFBDD6CEFFBDD6D6FFC6DE + D6FF8CA5A5FF000000000000000000000000525252FF636363FF636363FF5A5A + 5AFFADC6C6FFADC6BDFFADC6BDFFADC6BDFFADC6BDFFADC6BDFFADC6C6FFADC6 + BDFFADC6BDFFADC6BDFFADC6BDFFB5CECEFFADC6C6FFB5D6CEFFC6DEDEFFBDD6 + D6FF8CA5A5FF0000000000000000000000004A4A4AFF5A6363FF636363FF5A52 + 5AFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BD + BDFFA5BDBDFFA5BDBDFFA5BDBDFFA5BDBDFFB5CEC6FFBDD6D6FFB5CECEFF8CA5 + A5FF00000000000000000000000000000000424242FF5A5A5AFF525252FF7B94 + 8CFFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BDB5FFA5BD + B5FFA5BDB5FFA5BDB5FFA5BDB5FFADC6BDFFA5BDBDFFADC6BDFFADCEC6FF8CA5 + A5FF00000000000000000000000000000000424242FF525252FF525252FF9CB5 + ADFF9CB5ADFF9CB5ADFF9CB5ADFF9CB5ADFF9CB5ADFF9CB5ADFF9CB5ADFF9CB5 + ADFF9CB5ADFF9CB5ADFFA5BDB5FF9CB5B5FFA5BDBDFFADCEC6FFADC6C6FF8CA5 + A5FF00000000000000000000000000000000393939FF525252FF4A4A52FF94AD + ADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94ADADFF94AD + ADFF94ADADFF94ADADFF94ADADFFA5BDB5FF9CB5B5FF9CB5B5FFA5C6BDFF8CA5 + A5FF00000000000000000000000000000000313139FF4A4A4AFF7B948CFF94AD + A5FF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94ADA5FF94AD + A5FF94ADA5FF94ADA5FF9CB5ADFF94ADADFF9CB5B5FF9CBDB5FF8CA5A5FF0000 + 000000000000000000000000000000000000313131FF4A4A4AFF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF94ADADFF8CA5A5FF94ADADFF8CA5A5FF9CBDB5FF8CA5A5FF0000 + 000000000000000000000000000000000000313131FF4A4A4AFF7B948CFF7B94 + 8CFF7B948CFF7B948CFF7B948CFF7B948CFF7B948CFF7B948CFF7B948CFF7B94 + 8CFF7B948CFF7B948CFF7B948CFF7B948CFF94ADADFF8CA5A5FF8CA5A5FF0000 + 0000000000000000000000000000000000000000000042424AFF42424AFF4242 + 4AFF42424AFF42424AFF42424AFF42424AFF42424AFF42424AFF42424AFF4242 + 4AFF42424AFF42424AFF42424AFF42424AFF42424AFF42424AFF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000848484FF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C + 8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8C8C8CFF8484 + 84FF00000000000000000000000000000000848484FFDEF7F7FFA5BDB5FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7F7FF9CB5ADFFB5CE + CEFF737373FF0000000000000000000000007B7B7BFFD6F7EFFFA5BDB5FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94ADA5FFADCE + C6FF6B6B6BFF0000000000000000000000007B7B7BFFD6EFE7FFA5BDB5FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94ADADFFADC6 + C6FF636363FF0000000000000000000000007B7B7BFFCEE7DEFFA5BDB5FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8CA5A5FFADC6 + C6FF5A5A5AFF000000000000000000000000737373FFC6DED6FFA5BDB5FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF849C9CFFA5C6 + BDFF5A5A5AFF000000000000000000000000737373FFB5D6CEFFA5BDB5FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF849C9CFFA5BD + B5FF5A5A5AFF0000000000000000000000006B6B6BFFB5CEC6FF9CB5B5FFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF849C94FF9CBD + B5FF525252FF0000000000000000000000006B6B6BFFADCEC6FF9CB5ADFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7F7FF7B9C94FF9CB5 + B5FF525252FF000000000000000000000000636363FFADC6C6FF94ADADFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7F7FF7B9494FF94AD + ADFF4A4A4AFF0000000000000000000000005A5A5AFFADC6BDFF94ADA5FFE7E7 + E7FFF7F7F7FFF7F7F7FFF7F7F7FFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEF + EFFFEFEFEFFFEFEFEFFFEFEFEFFFF7F7F7FFEFEFEFFFDEDEDEFF73948CFF94AD + ADFF4A4A4AFF0000000000000000000000005A5A5AFFA5C6BDFF8CA59CFF8CA5 + A5FF8CA5A5FF849C9CFF7B948CFF738C84FF738C84FF738C84FF738C84FF738C + 84FF738C84FF738C8CFF738C8CFF738C8CFF738C8CFF738C8CFF6B8484FF8CAD + A5FF424242FF000000000000000000000000525252FFA5BDB5FFA5BDB5FFA5BD + B5FF9CB5B5FF94B5ADFF8CADA5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5A5FF8CA5 + A5FF424242FF000000000000000000000000525252FF9CB5B5FF9CB5ADFF9C9C + 9CFFB5CECEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94ADA5FF7B7B7BFF849C9CFF849C + 9CFF393939FF0000000000000000000000004A4A4AFF94ADA5FF8CA5A5FF7B7B + 7BFF9CB5B5FFFFFFFFFF5A736BFF6B8C84FF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9CB5B5FF6B6B6BFF849C9CFF849C + 9CFF393939FF0000000000000000000000004A4A4AFF94ADA5FF8CA5A5FF7B7B + 7BFF9CB5B5FFFFFFFFFF5A736BFF6B8C84FF8CA5A5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9CB5B5FF6B6B6BFF849C9CFF849C + 9CFF393939FF0000000000000000000000004A4A4AFF849C9CFF7B9C94FF7373 + 73FF94ADADFFFFFFFFFF52736BFF73948CFF94ADADFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94ADADFF6B6B6BFF7B9C94FF7B9C + 94FF313131FF000000000000000000000000424242FF7B9C94FF7B9C94FF6B6B + 6BFF8CADA5FFFFFFFFFF6B847BFF738C8CFF94ADA5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F7F7FF94ADADFF6B6B6BFF7B9C94FF7B9C + 94FF313131FF000000000000000000000000424242FF7B9494FF7B9494FF6B6B + 6BFF8CA59CFFFFFFFFFFE7E7E7FF9CB5ADFFA5BDB5FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFEFEFEFFFEFEFEFFFE7E7E7FF94ADA5FF6B6B6BFF7B9494FF7B94 + 94FF292929FF000000000000000000000000393939FF7B9494FF7B9494FF6363 + 63FF738C8CFFE7E7E7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFF7F7F7FFE7E7E7FFE7E7E7FFD6D6D6FF6B8C84FF5A5A5AFF7B9494FF7B94 + 94FF292929FF00000000000000000000000000000000292929FF212121FF1818 + 18FF181818FF181818FF181818FF181818FF181818FF181818FF181818FF1818 + 18FF181818FF181818FF181818FF181818FF292929FF292929FF212121FF2121 + 21FF000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000007B8C8CFF7B8C8CFF7B8C8CFF7B8C + 8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C + 8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C8CFF7B8C + 8CFF7B8C8CFF0000000000000000000000007B8C8CFF4A5A52FF4A5A52FF4A5A + 52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A + 52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A52FF4A5A + 52FF7B8C8CFF0000000000000000000000007B8C8CFF424A4AFF424A4AFF424A + 4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A + 4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A4AFF424A + 4AFF7B8C8CFF0000000000000000000000007B8C8CFF394242FF394242FF3942 + 42FF394242FF394242FF394242FF394242FF394242FF394242FF394242FF3942 + 42FF394242FF394242FF394242FF394242FF394242FF394242FFA5ADADFFA5AD + ADFF7B8C8CFF000000000000000000000000848C8CFF313939FF313939FF3139 + 39FF313939FF313939FF313939FF313939FF313939FF313939FFCED6D6FF3139 + 39FF313939FF313939FF313939FF313939FF313939FF313939FF313939FF3139 + 39FF848C8CFF000000000000000000000000848C8CFF293131FF293131FF2931 + 31FF293131FF293131FF293131FF293131FF293131FF293131FFD6DEDEFF2931 + 31FF293131FF293131FF293131FF293131FF293131FF293131FF293131FF2931 + 31FF848C8CFF000000000000000000000000848C84FFDEE7E7FFDEE7E7FFDEE7 + E7FFDEE7E7FFDEE7E7FFDEE7E7FFDEE7E7FFDEE7E7FFDEE7E7FFDEE7E7FF2129 + 29FF212929FF212929FF212929FF212929FF212929FF212929FFB5BDB5FFB5BD + B5FF848C84FF000000000000000000000000848484FF182118FF182118FF1821 + 18FF182118FF182118FF182118FF182118FF182118FF182118FF182118FF1821 + 18FF182118FF182118FF182118FF182118FF182118FF182118FF182118FF1821 + 18FF848484FF000000000000000000000000848484FF101810FF101810FF1018 + 10FF101810FF101810FF101810FF101810FF101810FF101810FF101810FF1018 + 10FF101810FF101810FF101810FF101810FF101810FF101810FF101810FF1018 + 10FF848484FF000000000000000000000000848484FF081010FF081010FF0810 + 10FF081010FF081010FF081010FF081010FF081010FF081010FF081010FF0810 + 10FF081010FF081010FF081010FF081010FF081010FF081010FFBDC6C6FFBDC6 + C6FF848484FF000000000000000000000000848484FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF080808FF080808FF080808FF080808FF080808FF080808FF080808FF0808 + 08FF848484FF000000000000000000000000848484FF000000FF000000FF0000 + 00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000 + 00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000 + 00FF848484FF000000000000000000000000848484FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF0000FFFF00 + 00FFFF0000FFFF0000FFFFFFFFFF000000FF000000FF000000FFC6C6C6FFC6C6 + C6FF848484FF000000000000000000000000848484FFFFFFFFFFFF0000FFFF00 + 00FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF00 + 00FFFF0000FFFF0000FFFFFFFFFF000000FF000000FF000000FF000000FF0000 + 00FF848484FF000000000000000000000000848484FFFFFFFFFFEF0000FFEF00 + 00FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF0000FFEF00 + 00FFEF0000FFEF0000FFFFFFFFFF000000FF000000FF000000FF000000FF0000 + 00FF848484FF000000000000000000000000848484FFFFFFFFFFD60000FFD600 + 00FFD60000FFD60000FFD60000FFD60000FFD60000FFD60000FFD60000FFD600 + 00FFD60000FFD60000FFFFFFFFFF000000FF000000FF000000FFC6C6C6FFC6C6 + C6FF848484FF000000000000000000000000848484FFFFFFFFFFBD0000FFBD00 + 00FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD0000FFBD00 + 00FFBD0000FFBD0000FFFFFFFFFF000000FF000000FF000000FF000000FF0000 + 00FF848484FF000000000000000000000000848484FFFFFFFFFFA50000FFA500 + 00FFA50000FFA50000FFA50000FFA50000FFA50000FFA50000FFA50000FFA500 + 00FFA50000FFA50000FFFFFFFFFF000000FF000000FF000000FF000000FF0000 + 00FF848484FF000000000000000000000000848484FFFFFFFFFF8C0000FF8C00 + 00FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C0000FF8C00 + 00FF8C0000FF8C0000FFFFFFFFFF000000FF000000FF000000FFC6C6C6FFC6C6 + C6FF848484FF000000000000000000000000848484FFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FF000000FF000000FF000000FF0000 + 00FF848484FF000000000000000000000000848484FF848484FF848484FF8484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF848484FF848484FF848484FF848484FF848484FF848484FF848484FF8484 + 84FF848484FF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000004A5AB5FF4A5AB5FF4A5AB5FF4A5A + B5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5AB5FF4A5A + B5FF3139ADFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF10219CFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF10219CFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139ADFF3139 + ADFF10219CFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A736BFF5A73 + 6BFF5A736BFF5A736BFF5A736BFF5A736BFF42635AFF00000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF294A4AFF00000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF294A4AFF00000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF294A4AFF00000000000000000000 + 0000000000000000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF42635AFF42635AFF42635AFF6B8484FF6B8484FF6B8484FF6B84 + 84FF6B8484FF6B8484FF6B8484FF6B8484FF6B8484FF6B8484FF6B8484FF6B84 + 84FF5A7373FF0000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF42635AFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF42635AFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000004A5AB5FF3139ADFF3139ADFF3139 + ADFF5A736BFF42635AFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000003139ADFF10219CFF10219CFF1021 + 9CFF5A736BFF42635AFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 00005A736BFF42635AFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 00005A736BFF42635AFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 00005A736BFF42635AFF42635AFF42635AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 000042635AFF294A4AFF294A4AFF294A4AFF6B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000006B8484FF5A7373FF5A7373FF5A73 + 73FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A7373FF5A73 + 73FF42635AFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000005A7373FF42635AFF42635AFF4263 + 5AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF42635AFF4263 + 5AFF42635AFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF000000000000000000000000828282FFA8A191FFA8A191FFA8A1 + 91FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A1 + 91FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A1 + 91FF777777FF0000000000000000000000007E7E7EFFA59C8CFFFFFFFFFFA59C + 8CFFA59C8CFFA59C8CFFFFFFFFFFA59C8CFFA59C8CFFA59C8CFFA59C8CFFA59C + 8CFFA59C8CFFA59C8CFFA59C8CFFA59C8CFFA59C8CFFA59C8CFFA59C8CFFA59C + 8CFF686868FF0000000000000000000000007D7D7DFFA19785FFA19785FF665F + 54FFA19785FFA19785FFA19785FF665F54FFA19785FFA19785FFA19785FFA197 + 85FFA19785FFA19785FFA19785FFA19785FFA19785FFA19785FFA19785FFA197 + 85FF616161FF000000000000000000000000787878FF9D9280FF9D9280FF9D92 + 80FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D92 + 80FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D92 + 80FF5E5E5EFF000000000000000000000000757575FF9A8D7AFF9A8D7AFF9A8D + 7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D + 7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D + 7AFF5B5B5BFF000000000000000000000000717171FF998C79FFFFFFFFFF9788 + 75FF978875FF978875FFFFFFFFFF978875FF978875FF978875FF978875FF9788 + 75FF978875FF978875FF978875FF978875FF978875FF978875FF978875FF9788 + 75FF585858FF0000000000000000000000006C6C6CFF93846FFF93846FFF5D53 + 46FF93846FFF93846FFF93846FFF5D5346FF93846FFF93846FFF93846FFF9384 + 6FFF93846FFF93846FFF93846FFF93846FFF93846FFF93846FFF93846FFF9384 + 6FFF555555FF000000000000000000000000686868FF917F6BFF917F6BFF917F + 6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F + 6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F + 6BFF525252FF000000000000000000000000656565FF8E7C66FF8E7C66FF8E7C + 66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FFFFFFFFFF8E7C66FF8E7C + 66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FFFFFFFFFF8E7C + 66FF4C4C4CFF0000000000000000000000005F5F5FFF8B7862FF8B7862FF8B78 + 62FF8B7862FF8B7862FF8B7862FF8B7862FF8B7862FF8B7862FF584C3EFF8B78 + 62FF8B7862FF8B7862FF8B7862FF8B7862FF8B7862FF8B7862FF8B7862FF584C + 3EFF484848FF0000000000000000000000005B5B5BFF8A765FFF8A765FFF8A76 + 5FFF8A765FFF8A765FFF8A765FFF8A765FFF8A765FFF8A765FFF8A765FFF8A76 + 5FFF8A765FFF8A765FFF8A765FFF8A765FFF8A765FFF8A765FFF8A765FFF8A76 + 5FFF454545FF000000000000000000000000555555FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF404040FF000000000000000000000000525252FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF3C3C3CFF0000000000000000000000004C4C4CFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF383838FF0000000000000000000000004C4C4CFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF383838FF000000000000000000000000484848FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF333333FF000000000000000000000000434343FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF323232FF000000000000000000000000404040FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFFFFFFFFFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFFFFFFFFFF8873 + 5DFF2C2C2CFF0000000000000000000000003D3D3DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF56493BFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF5649 + 3BFF2A2A2AFF0000000000000000000000002C2C2CFF2C2C2CFF222222FF1F1F + 1FFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C + 1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF292929FF2A2A2AFF202020FF2525 + 25FF2C2C2CFF0000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF000000000000000000000000828282FFA8A191FFA8A191FFA8A1 + 91FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A1 + 91FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A191FFA8A1 + 91FF777777FF0000000000000000000000007E7E7EFFA59C8CFFFFFFFFFFA59C + 8CFFA59C8CFFA59C8CFFFFFFFFFFA59C8CFFA59C8CFFA59C8CFFFFFFFFFFA59C + 8CFFA59C8CFFA59C8CFFFFFFFFFFA59C8CFFA59C8CFFA59C8CFFFFFFFFFFA59C + 8CFF686868FF0000000000000000000000007D7D7DFFA19785FFA19785FF665F + 54FFA19785FFA19785FFA19785FF665F54FFA19785FFA19785FFA19785FF665F + 54FFA19785FFA19785FFA19785FF665F54FFA19785FFA19785FFA19785FF665F + 54FF616161FF000000000000000000000000787878FF9D9280FF9D9280FF9D92 + 80FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D92 + 80FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D9280FF9D92 + 80FF5E5E5EFF000000000000000000000000757575FF9A8D7AFF9A8D7AFF9A8D + 7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D + 7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D7AFF9A8D + 7AFF5B5B5BFF000000000000000000000000717171FF998C79FFFFFFFFFF9788 + 75FF978875FF978875FFFFFFFFFF978875FF978875FF978875FFFFFFFFFF9788 + 75FF978875FF978875FFFFFFFFFF978875FF978875FF978875FFFFFFFFFF9788 + 75FF585858FF0000000000000000000000006C6C6CFF93846FFF93846FFF5D53 + 46FF93846FFF93846FFF93846FFF5D5346FF93846FFF93846FFF93846FFF5D53 + 46FF93846FFF93846FFF93846FFF5D5346FF93846FFF93846FFF93846FFF5D53 + 46FF555555FF000000000000000000000000686868FF917F6BFF917F6BFF917F + 6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F + 6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F6BFF917F + 6BFF525252FF000000000000000000000000656565FF8E7C66FF8E7C66FF8E7C + 66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C + 66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C66FF8E7C + 66FF4C4C4CFF0000000000000000000000005F5F5FFF8B7862FFFFFFFFFF8B78 + 62FF8B7862FF8B7862FFFFFFFFFF8B7862FF8B7862FF8B7862FFFFFFFFFF8B78 + 62FF8B7862FF8B7862FFFFFFFFFF8B7862FF8B7862FF8B7862FFFFFFFFFF8B78 + 62FF484848FF0000000000000000000000005B5B5BFF8A765FFF8A765FFF574B + 3CFF8A765FFF8A765FFF8A765FFF574B3CFF8A765FFF8A765FFF8A765FFF574B + 3CFF8A765FFF8A765FFF8A765FFF574B3CFF8A765FFF8A765FFF8A765FFF574B + 3CFF454545FF000000000000000000000000555555FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF404040FF000000000000000000000000525252FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF3C3C3CFF0000000000000000000000004C4C4CFF88735DFFFFFFFFFF8873 + 5DFF88735DFF88735DFFFFFFFFFF88735DFF88735DFF88735DFFFFFFFFFF8873 + 5DFF88735DFF88735DFFFFFFFFFF88735DFF88735DFF88735DFFFFFFFFFF8873 + 5DFF383838FF0000000000000000000000004C4C4CFF88735DFF88735DFF5649 + 3BFF88735DFF88735DFF88735DFF56493BFF88735DFF88735DFF88735DFF5649 + 3BFF88735DFF88735DFF88735DFF56493BFF88735DFF88735DFF88735DFF5649 + 3BFF383838FF000000000000000000000000484848FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF333333FF000000000000000000000000434343FF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF88735DFF8873 + 5DFF323232FF000000000000000000000000404040FF88735DFFFFFFFFFF8873 + 5DFF88735DFF88735DFFFFFFFFFF88735DFF88735DFF88735DFFFFFFFFFF8873 + 5DFF88735DFF88735DFFFFFFFFFF88735DFF88735DFF88735DFFFFFFFFFF8873 + 5DFF2C2C2CFF0000000000000000000000003D3D3DFF88735DFF88735DFF5649 + 3BFF88735DFF88735DFF88735DFF56493BFF88735DFF88735DFF88735DFF5649 + 3BFF88735DFF88735DFF88735DFF56493BFF88735DFF88735DFF88735DFF5649 + 3BFF2A2A2AFF0000000000000000000000002C2C2CFF2C2C2CFF222222FF1F1F + 1FFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C + 1CFF1C1C1CFF1C1C1CFF1C1C1CFF1C1C1CFF292929FF2A2A2AFF202020FF2525 + 25FF2C2C2CFF0000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -2410,10 +3567,54 @@ object MainForm: TMainForm 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000006B84 + 84FF6B8484FF6B8484FF00000000000000006B8484FF6B8484FF6B8484FF0000 + 0000000000006B8484FF6B8484FF6B8484FF0000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 + 000042635AFF5A7373FF6B8484FF000000000000000042635AFF5A7373FF6B84 + 84FF000000000000000042635AFF5A7373FF6B8484FF00000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000042635AFF5A7373FF6B8484FF000000000000000042635AFF5A73 + 73FF6B8484FF000000000000000042635AFF5A7373FF6B8484FF000000000000 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000042635AFF5A7373FF6B8484FF00000000000000004263 + 5AFF5A7373FF6B8484FF000000000000000042635AFF5A7373FF6B8484FF0000 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000005A7373FF5A7373FF6B8484FF000000000000 + 00005A7373FF5A7373FF6B8484FF00000000000000005A7373FF5A7373FF6B84 + 84FF000000000000000000000000000000000000000000000000000000000000 + 000000000000000000006B8484FF5A7373FF42635AFF00000000000000006B84 + 84FF5A7373FF42635AFF00000000000000006B8484FF5A7373FF42635AFF0000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000006B8484FF5A7373FF42635AFF00000000000000006B8484FF5A73 + 73FF42635AFF00000000000000006B8484FF5A7373FF42635AFF000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00006B8484FF5A7373FF42635AFF00000000000000006B8484FF5A7373FF4263 + 5AFF00000000000000006B8484FF5A7373FF42635AFF00000000000000000000 + 0000000000000000000000000000000000000000000000000000000000005A73 + 73FF42635AFF42635AFF00000000000000005A7373FF42635AFF42635AFF0000 + 0000000000005A7373FF42635AFF42635AFF0000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000FF000000FF0000 + 00FF000000FF00000000000000FF000000FF000000FF000000FF000000000000 + 00FF000000FF000000FF000000FF00000000000000FF000000FF000000FF0000 + 00FF000000000000000000000000000000000000000000000000000000FF0000 + 00FF0000000000000000000000FF000000FF0000000000000000000000000000 + 00FF000000FF00000000000000000000000000000000000000FF000000FF0000 + 0000000000000000000000000000000000000000000000000000000000FF0000 + 00FF0000000000000000000000FF000000FF000000FF00000000000000000000 + 00FF000000FF000000FF000000FF0000000000000000000000FF000000FF0000 + 0000000000000000000000000000000000000000000000000000000000FF0000 + 00FF0000000000000000000000FF000000FF0000000000000000000000000000 + 000000000000000000FF000000FF0000000000000000000000FF000000FF0000 + 0000000000000000000000000000000000000000000000000000000000FF0000 + 00FF0000000000000000000000FF000000FF000000FF000000FF000000000000 + 00FF000000FF000000FF000000FF0000000000000000000000FF000000FF0000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -2429,1006 +3630,111 @@ object MainForm: TMainForm 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000008D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D9CFF8D9D + 9CFF8D9D9CFF000000000000000000000000828282FF9D9D9DFFF4F4F4FFC8C8 + C8FF737373FFF4F4F4FFF0F0F0FFADADADFFADADADFFF4F4F4FFADADADFFF4F4 + F4FF9D9D9DFFEAEAEAFFC8C8C8FFF4F4F4FF9D9D9DFFEAEAEAFFBCBCBCFFDDDD + DDFF777777FF0000000000000000000000007E7E7EFF9D9D9DFFF0F0F0FF9D9D + 9DFFADADADFFF4F4F4FFC8C8C8FFEAEAEAFF9D9D9DFFF4F4F4FF898989FFADAD + ADFFADADADFFDDDDDDFFDDDDDDFFF4F4F4FFADADADFFF4F4F4FFDDDDDDFFDDDD + DDFF686868FF0000000000000000000000007D7D7DFFEAEAEAFF737373FFC8C8 + C8FFADADADFFF4F4F4FF9D9D9DFFADADADFF898989FFD4D4D4FFADADADFFF4F4 + F4FFF4F4F4FFE4E4E4FFC8C8C8FFF4F4F4FFADADADFFF4F4F4FFDDDDDDFFDDDD + DDFF616161FF000000000000000000000000787878FFF4F4F4FF898989FFF4F4 + F4FFC8C8C8FFF4F4F4FFBCBCBCFFF4F4F4FFF4F4F4FFBCBCBCFFC8C8C8FFF4F4 + F4FFF4F4F4FFF4F4F4FFADADADFFADADADFFE4E4E4FFEAEAEAFF9D9D9DFF9D9D + 9DFF5E5E5EFF000000000000000000000000757575FFF2F2F2FFF2F2F2FFF2F2 + F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2 + F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2F2FFF2F2 + F2FF5B5B5BFF000000000000000000000000717171FFC6A069FFC6A069FFC6A0 + 69FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A0 + 69FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A0 + 69FF585858FF0000000000000000000000006C6C6CFFC6A069FFC6A069FFC6A0 + 69FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A0 + 69FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A069FFC6A0 + 69FF555555FF000000000000000000000000686868FFD2B790FFC6A069FFC6A0 + 69FFE9E0D1FFC6A069FFC6A069FFE7DAC6FFD2B790FFC6A069FFE7DAC6FFEEE5 + DAFFDDC9B0FFC6A069FFDDC9B0FFEEE5DAFFCCAD7CFFD2B790FFEEE5DAFFDDC9 + B0FF525252FF000000000000000000000000656565FFEFE8DEFFC2975CFFDAC7 + A8FFFAF8F5FFC2975CFFC2975CFFF3EEE7FFE9DECCFFC2975CFFEDE4D7FFC297 + 5CFFF3EEE7FFC7A56FFFEDE4D7FFC7A56FFFEFE8DEFFCDAE83FFC2975CFFEFE8 + DEFF4C4C4CFF0000000000000000000000005F5F5FFFEEE7DDFFBE9258FFEEE7 + DDFFECE2D5FFBE9258FFDECDB1FFD3B892FFEEE7DDFFBE9258FFEEE7DDFFD8C3 + A5FFF2EDE6FFD8C3A5FFD8C3A5FFBE9258FFECE2D5FFBE9258FFBE9258FFEEE7 + DDFF484848FF0000000000000000000000005B5B5BFFD8C1A0FFEBE0D3FFE7DA + CBFFEBE0D3FFBF9154FFEFE6DCFFEBE1D4FFF5F0EBFFD2B790FFEFE6DCFFD8C1 + A0FFBF9154FFD8C1A0FFDECAB1FFBF9154FFEBE0D3FFBF9154FFEEE5DCFFD2B7 + 90FF454545FF000000000000000000000000555555FFBC8B51FFFBFAF9FFC399 + 63FFEBE1D4FFBC8B51FFEEE5DCFFBC8B51FFC39963FFEEE5DCFFEBE1D4FFBC8B + 51FFBC8B51FFBC8B51FFF2EBE5FFEBE1D4FFDDC9B0FFE2D3BEFFF5EFEBFFEBE1 + D4FF404040FF000000000000000000000000525252FFBC8B51FFBC8B51FFBC8B + 51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B + 51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B + 51FF3C3C3CFF0000000000000000000000004C4C4CFFBC8B51FFBC8B51FFBC8B + 51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B + 51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B51FFBC8B + 51FF383838FF0000000000000000000000004C4C4CFFE5E5E5FFE5E5E5FFE5E5 + E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5 + E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5 + E5FF383838FF000000000000000000000000484848FFE5E5E5FFE5E5E5FFE5E5 + E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5 + E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5E5FFE5E5 + E5FF333333FF000000000000000000000000434343FF9E9E9EFFE5E5E5FFDEDE + DEFF0C0C0CFFE5E5E5FFE5E5E5FF232323FFB1B1B1FFE5E5E5FF464646FF6F6F + 6FFF464646FFE5E5E5FF585858FF585858FFB1B1B1FF9E9E9EFF6F6F6FFF6F6F + 6FFF323232FF000000000000000000000000404040FF464646FFE5E5E5FF6F6F + 6FFF464646FFE5E5E5FFD6D6D6FF9E9E9EFF6F6F6FFFE5E5E5FF6F6F6FFFE5E5 + E5FF585858FFCDCDCDFFB1B1B1FFE5E5E5FF585858FFE5E5E5FFDEDEDEFF5858 + 58FF2C2C2CFF0000000000000000000000003D3D3DFF898989FFD6D6D6FF6F6F + 6FFF6F6F6FFFE5E5E5FF898989FFB1B1B1FF323232FFDEDEDEFF464646FF6F6F + 6FFFB1B1B1FFC0C0C0FFC0C0C0FFE5E5E5FF6F6F6FFFD6D6D6FF6F6F6FFF6F6F + 6FFF2A2A2AFF0000000000000000000000002A2A2AFF2A2A2AFF2A2A2AFF2A2A + 2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A + 2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A2AFF2A2A + 2AFF2A2A2AFF0000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000002A2A2A002A2A2A002A2A - 2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A - 2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A2A002A2A - 2A002A2A2A002A2A2A0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000003D3D3D0089898900D6D6 - D6006F6F6F006F6F6F00E5E5E50089898900B1B1B10032323200DEDEDE004646 - 46006F6F6F00B1B1B100C0C0C000C0C0C000E5E5E5006F6F6F00D6D6D6006F6F - 6F006F6F6F002A2A2A0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004040400046464600E5E5 - E5006F6F6F0046464600E5E5E500D6D6D6009E9E9E006F6F6F00E5E5E5006F6F - 6F00E5E5E50058585800CDCDCD00B1B1B100E5E5E50058585800E5E5E500DEDE - DE00585858002C2C2C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000434343009E9E9E00E5E5 - E500DEDEDE000C0C0C00E5E5E500E5E5E50023232300B1B1B100E5E5E5004646 - 46006F6F6F0046464600E5E5E5005858580058585800B1B1B1009E9E9E006F6F - 6F006F6F6F003232320000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000048484800E5E5E500E5E5 - E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5 - E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5 - E500E5E5E5003333330000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004C4C4C00E5E5E500E5E5 - E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5 - E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5E500E5E5 - E500E5E5E5003838380000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004C4C4C00BC8B5100BC8B - 5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B - 5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B - 5100BC8B51003838380000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000052525200BC8B5100BC8B - 5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B - 5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B5100BC8B - 5100BC8B51003C3C3C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000055555500BC8B5100FBFA - F900C3996300EBE1D400BC8B5100EEE5DC00BC8B5100C3996300EEE5DC00EBE1 - D400BC8B5100BC8B5100BC8B5100F2EBE500EBE1D400DDC9B000E2D3BE00F5EF - EB00EBE1D4004040400000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000005B5B5B00D8C1A000EBE0 - D300E7DACB00EBE0D300BF915400EFE6DC00EBE1D400F5F0EB00D2B79000EFE6 - DC00D8C1A000BF915400D8C1A000DECAB100BF915400EBE0D300BF915400EEE5 - DC00D2B790004545450000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000005F5F5F00EEE7DD00BE92 - 5800EEE7DD00ECE2D500BE925800DECDB100D3B89200EEE7DD00BE925800EEE7 - DD00D8C3A500F2EDE600D8C3A500D8C3A500BE925800ECE2D500BE925800BE92 - 5800EEE7DD004848480000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000065656500EFE8DE00C297 - 5C00DAC7A800FAF8F500C2975C00C2975C00F3EEE700E9DECC00C2975C00EDE4 - D700C2975C00F3EEE700C7A56F00EDE4D700C7A56F00EFE8DE00CDAE8300C297 - 5C00EFE8DE004C4C4C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000068686800D2B79000C6A0 - 6900C6A06900E9E0D100C6A06900C6A06900E7DAC600D2B79000C6A06900E7DA - C600EEE5DA00DDC9B000C6A06900DDC9B000EEE5DA00CCAD7C00D2B79000EEE5 - DA00DDC9B0005252520000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000006C6C6C00C6A06900C6A0 - 6900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A0 - 6900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A0 - 6900C6A069005555550000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000071717100C6A06900C6A0 - 6900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A0 - 6900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A06900C6A0 - 6900C6A069005858580000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000075757500F2F2F200F2F2 - F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2 - F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2F200F2F2 - F200F2F2F2005B5B5B0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000078787800F4F4F4008989 - 8900F4F4F400C8C8C800F4F4F400BCBCBC00F4F4F400F4F4F400BCBCBC00C8C8 - C800F4F4F400F4F4F400F4F4F400ADADAD00ADADAD00E4E4E400EAEAEA009D9D - 9D009D9D9D005E5E5E0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007D7D7D00EAEAEA007373 - 7300C8C8C800ADADAD00F4F4F4009D9D9D00ADADAD0089898900D4D4D400ADAD - AD00F4F4F400F4F4F400E4E4E400C8C8C800F4F4F400ADADAD00F4F4F400DDDD - DD00DDDDDD006161610000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007E7E7E009D9D9D00F0F0 - F0009D9D9D00ADADAD00F4F4F400C8C8C800EAEAEA009D9D9D00F4F4F4008989 - 8900ADADAD00ADADAD00DDDDDD00DDDDDD00F4F4F400ADADAD00F4F4F400DDDD - DD00DDDDDD006868680000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000828282009D9D9D00F4F4 - F400C8C8C80073737300F4F4F400F0F0F000ADADAD00ADADAD00F4F4F400ADAD - AD00F4F4F4009D9D9D00EAEAEA00C8C8C800F4F4F4009D9D9D00EAEAEA00BCBC - BC00DDDDDD007777770000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000005A73730042635A004263 - 5A0042635A0042635A0042635A0042635A0042635A0042635A0042635A004263 - 5A0042635A0042635A000000000000000000000000002C2C2C002C2C2C002222 - 22001F1F1F001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C - 1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C00292929002A2A2A002020 - 2000252525002C2C2C000000000000000000000000002C2C2C002C2C2C002222 - 22001F1F1F001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C - 1C001C1C1C001C1C1C001C1C1C001C1C1C001C1C1C00292929002A2A2A002020 - 2000252525002C2C2C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000003D3D3D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D005649 - 3B0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0056493B002A2A2A000000000000000000000000003D3D3D0088735D008873 - 5D0056493B0088735D0088735D0088735D0056493B0088735D0088735D008873 - 5D0056493B0088735D0088735D0088735D0056493B0088735D0088735D008873 - 5D0056493B002A2A2A0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000004040400088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D00FFFFFF008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D00FFFF - FF0088735D002C2C2C000000000000000000000000004040400088735D00FFFF - FF0088735D0088735D0088735D00FFFFFF0088735D0088735D0088735D00FFFF - FF0088735D0088735D0088735D00FFFFFF0088735D0088735D0088735D00FFFF - FF0088735D002C2C2C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000004343430088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D00323232000000000000000000000000004343430088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D003232320000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000042635A00294A4A00294A4A00294A4A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000004848480088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D00333333000000000000000000000000004848480088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D003333330000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000005A736B0042635A0042635A0042635A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000004C4C4C0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D00383838000000000000000000000000004C4C4C0088735D008873 - 5D0056493B0088735D0088735D0088735D0056493B0088735D0088735D008873 - 5D0056493B0088735D0088735D0088735D0056493B0088735D0088735D008873 - 5D0056493B003838380000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000005A736B0042635A0042635A0042635A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000004C4C4C0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D00383838000000000000000000000000004C4C4C0088735D00FFFF - FF0088735D0088735D0088735D00FFFFFF0088735D0088735D0088735D00FFFF - FF0088735D0088735D0088735D00FFFFFF0088735D0088735D0088735D00FFFF - FF0088735D003838380000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000005A736B0042635A0042635A0042635A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000005252520088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D003C3C3C000000000000000000000000005252520088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D003C3C3C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000003139AD0010219C001021 - 9C0010219C005A736B0042635A0042635A0042635A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000005555550088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D00404040000000000000000000000000005555550088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D0088735D0088735D0088735D0088735D0088735D0088735D008873 - 5D0088735D004040400000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B0042635A0042635A0042635A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000005B5B5B008A765F008A76 - 5F008A765F008A765F008A765F008A765F008A765F008A765F008A765F008A76 - 5F008A765F008A765F008A765F008A765F008A765F008A765F008A765F008A76 - 5F008A765F00454545000000000000000000000000005B5B5B008A765F008A76 - 5F00574B3C008A765F008A765F008A765F00574B3C008A765F008A765F008A76 - 5F00574B3C008A765F008A765F008A765F00574B3C008A765F008A765F008A76 - 5F00574B3C004545450000000000000000000000000000000000000000000000 - 00005A73730042635A0042635A0000000000000000005A73730042635A004263 - 5A0000000000000000005A73730042635A0042635A0000000000000000000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B0042635A0042635A0042635A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A000000000000000000000000005F5F5F008B7862008B78 - 62008B7862008B7862008B7862008B7862008B7862008B7862008B786200584C - 3E008B7862008B7862008B7862008B7862008B7862008B7862008B7862008B78 - 6200584C3E00484848000000000000000000000000005F5F5F008B786200FFFF - FF008B7862008B7862008B786200FFFFFF008B7862008B7862008B786200FFFF - FF008B7862008B7862008B786200FFFFFF008B7862008B7862008B786200FFFF - FF008B7862004848480000000000000000000000000000000000000000000000 - 0000000000006B8484005A73730042635A0000000000000000006B8484005A73 - 730042635A0000000000000000006B8484005A73730042635A00000000000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B0042635A0042635A0042635A006B8484005A7373005A73 - 73005A7373005A7373005A7373005A7373005A7373005A7373005A7373005A73 - 73005A73730042635A00000000000000000000000000656565008E7C66008E7C - 66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C6600FFFFFF008E7C - 66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C6600FFFF - FF008E7C66004C4C4C00000000000000000000000000656565008E7C66008E7C - 66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C - 66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C66008E7C - 66008E7C66004C4C4C0000000000000000000000000000000000000000000000 - 000000000000000000006B8484005A73730042635A0000000000000000006B84 - 84005A73730042635A0000000000000000006B8484005A73730042635A000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B0042635A0042635A0042635A006B8484006B8484006B84 - 84006B8484006B8484006B8484006B8484006B8484006B8484006B8484006B84 - 84006B8484005A73730000000000000000000000000068686800917F6B00917F - 6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F - 6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F - 6B00917F6B005252520000000000000000000000000068686800917F6B00917F - 6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F - 6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F6B00917F - 6B00917F6B005252520000000000000000000000000000000000000000000000 - 00000000000000000000000000006B8484005A73730042635A00000000000000 - 00006B8484005A73730042635A0000000000000000006B8484005A7373004263 - 5A0000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B0042635A0042635A0042635A0042635A0042635A004263 - 5A0042635A0042635A0042635A0042635A0042635A00294A4A00000000000000 - 000000000000000000000000000000000000000000006C6C6C0093846F009384 - 6F005D53460093846F0093846F0093846F005D53460093846F0093846F009384 - 6F0093846F0093846F0093846F0093846F0093846F0093846F0093846F009384 - 6F0093846F00555555000000000000000000000000006C6C6C0093846F009384 - 6F005D53460093846F0093846F0093846F005D53460093846F0093846F009384 - 6F005D53460093846F0093846F0093846F005D53460093846F0093846F009384 - 6F005D5346005555550000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000005A7373005A7373006B8484000000 - 0000000000005A7373005A7373006B84840000000000000000005A7373005A73 - 73006B848400000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B0042635A0042635A0042635A0042635A0042635A004263 - 5A0042635A0042635A0042635A0042635A0042635A00294A4A00000000000000 - 0000000000000000000000000000000000000000000071717100998C7900FFFF - FF00978875009788750097887500FFFFFF009788750097887500978875009788 - 7500978875009788750097887500978875009788750097887500978875009788 - 7500978875005858580000000000000000000000000071717100998C7900FFFF - FF00978875009788750097887500FFFFFF00978875009788750097887500FFFF - FF00978875009788750097887500FFFFFF00978875009788750097887500FFFF - FF00978875005858580000000000000000000000000000000000000000000000 - 000000000000000000000000000042635A005A7373006B848400000000000000 - 000042635A005A7373006B848400000000000000000042635A005A7373006B84 - 840000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B0042635A0042635A0042635A0042635A0042635A004263 - 5A0042635A0042635A0042635A0042635A0042635A00294A4A00000000000000 - 00000000000000000000000000000000000000000000757575009A8D7A009A8D - 7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D - 7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D - 7A009A8D7A005B5B5B00000000000000000000000000757575009A8D7A009A8D - 7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D - 7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D7A009A8D - 7A009A8D7A005B5B5B0000000000000000000000000000000000000000000000 - 0000000000000000000042635A005A7373006B84840000000000000000004263 - 5A005A7373006B848400000000000000000042635A005A7373006B8484000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD005A736B005A736B005A736B005A736B005A736B005A736B005A73 - 6B005A736B005A736B005A736B005A736B005A736B0042635A00000000000000 - 00000000000000000000000000000000000000000000787878009D9280009D92 - 80009D9280009D9280009D9280009D9280009D9280009D9280009D9280009D92 - 80009D9280009D9280009D9280009D9280009D9280009D9280009D9280009D92 - 80009D9280005E5E5E00000000000000000000000000787878009D9280009D92 - 80009D9280009D9280009D9280009D9280009D9280009D9280009D9280009D92 - 80009D9280009D9280009D9280009D9280009D9280009D9280009D9280009D92 - 80009D9280005E5E5E0000000000000000000000000000000000000000000000 - 00000000000042635A005A7373006B848400000000000000000042635A005A73 - 73006B848400000000000000000042635A005A7373006B848400000000000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD003139AD003139AD003139AD003139AD003139AD003139AD003139 - AD003139AD0010219C0000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007D7D7D00A1978500A197 - 8500665F5400A1978500A1978500A1978500665F5400A1978500A1978500A197 - 8500A1978500A1978500A1978500A1978500A1978500A1978500A1978500A197 - 8500A1978500616161000000000000000000000000007D7D7D00A1978500A197 - 8500665F5400A1978500A1978500A1978500665F5400A1978500A1978500A197 - 8500665F5400A1978500A1978500A1978500665F5400A1978500A1978500A197 - 8500665F54006161610000000000000000000000000000000000000000000000 - 00006B8484006B8484006B84840000000000000000006B8484006B8484006B84 - 840000000000000000006B8484006B8484006B84840000000000000000000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD003139AD003139AD003139AD003139AD003139AD003139AD003139 - AD003139AD0010219C0000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007E7E7E00A59C8C00FFFF - FF00A59C8C00A59C8C00A59C8C00FFFFFF00A59C8C00A59C8C00A59C8C00A59C - 8C00A59C8C00A59C8C00A59C8C00A59C8C00A59C8C00A59C8C00A59C8C00A59C - 8C00A59C8C00686868000000000000000000000000007E7E7E00A59C8C00FFFF - FF00A59C8C00A59C8C00A59C8C00FFFFFF00A59C8C00A59C8C00A59C8C00FFFF - FF00A59C8C00A59C8C00A59C8C00FFFFFF00A59C8C00A59C8C00A59C8C00FFFF - FF00A59C8C006868680000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004A5AB5003139AD003139 - AD003139AD003139AD003139AD003139AD003139AD003139AD003139AD003139 - AD003139AD0010219C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000082828200A8A19100A8A1 - 9100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A1 - 9100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A1 - 9100A8A191007777770000000000000000000000000082828200A8A19100A8A1 - 9100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A1 - 9100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A19100A8A1 - 9100A8A191007777770000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004A5AB5004A5AB5004A5A - B5004A5AB5004A5AB5004A5AB5004A5AB5004A5AB5004A5AB5004A5AB5004A5A - B5004A5AB5003139AD0000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C000000000000000000000000008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D9C008D9D - 9C008D9D9C008D9D9C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000006B6B - 6B00292929002121210018181800181818001818180018181800181818001818 - 1800181818001818180018181800181818001818180018181800181818004A4A - 4A0000000000000000000000000000000000000000000000000042424A004242 - 4A0042424A0042424A0042424A0042424A0042424A0042424A0042424A004242 - 4A0042424A0042424A0042424A0042424A0042424A0042424A0042424A000000 - 0000000000000000000000000000000000000000000000000000292929002121 - 2100181818001818180018181800181818001818180018181800181818001818 - 1800181818001818180018181800181818001818180029292900292929002121 - 2100212121000000000000000000000000000000000084848400848484008484 - 8400848484008484840084848400848484008484840084848400848484008484 - 8400848484008484840084848400848484008484840084848400848484008484 - 8400848484008484840000000000000000000000000000000000000000004242 - 4200FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF002929 - 29000000000000000000000000000000000000000000313131004A4A4A007B94 - 8C007B948C007B948C007B948C007B948C007B948C007B948C007B948C007B94 - 8C007B948C007B948C007B948C007B948C007B948C0094ADAD008CA5A5008CA5 - A5000000000000000000000000000000000000000000393939007B9494007B94 - 940063636300738C8C00E7E7E700FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00F7F7F700E7E7E700E7E7E700D6D6D6006B8C84005A5A5A007B94 - 94007B9494002929290000000000000000000000000084848400FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000000000000000000000000000 - 0000000000008484840000000000000000000000000000000000000000004242 - 4200FFFFFF00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DE - DE00C6DEDE00C6DEDE00C6DEDE00C6E7DE00C6DEDE00C6E7DE00FFFFFF003131 - 31000000000000000000000000000000000000000000313131004A4A4A008CA5 - A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5 - A5008CA5A5008CA5A50094ADAD008CA5A50094ADAD008CA5A5009CBDB5008CA5 - A5000000000000000000000000000000000000000000424242007B9494007B94 - 94006B6B6B008CA59C00FFFFFF00E7E7E7009CB5AD00A5BDB500FFFFFF00FFFF - FF00FFFFFF00FFFFFF00EFEFEF00EFEFEF00E7E7E70094ADA5006B6B6B007B94 - 94007B9494002929290000000000000000000000000084848400FFFFFF008C00 - 00008C0000008C0000008C0000008C0000008C0000008C0000008C0000008C00 - 00008C0000008C0000008C000000FFFFFF00000000000000000000000000C6C6 - C600C6C6C6008484840000000000000000000000000000000000000000004A4A - 4A00FFFFFF00BDDED600BDDED600BDDED600BDDED600BDDED600BDDED600BDDE - D600BDDED600BDDED600BDDED600BDDED600BDDED600CEE7E700FFFFFF003131 - 31000000000000000000000000000000000000000000313139004A4A4A007B94 - 8C0094ADA50094ADA50094ADA50094ADA50094ADA50094ADA50094ADA50094AD - A50094ADA50094ADA50094ADA5009CB5AD0094ADAD009CB5B5009CBDB5008CA5 - A5000000000000000000000000000000000000000000424242007B9C94007B9C - 94006B6B6B008CADA500FFFFFF006B847B00738C8C0094ADA500FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F7F7F70094ADAD006B6B6B007B9C - 94007B9C94003131310000000000000000000000000084848400FFFFFF00A500 - 0000A5000000A5000000A5000000A5000000A5000000A5000000A5000000A500 - 0000A5000000A5000000A5000000FFFFFF000000000000000000000000000000 - 0000000000008484840000000000000000000000000000000000000000004A4A - 4A00FFFFFF00BDDED600BDDED600BDDED600BDDED600BDDED600BDDED600BDDE - D600BDDED600BDDED600BDDED600BDDED600BDDED600CEE7E700FFFFFF003131 - 3100000000000000000000000000000000000000000039393900525252004A4A - 520094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094ADAD0094AD - AD0094ADAD0094ADAD0094ADAD0094ADAD00A5BDB5009CB5B5009CB5B500A5C6 - BD008CA5A500000000000000000000000000000000004A4A4A00849C9C007B9C - 94007373730094ADAD00FFFFFF0052736B0073948C0094ADAD00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0094ADAD006B6B6B007B9C - 94007B9C94003131310000000000000000000000000084848400FFFFFF00BD00 - 0000BD000000BD000000BD000000BD000000BD000000BD000000BD000000BD00 - 0000BD000000BD000000BD000000FFFFFF000000000000000000000000000000 - 0000000000008484840000000000000000000000000000000000000000004A4A - 4A00FFFFFF00C6DED600C6DED600C6DED600C6DED600C6DED600C6DED600C6DE - D600C6DED600C6DED600C6DED600C6DED600C6DED600D6EFE700FFFFFF003939 - 3900000000000000000000000000000000000000000042424200525252005252 - 52009CB5AD009CB5AD009CB5AD009CB5AD009CB5AD009CB5AD009CB5AD009CB5 - AD009CB5AD009CB5AD009CB5AD00A5BDB5009CB5B500A5BDBD00ADCEC600ADC6 - C6008CA5A500000000000000000000000000000000004A4A4A0094ADA5008CA5 - A5007B7B7B009CB5B500FFFFFF005A736B006B8C84008CA5A500FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF009CB5B5006B6B6B00849C - 9C00849C9C003939390000000000000000000000000084848400FFFFFF00D600 - 0000D6000000D6000000D6000000D6000000D6000000D6000000D6000000D600 - 0000D6000000D6000000D6000000FFFFFF00000000000000000000000000C6C6 - C600C6C6C6008484840000000000000000000000000000000000000000004A4A - 4A00FFFFFF00C6DED600C6DED600C6DED600C6DED600C6DED600C6DED600C6DE - D600C6DED600C6DED600C6DED600C6DED600C6DED600D6EFE700FFFFFF003939 - 39000000000000000000000000000000000000000000424242005A5A5A005252 - 52007B948C00A5BDB500A5BDB500A5BDB500A5BDB500A5BDB500A5BDB500A5BD - B500A5BDB500A5BDB500A5BDB500A5BDB500ADC6BD00A5BDBD00ADC6BD00ADCE - C6008CA5A500000000000000000000000000000000004A4A4A0094ADA5008CA5 - A5007B7B7B009CB5B500FFFFFF005A736B006B8C84008CA5A500FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF009CB5B5006B6B6B00849C - 9C00849C9C003939390000000000000000000000000084848400FFFFFF00EF00 - 0000EF000000EF000000EF000000EF000000EF000000EF000000EF000000EF00 - 0000EF000000EF000000EF000000FFFFFF000000000000000000000000000000 - 0000000000008484840000000000000000000000000000000000000000004A4A - 4A00FFFFFF00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DE - DE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00D6EFEF00FFFFFF003939 - 390000000000000000000000000000000000000000004A4A4A005A6363006363 - 63005A525A00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BD - BD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00A5BDBD00B5CEC600BDD6D600B5CE - CE008CA5A50000000000000000000000000000000000525252009CB5B5009CB5 - AD009C9C9C00B5CECE00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0094ADA5007B7B7B00849C - 9C00849C9C003939390000000000000000000000000084848400FFFFFF00FF00 - 0000FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF00 - 0000FF000000FF000000FF000000FFFFFF000000000000000000000000000000 - 0000000000008484840000000000000000000000000000000000000000005252 - 5200FFFFFF00C6E7DE00C6E7DE00C6E7DE00C6E7DE00C6E7DE00C6E7DE00C6E7 - DE00C6E7DE00C6E7DE00C6E7DE00C6E7DE00C6E7DE00D6F7EF00FFFFFF003939 - 3900000000000000000000000000000000000000000052525200636363006363 - 63005A5A5A00ADC6C600ADC6BD00ADC6BD00ADC6BD00ADC6BD00ADC6BD00ADC6 - C600ADC6BD00ADC6BD00ADC6BD00ADC6BD00B5CECE00ADC6C600B5D6CE00C6DE - DE00BDD6D6008CA5A50000000000000000000000000052525200A5BDB500A5BD - B500A5BDB5009CB5B50094B5AD008CADA5008CA5A5008CA5A5008CA5A5008CA5 - A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5A5008CA5 - A5008CA5A5004242420000000000000000000000000084848400FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FF000000FF00 - 0000FF000000FF000000FF000000FFFFFF00000000000000000000000000C6C6 - C600C6C6C6008484840000000000000000000000000000000000000000005A5A - 5A00FFFFFF00CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7 - E700CEE7E700CEE7E700CEE7E700CEE7E700CEE7E700DEF7F700FFFFFF004242 - 42000000000000000000000000000000000000000000525252006B6B6B006B6B - 6B005A5A5A007B948C00B5CEC600B5CEC600B5CEC600B5CEC600B5CEC600B5CE - C600B5CEC600B5CEC600B5CEC600B5CEC600B5CEC600BDD6D600BDD6CE00BDD6 - D600C6DED6008CA5A5000000000000000000000000005A5A5A00A5C6BD008CA5 - 9C008CA5A5008CA5A500849C9C007B948C00738C8400738C8400738C8400738C - 8400738C8400738C8400738C8C00738C8C00738C8C00738C8C00738C8C006B84 - 84008CADA5004242420000000000000000000000000084848400000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000008484840000000000000000000000000000000000000000005A5A - 5A00FFFFFF00D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700D6EF - E700D6EFE700D6EFE700D6EFE700D6EFE700D6EFE700DEF7F700FFFFFF004242 - 420000000000000000000000000000000000000000005A5A5A00737373007373 - 73007373730063636300B5CECE00B5CECE00B5CECE00B5CECE00B5CECE00B5CE - CE00B5CECE00B5CECE00B5CECE00B5CECE00B5CECE00B5CECE00B5CECE00BDD6 - D600C6DED6008CA5A5000000000000000000000000005A5A5A00ADC6BD0094AD - A500E7E7E700F7F7F700F7F7F700F7F7F700EFEFEF00EFEFEF00EFEFEF00EFEF - EF00EFEFEF00EFEFEF00EFEFEF00EFEFEF00F7F7F700EFEFEF00DEDEDE007394 - 8C0094ADAD004A4A4A0000000000000000000000000084848400080808000808 - 0800080808000808080008080800080808000808080008080800080808000808 - 0800080808000808080008080800080808000808080008080800080808000808 - 0800080808008484840000000000000000000000000000000000000000006363 - 6300FFFFFF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EF - EF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00D6EFEF00DEF7F700FFFFFF004A4A - 4A000000000000000000000000000000000000000000636363007B7373007373 - 730073737300636363007B948C00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DE - DE00BDD6D600BDD6D600BDD6D600BDD6D600BDD6D600BDD6D600BDD6D600CEE7 - DE00BDD6D6008CA5A50000000000000000000000000063636300ADC6C60094AD - AD00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F7F7F7007B94 - 940094ADAD004A4A4A0000000000000000000000000084848400081010000810 - 1000081010000810100008101000081010000810100008101000081010000810 - 100008101000081010000810100008101000081010000810100008101000BDC6 - C600BDC6C6008484840000000000000000000000000000000000000000006363 - 6300FFFFFF00D6F7EF00D6F7EF00D6F7EF00D6F7EF00D6F7EF00D6F7EF00D6F7 - EF00D6F7EF00D6F7EF00D6F7EF00D6F7EF00D6F7EF00DEFFF700FFFFFF004A4A - 4A000000000000000000000000000000000000000000636363007B7B7B007B7B - 7B007B7B7B007373730063636300636363006363630063636300636363006363 - 63007B948C00C6DED600C6DED600C6DED600C6DED600C6DED600C6DED600C6DE - D600CEE7E700BDD6D6008CA5A50000000000000000006B6B6B00ADCEC6009CB5 - AD00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F7F7F7007B9C - 94009CB5B5005252520000000000000000000000000084848400101810001018 - 1000101810001018100010181000101810001018100010181000101810001018 - 1000101810001018100010181000101810001018100010181000101810001018 - 1000101810008484840000000000000000000000000000000000000000006B6B - 6B00FFFFFF00DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7 - F700DEF7F700DEF7F700DEF7F700CEEFE700C6DEDE00C6DEDE00DEDEDE005252 - 520000000000000000000000000000000000000000006B6B6B00848484008484 - 8400848484008484840084848400848484008484840084848400848484008484 - 84006B6B6300C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DEDE00C6DE - DE00C6DEDE00D6EFE7008CA5A50000000000000000006B6B6B00B5CEC6009CB5 - B500FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00849C - 94009CBDB5005252520000000000000000000000000084848400182118001821 - 1800182118001821180018211800182118001821180018211800182118001821 - 1800182118001821180018211800182118001821180018211800182118001821 - 1800182118008484840000000000000000000000000000000000000000006B6B - 6B00FFFFFF00DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7 - F700DEF7F700F7F7F700D6D6D600C6C6C600B5B5B500ADADAD009C9C9C005252 - 5200000000000000000000000000000000000000000073737300848484008484 - 8400848484008484840084848400848484008484840084848400848484008484 - 8400848484006B6B6300E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700E7FF - F700F7FFFF00EFFFFF008CA5A500000000000000000073737300B5D6CE00A5BD - B500FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00849C - 9C00A5BDB5005A5A5A00000000000000000000000000848C8400DEE7E700DEE7 - E700DEE7E700DEE7E700DEE7E700DEE7E700DEE7E700DEE7E700DEE7E700DEE7 - E70021292900212929002129290021292900212929002129290021292900B5BD - B500B5BDB500848C840000000000000000000000000000000000000000006B6B - 6B00FFFFFF00DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7F700DEF7 - F700DEF7F700F7F7F700949494008C8C8C0073737300737373005A5A5A005A5A - 5A000000000000000000000000000000000000000000737373008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C006B6B6B006B6B6B006B6B6B006B6B6B006B6B6B006B6B - 6B006B6B6B006B6B6B0000000000000000000000000073737300C6DED600A5BD - B500FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00849C - 9C00A5C6BD005A5A5A00000000000000000000000000848C8C00293131002931 - 310029313100293131002931310029313100293131002931310029313100D6DE - DE00293131002931310029313100293131002931310029313100293131002931 - 310029313100848C8C0000000000000000000000000000000000000000006B6B - 6B00FFFFFF00E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700E7FF - F700E7FFF700F7F7F700A5A5A500FFFFFF00FFFFFF00FFFFFF00FFFFFF005A5A - 5A0000000000000000000000000000000000000000007B7B7B00948C8C00948C - 94008C8C8C008C948C008C8C94008C948C008C9494007B7B7B007B7B7B007B7B - 7B007B7B7B007B7B7B007B7B7B007B7B7B007B7B7B007B7B7B007B7B7B000000 - 000000000000000000000000000000000000000000007B7B7B00CEE7DE00A5BD - B500FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF008CA5 - A500ADC6C6005A5A5A00000000000000000000000000848C8C00313939003139 - 390031393900313939003139390031393900313939003139390031393900CED6 - D600313939003139390031393900313939003139390031393900313939003139 - 390031393900848C8C0000000000000000000000000000000000000000006B6B - 6B00FFFFFF00E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700E7FFF700E7FF - F700E7FFF700F7F7F700B5B5B500FFFFFF00D6F7EF00D6F7EF00B5D6CE006B6B - 6B00000000000000000000000000000000000000000084848400949494009494 - 9400949494009494940094949400949494009494940084848400000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007B7B7B00D6EFE700A5BD - B500FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0094AD - AD00ADC6C600636363000000000000000000000000007B8C8C00394242003942 - 4200394242003942420039424200394242003942420039424200394242003942 - 420039424200394242003942420039424200394242003942420039424200A5AD - AD00A5ADAD007B8C8C0000000000000000000000000000000000000000006B6B - 6B00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00C6C6C600FFFFFF00D6F7EF00B5D6CE006B6B6B000000 - 00000000000000000000000000000000000000000000848484009C9C9C009C9C - 9C009C9C9C009C9C9C009C9C9C009C9C9C009C9C9C0084848400000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007B7B7B00D6F7EF00A5BD - B500FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0094AD - A500ADCEC6006B6B6B000000000000000000000000007B8C8C00424A4A00424A - 4A00424A4A00424A4A00424A4A00424A4A00424A4A00424A4A00424A4A00424A - 4A00424A4A00424A4A00424A4A00424A4A00424A4A00424A4A00424A4A00424A - 4A00424A4A007B8C8C0000000000000000000000000000000000000000006B6B - 6B00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00CECECE00FFFFFF00B5D6CE0073737300000000000000 - 0000000000000000000000000000000000000000000000000000848484008484 - 8400848484008484840084848400848484008484840000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000084848400DEF7F700A5BD - B500FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF - FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00F7F7F7009CB5 - AD00B5CECE00737373000000000000000000000000007B8C8C004A5A52004A5A - 52004A5A52004A5A52004A5A52004A5A52004A5A52004A5A52004A5A52004A5A - 52004A5A52004A5A52004A5A52004A5A52004A5A52004A5A52004A5A52004A5A - 52004A5A52007B8C8C0000000000000000000000000000000000000000007373 - 73007373730073737300737373007B7B7B007B7B7B0084848400848484008484 - 8400848484008484840084848400848484008484840000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000848484008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C8C008C8C - 8C0084848400000000000000000000000000000000007B8C8C007B8C8C007B8C - 8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C - 8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C8C007B8C - 8C007B8C8C007B8C8C0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000424D3E000000000000003E000000 - 2800000060000000600000000100010000000000800400000000000000000000 - 000000000000000000000000FFFFFF0000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000FFFFFF000000000000000000FFFFFF00 - 0000000000000000800003000000000000000000800003000000000000000000 - 8000030000000000000000008000030000000000000000008000030000000000 - 0000000080000300000000000000000080000300000000000000000080000300 - 0000000000000000800003000000000000000000800003000000000000000000 - 8000030000000000000000008000030000000000000000008000030000000000 - 0000000080000300000000000000000080000300000000000000000080000300 - 0000000000000000800003000000000000000000800003000000000000000000 - 8000030000000000000000008000030000000000000000008000030000000000 - 00000000FFFFFF000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFF8003800003800003FFFFFFFF8003800003800003FFFFFF - FF8003800003800003E610CFFF8003800003800003E67CCFF800038000038000 - 03E630CFF80003800003800003E673CFF80003800003800003C21087F8000380 - 0003800003FFFFFF800003800003800003FFFFFF800003800003800003F18C7F - 800003800003800003F8C63F800003800003800003FC631F8000038000038000 - 03FE318F80003F800003800003FF18C780003F800003800003FE318F80003F80 - 0003800003FC631F80003F800003800003F8C63F8003FF800003800003F18C7F - 8003FF800003800003FFFFFF8003FF800003800003FFFFFF8003FF8000038000 - 03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFE0000FC0001FC00007800003E0000F80000F800003800003 - E0000F80000F800003800003E0000F80000F800003800003E0000F8000078000 - 03800003E0000F800007800003800003E0000F800007800003800003E0000F80 - 0007800003800003E0000F800003800003800003E0000F800003800003800003 - E0000F800003800003800003E0000F800003800003800003E0000F8000018000 - 03800003E0000F800001800003800003E0000F800001800003800003E0000F80 - 0003800003800003E0000F80001F800003800003E0000F803FFF800003800003 - E0001F803FFF800003800003E0003FC07FFF800003800003E0007FFFFFFFC000 - 07800003FFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 - 000000000000} + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000 + } end object pmMapTest: TPopupMenu - Left = 160 - Top = 64 + left = 160 + top = 64 object miMapTestPMSet: TMenuItem Caption = 'Параметры' OnClick = miMapTestSettingsClick end end object ColorDialog: TColorDialog - Left = 64 - Top = 146 + Color = clBlack + CustomColors.Strings = ( + 'ColorA=000000' + 'ColorB=000080' + 'ColorC=008000' + 'ColorD=008080' + 'ColorE=800000' + 'ColorF=800080' + 'ColorG=808000' + 'ColorH=808080' + 'ColorI=C0C0C0' + 'ColorJ=0000FF' + 'ColorK=00FF00' + 'ColorL=00FFFF' + 'ColorM=FF0000' + 'ColorN=FF00FF' + 'ColorO=FFFF00' + 'ColorP=FFFFFF' + 'ColorQ=C0DCC0' + 'ColorR=F0CAA6' + 'ColorS=F0FBFF' + 'ColorT=A4A0A0' + ) + left = 64 + top = 146 end end diff --git a/src/editor/f_main.pas b/src/editor/f_main.pas index d319300..9167af7 100644 --- a/src/editor/f_main.pas +++ b/src/editor/f_main.pas @@ -8,10 +8,14 @@ uses LCLIntf, LCLType, LMessages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ImgList, StdCtrls, Buttons, ComCtrls, ValEdit, Types, ToolWin, Menus, ExtCtrls, - CheckLst, Grids; + CheckLst, Grids, OpenGLContext; type + + { TMainForm } + TMainForm = class(TForm) + lLoad: TLabel; // Главное меню: MainMenu: TMainMenu; // "Файл": @@ -77,6 +81,9 @@ type // Панель инструментов: MainToolBar: TToolBar; + pbLoad: TProgressBar; + pLoadProgress: TPanel; + RenderPanel: TOpenGLControl; tbNewMap: TToolButton; tbOpenMap: TToolButton; tbSaveMap: TToolButton; @@ -107,12 +114,6 @@ type // Панель карты: PanelMap: TPanel; - // Панель отображения карты: - RenderPanel: TPanel; - // Панель загрузки: - pLoadProgress: TPanel; - lLoad: TLabel; - pbLoad: TProgressBar; // Полосы прокрутки: sbHorizontal: TScrollBar; sbVertical: TScrollBar; @@ -209,6 +210,7 @@ type procedure RenderPanelMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure RenderPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure RenderPanelMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + procedure RenderPanelPaint(Sender: TObject); procedure RenderPanelResize(Sender: TObject); procedure vleObjectPropertyEditButtonClick(Sender: TObject); procedure vleObjectPropertyGetPickList(Sender: TObject; const KeyName: String; Values: TStrings); @@ -321,14 +323,14 @@ procedure ChangeShownProperty(Name: String; NewValue: String); implementation uses - f_options, e_graphics, e_log, dglOpenGL, Math, + f_options, e_graphics, e_log, GL, GLExt, Math, f_mapoptions, g_basic, f_about, f_mapoptimization, f_mapcheck, f_addresource_texture, g_textures, f_activationtype, f_keys, MAPWRITER, MAPSTRUCT, - MAPREADER, f_selectmap, f_savemap, WADEDITOR, MAPDEF, + MAPREADER, f_selectmap, f_savemap, WADEDITOR, WADSTRUCT, MAPDEF, g_map, f_saveminimap, f_addresource, CONFIG, f_packmap, f_addresource_sound, f_maptest, f_choosetype, - g_language, f_selectlang, ClipBrd, Windows; + g_language, f_selectlang, ClipBrd; const UNDO_DELETE_PANEL = 1; @@ -419,9 +421,8 @@ type TCopyRecArray = Array of TCopyRec; var - hDC: THandle; - hRC: THandle; gEditorFont: DWORD; + gDataLoaded: Boolean = False; ShowMap: Boolean = False; DrawRect: PRect = nil; SnapToGrid: Boolean = True; @@ -1869,7 +1870,7 @@ end; function AddTexture(aWAD, aSection, aTex: String; silent: Boolean): Boolean; var - a: Integer; + a, FrameLen: Integer; ok: Boolean; FileName: String; ResourceName: String; @@ -1940,9 +1941,9 @@ begin if IsAnim(FullResourceName) then begin // Аним. текстура - GetFrame(FullResourceName, Data, Width, Height); + GetFrame(FullResourceName, Data, FrameLen, Width, Height); - if g_CreateTextureMemorySize(Data, ResourceName, 0, 0, Width, Height, 1) then + if g_CreateTextureMemorySize(Data, FrameLen, ResourceName, 0, 0, Width, Height, 1) then a := MainForm.lbTextureList.Items.Add(ResourceName); end else // Обычная текстура @@ -2520,51 +2521,57 @@ begin OptionsForm.ShowModal(); end; -procedure TMainForm.FormCreate(Sender: TObject); +procedure LoadStdFont(cfgres, texture: string; var FontID: DWORD); var - PixelFormat: GLuint; - pfd: TPIXELFORMATDESCRIPTOR; + cwdt, chgt: Byte; + spc: ShortInt; + ID: DWORD; + wad: TWADEditor_1; + cfgdata: Pointer; + cfglen: Integer; config: TConfig; - i: Integer; - s: String; begin - Randomize(); + cfglen := 0; - EditorDir := ExtractFilePath(Application.ExeName); + wad := TWADEditor_1.Create; + if wad.ReadFile(EditorDir+'data\Game.wad') then + wad.GetResource('FONTS', cfgres, cfgdata, cfglen); + wad.Free(); - e_InitLog(EditorDir+'Editor.log', WM_NEWFILE); + if cfglen <> 0 then + begin + if not g_CreateTextureWAD('FONT_STD', EditorDir+'data\Game.wad:FONTS\'+texture) then + e_WriteLog('ERROR ERROR ERROR', MSG_WARNING); - e_WriteLog('Init OpenGL', MSG_NOTIFY); + config := TConfig.CreateMem(cfgdata, cfglen); + cwdt := Min(Max(config.ReadInt('FontMap', 'CharWidth', 0), 0), 255); + chgt := Min(Max(config.ReadInt('FontMap', 'CharHeight', 0), 0), 255); + spc := Min(Max(config.ReadInt('FontMap', 'Kerning', 0), -128), 127); - InitOpenGL(); - hDC := GetDC(RenderPanel.Handle); + if g_GetTexture('FONT_STD', ID) then + e_TextureFontBuild(ID, FontID, cwdt, chgt, spc-2); - FillChar(pfd, SizeOf(pfd), 0); - with pfd do - begin - nSize := SizeOf(pfd); - nVersion := 1; - dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER; - dwLayerMask := PFD_MAIN_PLANE; - iPixelType := PFD_TYPE_RGBA; - cColorBits := 24; - cDepthBits := 32; - iLayerType := PFD_MAIN_PLANE; - end; - PixelFormat := ChoosePixelFormat (hDC, @pfd); - SetPixelFormat(hDC, PixelFormat, @pfd); + config.Free(); + end + else + e_WriteLog('Could not load FONT_STD', MSG_WARNING); - hRC := wglCreateContext(hDC); - ActivateRenderingContext(hDC, hRC); + if cfglen <> 0 then FreeMem(cfgdata); +end; - e_InitGL(False); +procedure TMainForm.FormCreate(Sender: TObject); +var + config: TConfig; + i: Integer; + s: String; +begin + Randomize(); - gEditorFont := e_SimpleFontCreate('Arial Cyr', 12, FW_BOLD, hDC); + EditorDir := ExtractFilePath(Application.ExeName); - slInvalidTextures := TStringList.Create; + e_InitLog(EditorDir+'Editor.log', WM_NEWFILE); - e_WriteLog('Loading data', MSG_NOTIFY); - LoadData(); + slInvalidTextures := TStringList.Create; ShowLayer(LAYER_BACK, True); ShowLayer(LAYER_WALLS, True); @@ -2657,9 +2664,14 @@ begin Application.OnIdle := OnIdle; end; +procedure PrintBlack(X, Y: Integer; Text: string; FontID: DWORD); +begin + // NOTE: all the font printing routines assume CP1251 + e_TextureFontPrintEx(X, Y, Text, FontID, 0, 0, 0, 1.0); +end; + procedure TMainForm.Draw(); var - ps: TPaintStruct; x, y: Integer; a, b: Integer; ID: DWORD; @@ -2668,7 +2680,6 @@ var ObjCount: Word; aX, aY, aX2, aY2, XX, ScaleSz: Integer; begin - BeginPaint(Handle, ps); e_BeginRender(); e_Clear(GL_COLOR_BUFFER_BIT, @@ -2755,7 +2766,7 @@ begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_TELEPORT]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_TELEPORT], gEditorFont); end; // Подсказка при выборе точки появления: @@ -2766,7 +2777,7 @@ begin 0, 0, 255); e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_SPAWN]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_SPAWN], gEditorFont); end; // Подсказка при выборе панели двери: @@ -2774,7 +2785,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_DOOR]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_DOOR], gEditorFont); end; // Подсказка при выборе панели с текстурой: @@ -2782,7 +2793,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+196, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+196, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_TEXTURE]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_TEXTURE], gEditorFont); end; // Подсказка при выборе панели индикации выстрела: @@ -2790,7 +2801,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+316, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+316, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_SHOT]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_SHOT], gEditorFont); end; // Подсказка при выборе панели лифта: @@ -2798,7 +2809,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+180, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_PANEL_LIFT]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_PANEL_LIFT], gEditorFont); end; // Подсказка при выборе монстра: @@ -2806,7 +2817,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+120, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+120, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_MONSTER]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_MONSTER], gEditorFont); end; // Подсказка при выборе области воздействия: @@ -2814,7 +2825,7 @@ begin begin e_DrawFillQuad(MousePos.X, MousePos.Y, MousePos.X+204, MousePos.Y+18, 192, 192, 192, 127); e_DrawQuad(MousePos.X, MousePos.Y, MousePos.X+204, MousePos.Y+18, 255, 255, 255); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(_lc[I_HINT_EXT_AREA]), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, _glc[I_HINT_EXT_AREA], gEditorFont); end; // Рисуем текстуры, если чертим панель: @@ -2844,10 +2855,10 @@ begin if MouseAction in [MOUSEACTION_DRAWPANEL, MOUSEACTION_DRAWTRIGGER] then begin // Чертим новый - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(Format(_lc[I_HINT_WIDTH], - [Abs(MousePos.X-MouseLDownPos.X)])), gEditorFont, 0, 0, 0); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+28, PChar(Format(_lc[I_HINT_HEIGHT], - [Abs(MousePos.Y-MouseLDownPos.Y)])), gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, Format(_glc[I_HINT_WIDTH], + [Abs(MousePos.X-MouseLDownPos.X)]), gEditorFont); + PrintBlack(MousePos.X+2, MousePos.Y+14, Format(_glc[I_HINT_HEIGHT], + [Abs(MousePos.Y-MouseLDownPos.Y)]), gEditorFont); end else // Растягиваем существующий if SelectedObjects[GetFirstSelected].ObjectType in [OBJECT_PANEL, OBJECT_TRIGGER] then @@ -2863,10 +2874,10 @@ begin Height := gTriggers[SelectedObjects[GetFirstSelected].ID].Height; end; - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+14, PChar(Format(_lc[I_HINT_WIDTH], [Width])), - gEditorFont, 0, 0, 0); - e_SimpleFontPrint(MousePos.X+8, MousePos.Y+28, PChar(Format(_lc[I_HINT_HEIGHT], [Height])), - gEditorFont, 0, 0, 0); + PrintBlack(MousePos.X+2, MousePos.Y+2, Format(_glc[I_HINT_WIDTH], [Width]), + gEditorFont); + PrintBlack(MousePos.X+2, MousePos.Y+14, Format(_glc[I_HINT_HEIGHT], [Height]), + gEditorFont); end; end; @@ -2962,8 +2973,7 @@ begin end; // Мини-карта e_EndRender(); - SwapBuffers(hDC); - EndPaint(Handle, ps); + RenderPanel.SwapBuffers(); end; procedure TMainForm.FormResize(Sender: TObject); @@ -3616,7 +3626,7 @@ begin trigger.Key := Trigger.Key or KEY_BLUETEAM; // Параметры триггера: - ZeroMemory(@trigger.Data.Default[0], 128); + FillByte(trigger.Data.Default[0], 128, 0); case trigger.TriggerType of // Переключаемая панель: @@ -3837,6 +3847,11 @@ begin end; end; +procedure TMainForm.RenderPanelPaint(Sender: TObject); +begin + Draw(); +end; + procedure TMainForm.RenderPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var @@ -3909,8 +3924,10 @@ begin begin if DrawRect = nil then New(DrawRect); - DrawRect.TopLeft := MouseRDownPos; - DrawRect.BottomRight := MousePos; + DrawRect.Top := MouseRDownPos.y; + DrawRect.Left := MouseRDownPos.x; + DrawRect.Bottom := MousePos.y; + DrawRect.Right := MousePos.x; end else // Двигаем выделенные объекты: @@ -3959,8 +3976,10 @@ begin begin if DrawRect = nil then New(DrawRect); - DrawRect.TopLeft := MouseLDownPos; - DrawRect.BottomRight := MousePos; + DrawRect.Top := MouseLDownPos.y; + DrawRect.Left := MouseLDownPos.x; + DrawRect.Bottom := MousePos.y; + DrawRect.Right := MousePos.x; end else // Двигаем карту: if MouseAction = MOUSEACTION_MOVEMAP then @@ -3983,7 +4002,7 @@ begin CanClose := MessageBox(0, PChar(_lc[I_MSG_EXIT_PROMT]), PChar(_lc[I_MSG_EXIT]), MB_ICONQUESTION or MB_YESNO or - MB_TASKMODAL or MB_DEFBUTTON1) = idYes; + MB_DEFBUTTON1) = idYes; end; procedure TMainForm.aExitExecute(Sender: TObject); @@ -4023,8 +4042,6 @@ begin config.Free(); slInvalidTextures.Free; - - wglDeleteContext(hRC); end; procedure TMainForm.RenderPanelResize(Sender: TObject); @@ -4632,9 +4649,9 @@ begin TRIGGER_EXIT: begin s := vleObjectProperty.Values[_lc[I_PROP_TR_NEXT_MAP]]; - ZeroMemory(@Data.MapName[0], 16); + FillByte(Data.MapName[0], 16, 0); if s <> '' then - CopyMemory(@Data.MapName[0], @s[1], Min(Length(s), 16)); + Move(Data.MapName[0], s[1], Min(Length(s), 16)); end; TRIGGER_TEXTURE: @@ -4671,9 +4688,9 @@ begin TRIGGER_SOUND: begin s := vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_NAME]]; - ZeroMemory(@Data.SoundName[0], 64); + FillByte(Data.SoundName[0], 64, 0); if s <> '' then - CopyMemory(@Data.SoundName[0], @s[1], Min(Length(s), 64)); + Move(Data.SoundName[0], s[1], Min(Length(s), 64)); Data.Volume := Min(StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_VOLUME]], 0), 255); Data.Pan := Min(StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_SOUND_PAN]], 0), 255); @@ -4725,9 +4742,9 @@ begin TRIGGER_MUSIC: begin s := vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_NAME]]; - ZeroMemory(@Data.MusicName[0], 64); + FillByte(Data.MusicName[0], 64, 0); if s <> '' then - CopyMemory(@Data.MusicName[0], @s[1], Min(Length(s), 64)); + Move(Data.MusicName[0], s[1], Min(Length(s), 64)); if vleObjectProperty.Values[_lc[I_PROP_TR_MUSIC_ACT]] = _lc[I_PROP_TR_MUSIC_ON] then Data.MusicAction := 1 @@ -4785,9 +4802,9 @@ begin Data.MessageSendTo := 5; s := vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TEXT]]; - ZeroMemory(@Data.MessageText[0], 100); + FillByte(Data.MessageText[0], 100, 0); if s <> '' then - CopyMemory(@Data.MessageText[0], @s[1], Min(Length(s), 100)); + Move(Data.MessageText[0], s[1], Min(Length(s), 100)); Data.MessageTime := Min(Max( StrToIntDef(vleObjectProperty.Values[_lc[I_PROP_TR_MESSAGE_TIME]], 0), 0), 65535); @@ -4915,7 +4932,7 @@ begin [SelectedTexture()])), PChar(_lc[I_MSG_DEL_TEXTURE]), MB_ICONQUESTION or MB_YESNO or - MB_TASKMODAL or MB_DEFBUTTON1) <> idYes then + MB_DEFBUTTON1) <> idYes then Exit; if gPanels <> nil then @@ -4940,7 +4957,7 @@ begin if (MessageBox(0, PChar(_lc[I_MSG_CLEAR_MAP_PROMT]), PChar(_lc[I_MSG_CLEAR_MAP]), MB_ICONQUESTION or MB_YESNO or - MB_TASKMODAL or MB_DEFBUTTON1) = mrYes) then + MB_DEFBUTTON1) = mrYes) then FullClear(); end; @@ -5761,13 +5778,13 @@ begin begin str := SelectMapForm.lbMapList.Items[SelectMapForm.lbMapList.ItemIndex]; MapName := ''; - CopyMemory(@MapName[0], @str[1], Min(16, Length(str))); + Move(MapName[0], str[1], Min(16, Length(str))); if MessageBox(0, PChar(Format(_lc[I_MSG_DELETE_MAP_PROMT], [MapName, OpenDialog.FileName])), PChar(_lc[I_MSG_DELETE_MAP]), MB_ICONQUESTION or MB_YESNO or - MB_TASKMODAL or MB_DEFBUTTON2) <> mrYes then + MB_DEFBUTTON2) <> mrYes then Exit; WAD.RemoveResource('', MapName); @@ -5776,7 +5793,7 @@ begin [MapName])), PChar(_lc[I_MSG_MAP_DELETED]), MB_ICONINFORMATION or MB_OK or - MB_TASKMODAL or MB_DEFBUTTON1); + MB_DEFBUTTON1); WAD.SaveTo(OpenDialog.FileName); @@ -6014,6 +6031,17 @@ end; procedure TMainForm.OnIdle(Sender: TObject; var Done: Boolean); begin + // FIXME: this is a shitty hack + if not gDataLoaded then + begin + e_WriteLog('Init OpenGL', MSG_NOTIFY); + e_InitGL(); + e_WriteLog('Loading data', MSG_NOTIFY); + LoadStdFont('STDTXT', 'STDFONT', gEditorFont); + LoadData(); + gDataLoaded := True; + MainForm.FormResize(nil); + end; Draw(); end; @@ -6222,10 +6250,7 @@ begin Application.Minimize(); if ExecuteProcess(TestD2dExe, cmd) < 0 then begin - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, - nil, GetLastError(), LANG_SYSTEM_DEFAULT, - @lpMsgBuf, 0, nil); - MessageBox(0, lpMsgBuf, + MessageBox(0, 'FIXME', PChar(_lc[I_MSG_EXEC_ERROR]), MB_OK or MB_ICONERROR); end; diff --git a/src/editor/f_mapoptions.lfm b/src/editor/f_mapoptions.lfm index 418547a..f33a7b6 100644 --- a/src/editor/f_mapoptions.lfm +++ b/src/editor/f_mapoptions.lfm @@ -1,247 +1,274 @@ object MapOptionsForm: TMapOptionsForm Left = 594 + Height = 350 Top = 204 + Width = 340 BorderIcons = [biSystemMenu] BorderStyle = bsSingle Caption = 'Параметры карты' ClientHeight = 350 ClientWidth = 340 Color = clBtnFace - Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' - Font.Style = [] + OnActivate = FormActivate Position = poScreenCenter ShowHint = True - OnActivate = FormActivate - PixelsPerInch = 96 + LCLVersion = '1.6.0.4' object LabelDesc: TLabel Left = 3 + Height = 13 Top = 43 Width = 87 - Height = 13 Caption = 'Описание карты:' + ParentColor = False end object lCharCountName: TLabel Left = 131 + Height = 13 Top = 3 Width = 41 - Height = 13 Alignment = taRightJustify AutoSize = False Caption = '00\32' + ParentColor = False end object lCharCountDescription: TLabel Left = 131 + Height = 13 Top = 43 Width = 41 - Height = 13 Alignment = taRightJustify AutoSize = False Caption = '000\256' + ParentColor = False end object LabelName: TLabel Left = 3 + Height = 13 Top = 3 Width = 87 - Height = 13 Caption = 'Название карты:' + ParentColor = False end object LabelBack: TLabel Left = 3 + Height = 13 Top = 131 Width = 26 - Height = 13 Caption = 'Фон:' + ParentColor = False end object LabelMusic: TLabel Left = 3 + Height = 13 Top = 171 Width = 43 - Height = 13 Caption = 'Музыка:' + ParentColor = False end object LabelAuthor: TLabel Left = 3 + Height = 13 Top = 83 Width = 33 - Height = 13 Caption = 'Автор:' + ParentColor = False end object lCharCountAuthor: TLabel Left = 131 + Height = 13 Top = 83 Width = 41 - Height = 13 Alignment = taRightJustify AutoSize = False Caption = '00\32' + ParentColor = False end object GBStats: TGroupBox Left = 179 + Height = 118 Top = 3 Width = 158 - Height = 118 Caption = 'Статистика:' + ClientHeight = 100 + ClientWidth = 154 TabOrder = 3 object lPanelCount: TLabel Left = 80 + Height = 13 Top = 18 Width = 64 - Height = 13 AutoSize = False + ParentColor = False end object lTextureCount: TLabel Left = 80 + Height = 13 Top = 2 Width = 64 - Height = 13 AutoSize = False + ParentColor = False end object lItemCount: TLabel Left = 80 + Height = 13 Top = 34 Width = 64 - Height = 13 AutoSize = False + ParentColor = False end object LabelPanels: TLabel Left = 6 + Height = 13 Top = 18 Width = 47 - Height = 13 Caption = 'Панелей:' + ParentColor = False end object LabelTexs: TLabel Left = 6 + Height = 13 Top = 2 Width = 44 - Height = 13 Caption = 'Текстур:' + ParentColor = False end object LabelItems: TLabel Left = 6 + Height = 13 Top = 34 Width = 60 - Height = 13 Caption = 'Предметов:' + ParentColor = False end object LabelMonsters: TLabel Left = 6 + Height = 13 Top = 50 Width = 53 - Height = 13 Caption = 'Монстров:' + ParentColor = False end object lMonsterCount: TLabel Left = 80 + Height = 13 Top = 50 Width = 64 - Height = 13 AutoSize = False + ParentColor = False end object LabelAreas: TLabel Left = 6 + Height = 13 Top = 66 Width = 52 - Height = 13 Caption = 'Областей:' + ParentColor = False end object lAreaCount: TLabel Left = 80 + Height = 13 Top = 66 Width = 64 - Height = 13 AutoSize = False + ParentColor = False end object LabelTriggers: TLabel Left = 6 + Height = 13 Top = 82 Width = 56 - Height = 13 Caption = 'Триггеров:' + ParentColor = False end object lTriggerCount: TLabel Left = 80 + Height = 13 Top = 82 Width = 64 - Height = 13 AutoSize = False + ParentColor = False end end object bOK: TButton Left = 163 + Height = 25 Top = 323 Width = 75 - Height = 25 Caption = 'ОК' Default = True - TabOrder = 11 OnClick = bOKClick + TabOrder = 11 end object bCancel: TButton Left = 251 + Height = 25 Top = 323 Width = 75 - Height = 25 Cancel = True Caption = 'Отмена' - TabOrder = 12 OnClick = bCancelClick + TabOrder = 12 end object GBSizes: TGroupBox Left = 3 + Height = 105 Top = 216 Width = 334 - Height = 105 Caption = 'Размеры:' + ClientHeight = 87 + ClientWidth = 330 TabOrder = 10 object LabelWidth: TLabel - Left = 14 - Top = 10 - Width = 42 + Left = 8 Height = 13 + Top = 3 + Width = 42 AutoSize = False Caption = 'Ширина:' + ParentColor = False end object LabelHeight: TLabel - Left = 14 - Top = 36 - Width = 41 + Left = 8 Height = 13 + Top = 29 + Width = 41 AutoSize = False Caption = 'Высота:' + ParentColor = False end object LabelCurSize: TLabel - Left = 14 - Top = 66 - Width = 48 + Left = 2 Height = 13 + Top = 56 + Width = 48 AutoSize = False Caption = 'Текущий:' + ParentColor = False end object lCurrentMapSizes: TLabel - Left = 67 - Top = 66 - Width = 68 + Left = 56 Height = 13 + Top = 59 + Width = 68 AutoSize = False + ParentColor = False end object sbMoveCenter: TSpeedButton - Left = 262 - Top = 26 - Width = 25 + Left = 280 Height = 25 - GroupIndex = 1 + Top = 20 + Width = 25 Down = True + GroupIndex = 1 end object sbMoveUpLeft: TSpeedButton - Left = 238 - Top = 2 - Width = 25 + Left = 256 Height = 25 - GroupIndex = 1 + Top = -4 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -268,14 +295,15 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object sbMoveUp: TSpeedButton - Left = 262 - Top = 2 - Width = 25 + Left = 280 Height = 25 - GroupIndex = 1 + Top = -4 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -302,14 +330,15 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object sbMoveUpRight: TSpeedButton - Left = 286 - Top = 2 - Width = 25 + Left = 304 Height = 25 - GroupIndex = 1 + Top = -4 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -336,14 +365,15 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object sbMoveRight: TSpeedButton - Left = 286 - Top = 26 - Width = 25 + Left = 304 Height = 25 - GroupIndex = 1 + Top = 20 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -370,14 +400,15 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object sbMoveLeft: TSpeedButton - Left = 238 - Top = 26 - Width = 25 + Left = 256 Height = 25 - GroupIndex = 1 + Top = 20 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -404,14 +435,15 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object sbMoveDownLeft: TSpeedButton - Left = 238 - Top = 50 - Width = 25 + Left = 256 Height = 25 - GroupIndex = 1 + Top = 44 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -438,14 +470,15 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object sbMoveDown: TSpeedButton - Left = 262 - Top = 50 - Width = 25 + Left = 280 Height = 25 - GroupIndex = 1 + Top = 44 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -472,14 +505,15 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object sbMoveDownRight: TSpeedButton - Left = 286 - Top = 50 - Width = 25 + Left = 304 Height = 25 - GroupIndex = 1 + Top = 44 + Width = 25 Glyph.Data = { 36030000424D3603000000000000360000002800000010000000100000000100 18000000000000030000120B0000120B00000000000000000000FF00FFFF00FF @@ -506,67 +540,75 @@ object MapOptionsForm: TMapOptionsForm 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF - 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + } + GroupIndex = 1 end object LabelMapMove: TLabel - Left = 142 - Top = 4 - Width = 85 + Left = 160 Height = 39 + Top = 0 + Width = 85 Alignment = taRightJustify AutoSize = False - BiDiMode = bdLeftToRight Caption = 'Направление смещения объектов карты:' - ParentBiDiMode = False + ParentBidiMode = False + ParentColor = False WordWrap = True end object eMapWidth: TEdit - Left = 66 - Top = 7 - Width = 45 + Left = 60 Height = 21 + Top = 0 + Width = 45 MaxLength = 5 + OnKeyPress = eMapSizeKeyPress TabOrder = 0 Text = '0' - OnKeyPress = eMapSizeKeyPress end object UpDown1: TUpDown - Left = 111 - Top = 7 - Width = 17 + Left = 105 Height = 21 + Top = 0 + Width = 17 Associate = eMapWidth - Max = 16384 Increment = 16 + Max = 16384 + Min = 0 + Position = 0 TabOrder = 1 Thousands = False + Wrap = False end object eMapHeight: TEdit - Left = 66 - Top = 33 - Width = 45 + Left = 60 Height = 21 + Top = 26 + Width = 45 MaxLength = 5 + OnKeyPress = eMapSizeKeyPress TabOrder = 2 Text = '0' - OnKeyPress = eMapSizeKeyPress end object UpDown2: TUpDown - Left = 111 - Top = 33 - Width = 17 + Left = 105 Height = 21 + Top = 26 + Width = 17 Associate = eMapHeight - Max = 16384 Increment = 16 + Max = 16384 + Min = 0 + Position = 0 TabOrder = 3 Thousands = False + Wrap = False end object cbSnapping: TCheckBox - Left = 158 + Left = 128 + Height = 19 Top = 50 - Width = 73 - Height = 33 + Width = 123 Alignment = taLeftJustify Caption = 'Сохранять привязку' Checked = True @@ -576,89 +618,89 @@ object MapOptionsForm: TMapOptionsForm end object eMapDescription: TEdit Left = 3 + Height = 21 Top = 59 Width = 174 - Height = 21 MaxLength = 256 - TabOrder = 1 OnChange = eMapDescriptionChange + TabOrder = 1 end object eMapName: TEdit Left = 3 + Height = 21 Top = 19 Width = 174 - Height = 21 MaxLength = 32 - TabOrder = 0 OnChange = eMapNameChange + TabOrder = 0 end object eBack: TEdit Left = 3 + Height = 21 Top = 147 Width = 278 - Height = 21 - TabStop = False Color = clBtnFace + OnChange = eMapDescriptionChange ReadOnly = True + TabStop = False TabOrder = 4 - OnChange = eMapDescriptionChange end object eMusic: TEdit Left = 3 + Height = 21 Top = 187 Width = 278 - Height = 21 - TabStop = False Color = clBtnFace + OnChange = eMapDescriptionChange ReadOnly = True + TabStop = False TabOrder = 7 - OnChange = eMapDescriptionChange end object bSelectBack: TButton Left = 311 - Top = 146 - Width = 23 Height = 23 Hint = 'Выбрать фон' + Top = 146 + Width = 23 Caption = '...' - TabOrder = 5 OnClick = bSelectBackClick + TabOrder = 5 end object bSelectMusic: TButton Left = 311 - Top = 186 - Width = 23 Height = 23 Hint = 'Выбрать музыку' + Top = 186 + Width = 23 Caption = '...' - TabOrder = 8 OnClick = bSelectMusicClick + TabOrder = 8 end object eAuthor: TEdit Left = 3 + Height = 21 Top = 99 Width = 174 - Height = 21 MaxLength = 32 - TabOrder = 2 OnChange = eAuthorChange + TabOrder = 2 end object bRemoveBack: TButton Left = 285 - Top = 146 - Width = 23 Height = 23 Hint = 'Убрать фон' - TabOrder = 6 + Top = 146 + Width = 23 OnClick = bRemoveBackClick + TabOrder = 6 end object bRemoveMusic: TButton Left = 285 - Top = 186 - Width = 23 Height = 23 Hint = 'Убрать музыку' - TabOrder = 9 + Top = 186 + Width = 23 OnClick = bRemoveMusicClick + TabOrder = 9 end end diff --git a/src/editor/f_options.lfm b/src/editor/f_options.lfm index 37d9ec1..d400d8b 100644 --- a/src/editor/f_options.lfm +++ b/src/editor/f_options.lfm @@ -1,232 +1,246 @@ object OptionsForm: TOptionsForm Left = 202 + Height = 262 Top = 174 + Width = 435 BorderIcons = [biSystemMenu] BorderStyle = bsSingle Caption = 'Настройки редактора' ClientHeight = 262 - ClientWidth = 415 + ClientWidth = 435 Color = clBtnFace - Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' - Font.Style = [] - Position = poScreenCenter OnActivate = FormActivate - PixelsPerInch = 96 + Position = poScreenCenter + LCLVersion = '1.6.0.4' object GroupBox1: TGroupBox Left = 8 - Top = 0 - Width = 401 Height = 225 + Top = 0 + Width = 425 + ClientHeight = 207 + ClientWidth = 421 TabOrder = 0 object sDotColor: TShape - Left = 318 + Left = 344 + Height = 25 Top = 2 Width = 57 - Height = 25 end object LabelGrid: TLabel Left = 6 + Height = 13 Top = 74 Width = 61 - Height = 13 Caption = 'Шаги сетки:' + ParentColor = False end object LabelGridCol: TLabel Left = 190 + Height = 13 Top = 2 Width = 60 - Height = 13 Caption = 'Цвет сетки:' + ParentColor = False end object LabelBack: TLabel Left = 190 + Height = 13 Top = 43 Width = 57 - Height = 13 Caption = 'Цвет фона:' + ParentColor = False end object sBackColor: TShape - Left = 318 + Left = 344 + Height = 25 Top = 43 Width = 57 - Height = 25 Brush.Color = clBlack end object LabelPreview: TLabel Left = 190 - Top = 73 - Width = 84 - Height = 39 + Height = 13 + Top = 72 + Width = 216 Caption = 'Цвет фона поля предпросмотра текстуры:' + ParentColor = False WordWrap = True end object sPreviewColor: TShape - Left = 318 - Top = 83 - Width = 57 + Left = 344 Height = 25 + Top = 88 + Width = 57 Brush.Color = clBlack end object LabelMinimap: TLabel Left = 190 + Height = 13 Top = 131 Width = 112 - Height = 13 Caption = 'Масштаб мини-карты:' + ParentColor = False end object LabelRecent: TLabel Left = 190 + Height = 13 Top = 162 - Width = 121 - Height = 26 + Width = 199 Caption = 'Запоминать последних открытых карт:' + ParentColor = False WordWrap = True end object LabelLanguage: TLabel Left = 6 + Height = 13 Top = 162 Width = 31 - Height = 13 Caption = 'Язык:' + ParentColor = False end object LabelGridSize: TLabel Left = 6 + Height = 13 Top = 122 - Width = 73 - Height = 26 + Width = 105 Caption = 'Размер точек сетки:' + ParentColor = False WordWrap = True end object cbShowDots: TCheckBox Left = 6 + Height = 19 Top = 2 - Width = 121 - Height = 17 + Width = 114 Caption = 'Показывать сетку' TabOrder = 0 end object UpDown1: TUpDown Left = 143 + Height = 21 Top = 74 Width = 12 - Height = 21 Associate = eDotStepOne - Min = 2 Max = 255 + Min = 2 Position = 16 TabOrder = 6 + Wrap = False end object eDotStepOne: TEdit Left = 86 + Height = 21 Top = 74 Width = 57 - Height = 21 TabOrder = 1 Text = '16' end object bGrid: TButton - Left = 376 + Left = 402 + Height = 25 Top = 2 Width = 11 - Height = 25 Caption = '..' - TabOrder = 2 OnClick = bGridClick + TabOrder = 2 end object bBack: TButton - Left = 376 + Left = 402 + Height = 25 Top = 43 Width = 11 - Height = 25 Caption = '..' - TabOrder = 3 OnClick = bBackClick + TabOrder = 3 end object bPreview: TButton - Left = 376 - Top = 83 - Width = 11 + Left = 402 Height = 25 + Top = 88 + Width = 11 Caption = '..' - TabOrder = 4 OnClick = bPreviewClick + TabOrder = 4 end object cbScale: TComboBox - Left = 318 + Left = 344 + Height = 21 Top = 131 Width = 70 - Height = 21 - Style = csDropDownList ItemHeight = 13 ItemIndex = 0 - TabOrder = 5 - Text = '1x' Items.Strings = ( '1x' - '2x') + '2x' + ) + Style = csDropDownList + TabOrder = 5 + Text = '1x' end object cbShowTexture: TCheckBox Left = 6 + Height = 19 Top = 18 Width = 169 - Height = 17 Caption = 'Показывать текстуру панели' TabOrder = 7 end object cbShowSize: TCheckBox Left = 6 + Height = 19 Top = 34 - Width = 169 - Height = 17 + Width = 171 Caption = 'Показывать размеры панели' TabOrder = 8 end object eRecent: TEdit - Left = 318 - Top = 166 - Width = 57 + Left = 344 Height = 21 + Top = 184 + Width = 57 TabOrder = 9 Text = '5' end object UpDown3: TUpDown - Left = 375 - Top = 166 - Width = 12 + Left = 401 Height = 21 + Top = 184 + Width = 12 Associate = eRecent - Min = 2 Max = 10 + Min = 2 Position = 5 TabOrder = 10 + Wrap = False end object eDotStepTwo: TEdit Left = 86 + Height = 21 Top = 98 Width = 57 - Height = 21 TabOrder = 11 Text = '8' end object UpDown2: TUpDown Left = 143 + Height = 21 Top = 98 Width = 12 - Height = 21 Associate = eDotStepTwo - Min = 2 Max = 255 + Min = 2 Position = 8 TabOrder = 12 + Wrap = False end object rbRussian: TRadioButton Left = 86 + Height = 19 Top = 162 - Width = 81 - Height = 17 + Width = 62 Caption = 'Русский' Checked = True TabOrder = 13 @@ -234,47 +248,72 @@ object OptionsForm: TOptionsForm end object rbEnglish: TRadioButton Left = 86 + Height = 19 Top = 186 - Width = 81 - Height = 17 + Width = 54 Caption = 'English' TabOrder = 14 end object cbDotSize: TComboBox - Left = 86 - Top = 126 - Width = 73 + Left = 82 Height = 21 + Top = 136 + Width = 73 ItemHeight = 13 - TabOrder = 15 - Text = '1' + ItemIndex = 0 Items.Strings = ( '1' - '2') + '2' + ) + TabOrder = 15 + Text = '1' end end object bOK: TButton - Left = 240 + Left = 262 + Height = 25 Top = 232 Width = 75 - Height = 25 Caption = 'ОК' Default = True - TabOrder = 1 OnClick = bOKClick + TabOrder = 1 end object bCancel: TButton - Left = 336 + Left = 358 + Height = 25 Top = 232 Width = 75 - Height = 25 Cancel = True Caption = 'Отмена' - TabOrder = 2 OnClick = bCancelClick + TabOrder = 2 end object ColorDialog: TColorDialog - Left = 200 - Top = 232 + Color = clBlack + CustomColors.Strings = ( + 'ColorA=000000' + 'ColorB=000080' + 'ColorC=008000' + 'ColorD=008080' + 'ColorE=800000' + 'ColorF=800080' + 'ColorG=808000' + 'ColorH=808080' + 'ColorI=C0C0C0' + 'ColorJ=0000FF' + 'ColorK=00FF00' + 'ColorL=00FFFF' + 'ColorM=FF0000' + 'ColorN=FF00FF' + 'ColorO=FFFF00' + 'ColorP=FFFFFF' + 'ColorQ=C0DCC0' + 'ColorR=F0CAA6' + 'ColorS=F0FBFF' + 'ColorT=A4A0A0' + ) + left = 200 + top = 232 end end diff --git a/src/editor/g_language.pas b/src/editor/g_language.pas index 2a99675..7a9b194 100644 --- a/src/editor/g_language.pas +++ b/src/editor/g_language.pas @@ -1,4 +1,4 @@ -Unit g_language; +Unit g_language; {$MODE Delphi} @@ -602,7 +602,8 @@ Const LANGUAGE_ENGLISH_N = 2; Var - _lc: Array [TStrings_Locale] of String; + _lc: Array [TStrings_Locale] of String; // for the GUI (in UTF-8) + _glc: Array [TStrings_Locale] of String; // for GL text (in CP1251) BoolNames: Array [False..True] of String; DirNames: Array [D_LEFT..D_RIGHT] of String; @@ -628,7 +629,7 @@ Uses f_addresource_sky, f_addresource_sound, f_addresource_texture, f_choosetype, f_keys, f_mapcheck, f_mapoptions, f_maptest, f_mapoptimization, f_options, - f_packmap, f_savemap, f_saveminimap, f_selectmap, Forms; + f_packmap, f_savemap, f_saveminimap, f_selectmap, Forms, utils; Const g_lang_default: Array [TStrings_Locale] of Array [1..3] of String = ( @@ -2441,7 +2442,11 @@ begin n := LANGUAGE_RUSSIAN_N; for i := Low(TStrings_Locale) to High(TStrings_Locale) do + begin _lc[i] := g_lang_default[i][n]; + // have to cache a CP1251 version for GL text + _glc[i] := utf8to1251(g_lang_default[i][n]); + end; SetupArrays(); SetupCaptions(); @@ -2463,4 +2468,4 @@ begin CloseFile(F); end; -End. \ No newline at end of file +End. diff --git a/src/editor/g_map.pas b/src/editor/g_map.pas index d61a0e2..a49b6f9 100644 --- a/src/editor/g_map.pas +++ b/src/editor/g_map.pas @@ -1378,7 +1378,7 @@ var FileName, SectionName, ResName, _fn: String; TextureRes: String; pData: Pointer; - Len: Integer; + Len, FrameLen: Integer; Error: Boolean; NoTextureID: DWORD; NW, NH: Word; @@ -1457,14 +1457,14 @@ begin end else // Anim begin // Анимированная текстура - if not GetFrame(TextureRes, Data, Width, Height) then + if not GetFrame(TextureRes, Data, FrameLen, Width, Height) then begin // Кадры e_WriteLog(Format('GetFrame() error, res=%s', [textures[a].Resource]), MSG_WARNING); Error := True; end; - if not g_CreateTextureMemorySize(Data, textures[a].Resource, 0, 0, Width, Height, 1) then + if not g_CreateTextureMemorySize(Data, FrameLen, textures[a].Resource, 0, 0, Width, Height, 1) then begin // Сама текстура e_WriteLog(Format('g_CreateTextureMemorySize() error, res=%s', [textures[a].Resource]), MSG_WARNING); diff --git a/src/editor/g_textures.pas b/src/editor/g_textures.pas index 5cad990..7c13013 100644 --- a/src/editor/g_textures.pas +++ b/src/editor/g_textures.pas @@ -13,7 +13,7 @@ function g_SimpleCreateTextureWADSize(var ID: DWORD; Resource: string; function g_CreateTextureWAD(TextureName: ShortString; Resource: string; flag: Byte = 0): Boolean; function g_CreateTextureWADSize(TextureName: ShortString; Resource: string; X, Y, Width, Height: Word; flag: Byte = 0): Boolean; -function g_CreateTextureMemorySize(pData: Pointer; Name: ShortString; X, Y, +function g_CreateTextureMemorySize(pData: Pointer; dataLen: Integer; Name: ShortString; X, Y, Width, Height: Word; flag: Byte = 0): Boolean; function g_GetTexture(TextureName: ShortString; var ID: DWORD): Boolean; @@ -82,7 +82,7 @@ begin if WAD.GetResource(SectionName, ResourceName, TextureData, ResourceLength) then begin - if e_CreateTextureMem(TextureData, ID) then Result := True; + if e_CreateTextureMem(TextureData, ResourceLength, ID) then Result := True; FreeMem(TextureData); end else @@ -93,7 +93,7 @@ begin WAD.Destroy; end; -function g_CreateTextureMemorySize(pData: Pointer; Name: ShortString; X, Y, +function g_CreateTextureMemorySize(pData: Pointer; dataLen: Integer; Name: ShortString; X, Y, Width, Height: Word; flag: Byte = 0): Boolean; var find_id: DWORD; @@ -104,7 +104,7 @@ begin find_id := FindTexture; - if not e_CreateTextureMemEx(pData, TexturesArray[find_id].ID, X, Y, Width, Height) then + if not e_CreateTextureMemEx(pData, dataLen, TexturesArray[find_id].ID, X, Y, Width, Height) then begin FreeMem(pData); Exit; @@ -139,7 +139,7 @@ begin if WAD.GetResource(SectionName, ResourceName, TextureData, ResourceLength) then begin - Result := e_CreateTextureMem(TextureData, TexturesArray[find_id].ID); + Result := e_CreateTextureMem(TextureData, ResourceLength, TexturesArray[find_id].ID); FreeMem(TextureData); if Result then begin @@ -176,7 +176,7 @@ begin if WAD.GetResource(SectionName, ResourceName, TextureData, ResourceLength) then begin - if e_CreateTextureMemEx(TextureData, ID, X, Y, Width, Height) then Result := True; + if e_CreateTextureMemEx(TextureData, ResourceLength, ID, X, Y, Width, Height) then Result := True; FreeMem(TextureData); end else @@ -207,7 +207,7 @@ begin if WAD.GetResource(SectionName, ResourceName, TextureData, ResourceLength) then begin - Result := e_CreateTextureMemEx(TextureData, TexturesArray[find_id].ID, X, Y, Width, Height); + Result := e_CreateTextureMemEx(TextureData, ResourceLength, TexturesArray[find_id].ID, X, Y, Width, Height); FreeMem(TextureData); if Result then begin diff --git a/src/engine/e_graphics.pas b/src/engine/e_graphics.pas index e4eb35a..63a9e5b 100644 --- a/src/engine/e_graphics.pas +++ b/src/engine/e_graphics.pas @@ -1,9 +1,26 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$MODE DELPHI} unit e_graphics; interface uses - windows, SysUtils, Math, e_log, e_textures, dglOpenGL; + SysUtils, Classes, Math, e_log, e_textures, GL, GLExt, MAPDEF, + ImagingTypes, Imaging, ImagingUtility; type TMirrorType=(M_NONE, M_HORIZONTAL, M_VERTICAL); @@ -13,11 +30,16 @@ type X, Y: Integer; end; + TPoint = MAPDEF.TPoint; // TODO: create an utiltypes.pas or something + // for other types like rect as well + TPoint2f = record X, Y: Double; end; - TRect = windows.TRect; + TRect = record + Left, Top, Right, Bottom: Integer; + end; TRectWH = record X, Y: Integer; @@ -37,7 +59,7 @@ type //------------------------------------------------------------------ // ïðîòîòèïû ôóíêöèé //------------------------------------------------------------------ -procedure e_InitGL(VSync: Boolean); +procedure e_InitGL(); procedure e_SetViewPort(X, Y, Width, Height: Word); procedure e_ResizeWindow(Width, Height: Integer); @@ -57,22 +79,16 @@ procedure e_DrawQuad(X1, Y1, X2, Y2: Integer; Red, Green, Blue: Byte; Alpha: Byt procedure e_DrawFillQuad(X1, Y1, X2, Y2: Integer; Red, Green, Blue, Alpha: Byte; Blending: TBlending = B_NONE); +function e_CreateTextureImg (var img: TImageData; var ID: DWORD): Boolean; function e_CreateTexture(FileName: string; var ID: DWORD): Boolean; function e_CreateTextureEx(FileName: string; var ID: DWORD; fX, fY, fWidth, fHeight: Word): Boolean; -function e_CreateTextureMem(pData: Pointer; var ID: DWORD): Boolean; -function e_CreateTextureMemEx(pData: Pointer; var ID: DWORD; fX, fY, fWidth, fHeight: Word): Boolean; +function e_CreateTextureMem(pData: Pointer; dataSize: LongInt; var ID: DWORD): Boolean; +function e_CreateTextureMemEx(pData: Pointer; dataSize: LongInt; var ID: DWORD; fX, fY, fWidth, fHeight: Word): Boolean; procedure e_GetTextureSize(ID: DWORD; Width, Height: PWord); function e_GetTextureSize2(ID: DWORD): TRectWH; procedure e_DeleteTexture(ID: DWORD); procedure e_RemoveAllTextures(); -// SimpleFont -function e_SimpleFontCreate(FontName: PChar; Size: Byte; Weight: Word; DC: HDC): DWORD; -procedure e_SimpleFontFree(Font: DWORD); -procedure e_SimpleFontPrint(X, Y: SmallInt; Text: PChar; Font: Integer; Red, Green, Blue: Byte); -procedure e_SimpleFontPrintEx(X, Y: SmallInt; Text: PChar; Font: DWORD; Red, Green, Blue, - sRed, sGreen, sBlue, sWidth: Byte); - // CharFont function e_CharFont_Create(sp: ShortInt=0): DWORD; procedure e_CharFont_AddChar(FontID: DWORD; Texture: Integer; c: Char; w: Byte); @@ -88,7 +104,7 @@ procedure e_CharFont_Remove(FontID: DWORD); procedure e_CharFont_RemoveAll(); // TextureFont -procedure e_TextureFontBuild(Texture: DWORD; var FontID: DWORD; XCount, YCount: Word; +procedure e_TextureFontBuild(Tex: DWORD; var FontID: DWORD; XCount, YCount: Word; Space: ShortInt=0); procedure e_TextureFontKill(FontID: DWORD); procedure e_TextureFontPrint(X, Y: GLint; Text: string; FontID: DWORD); @@ -98,38 +114,46 @@ procedure e_TextureFontPrintFmt(X, Y: GLint; Text: string; FontID: DWORD; Shadow procedure e_TextureFontGetSize(ID: DWORD; var CharWidth, CharHeight: Byte); procedure e_RemoveAllTextureFont(); +function e_TextureFontCharWidth (ch: Char; FontID: DWORD): Integer; +procedure e_TextureFontPrintCharEx (X, Y: Integer; Ch: Char; FontID: DWORD; Shadow: Boolean = False); + procedure e_ReleaseEngine(); procedure e_BeginRender(); -procedure e_Clear(Mask: TGLbitfield; Red, Green, Blue: Single); +procedure e_Clear(Mask: TGLbitfield; Red, Green, Blue: Single); overload; +procedure e_Clear(); overload; procedure e_EndRender(); -function e_GetGamma(DC: HDC): Byte; -procedure e_SetGamma(Gamma: Byte; DC: HDC); - -procedure e_MakeScreenshot(FileName: string; Width, Height: Word); - function _RGB(Red, Green, Blue: Byte): TRGB; function _Point(X, Y: Integer): TPoint2i; function _Rect(X, Y: Integer; Width, Height: Word): TRectWH; +function _TRect(L, T, R, B: LongInt): TRect; +//function e_getTextGLId (ID: DWORD): GLuint; var e_Colors: TRGB; + e_NoGraphics: Boolean = False; + e_FastScreenshots: Boolean = true; // it's REALLY SLOW with `false` + implementation +uses + paszlib, crc, utils; + + type TTexture = record - ID: DWORD; - Width: Word; - Height: Word; + tx: GLTexture; end; TTextureFont = record - TextureID: DWORD; - Base: GLuint; - CharWidth: Byte; - CharHeight: Byte; + Texture: DWORD; + TextureID: DWORD; + Base: Uint32; + CharWidth: Byte; + CharHeight: Byte; + XC, YC, SPC: Word; end; TCharFont = record @@ -143,25 +167,35 @@ type Live: Boolean; end; + TSavedTexture = record + TexID: DWORD; + OldID: DWORD; + Pixels: Pointer; + end; + var e_Textures: array of TTexture = nil; e_TextureFonts: array of TTextureFont = nil; e_CharFonts: array of TCharFont; + //e_SavedTextures: array of TSavedTexture; + +//function e_getTextGLId (ID: DWORD): GLuint; begin result := e_Textures[ID].tx.id; end; //------------------------------------------------------------------ // Èíèöèàëèçèðóåò OpenGL //------------------------------------------------------------------ -procedure e_InitGL(VSync: Boolean); +procedure e_InitGL(); begin - if VSync then - wglSwapIntervalEXT(1) - else - wglSwapIntervalEXT(0); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); + if e_NoGraphics then + begin + e_DummyTextures := True; + Exit; + end; e_Colors.R := 255; e_Colors.G := 255; e_Colors.B := 255; + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); glClearColor(0, 0, 0, 0); end; @@ -170,6 +204,7 @@ var mat: Array [0..15] of GLDouble; begin + if e_NoGraphics then Exit; glLoadIdentity(); glScissor(X, Y, Width, Height); glViewport(X, Y, Width, Height); @@ -200,7 +235,7 @@ begin glLoadMatrixd(@mat[0]); glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + glLoadIdentity(); end; //------------------------------------------------------------------ @@ -212,7 +247,7 @@ var begin if e_Textures <> nil then for i := 0 to High(e_Textures) do - if e_Textures[i].Width = 0 then + if e_Textures[i].tx.Width = 0 then begin Result := i; Exit; @@ -236,6 +271,7 @@ end; function e_CreateTexture(FileName: String; var ID: DWORD): Boolean; var find_id: DWORD; + fmt: Word; begin Result := False; @@ -243,8 +279,8 @@ begin find_id := FindTexture(); - if not LoadTexture(FileName, e_Textures[find_id].ID, e_Textures[find_id].Width, - e_Textures[find_id].Height) then Exit; + if not LoadTexture(FileName, e_Textures[find_id].tx, e_Textures[find_id].tx.Width, + e_Textures[find_id].tx.Height, @fmt) then Exit; ID := find_id; @@ -254,81 +290,92 @@ end; function e_CreateTextureEx(FileName: String; var ID: DWORD; fX, fY, fWidth, fHeight: Word): Boolean; var find_id: DWORD; + fmt: Word; begin Result := False; find_id := FindTexture(); - if not LoadTextureEx(FileName, e_Textures[find_id].ID, fX, fY, fWidth, fHeight) then Exit; - - e_Textures[find_id].Width := fWidth; - e_Textures[find_id].Height := fHeight; + if not LoadTextureEx(FileName, e_Textures[find_id].tx, fX, fY, fWidth, fHeight, @fmt) then exit; ID := find_id; Result := True; end; -function e_CreateTextureMem(pData: Pointer; var ID: DWORD): Boolean; +function e_CreateTextureMem(pData: Pointer; dataSize: LongInt; var ID: DWORD): Boolean; var find_id: DWORD; + fmt: Word; begin Result := False; find_id := FindTexture; - if not LoadTextureMem(pData, e_Textures[find_id].ID, e_Textures[find_id].Width, - e_Textures[find_id].Height) then Exit; + if not LoadTextureMem(pData, dataSize, e_Textures[find_id].tx, e_Textures[find_id].tx.Width, e_Textures[find_id].tx.Height, @fmt) then exit; id := find_id; Result := True; end; -function e_CreateTextureMemEx(pData: Pointer; var ID: DWORD; fX, fY, fWidth, fHeight: Word): Boolean; +function e_CreateTextureMemEx(pData: Pointer; dataSize: LongInt; var ID: DWORD; fX, fY, fWidth, fHeight: Word): Boolean; var find_id: DWORD; + fmt: Word; begin Result := False; find_id := FindTexture(); - if not LoadTextureMemEx(pData, e_Textures[find_id].ID, fX, fY, fWidth, fHeight) then Exit; - - e_Textures[find_id].Width := fWidth; - e_Textures[find_id].Height := fHeight; + if not LoadTextureMemEx(pData, dataSize, e_Textures[find_id].tx, fX, fY, fWidth, fHeight, @fmt) then exit; ID := find_id; Result := True; end; +function e_CreateTextureImg (var img: TImageData; var ID: DWORD): Boolean; +var + find_id: DWORD; + fmt, tw, th: Word; +begin + result := false; + find_id := FindTexture(); + if not LoadTextureImg(img, e_Textures[find_id].tx, tw, th, @fmt) then exit; + ID := find_id; + result := True; +end; + procedure e_GetTextureSize(ID: DWORD; Width, Height: PWord); begin - if Width <> nil then Width^ := e_Textures[ID].Width; - if Height <> nil then Height^ := e_Textures[ID].Height; + if Width <> nil then Width^ := e_Textures[ID].tx.Width; + if Height <> nil then Height^ := e_Textures[ID].tx.Height; end; function e_GetTextureSize2(ID: DWORD): TRectWH; var - data: Pointer; + data: PChar; x, y: Integer; w, h: Word; a: Boolean; lastline: Integer; begin - w := e_Textures[ID].Width; - h := e_Textures[ID].Height; - data := GetMemory(w*h*4); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, e_Textures[ID].ID); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + w := e_Textures[ID].tx.Width; + h := e_Textures[ID].tx.Height; Result.Y := 0; Result.X := 0; Result.Width := w; Result.Height := h; + if e_NoGraphics then Exit; + + data := GetMemory(w*h*4); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, e_Textures[ID].tx.id); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + for y := h-1 downto 0 do begin lastline := y; @@ -336,7 +383,7 @@ begin for x := 1 to w-4 do begin - a := Byte(Pointer(Integer(data)+y*w*4+x*4+3)^) <> 0; + a := Byte((data+y*w*4+x*4+3)^) <> 0; if a then Break; end; @@ -354,7 +401,7 @@ begin for x := 1 to w-4 do begin - a := Byte(Pointer(Integer(data)+y*w*4+x*4+3)^) <> 0; + a := Byte((data+y*w*4+x*4+3)^) <> 0; if a then Break; end; @@ -372,7 +419,7 @@ begin for y := 1 to h-4 do begin - a := Byte(Pointer(Integer(data)+y*w*4+x*4+3)^) <> 0; + a := Byte((data+y*w*4+x*4+3)^) <> 0; if a then Break; end; @@ -390,7 +437,7 @@ begin for y := 1 to h-4 do begin - a := Byte(Pointer(Integer(data)+y*w*4+x*4+3)^) <> 0; + a := Byte((data+y*w*4+x*4+3)^) <> 0; if a then Break; end; @@ -411,11 +458,27 @@ begin e_SetViewPort(0, 0, Width, Height); end; +procedure drawTxQuad (x0, y0, w, h: Integer; u, v: single; Mirror: TMirrorType); +var + x1, y1, tmp: Integer; +begin + if (w < 1) or (h < 1) then exit; + x1 := x0+w; + y1 := y0+h; + if Mirror = M_HORIZONTAL then begin tmp := x1; x1 := x0; x0 := tmp; end + else if Mirror = M_VERTICAL then begin tmp := y1; y1 := y0; y0 := tmp; end; + glTexCoord2f(0, v); glVertex2i(x0, y0); + glTexCoord2f(0, 0); glVertex2i(x0, y1); + glTexCoord2f(u, 0); glVertex2i(x1, y1); + glTexCoord2f(u, v); glVertex2i(x1, y0); +end; + procedure e_Draw(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; Blending: Boolean; Mirror: TMirrorType = M_NONE); -begin +begin + if e_NoGraphics then Exit; glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); - + if (Alpha > 0) or (AlphaChannel) or (Blending) then glEnable(GL_BLEND) else @@ -431,32 +494,39 @@ begin glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, e_Textures[ID].ID); + glBindTexture(GL_TEXTURE_2D, e_Textures[ID].tx.id); glBegin(GL_QUADS); + drawTxQuad(X, Y, e_Textures[id].tx.width, e_Textures[id].tx.height, e_Textures[ID].tx.u, e_Textures[ID].tx.v, Mirror); + + //u := e_Textures[ID].tx.u; + //v := e_Textures[ID].tx.v; + + { if Mirror = M_NONE then begin - glTexCoord2i(1, 0); glVertex2i(X + e_Textures[id].Width, Y); - glTexCoord2i(0, 0); glVertex2i(X, Y); - glTexCoord2i(0, -1); glVertex2i(X, Y + e_Textures[id].Height); - glTexCoord2i(1, -1); glVertex2i(X + e_Textures[id].Width, Y + e_Textures[id].Height); + glTexCoord2f(u, 0); glVertex2i(X + e_Textures[id].tx.Width, Y); + glTexCoord2f(0, 0); glVertex2i(X, Y); + glTexCoord2f(0, -v); glVertex2i(X, Y + e_Textures[id].tx.Height); + glTexCoord2f(u, -v); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height); end else if Mirror = M_HORIZONTAL then begin - glTexCoord2i(1, 0); glVertex2i(X, Y); - glTexCoord2i(0, 0); glVertex2i(X + e_Textures[id].Width, Y); - glTexCoord2i(0, -1); glVertex2i(X + e_Textures[id].Width, Y + e_Textures[id].Height); - glTexCoord2i(1, -1); glVertex2i(X, Y + e_Textures[id].Height); + glTexCoord2f(u, 0); glVertex2i(X, Y); + glTexCoord2f(0, 0); glVertex2i(X + e_Textures[id].tx.Width, Y); + glTexCoord2f(0, -v); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height); + glTexCoord2f(u, -v); glVertex2i(X, Y + e_Textures[id].tx.Height); end else if Mirror = M_VERTICAL then begin - glTexCoord2i(1, -1); glVertex2i(X + e_Textures[id].Width, Y); - glTexCoord2i(0, -1); glVertex2i(X, Y); - glTexCoord2i(0, 0); glVertex2i(X, Y + e_Textures[id].Height); - glTexCoord2i(1, 0); glVertex2i(X + e_Textures[id].Width, Y + e_Textures[id].Height); + glTexCoord2f(u, -v); glVertex2i(X + e_Textures[id].tx.Width, Y); + glTexCoord2f(0, -v); glVertex2i(X, Y); + glTexCoord2f(0, 0); glVertex2i(X, Y + e_Textures[id].tx.Height); + glTexCoord2f(u, 0); glVertex2i(X + e_Textures[id].tx.Width, Y + e_Textures[id].tx.Height); end; + } glEnd(); @@ -465,7 +535,10 @@ end; procedure e_DrawSize(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; Blending: Boolean; Width, Height: Word; Mirror: TMirrorType = M_NONE); +var + u, v: Single; begin + if e_NoGraphics then Exit; glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); if (Alpha > 0) or (AlphaChannel) or (Blending) then @@ -483,13 +556,16 @@ begin glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, e_Textures[ID].ID); + glBindTexture(GL_TEXTURE_2D, e_Textures[ID].tx.id); + + u := e_Textures[ID].tx.u; + v := e_Textures[ID].tx.v; glBegin(GL_QUADS); - glTexCoord2i(0, 1); glVertex2i(X, Y); - glTexCoord2i(1, 1); glVertex2i(X + Width, Y); - glTexCoord2i(1, 0); glVertex2i(X + Width, Y + Height); - glTexCoord2i(0, 0); glVertex2i(X, Y + Height); + glTexCoord2f(0, v); glVertex2i(X, Y); + glTexCoord2f(u, v); glVertex2i(X + Width, Y); + glTexCoord2f(u, 0); glVertex2i(X + Width, Y + Height); + glTexCoord2f(0, 0); glVertex2i(X, Y + Height); glEnd(); glDisable(GL_BLEND); @@ -498,6 +574,7 @@ end; procedure e_DrawSizeMirror(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; Blending: Boolean; Width, Height: Word; Mirror: TMirrorType = M_NONE); begin + if e_NoGraphics then Exit; glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); if (Alpha > 0) or (AlphaChannel) or (Blending) then @@ -515,33 +592,9 @@ begin glBlendFunc(GL_SRC_ALPHA, GL_ONE); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, e_Textures[ID].ID); + glBindTexture(GL_TEXTURE_2D, e_Textures[ID].tx.id); glBegin(GL_QUADS); - - if Mirror = M_NONE then - begin - glTexCoord2i(1, 0); glVertex2i(X + Width, Y); - glTexCoord2i(0, 0); glVertex2i(X, Y); - glTexCoord2i(0, -1); glVertex2i(X, Y + Height); - glTexCoord2i(1, -1); glVertex2i(X + Width, Y + Height); - end - else - if Mirror = M_HORIZONTAL then - begin - glTexCoord2i(1, 0); glVertex2i(X, Y); - glTexCoord2i(0, 0); glVertex2i(X + Width, Y); - glTexCoord2i(0, -1); glVertex2i(X + Width, Y + Height); - glTexCoord2i(1, -1); glVertex2i(X, Y + Height); - end - else - if Mirror = M_VERTICAL then - begin - glTexCoord2i(1, -1); glVertex2i(X + Width, Y); - glTexCoord2i(0, -1); glVertex2i(X, Y); - glTexCoord2i(0, 0); glVertex2i(X, Y + Height); - glTexCoord2i(1, 0); glVertex2i(X + Width, Y + Height); - end; - + drawTxQuad(X, Y, Width, Height, e_Textures[ID].tx.u, e_Textures[ID].tx.v, Mirror); glEnd(); glDisable(GL_BLEND); @@ -550,9 +603,10 @@ end; procedure e_DrawFill(ID: DWORD; X, Y: Integer; XCount, YCount: Word; Alpha: Integer; AlphaChannel: Boolean; Blending: Boolean); var - X2, Y2: Integer; - + X2, Y2, dx, w, h: Integer; + u, v: Single; begin + if e_NoGraphics then Exit; glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); if (Alpha > 0) or (AlphaChannel) or (Blending) then @@ -576,31 +630,64 @@ begin YCount := 1; glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, e_Textures[ID].ID); + glBindTexture(GL_TEXTURE_2D, e_Textures[ID].tx.id); - X2 := X + e_Textures[ID].Width * XCount; - Y2 := Y + e_Textures[ID].Height * YCount; - - glBegin(GL_QUADS); - glTexCoord2i(0, YCount); glVertex2i(X, Y); - glTexCoord2i(XCount, YCount); glVertex2i(X2, Y); - glTexCoord2i(XCount, 0); glVertex2i(X2, Y2); - glTexCoord2i(0, 0); glVertex2i(X, Y2); - glEnd(); + X2 := X + e_Textures[ID].tx.width * XCount; + Y2 := Y + e_Textures[ID].tx.height * YCount; + + //k8: this SHOULD work... i hope + if (e_Textures[ID].tx.width = e_Textures[ID].tx.glwidth) and (e_Textures[ID].tx.height = e_Textures[ID].tx.glheight) then + begin + glBegin(GL_QUADS); + glTexCoord2i(0, YCount); glVertex2i(X, Y); + glTexCoord2i(XCount, YCount); glVertex2i(X2, Y); + glTexCoord2i(XCount, 0); glVertex2i(X2, Y2); + glTexCoord2i(0, 0); glVertex2i(X, Y2); + glEnd(); + end + else + begin + glBegin(GL_QUADS); + // hard day's night + u := e_Textures[ID].tx.u; + v := e_Textures[ID].tx.v; + w := e_Textures[ID].tx.width; + h := e_Textures[ID].tx.height; + while YCount > 0 do + begin + dx := XCount; + x2 := X; + while dx > 0 do + begin + glTexCoord2f(0, v); glVertex2i(X, Y); + glTexCoord2f(u, v); glVertex2i(X+w, Y); + glTexCoord2f(u, 0); glVertex2i(X+w, Y+h); + glTexCoord2f(0, 0); glVertex2i(X, Y+h); + Inc(X, w); + Dec(dx); + end; + X := x2; + Inc(Y, h); + Dec(YCount); + end; + glEnd(); + end; glDisable(GL_BLEND); end; procedure e_DrawAdv(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; Blending: Boolean; Angle: Single; RC: PPoint; Mirror: TMirrorType = M_NONE); -begin +begin + if e_NoGraphics then Exit; + glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); if (Alpha > 0) or (AlphaChannel) or (Blending) then glEnable(GL_BLEND) else glDisable(GL_BLEND); - + if (AlphaChannel) or (Alpha > 0) then glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -619,33 +706,10 @@ begin end; glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, e_Textures[id].ID); + glBindTexture(GL_TEXTURE_2D, e_Textures[id].tx.id); glBegin(GL_QUADS); //0-1 1-1 //00 10 - if Mirror = M_NONE then - begin - glTexCoord2i(1, 0); glVertex2i(X + e_Textures[id].Width, Y); - glTexCoord2i(0, 0); glVertex2i(X, Y); - glTexCoord2i(0, -1); glVertex2i(X, Y + e_Textures[id].Height); - glTexCoord2i(1, -1); glVertex2i(X + e_Textures[id].Width, Y + e_Textures[id].Height); - end - else - if Mirror = M_HORIZONTAL then - begin - glTexCoord2i(1, 0); glVertex2i(X, Y); - glTexCoord2i(0, 0); glVertex2i(X + e_Textures[id].Width, Y); - glTexCoord2i(0, -1); glVertex2i(X + e_Textures[id].Width, Y + e_Textures[id].Height); - glTexCoord2i(1, -1); glVertex2i(X, Y + e_Textures[id].Height); - end - else - if Mirror = M_VERTICAL then - begin - glTexCoord2i(1, -1); glVertex2i(X + e_Textures[id].Width, Y); - glTexCoord2i(0, -1); glVertex2i(X, Y); - glTexCoord2i(0, 0); glVertex2i(X, Y + e_Textures[id].Height); - glTexCoord2i(1, 0); glVertex2i(X + e_Textures[id].Width, Y + e_Textures[id].Height); - end; - + drawTxQuad(X, Y, e_Textures[id].tx.width, e_Textures[id].tx.height, e_Textures[ID].tx.u, e_Textures[ID].tx.v, Mirror); glEnd(); if Angle <> 0 then @@ -656,10 +720,11 @@ end; procedure e_DrawPoint(Size: Byte; X, Y: Integer; Red, Green, Blue: Byte); begin + if e_NoGraphics then Exit; glDisable(GL_TEXTURE_2D); glColor3ub(Red, Green, Blue); glPointSize(Size); - + if (Size = 2) or (Size = 4) then X := X + 1; @@ -670,45 +735,9 @@ begin glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); end; -procedure e_LineCorrection(var X1, Y1, X2, Y2: Integer); -begin - // Make lines only top-left/bottom-right and top-right/bottom-left - if Y2 < Y1 then - begin - X1 := X1 xor X2; - X2 := X1 xor X2; - X1 := X1 xor X2; - - Y1 := Y1 xor Y2; - Y2 := Y1 xor Y2; - Y1 := Y1 xor Y2; - end; - - // Pixel-perfect hack - if X1 < X2 then - Inc(X2) - else - Inc(X1); - Inc(Y2); -end; - procedure e_DrawQuad(X1, Y1, X2, Y2: Integer; Red, Green, Blue: Byte; Alpha: Byte = 0); -var - nX1, nY1, nX2, nY2: Integer; begin - // Only top-left/bottom-right quad - if X1 > X2 then - begin - X1 := X1 xor X2; - X2 := X1 xor X2; - X1 := X1 xor X2; - end; - if Y1 > Y2 then - begin - Y1 := Y1 xor Y2; - Y2 := Y1 xor Y2; - Y1 := Y1 xor Y2; - end; + if e_NoGraphics then Exit; if Alpha > 0 then begin @@ -721,30 +750,11 @@ begin glColor4ub(Red, Green, Blue, 255-Alpha); glLineWidth(1); - glBegin(GL_LINES); - nX1 := X1; nY1 := Y1; - nX2 := X2; nY2 := Y1; - e_LineCorrection(nX1, nY1, nX2, nY2); // Pixel-perfect lines - glVertex2i(nX1, nY1); - glVertex2i(nX2, nY2); - - nX1 := X2; nY1 := Y1; - nX2 := X2; nY2 := Y2; - e_LineCorrection(nX1, nY1, nX2, nY2); - glVertex2i(nX1, nY1); - glVertex2i(nX2, nY2); - - nX1 := X2; nY1 := Y2; - nX2 := X1; nY2 := Y2; - e_LineCorrection(nX1, nY1, nX2, nY2); - glVertex2i(nX1, nY1); - glVertex2i(nX2, nY2); - - nX1 := X1; nY1 := Y2; - nX2 := X1; nY2 := Y1; - e_LineCorrection(nX1, nY1, nX2, nY2); - glVertex2i(nX1, nY1); - glVertex2i(nX2, nY2); + glBegin(GL_LINE_LOOP); + glVertex2f(X1 + 0.5, Y1 + 0.5); + glVertex2f(X2 + 0.5, Y1 + 0.5); + glVertex2f(X2 + 0.5, Y2 + 0.5); + glVertex2f(X1 + 0.5, Y2 + 0.5); glEnd(); glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); @@ -755,6 +765,7 @@ end; procedure e_DrawFillQuad(X1, Y1, X2, Y2: Integer; Red, Green, Blue, Alpha: Byte; Blending: TBlending = B_NONE); begin + if e_NoGraphics then Exit; if (Alpha > 0) or (Blending <> B_NONE) then glEnable(GL_BLEND) else @@ -792,9 +803,10 @@ end; procedure e_DrawLine(Width: Byte; X1, Y1, X2, Y2: Integer; Red, Green, Blue: Byte; Alpha: Byte = 0); begin + if e_NoGraphics then Exit; // Pixel-perfect lines - if Width = 1 then - e_LineCorrection(X1, Y1, X2, Y2); + //if Width = 1 then + // e_LineCorrection(X1, Y1, X2, Y2); if Alpha > 0 then begin @@ -822,10 +834,11 @@ end; //------------------------------------------------------------------ procedure e_DeleteTexture(ID: DWORD); begin - glDeleteTextures(1, @e_Textures[ID].ID); - e_Textures[ID].ID := 0; - e_Textures[ID].Width := 0; - e_Textures[ID].Height := 0; + if not e_NoGraphics then + glDeleteTextures(1, @e_Textures[ID].tx.id); + e_Textures[ID].tx.id := 0; + e_Textures[ID].tx.Width := 0; + e_Textures[ID].tx.Height := 0; end; //------------------------------------------------------------------ @@ -838,7 +851,7 @@ begin if e_Textures = nil then Exit; for i := 0 to High(e_Textures) do - if e_Textures[i].Width <> 0 then e_DeleteTexture(i); + if e_Textures[i].tx.Width <> 0 then e_DeleteTexture(i); e_Textures := nil; end; @@ -853,196 +866,29 @@ end; procedure e_BeginRender(); begin + if e_NoGraphics then Exit; glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0); end; -procedure e_Clear(Mask: TGLbitfield; Red, Green, Blue: Single); -begin - glClearColor(Red, Green, Blue, 0); - glClear(Mask); -end; - -procedure e_EndRender(); -begin - glPopMatrix(); -end; - -procedure e_MakeScreenshot(FileName: String; Width, Height: Word); -type - aRGB = Array [0..1] of TRGB; - PaRGB = ^aRGB; - - TByteArray = Array [0..1] of Byte; - PByteArray = ^TByteArray; - -var - FILEHEADER: BITMAPFILEHEADER; - INFOHEADER: BITMAPINFOHEADER; - pixels: PByteArray; - tmp: Byte; - i: Integer; - F: File of Byte; - -begin - if (Width mod 4) > 0 then - Width := Width + 4 - (Width mod 4); - - GetMem(pixels, Width*Height*3); - glReadPixels(0, 0, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pixels); - - {$R-} - for i := 0 to Width * Height - 1 do - with PaRGB(pixels)[i] do - begin - tmp := R; - R := B; - B := tmp; - end; - {$R+} - - with FILEHEADER do - begin - bfType := $4D42; // "BM" - bfSize := Width*Height*3 + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER); - bfReserved1 := 0; - bfReserved2 := 0; - bfOffBits := SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER); - end; - - with INFOHEADER do - begin - biSize := SizeOf(BITMAPINFOHEADER); - biWidth := Width; - biHeight := Height; - biPlanes := 1; - biBitCount := 24; - biCompression := 0; - biSizeImage := Width*Height*3; - biXPelsPerMeter := 0; - biYPelsPerMeter := 0; - biClrUsed := 0; - biClrImportant := 0; - end; - - AssignFile(F, FileName); - Rewrite(F); - - BlockWrite(F, FILEHEADER, SizeOf(FILEHEADER)); - BlockWrite(F, INFOHEADER, SizeOf(INFOHEADER)); - BlockWrite(F, pixels[0], Width*Height*3); - - CloseFile(F); - - FreeMem(pixels); -end; - -function e_GetGamma(DC: HDC): Byte; -var - ramp: array [0..256*3-1] of Word; - rgb: array [0..2] of Double; - sum: double; - count: integer; - min: integer; - max: integer; - A, B: double; - i, j: integer; -begin - rgb[0] := 1.0; - rgb[1] := 1.0; - rgb[2] := 1.0; - - GetDeviceGammaRamp(DC, ramp); - - for i := 0 to 2 do - begin - sum := 0; - count := 0; - min := 256 * i; - max := min + 256; - - for j := min to max - 1 do - if ramp[j] > 0 then - begin - B := (j mod 256)/256; - A := ramp[j]/65536; - sum := sum + ln(A)/ln(B); - inc(count); - end; - rgb[i] := sum / count; - end; - - Result := 100 - Trunc(((rgb[0] + rgb[1] + rgb[2])/3 - 0.23) * 100/(2.7 - 0.23)); -end; - -procedure e_SetGamma(Gamma: Byte; DC: HDC); -var - ramp: array [0..256*3-1] of Word; - i: integer; - r: double; - g: double; -begin - g := (100 - Gamma)*(2.7 - 0.23)/100 + 0.23; - - for i := 0 to 255 do - begin - r := Exp(g * ln(i/256))*65536; - if r < 0 then r := 0 - else if r > 65535 then r := 65535; - ramp[i] := trunc(r); - ramp[i + 256] := trunc(r); - ramp[i + 512] := trunc(r); - end; - - SetDeviceGammaRamp(DC, ramp); -end; - -function e_SimpleFontCreate(FontName: PChar; Size: Byte; Weight: Word; DC: HDC): DWORD; -var - font: HFONT; -begin - Result := glGenLists(96); // Generate enough display lists to hold - font := CreateFont(-Size, // height of font - 0, // average character width - 0, // angle of escapement - 0, // base-line orientation angle - Weight, // font weight - 0, // italic - 0, // underline - 0, // strikeout - RUSSIAN_CHARSET, // character set - OUT_TT_PRECIS, // output precision - CLIP_DEFAULT_PRECIS, // clipping precision - ANTIALIASED_QUALITY, // output quality - FF_DONTCARE or DEFAULT_PITCH, // pitch and family - FontName); // font - SelectObject(DC, font); // Sets the new font as the current font in the device context - wglUseFontBitmaps(DC, 32, 224, Result); // Creates a set display lists containing the bitmap fonts -end; - -procedure e_SimpleFontFree(Font: DWORD); +procedure e_Clear(Mask: TGLbitfield; Red, Green, Blue: Single); overload; begin - glDeleteLists(Font, 223); // Delete the font display lists, returning used memory + if e_NoGraphics then Exit; + glClearColor(Red, Green, Blue, 0); + glClear(Mask); end; -procedure e_SimpleFontPrint(X, Y: SmallInt; Text: PChar; Font: Integer; Red, Green, Blue: Byte); +procedure e_Clear(); overload; begin - glPopAttrib(); // Rendering bug workaround - - glColor3ub(Red, Green, Blue); - glDisable(GL_TEXTURE_2D); // Turn off textures, don't want our text textured - glRasterPos2i(X, Y); // Position the Text - glPushAttrib(GL_LIST_BIT); // Save's the current base list - glListBase(DWORD(Font-32)); // Set the base list to our character list - glCallLists(Length(Text), GL_UNSIGNED_BYTE, Text); // Display the text - glPopAttrib(); // Restore the old base list + if e_NoGraphics then Exit; + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); end; -procedure e_SimpleFontPrintEx(X, Y: SmallInt; Text: PChar; Font: DWORD; Red, Green, Blue, - sRed, sGreen, sBlue, sWidth: Byte); +procedure e_EndRender(); begin - e_SimpleFontPrint(X, Y, Text, Font, Red, Green, Blue); - e_SimpleFontPrint(X+sWidth, Y+sWidth, Text, Font, sRed, sGreen, sBlue); + if e_NoGraphics then Exit; + glPopMatrix(); end; function e_CharFont_Create(sp: ShortInt=0): DWORD; @@ -1096,6 +942,7 @@ procedure e_CharFont_Print(FontID: DWORD; X, Y: Integer; Text: string); var a: Integer; begin + if e_NoGraphics then Exit; if Text = '' then Exit; if e_CharFonts = nil then Exit; if Integer(FontID) > High(e_CharFonts) then Exit; @@ -1118,6 +965,7 @@ var a: Integer; c: TRGB; begin + if e_NoGraphics then Exit; if Text = '' then Exit; if e_CharFonts = nil then Exit; if Integer(FontID) > High(e_CharFonts) then Exit; @@ -1152,6 +1000,7 @@ var tc, c: TRGB; w, h: Word; begin + if e_NoGraphics then Exit; if Text = '' then Exit; if e_CharFonts = nil then Exit; if Integer(FontID) > High(e_CharFonts) then Exit; @@ -1356,18 +1205,19 @@ begin if e_CharFonts = nil then Exit; for a := 0 to High(e_CharFonts) do - e_CharFont_Remove(a); + e_CharFont_Remove(a); e_CharFonts := nil; end; -procedure e_TextureFontBuild(Texture: DWORD; var FontID: DWORD; XCount, YCount: Word; +procedure e_TextureFontBuild(Tex: DWORD; var FontID: DWORD; XCount, YCount: Word; Space: ShortInt=0); var loop1 : GLuint; cx, cy : real; i, id: DWORD; begin + if e_NoGraphics then Exit; e_WriteLog('Creating texture font...', MSG_NOTIFY); id := DWORD(-1); @@ -1389,33 +1239,37 @@ begin with e_TextureFonts[id] do begin Base := glGenLists(XCount*YCount); - TextureID := e_Textures[Texture].ID; - CharWidth := (e_Textures[Texture].Width div XCount)+Space; - CharHeight := e_Textures[Texture].Height div YCount; + TextureID := e_Textures[Tex].tx.id; + CharWidth := (e_Textures[Tex].tx.Width div XCount)+Space; + CharHeight := e_Textures[Tex].tx.Height div YCount; + XC := XCount; + YC := YCount; + Texture := Tex; + SPC := Space; end; - - glBindTexture(GL_TEXTURE_2D, e_Textures[Texture].ID); + + glBindTexture(GL_TEXTURE_2D, e_Textures[Tex].tx.id); for loop1 := 0 to XCount*YCount-1 do begin cx := (loop1 mod XCount)/XCount; - cy := (loop1 div YCount)/YCount; + cy := (loop1 div YCount)/YCount; - glNewList(e_TextureFonts[id].Base+loop1, GL_COMPILE); - glBegin(GL_QUADS); + glNewList(e_TextureFonts[id].Base+loop1, GL_COMPILE); + glBegin(GL_QUADS); glTexCoord2f(cx, 1.0-cy-1/YCount); - glVertex2d(0, e_Textures[Texture].Height div YCount); + glVertex2d(0, e_Textures[Tex].tx.Height div YCount); - glTexCoord2f(cx+1/XCount, 1.0-cy-1/YCount); - glVertex2i(e_Textures[Texture].Width div XCount, e_Textures[Texture].Height div YCount); + glTexCoord2f(cx+1/XCount, 1.0-cy-1/YCount); + glVertex2i(e_Textures[Tex].tx.Width div XCount, e_Textures[Tex].tx.Height div YCount); - glTexCoord2f(cx+1/XCount, 1.0-cy); - glVertex2i(e_Textures[Texture].Width div XCount, 0); + glTexCoord2f(cx+1/XCount, 1.0-cy); + glVertex2i(e_Textures[Tex].tx.Width div XCount, 0); - glTexCoord2f(cx, 1.0-cy); + glTexCoord2f(cx, 1.0-cy); glVertex2i(0, 0); glEnd(); - glTranslated((e_Textures[Texture].Width div XCount)+Space, 0, 0); - glEndList(); + glTranslated((e_Textures[Tex].tx.Width div XCount)+Space, 0, 0); + glEndList(); end; FontID := id; @@ -1423,12 +1277,14 @@ end; procedure e_TextureFontKill(FontID: DWORD); begin - glDeleteLists(e_TextureFonts[FontID].Base, 256); + if e_NoGraphics then Exit; + glDeleteLists(e_TextureFonts[FontID].Base, 256); e_TextureFonts[FontID].Base := 0; end; procedure e_TextureFontPrint(X, Y: GLint; Text: string; FontID: DWORD); begin + if e_NoGraphics then Exit; if Integer(FontID) > High(e_TextureFonts) then Exit; if Text = '' then Exit; @@ -1452,6 +1308,7 @@ end; // god forgive me for this, but i cannot figure out how to do it without lists procedure e_TextureFontPrintChar(X, Y: Integer; Ch: Char; FontID: DWORD; Shadow: Boolean = False); begin + if e_NoGraphics then Exit; glPushMatrix; if Shadow then @@ -1470,12 +1327,31 @@ begin glPopMatrix; end; +procedure e_TextureFontPrintCharEx (X, Y: Integer; Ch: Char; FontID: DWORD; Shadow: Boolean = False); +begin + glBindTexture(GL_TEXTURE_2D, e_TextureFonts[FontID].TextureID); + glEnable(GL_TEXTURE_2D); + //glListBase(DWORD(Integer(e_TextureFonts[FontID].Base)-32)); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + e_TextureFontPrintChar(X, Y, Ch, FontID, Shadow); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); +end; + +function e_TextureFontCharWidth (ch: Char; FontID: DWORD): Integer; +begin + result := e_TextureFonts[FontID].CharWidth; +end; + procedure e_TextureFontPrintFmt(X, Y: Integer; Text: string; FontID: DWORD; Shadow: Boolean = False); var a, TX, TY, len: Integer; tc, c: TRGB; w: Word; begin + if e_NoGraphics then Exit; if Text = '' then Exit; if e_TextureFonts = nil then Exit; if Integer(FontID) > High(e_TextureFonts) then Exit; @@ -1565,6 +1441,7 @@ end; procedure e_TextureFontPrintEx(X, Y: GLint; Text: string; FontID: DWORD; Red, Green, Blue: Byte; Scale: Single; Shadow: Boolean = False); begin + if e_NoGraphics then Exit; if Text = '' then Exit; glPushMatrix; @@ -1598,6 +1475,9 @@ end; procedure e_TextureFontGetSize(ID: DWORD; var CharWidth, CharHeight: Byte); begin + CharWidth := 16; + CharHeight := 16; + if e_NoGraphics then Exit; if Integer(ID) > High(e_TextureFonts) then Exit; CharWidth := e_TextureFonts[ID].CharWidth; @@ -1608,6 +1488,7 @@ procedure e_RemoveAllTextureFont(); var i: integer; begin + if e_NoGraphics then Exit; if e_TextureFonts = nil then Exit; for i := 0 to High(e_TextureFonts) do @@ -1641,6 +1522,12 @@ begin Result.Height := Height; end; +function _TRect(L, T, R, B: LongInt): TRect; +begin + Result.Top := T; + Result.Left := L; + Result.Right := R; + Result.Bottom := B; +end; end. - diff --git a/src/engine/e_textures.pas b/src/engine/e_textures.pas index 9dd9192..e6246bc 100644 --- a/src/engine/e_textures.pas +++ b/src/engine/e_textures.pas @@ -1,3 +1,19 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$MODE DELPHI} unit e_textures; { This unit provides interface to load 24-bit and 32-bit uncompressed images @@ -7,53 +23,98 @@ unit e_textures; interface uses - Windows, dglOpenGL, SysUtils, e_log; + GL, GLExt, SysUtils, e_log, + ImagingTypes, Imaging, ImagingUtility; + +type + GLTexture = record + id: GLuint; + width, height: Word; // real + glwidth, glheight: Word; // powerof2 + u, v: Single; // usually 1.0 + fmt: GLuint; + end; var - fUseMipmaps: Boolean = False; + e_DummyTextures: Boolean = False; + e_glLegacyNPOT: Boolean = False; TEXTUREFILTER: Integer = GL_NEAREST; -// Standard set of images loading functions -function LoadTexture( Filename: String; var Texture: GLuint; - var pWidth, pHeight: Word ): Boolean; +function CreateTexture (var tex: GLTexture; Width, Height, aFormat: Word; pData: Pointer): Boolean; -function LoadTextureEx( Filename: String; var Texture: GLuint; - fX, fY, fWidth, fHeight: Word ): Boolean; +// Standard set of images loading functions +function LoadTexture (Filename: String; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; +function LoadTextureEx (Filename: String; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord=nil): Boolean; +function LoadTextureMem (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; +function LoadTextureMemEx (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord=nil): Boolean; -function LoadTextureMem( pData: Pointer; var Texture: GLuint; - var pWidth, pHeight: Word ): Boolean; +// `img` must be valid! +function LoadTextureImg (var img: TImageData; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; -function LoadTextureMemEx( pData: Pointer; var Texture: GLuint; - fX, fY, fWidth, fHeight: Word ): Boolean; implementation -type - TTGAHeader = packed record - FileType: Byte; - ColorMapType: Byte; - ImageType: Byte; - ColorMapSpec: array[0..4] of Byte; - OrigX: array[0..1] of Byte; - OrigY: array[0..1] of Byte; - Width: array[0..1] of Byte; - Height: array[0..1] of Byte; - BPP: Byte; - ImageInfo: Byte; - end; +uses + Classes, BinEditor, utils; + + +function AlignP2 (n: Word): Word; +begin + Dec(n); + n := n or (n shr 1); + n := n or (n shr 2); + n := n or (n shr 4); + n := n or (n shr 8); + n := n or (n shr 16); + Inc(n); + Result := n; +end; + // This is auxiliary function that creates OpenGL texture from raw image data -function CreateTexture( Width, Height, Format: Word; pData: Pointer ): Integer; +function CreateTexture (var tex: GLTexture; Width, Height, aFormat: Word; pData: Pointer): Boolean; var Texture: GLuint; + fmt: GLenum; + buf: PByte; + f, c: Integer; begin - glGenTextures( 1, @Texture ); - glBindTexture( GL_TEXTURE_2D, Texture ); + tex.width := Width; + tex.height := Height; + tex.glwidth := Width; + tex.glheight := Height; + tex.u := 1; + tex.v := 1; + + if e_glLegacyNPOT then + begin + tex.glwidth := AlignP2(Width); + tex.glheight := AlignP2(Height); + if tex.glwidth <> tex.width then tex.u := (tex.width+0.0)/(tex.glwidth+0.0); + if tex.glheight <> tex.height then tex.v := (tex.height+0.0)/(tex.glheight+0.0); + end; - {Texture blends with object background} - glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - {Texture does NOT blend with object background} - // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); + //if (tex.glwidth <> tex.width) or (tex.glheight <> tex.height) then + // e_WriteLog(Format('NPOT: orig is %ux%u; gl is %ux%u; u=%f; v=%f', [Width, Height, tex.glwidth, tex.glheight, tex.u, tex.v]), MSG_NOTIFY); + + if e_DummyTextures then + begin + tex.id := GLuint(-1); + Result := True; + Exit; + end; + + glGenTextures(1, @Texture); + tex.id := Texture; + glBindTexture(GL_TEXTURE_2D, Texture); + + if (tex.glwidth <> tex.width) or (tex.glheight <> tex.height) then + e_WriteLog(Format('NPOT: %u is %ux%u; gl is %ux%u; u=%f; v=%f', [tex.id, Width, Height, tex.glwidth, tex.glheight, tex.u, tex.v]), MSG_NOTIFY); + + // texture blends with object background + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + // texture does NOT blend with object background + //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); { Select a filtering type. @@ -66,370 +127,249 @@ begin } // for GL_TEXTURE_MAG_FILTER only first two can be used - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TEXTUREFILTER ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TEXTUREFILTER); // for GL_TEXTURE_MIN_FILTER all of the above can be used - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TEXTUREFILTER ); - - if Format = GL_RGBA then - begin - if fUseMipmaps then - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, Width, Height, GL_RGBA, - GL_UNSIGNED_BYTE, pData ) - else - glTexImage2D( GL_TEXTURE_2D, 0, 4, Width, Height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, pData ); - end else - begin - if fUseMipmaps then - gluBuild2DMipmaps( GL_TEXTURE_2D, 3, Width, Height, GL_RGB, - GL_UNSIGNED_BYTE, pData ) - else - glTexImage2D( GL_TEXTURE_2D, 0, 3, Width, Height, - 0, GL_RGB, GL_UNSIGNED_BYTE, pData ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TEXTUREFILTER); + + // create empty texture + if aFormat = GL_RGBA then fmt := GL_RGBA else fmt := GL_RGB; // silly, yeah? + glTexImage2D(GL_TEXTURE_2D, 0, fmt, tex.glwidth, tex.glheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil); + + (* + GetMem(buf, tex.glwidth*4*tex.glheight); + try + FillChar(buf^, tex.glwidth*4*tex.glheight, 255); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex.glwidth, tex.glheight, fmt, GL_UNSIGNED_BYTE, buf); + if (tex.glheight = 128) and (tex.height = 80) then + begin + for f := 0 to tex.glheight-1 do + begin + for c := 0 to tex.glwidth-1 do + begin + buf[f*(tex.glwidth*4)+c*4+0] := 255; + buf[f*(tex.glwidth*4)+c*4+1] := 127; + buf[f*(tex.glwidth*4)+c*4+2] := 0; + end; + end; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 82, tex.glwidth, {tex.glheight}1, fmt, GL_UNSIGNED_BYTE, buf); + end; + finally + FreeMem(buf); end; + *) - Result := Texture; + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, fmt, GL_UNSIGNED_BYTE, pData); + //glTexSubImage2D(GL_TEXTURE_2D, 0, 0, tex.glheight-tex.height, Width, Height, fmt, GL_UNSIGNED_BYTE, pData); + + glBindTexture(GL_TEXTURE_2D, 0); + + Result := true; end; -function LoadTextureMem( pData: Pointer; var Texture: GLuint; - var pWidth, pHeight: Word ): Boolean; +// `img` must be valid! +function LoadTextureImg (var img: TImageData; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; var - TGAHeader: TTGAHeader; - image: Pointer; - Width, Height: Integer; - ImageSize: Integer; - i: Integer; - Front: ^Byte; - Back: ^Byte; - Temp: Byte; - BPP: Byte; - + image, ii: PByte; + width, height: Integer; + imageSize: Integer; + x, y: Integer; + clr: TColor32Rec; begin - Result := False; + result := false; pWidth := 0; pHeight := 0; + if Fmt <> nil then Fmt^ := GL_RGBA; // anyway - CopyMemory( @TGAHeader, pData, SizeOf(TGAHeader) ); - - if ( TGAHeader.ImageType <> 2 ) then + if (img.width < 1) or (img.width > 32768) or (img.height < 1) or (img.height > 32768) then begin - e_WriteLog( 'Error loading texture: Bad ImageType', MSG_WARNING ); - Exit; + e_WriteLog('Error loading texture: invalid image dimensions', MSG_WARNING); + exit; end; - - if ( TGAHeader.ColorMapType <> 0 ) then - begin - e_WriteLog( 'Error loading texture: Bad ColorMapType', MSG_WARNING ); - Exit; + //ConvertImage(img, ifA8R8G8B8); + width := img.width; + height := img.height; + pWidth := width; + pHeight := height; + imageSize := Width*Height*4; + GetMem(image, imageSize); + try + // it's slow, but i don't care for now + ii := image; + for y := height-1 downto 0 do + begin + for x := 0 to width-1 do + begin + clr := GetPixel32(img, x, y); + ii^ := clr.r; Inc(ii); + ii^ := clr.g; Inc(ii); + ii^ := clr.b; Inc(ii); + ii^ := clr.a; Inc(ii); + end; + end; + CreateTexture(Texture, width, height, GL_RGBA, image); + result := true; + finally + FreeMem(image); end; - - if ( TGAHeader.BPP < 24 ) then - begin - e_WriteLog( 'Error loading texture: BPP less than 24', MSG_WARNING ); - Exit; - end; - - Width := TGAHeader.Width[0] + TGAHeader.Width[1] * 256; - Height := TGAHeader.Height[0] + TGAHeader.Height[1] * 256; - BPP := TGAHeader.BPP; - - ImageSize := Width * Height * (BPP div 8); - - GetMem( Image, ImageSize ); - CopyMemory( Image, Pointer( Integer(pData) + SizeOf(TGAHeader) ), ImageSize ); - - for i := 0 to Width * Height - 1 do - begin - Front := Pointer( Integer(Image) + i*(BPP div 8) ); - Back := Pointer( Integer(Image) + i*(BPP div 8) + 2 ); - Temp := Front^; - Front^ := Back^; - Back^ := Temp; - end; - - if ( BPP = 24 ) then - Texture := CreateTexture( Width, Height, GL_RGB, Image ) - else - Texture := CreateTexture( Width, Height, GL_RGBA, Image ); - - FreeMem( Image ); - - pWidth := Width; - pHeight := Height; - - Result := True; end; -function LoadTextureMemEx( pData: Pointer; var Texture: GLuint; - fX, fY, fWidth, fHeight: Word ): Boolean; -var - TGAHeader: TTGAHeader; - image, image2: Pointer; - Width, Height: Integer; - ImageSize: Integer; - i, a, b: Integer; - Front: ^Byte; - Back: ^Byte; - Temp: Byte; - BPP: Byte; - Base: Integer; +function LoadTextureMem (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; +var + image, ii: PByte; + width, height: Integer; + imageSize: Integer; + img: TImageData; + x, y: Integer; + clr: TColor32Rec; begin - Result := False; - - CopyMemory( @TGAHeader, pData, SizeOf(TGAHeader) ); - - if ( TGAHeader.ImageType <> 2 ) then - begin - e_WriteLog( 'Error loading texture: Bad ImageType', MSG_WARNING ); - Exit; - end; + result := false; + pWidth := 0; + pHeight := 0; + if Fmt <> nil then Fmt^ := GL_RGBA; // anyway - if ( TGAHeader.ColorMapType <> 0 ) then + InitImage(img); + if not LoadImageFromMemory(pData, dataSize, img) then begin - e_WriteLog( 'Error loading texture: Bad ColorMapType', MSG_WARNING ); - Exit; + e_WriteLog('Error loading texture: unknown image format', MSG_WARNING); + exit; end; - - if ( TGAHeader.BPP < 24 ) then - begin - e_WriteLog( 'Error loading texture: BPP less than 24', MSG_WARNING ); - Exit; + try + result := LoadTextureImg(img, Texture, pWidth, pHeight, Fmt); + finally + FreeImage(img); end; +end; - Width := TGAHeader.Width[0] + TGAHeader.Width[1] * 256; - Height := TGAHeader.Height[0] + TGAHeader.Height[1] * 256; - BPP := TGAHeader.BPP; - - if fX > Width then Exit; - if fY > Height then Exit; - if fX+fWidth > Width then Exit; - if fY+fHeight > Height then Exit; - - ImageSize := Width * Height * (BPP div 8); - GetMem( Image2, ImageSize ); - CopyMemory( Image2, Pointer( Integer(pData) + SizeOf(TGAHeader) ), ImageSize ); - a := BPP div 8; +function LoadTextureMemEx (pData: Pointer; dataSize: LongInt; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord=nil): Boolean; +var + image, ii: PByte; + width, height: Integer; + imageSize: Integer; + img: TImageData; + x, y: Integer; + clr: TColor32Rec; +begin + result := false; + if Fmt <> nil then Fmt^ := GL_RGBA; // anyway - for i := 0 to Width * Height - 1 do + InitImage(img); + if not LoadImageFromMemory(pData, dataSize, img) then begin - Front := Pointer( Integer(Image2) + i * a ); - Back := Pointer( Integer(Image2) + i * a + 2 ); - Temp := Front^; - Front^ := Back^; - Back^ := Temp; + e_WriteLog('Error loading texture: unknown image format', MSG_WARNING); + exit; + end; + try + if (img.width < 1) or (img.width > 32768) or (img.height < 1) or (img.height > 32768) then + begin + e_WriteLog('Error loading texture: invalid image dimensions', MSG_WARNING); + exit; + end; + //ConvertImage(img, ifA8R8G8B8); + if fX > img.width then exit; + if fY > img.height then exit; + if fX+fWidth > img.width then exit; + if fY+fHeight > img.height then exit; + //writeln('fX=', fX, '; fY=', fY, '; fWidth=', fWidth, '; fHeight=', fHeight); + imageSize := img.width*img.height*4; + GetMem(image, imageSize); + try + // it's slow, but i don't care for now + ii := image; + for y := fY+fHeight-1 downto fY do + begin + for x := fX to fX+fWidth-1 do + begin + clr := GetPixel32(img, x, y); + ii^ := clr.r; Inc(ii); + ii^ := clr.g; Inc(ii); + ii^ := clr.b; Inc(ii); + ii^ := clr.a; Inc(ii); + end; + end; + CreateTexture(Texture, fWidth, fHeight, GL_RGBA, image); + result := true; + finally + FreeMem(image); + end; + finally + FreeImage(img); end; - - fY := Height - (fY + fHeight); - - ImageSize := fHeight * fWidth * (BPP div 8); - GetMem( Image, ImageSize ); - - Base := Integer( Image2 ) + fY * Width * (BPP div 8) + fX * (BPP div 8); - a := fWidth * (BPP div 8); - b := Width * (BPP div 8); - - for i := 0 to fHeight-1 do - CopyMemory( Pointer( Integer(image) + a*i ), Pointer( Base + b*i ), a ); - - if ( BPP = 24 ) then - Texture := CreateTexture( fWidth, fHeight, GL_RGB, image ) - else - Texture := CreateTexture( fWidth, fHeight, GL_RGBA, image ); - - FreeMem( Image ); - FreeMem( Image2 ); - - Result := True; end; -function LoadTexture( Filename: String; var Texture: GLuint; - var pWidth, pHeight: Word ): Boolean; -var - TGAHeader: TTGAHeader; - TGAFile: File; - bytesRead: Integer; - image: Pointer; - Width, Height: Integer; - ImageSize: Integer; - i: Integer; - Front: ^Byte; - Back: ^Byte; - Temp: Byte; - BPP: Byte; +function LoadTexture (filename: AnsiString; var Texture: GLTexture; var pWidth, pHeight: Word; Fmt: PWord=nil): Boolean; +var + fs: TStream; + img: Pointer; + imageSize: LongInt; begin - Result := False; + result := False; pWidth := 0; pHeight := 0; + if Fmt <> nil then Fmt^ := GL_RGBA; // anyway + fs := nil; - if not FileExists(Filename) then - begin - e_WriteLog('Texture ' + Filename + ' not found', MSG_WARNING); - Exit; + try + fs := openDiskFileRO(filename); + except + fs := nil; end; - - AssignFile( TGAFile, Filename ); - Reset( TGAFile, 1 ); - BlockRead( TGAFile, TGAHeader, SizeOf(TGAHeader) ); - - if ( TGAHeader.ImageType <> 2 ) then + if fs = nil then begin - CloseFile( TGAFile ); - e_WriteLog( 'Error loading texture: Bad ImageType', MSG_WARNING ); - Exit; + e_WriteLog('Texture "'+filename+'" not found', MSG_WARNING); + exit; end; - if ( TGAHeader.ColorMapType <> 0 ) then - begin - CloseFile( TGAFile ); - e_WriteLog( 'Error loading texture: Bad ColorMapType', MSG_WARNING ); - Exit; + try + imageSize := fs.size; + GetMem(img, imageSize); + try + fs.readBuffer(img^, imageSize); + result := LoadTextureMem(img, imageSize, Texture, pWidth, pHeight, Fmt); + finally + FreeMem(img); + end; + finally + fs.Free(); end; - - if ( TGAHeader.BPP < 24 ) then - begin - CloseFile( TGAFile ); - e_WriteLog( 'Error loading texture: BPP less than 24', MSG_WARNING ); - Exit; - end; - - Width := TGAHeader.Width[0] + TGAHeader.Width[1] * 256; - Height := TGAHeader.Height[0] + TGAHeader.Height[1] * 256; - BPP := TGAHeader.BPP; - - ImageSize := Width * Height * (BPP div 8); - - GetMem( Image, ImageSize ); - - BlockRead( TGAFile, image^, ImageSize, bytesRead ); - if ( bytesRead <> ImageSize ) then - begin - CloseFile( TGAFile ); - Exit; - end; - - CloseFile( TGAFile ); - - for i := 0 to Width * Height - 1 do - begin - Front := Pointer( Integer(Image) + i * (BPP div 8) ); - Back := Pointer( Integer(Image) + i * (BPP div 8) + 2 ); - Temp := Front^; - Front^ := Back^; - Back^ := Temp; - end; - - if ( BPP = 24 ) then - Texture := CreateTexture( Width, Height, GL_RGB, Image ) - else - Texture := CreateTexture( Width, Height, GL_RGBA, Image ); - - FreeMem( Image ); - - pWidth := Width; - pHeight := Height; - - Result := True; end; -function LoadTextureEx( Filename: String; var Texture: GLuint; - fX, fY, fWidth, fHeight: Word ): Boolean; + +function LoadTextureEx (filename: AnsiString; var Texture: GLTexture; fX, fY, fWidth, fHeight: Word; Fmt: PWord=nil): Boolean; var - TGAHeader: TTGAHeader; - TGAFile: File; - image, image2: Pointer; - Width, Height: Integer; - ImageSize: Integer; - i: Integer; - Front: ^Byte; - Back: ^Byte; - Temp: Byte; - BPP: Byte; - Base: Integer; - + fs: TStream; + img: Pointer; + imageSize: LongInt; begin - Result := False; - - if not FileExists(Filename) then - begin - e_WriteLog( 'Texture ' + Filename + ' not found', MSG_WARNING ); - Exit; - end; - - AssignFile( TGAFile, Filename ); - Reset( TGAFile, 1 ); - BlockRead( TGAFile, TGAHeader, SizeOf(TGAHeader) ); - - if ( TGAHeader.ImageType <> 2 ) then - begin - CloseFile( TGAFile ); - e_WriteLog( 'Error loading texture: Bad ImageType', MSG_WARNING ); - Exit; - end; - - if ( TGAHeader.ColorMapType <> 0 ) then - begin - CloseFile( TGAFile ); - e_WriteLog( 'Error loading texture: Bad ColorMapType', MSG_WARNING ); - Exit; + result := False; + if Fmt <> nil then Fmt^ := GL_RGBA; // anyway + fs := nil; + + try + fs := openDiskFileRO(filename); + except + fs := nil; end; - - if ( TGAHeader.BPP < 24 ) then + if fs = nil then begin - CloseFile( TGAFile ); - e_WriteLog( 'Error loading texture: BPP less than 24', MSG_WARNING ); - Exit; + e_WriteLog('Texture "'+filename+'" not found', MSG_WARNING); + exit; end; - Width := TGAHeader.Width[0] + TGAHeader.Width[1] * 256; - Height := TGAHeader.Height[0] + TGAHeader.Height[1] * 256; - BPP := TGAHeader.BPP; - - if fX > Width then Exit; - if fY > Height then Exit; - if fX+fWidth > Width then Exit; - if fY+fHeight > Height then Exit; - - ImageSize := Width * Height * (BPP div 8); - GetMem( Image2, ImageSize ); - BlockRead( TGAFile, Image2^, ImageSize ); - - CloseFile( TGAFile ); - - for i := 0 to Width * Height - 1 do - begin - Front := Pointer( Integer(Image2) + i * (BPP div 8) ); - Back := Pointer( Integer(Image2) + i * (BPP div 8) + 2 ); - Temp := Front^; - Front^ := Back^; - Back^ := Temp; + try + imageSize := fs.size; + GetMem(img, imageSize); + try + fs.readBuffer(img^, imageSize); + result := LoadTextureMemEx(img, imageSize, Texture, fX, fY, fWidth, fHeight, Fmt); + finally + FreeMem(img); + end; + finally + fs.Free(); end; - - fY := Height - (fY + fHeight); - - ImageSize := fHeight * fWidth * (BPP div 8); - GetMem( Image, ImageSize ); - - Base := Integer(Image2) + fY * Width * (BPP div 8) + fX * (BPP div 8); - - for i := 0 to fHeight-1 do - begin - CopyMemory( Pointer( Integer(image) + fWidth * (BPP div 8) * i ), - Pointer( Base + Width * (BPP div 8) * i), fWidth * (BPP div 8) ); - end; - - if ( BPP = 24 ) then - Texture := CreateTexture( fWidth, fHeight, GL_RGB, Image ) - else - Texture := CreateTexture( fWidth, fHeight, GL_RGBA, Image ); - - FreeMem( Image ); - FreeMem( Image2 ); - - Result := True; end; end. - diff --git a/src/lib/dgl/GL.pas b/src/lib/dgl/GL.pas deleted file mode 100644 index c3eda2f..0000000 --- a/src/lib/dgl/GL.pas +++ /dev/null @@ -1,2226 +0,0 @@ -(*++ BUILD Version: 0004 // Increment this if a change has global effects - -Copyright (c) 1985-96, Microsoft Corporation - -Module Name: - - gl.h - -Abstract: - - Procedure declarations, constant definitions and macros for the OpenGL - component. - ---*) - -(* -** Copyright 1996 Silicon Graphics, Inc. -** All Rights Reserved. -** -** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; -** the contents of this file may not be disclosed to third parties, copied or -** duplicated in any form, in whole or in part, without the prior written -** permission of Silicon Graphics, Inc. -** -** RESTRICTED RIGHTS LEGEND: -** Use, duplication or disclosure by the Government is subject to restrictions -** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data -** and Computer Software clause at DFARS 252.227-7013, and/or in similar or -** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - -** rights reserved under the Copyright Laws of the United States. -*) - -{******************************************************************************} -{ Converted to Delphi by Tom Nuydens (tom@delphi3d.net) } -{ For the latest updates, visit Delphi3D: http://www.delphi3d.net } -{******************************************************************************} - -unit GL; - -interface - -uses - SysUtils, Windows; - -type - GLenum = Cardinal; PGLenum = ^GLenum; - GLboolean = Byte; PGLboolean = ^GLboolean; - GLbitfield = Cardinal; PGLbitfield = ^GLbitfield; - GLbyte = ShortInt; PGLbyte = ^GLbyte; - GLshort = SmallInt; PGLshort = ^GLshort; - GLint = Integer; PGLint = ^GLint; - GLsizei = Integer; PGLsizei = ^GLsizei; - GLubyte = Byte; PGLubyte = ^GLubyte; - GLushort = Word; PGLushort = ^GLushort; - GLuint = Cardinal; PGLuint = ^GLuint; - GLfloat = Single; PGLfloat = ^GLfloat; - GLclampf = Single; PGLclampf = ^GLclampf; - GLdouble = Double; PGLdouble = ^GLdouble; - GLclampd = Double; PGLclampd = ^GLclampd; -{ GLvoid = void; } PGLvoid = Pointer; - -{******************************************************************************} - -const - // Version - GL_VERSION_1_1 = 1; - - // AccumOp - GL_ACCUM = $0100; - GL_LOAD = $0101; - GL_RETURN = $0102; - GL_MULT = $0103; - GL_ADD = $0104; - - // AlphaFunction - GL_NEVER = $0200; - GL_LESS = $0201; - GL_EQUAL = $0202; - GL_LEQUAL = $0203; - GL_GREATER = $0204; - GL_NOTEQUAL = $0205; - GL_GEQUAL = $0206; - GL_ALWAYS = $0207; - - // AttribMask - GL_CURRENT_BIT = $00000001; - GL_POINT_BIT = $00000002; - GL_LINE_BIT = $00000004; - GL_POLYGON_BIT = $00000008; - GL_POLYGON_STIPPLE_BIT = $00000010; - GL_PIXEL_MODE_BIT = $00000020; - GL_LIGHTING_BIT = $00000040; - GL_FOG_BIT = $00000080; - GL_DEPTH_BUFFER_BIT = $00000100; - GL_ACCUM_BUFFER_BIT = $00000200; - GL_STENCIL_BUFFER_BIT = $00000400; - GL_VIEWPORT_BIT = $00000800; - GL_TRANSFORM_BIT = $00001000; - GL_ENABLE_BIT = $00002000; - GL_COLOR_BUFFER_BIT = $00004000; - GL_HINT_BIT = $00008000; - GL_EVAL_BIT = $00010000; - GL_LIST_BIT = $00020000; - GL_TEXTURE_BIT = $00040000; - GL_SCISSOR_BIT = $00080000; - GL_ALL_ATTRIB_BITS = $000FFFFF; - - // BeginMode - GL_POINTS = $0000; - GL_LINES = $0001; - GL_LINE_LOOP = $0002; - GL_LINE_STRIP = $0003; - GL_TRIANGLES = $0004; - GL_TRIANGLE_STRIP = $0005; - GL_TRIANGLE_FAN = $0006; - GL_QUADS = $0007; - GL_QUAD_STRIP = $0008; - GL_POLYGON = $0009; - - // BlendingFactorDest - GL_ZERO = 0; - GL_ONE = 1; - GL_SRC_COLOR = $0300; - GL_ONE_MINUS_SRC_COLOR = $0301; - GL_SRC_ALPHA = $0302; - GL_ONE_MINUS_SRC_ALPHA = $0303; - GL_DST_ALPHA = $0304; - GL_ONE_MINUS_DST_ALPHA = $0305; - - // BlendingFactorSrc - // GL_ZERO - // GL_ONE - GL_DST_COLOR = $0306; - GL_ONE_MINUS_DST_COLOR = $0307; - GL_SRC_ALPHA_SATURATE = $0308; - // GL_SRC_ALPHA - // GL_ONE_MINUS_SRC_ALPHA - // GL_DST_ALPHA - // GL_ONE_MINUS_DST_ALPHA - - // Boolean - GL_TRUE = 1; - GL_FALSE = 0; - - // ClearBufferMask - // GL_COLOR_BUFFER_BIT - // GL_ACCUM_BUFFER_BIT - // GL_STENCIL_BUFFER_BIT - // GL_DEPTH_BUFFER_BIT - - // ClientArrayType - // GL_VERTEX_ARRAY - // GL_NORMAL_ARRAY - // GL_COLOR_ARRAY - // GL_INDEX_ARRAY - // GL_TEXTURE_COORD_ARRAY - // GL_EDGE_FLAG_ARRAY - - // ClipPlaneName - GL_CLIP_PLANE0 = $3000; - GL_CLIP_PLANE1 = $3001; - GL_CLIP_PLANE2 = $3002; - GL_CLIP_PLANE3 = $3003; - GL_CLIP_PLANE4 = $3004; - GL_CLIP_PLANE5 = $3005; - - // ColorMaterialFace - // GL_FRONT - // GL_BACK - // GL_FRONT_AND_BACK - - // ColorMaterialParameter - // GL_AMBIENT - // GL_DIFFUSE - // GL_SPECULAR - // GL_EMISSION - // GL_AMBIENT_AND_DIFFUSE - - // ColorPointerType - // GL_BYTE - // GL_UNSIGNED_BYTE - // GL_SHORT - // GL_UNSIGNED_SHORT - // GL_INT - // GL_UNSIGNED_INT - // GL_FLOAT - // GL_DOUBLE - - // CullFaceMode - // GL_FRONT - // GL_BACK - // GL_FRONT_AND_BACK - - // DataType - GL_BYTE = $1400; - GL_UNSIGNED_BYTE = $1401; - GL_SHORT = $1402; - GL_UNSIGNED_SHORT = $1403; - GL_INT = $1404; - GL_UNSIGNED_INT = $1405; - GL_FLOAT = $1406; - GL_2_BYTES = $1407; - GL_3_BYTES = $1408; - GL_4_BYTES = $1409; - GL_DOUBLE = $140A; - - // DepthFunction - // GL_NEVER - // GL_LESS - // GL_EQUAL - // GL_LEQUAL - // GL_GREATER - // GL_NOTEQUAL - // GL_GEQUAL - // GL_ALWAYS - - // DrawBufferMode - GL_NONE = 0; - GL_FRONT_LEFT = $0400; - GL_FRONT_RIGHT = $0401; - GL_BACK_LEFT = $0402; - GL_BACK_RIGHT = $0403; - GL_FRONT = $0404; - GL_BACK = $0405; - GL_LEFT = $0406; - GL_RIGHT = $0407; - GL_FRONT_AND_BACK = $0408; - GL_AUX0 = $0409; - GL_AUX1 = $040A; - GL_AUX2 = $040B; - GL_AUX3 = $040C; - - // Enable - // GL_FOG - // GL_LIGHTING - // GL_TEXTURE_1D - // GL_TEXTURE_2D - // GL_LINE_STIPPLE - // GL_POLYGON_STIPPLE - // GL_CULL_FACE - // GL_ALPHA_TEST - // GL_BLEND - // GL_INDEX_LOGIC_OP - // GL_COLOR_LOGIC_OP - // GL_DITHER - // GL_STENCIL_TEST - // GL_DEPTH_TEST - // GL_CLIP_PLANE0 - // GL_CLIP_PLANE1 - // GL_CLIP_PLANE2 - // GL_CLIP_PLANE3 - // GL_CLIP_PLANE4 - // GL_CLIP_PLANE5 - // GL_LIGHT0 - // GL_LIGHT1 - // GL_LIGHT2 - // GL_LIGHT3 - // GL_LIGHT4 - // GL_LIGHT5 - // GL_LIGHT6 - // GL_LIGHT7 - // GL_TEXTURE_GEN_S - // GL_TEXTURE_GEN_T - // GL_TEXTURE_GEN_R - // GL_TEXTURE_GEN_Q - // GL_MAP1_VERTEX_3 - // GL_MAP1_VERTEX_4 - // GL_MAP1_COLOR_4 - // GL_MAP1_INDEX - // GL_MAP1_NORMAL - // GL_MAP1_TEXTURE_COORD_1 - // GL_MAP1_TEXTURE_COORD_2 - // GL_MAP1_TEXTURE_COORD_3 - // GL_MAP1_TEXTURE_COORD_4 - // GL_MAP2_VERTEX_3 - // GL_MAP2_VERTEX_4 - // GL_MAP2_COLOR_4 - // GL_MAP2_INDEX - // GL_MAP2_NORMAL - // GL_MAP2_TEXTURE_COORD_1 - // GL_MAP2_TEXTURE_COORD_2 - // GL_MAP2_TEXTURE_COORD_3 - // GL_MAP2_TEXTURE_COORD_4 - // GL_POINT_SMOOTH - // GL_LINE_SMOOTH - // GL_POLYGON_SMOOTH - // GL_SCISSOR_TEST - // GL_COLOR_MATERIAL - // GL_NORMALIZE - // GL_AUTO_NORMAL - // GL_VERTEX_ARRAY - // GL_NORMAL_ARRAY - // GL_COLOR_ARRAY - // GL_INDEX_ARRAY - // GL_TEXTURE_COORD_ARRAY - // GL_EDGE_FLAG_ARRAY - // GL_POLYGON_OFFSET_POINT - // GL_POLYGON_OFFSET_LINE - // GL_POLYGON_OFFSET_FILL - - // ErrorCode - GL_NO_ERROR = 0; - GL_INVALID_ENUM = $0500; - GL_INVALID_VALUE = $0501; - GL_INVALID_OPERATION = $0502; - GL_STACK_OVERFLOW = $0503; - GL_STACK_UNDERFLOW = $0504; - GL_OUT_OF_MEMORY = $0505; - - // FeedBackMode - GL_2D = $0600; - GL_3D = $0601; - GL_3D_COLOR = $0602; - GL_3D_COLOR_TEXTURE = $0603; - GL_4D_COLOR_TEXTURE = $0604; - - // FeedBackToken - GL_PASS_THROUGH_TOKEN = $0700; - GL_POINT_TOKEN = $0701; - GL_LINE_TOKEN = $0702; - GL_POLYGON_TOKEN = $0703; - GL_BITMAP_TOKEN = $0704; - GL_DRAW_PIXEL_TOKEN = $0705; - GL_COPY_PIXEL_TOKEN = $0706; - GL_LINE_RESET_TOKEN = $0707; - - // FogMode - // GL_LINEAR - GL_EXP = $0800; - GL_EXP2 = $0801; - - // FogParameter - // GL_FOG_COLOR - // GL_FOG_DENSITY - // GL_FOG_END - // GL_FOG_INDEX - // GL_FOG_MODE - // GL_FOG_START - - // FrontFaceDirection - GL_CW = $0900; - GL_CCW = $0901; - - // GetMapTarget - GL_COEFF = $0A00; - GL_ORDER = $0A01; - GL_DOMAIN = $0A02; - - // GetPixelMap - // GL_PIXEL_MAP_I_TO_I - // GL_PIXEL_MAP_S_TO_S - // GL_PIXEL_MAP_I_TO_R - // GL_PIXEL_MAP_I_TO_G - // GL_PIXEL_MAP_I_TO_B - // GL_PIXEL_MAP_I_TO_A - // GL_PIXEL_MAP_R_TO_R - // GL_PIXEL_MAP_G_TO_G - // GL_PIXEL_MAP_B_TO_B - // GL_PIXEL_MAP_A_TO_A - - // GetPointerTarget - // GL_VERTEX_ARRAY_POINTER - // GL_NORMAL_ARRAY_POINTER - // GL_COLOR_ARRAY_POINTER - // GL_INDEX_ARRAY_POINTER - // GL_TEXTURE_COORD_ARRAY_POINTER - // GL_EDGE_FLAG_ARRAY_POINTER - - // GetTarget - GL_CURRENT_COLOR = $0B00; - GL_CURRENT_INDEX = $0B01; - GL_CURRENT_NORMAL = $0B02; - GL_CURRENT_TEXTURE_COORDS = $0B03; - GL_CURRENT_RASTER_COLOR = $0B04; - GL_CURRENT_RASTER_INDEX = $0B05; - GL_CURRENT_RASTER_TEXTURE_COORDS = $0B06; - GL_CURRENT_RASTER_POSITION = $0B07; - GL_CURRENT_RASTER_POSITION_VALID = $0B08; - GL_CURRENT_RASTER_DISTANCE = $0B09; - GL_POINT_SMOOTH = $0B10; - GL_POINT_SIZE = $0B11; - GL_POINT_SIZE_RANGE = $0B12; - GL_POINT_SIZE_GRANULARITY = $0B13; - GL_LINE_SMOOTH = $0B20; - GL_LINE_WIDTH = $0B21; - GL_LINE_WIDTH_RANGE = $0B22; - GL_LINE_WIDTH_GRANULARITY = $0B23; - GL_LINE_STIPPLE = $0B24; - GL_LINE_STIPPLE_PATTERN = $0B25; - GL_LINE_STIPPLE_REPEAT = $0B26; - GL_LIST_MODE = $0B30; - GL_MAX_LIST_NESTING = $0B31; - GL_LIST_BASE = $0B32; - GL_LIST_INDEX = $0B33; - GL_POLYGON_MODE = $0B40; - GL_POLYGON_SMOOTH = $0B41; - GL_POLYGON_STIPPLE = $0B42; - GL_EDGE_FLAG = $0B43; - GL_CULL_FACE = $0B44; - GL_CULL_FACE_MODE = $0B45; - GL_FRONT_FACE = $0B46; - GL_LIGHTING = $0B50; - GL_LIGHT_MODEL_LOCAL_VIEWER = $0B51; - GL_LIGHT_MODEL_TWO_SIDE = $0B52; - GL_LIGHT_MODEL_AMBIENT = $0B53; - GL_SHADE_MODEL = $0B54; - GL_COLOR_MATERIAL_FACE = $0B55; - GL_COLOR_MATERIAL_PARAMETER = $0B56; - GL_COLOR_MATERIAL = $0B57; - GL_FOG = $0B60; - GL_FOG_INDEX = $0B61; - GL_FOG_DENSITY = $0B62; - GL_FOG_START = $0B63; - GL_FOG_END = $0B64; - GL_FOG_MODE = $0B65; - GL_FOG_COLOR = $0B66; - GL_DEPTH_RANGE = $0B70; - GL_DEPTH_TEST = $0B71; - GL_DEPTH_WRITEMASK = $0B72; - GL_DEPTH_CLEAR_VALUE = $0B73; - GL_DEPTH_FUNC = $0B74; - GL_ACCUM_CLEAR_VALUE = $0B80; - GL_STENCIL_TEST = $0B90; - GL_STENCIL_CLEAR_VALUE = $0B91; - GL_STENCIL_FUNC = $0B92; - GL_STENCIL_VALUE_MASK = $0B93; - GL_STENCIL_FAIL = $0B94; - GL_STENCIL_PASS_DEPTH_FAIL = $0B95; - GL_STENCIL_PASS_DEPTH_PASS = $0B96; - GL_STENCIL_REF = $0B97; - GL_STENCIL_WRITEMASK = $0B98; - GL_MATRIX_MODE = $0BA0; - GL_NORMALIZE = $0BA1; - GL_VIEWPORT = $0BA2; - GL_MODELVIEW_STACK_DEPTH = $0BA3; - GL_PROJECTION_STACK_DEPTH = $0BA4; - GL_TEXTURE_STACK_DEPTH = $0BA5; - GL_MODELVIEW_MATRIX = $0BA6; - GL_PROJECTION_MATRIX = $0BA7; - GL_TEXTURE_MATRIX = $0BA8; - GL_ATTRIB_STACK_DEPTH = $0BB0; - GL_CLIENT_ATTRIB_STACK_DEPTH = $0BB1; - GL_ALPHA_TEST = $0BC0; - GL_ALPHA_TEST_FUNC = $0BC1; - GL_ALPHA_TEST_REF = $0BC2; - GL_DITHER = $0BD0; - GL_BLEND_DST = $0BE0; - GL_BLEND_SRC = $0BE1; - GL_BLEND = $0BE2; - GL_LOGIC_OP_MODE = $0BF0; - GL_INDEX_LOGIC_OP = $0BF1; - GL_COLOR_LOGIC_OP = $0BF2; - GL_AUX_BUFFERS = $0C00; - GL_DRAW_BUFFER = $0C01; - GL_READ_BUFFER = $0C02; - GL_SCISSOR_BOX = $0C10; - GL_SCISSOR_TEST = $0C11; - GL_INDEX_CLEAR_VALUE = $0C20; - GL_INDEX_WRITEMASK = $0C21; - GL_COLOR_CLEAR_VALUE = $0C22; - GL_COLOR_WRITEMASK = $0C23; - GL_INDEX_MODE = $0C30; - GL_RGBA_MODE = $0C31; - GL_DOUBLEBUFFER = $0C32; - GL_STEREO = $0C33; - GL_RENDER_MODE = $0C40; - GL_PERSPECTIVE_CORRECTION_HINT = $0C50; - GL_POINT_SMOOTH_HINT = $0C51; - GL_LINE_SMOOTH_HINT = $0C52; - GL_POLYGON_SMOOTH_HINT = $0C53; - GL_FOG_HINT = $0C54; - GL_TEXTURE_GEN_S = $0C60; - GL_TEXTURE_GEN_T = $0C61; - GL_TEXTURE_GEN_R = $0C62; - GL_TEXTURE_GEN_Q = $0C63; - GL_PIXEL_MAP_I_TO_I = $0C70; - GL_PIXEL_MAP_S_TO_S = $0C71; - GL_PIXEL_MAP_I_TO_R = $0C72; - GL_PIXEL_MAP_I_TO_G = $0C73; - GL_PIXEL_MAP_I_TO_B = $0C74; - GL_PIXEL_MAP_I_TO_A = $0C75; - GL_PIXEL_MAP_R_TO_R = $0C76; - GL_PIXEL_MAP_G_TO_G = $0C77; - GL_PIXEL_MAP_B_TO_B = $0C78; - GL_PIXEL_MAP_A_TO_A = $0C79; - GL_PIXEL_MAP_I_TO_I_SIZE = $0CB0; - GL_PIXEL_MAP_S_TO_S_SIZE = $0CB1; - GL_PIXEL_MAP_I_TO_R_SIZE = $0CB2; - GL_PIXEL_MAP_I_TO_G_SIZE = $0CB3; - GL_PIXEL_MAP_I_TO_B_SIZE = $0CB4; - GL_PIXEL_MAP_I_TO_A_SIZE = $0CB5; - GL_PIXEL_MAP_R_TO_R_SIZE = $0CB6; - GL_PIXEL_MAP_G_TO_G_SIZE = $0CB7; - GL_PIXEL_MAP_B_TO_B_SIZE = $0CB8; - GL_PIXEL_MAP_A_TO_A_SIZE = $0CB9; - GL_UNPACK_SWAP_BYTES = $0CF0; - GL_UNPACK_LSB_FIRST = $0CF1; - GL_UNPACK_ROW_LENGTH = $0CF2; - GL_UNPACK_SKIP_ROWS = $0CF3; - GL_UNPACK_SKIP_PIXELS = $0CF4; - GL_UNPACK_ALIGNMENT = $0CF5; - GL_PACK_SWAP_BYTES = $0D00; - GL_PACK_LSB_FIRST = $0D01; - GL_PACK_ROW_LENGTH = $0D02; - GL_PACK_SKIP_ROWS = $0D03; - GL_PACK_SKIP_PIXELS = $0D04; - GL_PACK_ALIGNMENT = $0D05; - GL_MAP_COLOR = $0D10; - GL_MAP_STENCIL = $0D11; - GL_INDEX_SHIFT = $0D12; - GL_INDEX_OFFSET = $0D13; - GL_RED_SCALE = $0D14; - GL_RED_BIAS = $0D15; - GL_ZOOM_X = $0D16; - GL_ZOOM_Y = $0D17; - GL_GREEN_SCALE = $0D18; - GL_GREEN_BIAS = $0D19; - GL_BLUE_SCALE = $0D1A; - GL_BLUE_BIAS = $0D1B; - GL_ALPHA_SCALE = $0D1C; - GL_ALPHA_BIAS = $0D1D; - GL_DEPTH_SCALE = $0D1E; - GL_DEPTH_BIAS = $0D1F; - GL_MAX_EVAL_ORDER = $0D30; - GL_MAX_LIGHTS = $0D31; - GL_MAX_CLIP_PLANES = $0D32; - GL_MAX_TEXTURE_SIZE = $0D33; - GL_MAX_PIXEL_MAP_TABLE = $0D34; - GL_MAX_ATTRIB_STACK_DEPTH = $0D35; - GL_MAX_MODELVIEW_STACK_DEPTH = $0D36; - GL_MAX_NAME_STACK_DEPTH = $0D37; - GL_MAX_PROJECTION_STACK_DEPTH = $0D38; - GL_MAX_TEXTURE_STACK_DEPTH = $0D39; - GL_MAX_VIEWPORT_DIMS = $0D3A; - GL_MAX_CLIENT_ATTRIB_STACK_DEPTH = $0D3B; - GL_SUBPIXEL_BITS = $0D50; - GL_INDEX_BITS = $0D51; - GL_RED_BITS = $0D52; - GL_GREEN_BITS = $0D53; - GL_BLUE_BITS = $0D54; - GL_ALPHA_BITS = $0D55; - GL_DEPTH_BITS = $0D56; - GL_STENCIL_BITS = $0D57; - GL_ACCUM_RED_BITS = $0D58; - GL_ACCUM_GREEN_BITS = $0D59; - GL_ACCUM_BLUE_BITS = $0D5A; - GL_ACCUM_ALPHA_BITS = $0D5B; - GL_NAME_STACK_DEPTH = $0D70; - GL_AUTO_NORMAL = $0D80; - GL_MAP1_COLOR_4 = $0D90; - GL_MAP1_INDEX = $0D91; - GL_MAP1_NORMAL = $0D92; - GL_MAP1_TEXTURE_COORD_1 = $0D93; - GL_MAP1_TEXTURE_COORD_2 = $0D94; - GL_MAP1_TEXTURE_COORD_3 = $0D95; - GL_MAP1_TEXTURE_COORD_4 = $0D96; - GL_MAP1_VERTEX_3 = $0D97; - GL_MAP1_VERTEX_4 = $0D98; - GL_MAP2_COLOR_4 = $0DB0; - GL_MAP2_INDEX = $0DB1; - GL_MAP2_NORMAL = $0DB2; - GL_MAP2_TEXTURE_COORD_1 = $0DB3; - GL_MAP2_TEXTURE_COORD_2 = $0DB4; - GL_MAP2_TEXTURE_COORD_3 = $0DB5; - GL_MAP2_TEXTURE_COORD_4 = $0DB6; - GL_MAP2_VERTEX_3 = $0DB7; - GL_MAP2_VERTEX_4 = $0DB8; - GL_MAP1_GRID_DOMAIN = $0DD0; - GL_MAP1_GRID_SEGMENTS = $0DD1; - GL_MAP2_GRID_DOMAIN = $0DD2; - GL_MAP2_GRID_SEGMENTS = $0DD3; - GL_TEXTURE_1D = $0DE0; - GL_TEXTURE_2D = $0DE1; - GL_FEEDBACK_BUFFER_POINTER = $0DF0; - GL_FEEDBACK_BUFFER_SIZE = $0DF1; - GL_FEEDBACK_BUFFER_TYPE = $0DF2; - GL_SELECTION_BUFFER_POINTER = $0DF3; - GL_SELECTION_BUFFER_SIZE = $0DF4; - // GL_TEXTURE_BINDING_1D - // GL_TEXTURE_BINDING_2D - // GL_VERTEX_ARRAY - // GL_NORMAL_ARRAY - // GL_COLOR_ARRAY - // GL_INDEX_ARRAY - // GL_TEXTURE_COORD_ARRAY - // GL_EDGE_FLAG_ARRAY - // GL_VERTEX_ARRAY_SIZE - // GL_VERTEX_ARRAY_TYPE - // GL_VERTEX_ARRAY_STRIDE - // GL_NORMAL_ARRAY_TYPE - // GL_NORMAL_ARRAY_STRIDE - // GL_COLOR_ARRAY_SIZE - // GL_COLOR_ARRAY_TYPE - // GL_COLOR_ARRAY_STRIDE - // GL_INDEX_ARRAY_TYPE - // GL_INDEX_ARRAY_STRIDE - // GL_TEXTURE_COORD_ARRAY_SIZE - // GL_TEXTURE_COORD_ARRAY_TYPE - // GL_TEXTURE_COORD_ARRAY_STRIDE - // GL_EDGE_FLAG_ARRAY_STRIDE - // GL_POLYGON_OFFSET_FACTOR - // GL_POLYGON_OFFSET_UNITS - - // GetTextureParameter - // GL_TEXTURE_MAG_FILTER - // GL_TEXTURE_MIN_FILTER - // GL_TEXTURE_WRAP_S - // GL_TEXTURE_WRAP_T - GL_TEXTURE_WIDTH = $1000; - GL_TEXTURE_HEIGHT = $1001; - GL_TEXTURE_INTERNAL_FORMAT = $1003; - GL_TEXTURE_BORDER_COLOR = $1004; - GL_TEXTURE_BORDER = $1005; - // GL_TEXTURE_RED_SIZE - // GL_TEXTURE_GREEN_SIZE - // GL_TEXTURE_BLUE_SIZE - // GL_TEXTURE_ALPHA_SIZE - // GL_TEXTURE_LUMINANCE_SIZE - // GL_TEXTURE_INTENSITY_SIZE - // GL_TEXTURE_PRIORITY - // GL_TEXTURE_RESIDENT - - // HintMode - GL_DONT_CARE = $1100; - GL_FASTEST = $1101; - GL_NICEST = $1102; - - // HintTarget - // GL_PERSPECTIVE_CORRECTION_HINT - // GL_POINT_SMOOTH_HINT - // GL_LINE_SMOOTH_HINT - // GL_POLYGON_SMOOTH_HINT - // GL_FOG_HINT - - // IndexPointerType - // GL_SHORT - // GL_INT - // GL_FLOAT - // GL_DOUBLE - - // LightModelParameter - // GL_LIGHT_MODEL_AMBIENT - // GL_LIGHT_MODEL_LOCAL_VIEWER - // GL_LIGHT_MODEL_TWO_SIDE - - // LightName - GL_LIGHT0 = $4000; - GL_LIGHT1 = $4001; - GL_LIGHT2 = $4002; - GL_LIGHT3 = $4003; - GL_LIGHT4 = $4004; - GL_LIGHT5 = $4005; - GL_LIGHT6 = $4006; - GL_LIGHT7 = $4007; - - // LightParameter - GL_AMBIENT = $1200; - GL_DIFFUSE = $1201; - GL_SPECULAR = $1202; - GL_POSITION = $1203; - GL_SPOT_DIRECTION = $1204; - GL_SPOT_EXPONENT = $1205; - GL_SPOT_CUTOFF = $1206; - GL_CONSTANT_ATTENUATION = $1207; - GL_LINEAR_ATTENUATION = $1208; - GL_QUADRATIC_ATTENUATION = $1209; - - // InterleavedArrays - // GL_V2F - // GL_V3F - // GL_C4UB_V2F - // GL_C4UB_V3F - // GL_C3F_V3F - // GL_N3F_V3F - // GL_C4F_N3F_V3F - // GL_T2F_V3F - // GL_T4F_V4F - // GL_T2F_C4UB_V3F - // GL_T2F_C3F_V3F - // GL_T2F_N3F_V3F - // GL_T2F_C4F_N3F_V3F - // GL_T4F_C4F_N3F_V4F - - // ListMode - GL_COMPILE = $1300; - GL_COMPILE_AND_EXECUTE = $1301; - - // ListNameType - // GL_BYTE - // GL_UNSIGNED_BYTE - // GL_SHORT - // GL_UNSIGNED_SHORT - // GL_INT - // GL_UNSIGNED_INT - // GL_FLOAT - // GL_2_BYTES - // GL_3_BYTES - // GL_4_BYTES - - // LogicOp - GL_CLEAR = $1500; - GL_AND = $1501; - GL_AND_REVERSE = $1502; - GL_COPY = $1503; - GL_AND_INVERTED = $1504; - GL_NOOP = $1505; - GL_XOR = $1506; - GL_OR = $1507; - GL_NOR = $1508; - GL_EQUIV = $1509; - GL_INVERT = $150A; - GL_OR_REVERSE = $150B; - GL_COPY_INVERTED = $150C; - GL_OR_INVERTED = $150D; - GL_NAND = $150E; - GL_SET = $150F; - - // MapTarget - // GL_MAP1_COLOR_4 - // GL_MAP1_INDEX - // GL_MAP1_NORMAL - // GL_MAP1_TEXTURE_COORD_1 - // GL_MAP1_TEXTURE_COORD_2 - // GL_MAP1_TEXTURE_COORD_3 - // GL_MAP1_TEXTURE_COORD_4 - // GL_MAP1_VERTEX_3 - // GL_MAP1_VERTEX_4 - // GL_MAP2_COLOR_4 - // GL_MAP2_INDEX - // GL_MAP2_NORMAL - // GL_MAP2_TEXTURE_COORD_1 - // GL_MAP2_TEXTURE_COORD_2 - // GL_MAP2_TEXTURE_COORD_3 - // GL_MAP2_TEXTURE_COORD_4 - // GL_MAP2_VERTEX_3 - // GL_MAP2_VERTEX_4 - - // MaterialFace - // GL_FRONT - // GL_BACK - // GL_FRONT_AND_BACK - - // MaterialParameter - GL_EMISSION = $1600; - GL_SHININESS = $1601; - GL_AMBIENT_AND_DIFFUSE = $1602; - GL_COLOR_INDEXES = $1603; - // GL_AMBIENT - // GL_DIFFUSE - // GL_SPECULAR - - // MatrixMode - GL_MODELVIEW = $1700; - GL_PROJECTION = $1701; - GL_TEXTURE = $1702; - - // MeshMode1 - // GL_POINT - // GL_LINE - - // MeshMode2 - // GL_POINT - // GL_LINE - // GL_FILL - - // NormalPointerType - // GL_BYTE - // GL_SHORT - // GL_INT - // GL_FLOAT - // GL_DOUBLE - - // PixelCopyType - GL_COLOR = $1800; - GL_DEPTH = $1801; - GL_STENCIL = $1802; - - // PixelFormat - GL_COLOR_INDEX = $1900; - GL_STENCIL_INDEX = $1901; - GL_DEPTH_COMPONENT = $1902; - GL_RED = $1903; - GL_GREEN = $1904; - GL_BLUE = $1905; - GL_ALPHA = $1906; - GL_RGB = $1907; - GL_RGBA = $1908; - GL_LUMINANCE = $1909; - GL_LUMINANCE_ALPHA = $190A; - - // PixelMap - // GL_PIXEL_MAP_I_TO_I - // GL_PIXEL_MAP_S_TO_S - // GL_PIXEL_MAP_I_TO_R - // GL_PIXEL_MAP_I_TO_G - // GL_PIXEL_MAP_I_TO_B - // GL_PIXEL_MAP_I_TO_A - // GL_PIXEL_MAP_R_TO_R - // GL_PIXEL_MAP_G_TO_G - // GL_PIXEL_MAP_B_TO_B - // GL_PIXEL_MAP_A_TO_A - - // PixelStore - // GL_UNPACK_SWAP_BYTES - // GL_UNPACK_LSB_FIRST - // GL_UNPACK_ROW_LENGTH - // GL_UNPACK_SKIP_ROWS - // GL_UNPACK_SKIP_PIXELS - // GL_UNPACK_ALIGNMENT - // GL_PACK_SWAP_BYTES - // GL_PACK_LSB_FIRST - // GL_PACK_ROW_LENGTH - // GL_PACK_SKIP_ROWS - // GL_PACK_SKIP_PIXELS - // GL_PACK_ALIGNMENT - - // PixelTransfer - // GL_MAP_COLOR - // GL_MAP_STENCIL - // GL_INDEX_SHIFT - // GL_INDEX_OFFSET - // GL_RED_SCALE - // GL_RED_BIAS - // GL_GREEN_SCALE - // GL_GREEN_BIAS - // GL_BLUE_SCALE - // GL_BLUE_BIAS - // GL_ALPHA_SCALE - // GL_ALPHA_BIAS - // GL_DEPTH_SCALE - // GL_DEPTH_BIAS - - // PixelType - GL_BITMAP = $1A00; - // GL_BYTE - // GL_UNSIGNED_BYTE - // GL_SHORT - // GL_UNSIGNED_SHORT - // GL_INT - // GL_UNSIGNED_INT - // GL_FLOAT - - // PolygonMode - GL_POINT = $1B00; - GL_LINE = $1B01; - GL_FILL = $1B02; - - // ReadBufferMode - // GL_FRONT_LEFT - // GL_FRONT_RIGHT - // GL_BACK_LEFT - // GL_BACK_RIGHT - // GL_FRONT - // GL_BACK - // GL_LEFT - // GL_RIGHT - // GL_AUX0 - // GL_AUX1 - // GL_AUX2 - // GL_AUX3 - - // RenderingMode - GL_RENDER = $1C00; - GL_FEEDBACK = $1C01; - GL_SELECT = $1C02; - - // ShadingModel - GL_FLAT = $1D00; - GL_SMOOTH = $1D01; - - // StencilFunction - // GL_NEVER - // GL_LESS - // GL_EQUAL - // GL_LEQUAL - // GL_GREATER - // GL_NOTEQUAL - // GL_GEQUAL - // GL_ALWAYS - - // StencilOp - // GL_ZERO - GL_KEEP = $1E00; - GL_REPLACE = $1E01; - GL_INCR = $1E02; - GL_DECR = $1E03; - // GL_INVERT - - // StringName - GL_VENDOR = $1F00; - GL_RENDERER = $1F01; - GL_VERSION = $1F02; - GL_EXTENSIONS = $1F03; - - // TextureCoordName - GL_S = $2000; - GL_T = $2001; - GL_R = $2002; - GL_Q = $2003; - - // TexCoordPointerType - // GL_SHORT - // GL_INT - // GL_FLOAT - // GL_DOUBLE - - // TextureEnvMode - GL_MODULATE = $2100; - GL_DECAL = $2101; - // GL_BLEND - // GL_REPLACE - - // TextureEnvParameter - GL_TEXTURE_ENV_MODE = $2200; - GL_TEXTURE_ENV_COLOR = $2201; - - // TextureEnvTarget - GL_TEXTURE_ENV = $2300; - - // TextureGenMode - GL_EYE_LINEAR = $2400; - GL_OBJECT_LINEAR = $2401; - GL_SPHERE_MAP = $2402; - - // TextureGenParameter - GL_TEXTURE_GEN_MODE = $2500; - GL_OBJECT_PLANE = $2501; - GL_EYE_PLANE = $2502; - - // TextureMagFilter - GL_NEAREST = $2600; - GL_LINEAR = $2601; - - // TextureMinFilter - // GL_NEAREST - // GL_LINEAR - GL_NEAREST_MIPMAP_NEAREST = $2700; - GL_LINEAR_MIPMAP_NEAREST = $2701; - GL_NEAREST_MIPMAP_LINEAR = $2702; - GL_LINEAR_MIPMAP_LINEAR = $2703; - - // TextureParameterName - GL_TEXTURE_MAG_FILTER = $2800; - GL_TEXTURE_MIN_FILTER = $2801; - GL_TEXTURE_WRAP_S = $2802; - GL_TEXTURE_WRAP_T = $2803; - // GL_TEXTURE_BORDER_COLOR - // GL_TEXTURE_PRIORITY - - // TextureTarget - // GL_TEXTURE_1D - // GL_TEXTURE_2D - // GL_PROXY_TEXTURE_1D - // GL_PROXY_TEXTURE_2D - - // TextureWrapMode - GL_CLAMP = $2900; - GL_REPEAT = $2901; - - // VertexPointerType - // GL_SHORT - // GL_INT - // GL_FLOAT - // GL_DOUBLE - - // ClientAttribMask - GL_CLIENT_PIXEL_STORE_BIT = $00000001; - GL_CLIENT_VERTEX_ARRAY_BIT = $00000002; - GL_CLIENT_ALL_ATTRIB_BITS = $FFFFFFFF; - - // polygon_offset - GL_POLYGON_OFFSET_FACTOR = $8038; - GL_POLYGON_OFFSET_UNITS = $2A00; - GL_POLYGON_OFFSET_POINT = $2A01; - GL_POLYGON_OFFSET_LINE = $2A02; - GL_POLYGON_OFFSET_FILL = $8037; - - // texture - GL_ALPHA4 = $803B; - GL_ALPHA8 = $803C; - GL_ALPHA12 = $803D; - GL_ALPHA16 = $803E; - GL_LUMINANCE4 = $803F; - GL_LUMINANCE8 = $8040; - GL_LUMINANCE12 = $8041; - GL_LUMINANCE16 = $8042; - GL_LUMINANCE4_ALPHA4 = $8043; - GL_LUMINANCE6_ALPHA2 = $8044; - GL_LUMINANCE8_ALPHA8 = $8045; - GL_LUMINANCE12_ALPHA4 = $8046; - GL_LUMINANCE12_ALPHA12 = $8047; - GL_LUMINANCE16_ALPHA16 = $8048; - GL_INTENSITY = $8049; - GL_INTENSITY4 = $804A; - GL_INTENSITY8 = $804B; - GL_INTENSITY12 = $804C; - GL_INTENSITY16 = $804D; - GL_R3_G3_B2 = $2A10; - GL_RGB4 = $804F; - GL_RGB5 = $8050; - GL_RGB8 = $8051; - GL_RGB10 = $8052; - GL_RGB12 = $8053; - GL_RGB16 = $8054; - GL_RGBA2 = $8055; - GL_RGBA4 = $8056; - GL_RGB5_A1 = $8057; - GL_RGBA8 = $8058; - GL_RGB10_A2 = $8059; - GL_RGBA12 = $805A; - GL_RGBA16 = $805B; - GL_TEXTURE_RED_SIZE = $805C; - GL_TEXTURE_GREEN_SIZE = $805D; - GL_TEXTURE_BLUE_SIZE = $805E; - GL_TEXTURE_ALPHA_SIZE = $805F; - GL_TEXTURE_LUMINANCE_SIZE = $8060; - GL_TEXTURE_INTENSITY_SIZE = $8061; - GL_PROXY_TEXTURE_1D = $8063; - GL_PROXY_TEXTURE_2D = $8064; - - // texture_object - GL_TEXTURE_PRIORITY = $8066; - GL_TEXTURE_RESIDENT = $8067; - GL_TEXTURE_BINDING_1D = $8068; - GL_TEXTURE_BINDING_2D = $8069; - - // vertex_array - GL_VERTEX_ARRAY = $8074; - GL_NORMAL_ARRAY = $8075; - GL_COLOR_ARRAY = $8076; - GL_INDEX_ARRAY = $8077; - GL_TEXTURE_COORD_ARRAY = $8078; - GL_EDGE_FLAG_ARRAY = $8079; - GL_VERTEX_ARRAY_SIZE = $807A; - GL_VERTEX_ARRAY_TYPE = $807B; - GL_VERTEX_ARRAY_STRIDE = $807C; - GL_NORMAL_ARRAY_TYPE = $807E; - GL_NORMAL_ARRAY_STRIDE = $807F; - GL_COLOR_ARRAY_SIZE = $8081; - GL_COLOR_ARRAY_TYPE = $8082; - GL_COLOR_ARRAY_STRIDE = $8083; - GL_INDEX_ARRAY_TYPE = $8085; - GL_INDEX_ARRAY_STRIDE = $8086; - GL_TEXTURE_COORD_ARRAY_SIZE = $8088; - GL_TEXTURE_COORD_ARRAY_TYPE = $8089; - GL_TEXTURE_COORD_ARRAY_STRIDE = $808A; - GL_EDGE_FLAG_ARRAY_STRIDE = $808C; - GL_VERTEX_ARRAY_POINTER = $808E; - GL_NORMAL_ARRAY_POINTER = $808F; - GL_COLOR_ARRAY_POINTER = $8090; - GL_INDEX_ARRAY_POINTER = $8091; - GL_TEXTURE_COORD_ARRAY_POINTER = $8092; - GL_EDGE_FLAG_ARRAY_POINTER = $8093; - GL_V2F = $2A20; - GL_V3F = $2A21; - GL_C4UB_V2F = $2A22; - GL_C4UB_V3F = $2A23; - GL_C3F_V3F = $2A24; - GL_N3F_V3F = $2A25; - GL_C4F_N3F_V3F = $2A26; - GL_T2F_V3F = $2A27; - GL_T4F_V4F = $2A28; - GL_T2F_C4UB_V3F = $2A29; - GL_T2F_C3F_V3F = $2A2A; - GL_T2F_N3F_V3F = $2A2B; - GL_T2F_C4F_N3F_V3F = $2A2C; - GL_T4F_C4F_N3F_V4F = $2A2D; - - // Extensions - GL_EXT_vertex_array = 1; - GL_WIN_swap_hint = 1; - GL_EXT_bgra = 1; - GL_EXT_paletted_texture = 1; - - // EXT_vertex_array - GL_VERTEX_ARRAY_EXT = $8074; - GL_NORMAL_ARRAY_EXT = $8075; - GL_COLOR_ARRAY_EXT = $8076; - GL_INDEX_ARRAY_EXT = $8077; - GL_TEXTURE_COORD_ARRAY_EXT = $8078; - GL_EDGE_FLAG_ARRAY_EXT = $8079; - GL_VERTEX_ARRAY_SIZE_EXT = $807A; - GL_VERTEX_ARRAY_TYPE_EXT = $807B; - GL_VERTEX_ARRAY_STRIDE_EXT = $807C; - GL_VERTEX_ARRAY_COUNT_EXT = $807D; - GL_NORMAL_ARRAY_TYPE_EXT = $807E; - GL_NORMAL_ARRAY_STRIDE_EXT = $807F; - GL_NORMAL_ARRAY_COUNT_EXT = $8080; - GL_COLOR_ARRAY_SIZE_EXT = $8081; - GL_COLOR_ARRAY_TYPE_EXT = $8082; - GL_COLOR_ARRAY_STRIDE_EXT = $8083; - GL_COLOR_ARRAY_COUNT_EXT = $8084; - GL_INDEX_ARRAY_TYPE_EXT = $8085; - GL_INDEX_ARRAY_STRIDE_EXT = $8086; - GL_INDEX_ARRAY_COUNT_EXT = $8087; - GL_TEXTURE_COORD_ARRAY_SIZE_EXT = $8088; - GL_TEXTURE_COORD_ARRAY_TYPE_EXT = $8089; - GL_TEXTURE_COORD_ARRAY_STRIDE_EXT = $808A; - GL_TEXTURE_COORD_ARRAY_COUNT_EXT = $808B; - GL_EDGE_FLAG_ARRAY_STRIDE_EXT = $808C; - GL_EDGE_FLAG_ARRAY_COUNT_EXT = $808D; - GL_VERTEX_ARRAY_POINTER_EXT = $808E; - GL_NORMAL_ARRAY_POINTER_EXT = $808F; - GL_COLOR_ARRAY_POINTER_EXT = $8090; - GL_INDEX_ARRAY_POINTER_EXT = $8091; - GL_TEXTURE_COORD_ARRAY_POINTER_EXT = $8092; - GL_EDGE_FLAG_ARRAY_POINTER_EXT = $8093; - GL_DOUBLE_EXT = GL_DOUBLE; - - // EXT_bgra - GL_BGR_EXT = $80E0; - GL_BGRA_EXT = $80E1; - - // EXT_paletted_texture - - // These must match the GL_COLOR_TABLE_*_SGI enumerants - GL_COLOR_TABLE_FORMAT_EXT = $80D8; - GL_COLOR_TABLE_WIDTH_EXT = $80D9; - GL_COLOR_TABLE_RED_SIZE_EXT = $80DA; - GL_COLOR_TABLE_GREEN_SIZE_EXT = $80DB; - GL_COLOR_TABLE_BLUE_SIZE_EXT = $80DC; - GL_COLOR_TABLE_ALPHA_SIZE_EXT = $80DD; - GL_COLOR_TABLE_LUMINANCE_SIZE_EXT = $80DE; - GL_COLOR_TABLE_INTENSITY_SIZE_EXT = $80DF; - - GL_COLOR_INDEX1_EXT = $80E2; - GL_COLOR_INDEX2_EXT = $80E3; - GL_COLOR_INDEX4_EXT = $80E4; - GL_COLOR_INDEX8_EXT = $80E5; - GL_COLOR_INDEX12_EXT = $80E6; - GL_COLOR_INDEX16_EXT = $80E7; - - // For compatibility with OpenGL v1.0 - GL_LOGIC_OP = GL_INDEX_LOGIC_OP; - GL_TEXTURE_COMPONENTS = GL_TEXTURE_INTERNAL_FORMAT; - -{******************************************************************************} - -var - glAccum: procedure(op: GLenum; value: GLfloat); stdcall; - glAlphaFunc: procedure(func: GLenum; ref: GLclampf); stdcall; - glAreTexturesResident: function (n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; stdcall; - glArrayElement: procedure(i: GLint); stdcall; - glBegin: procedure(mode: GLenum); stdcall; - glBindTexture: procedure(target: GLenum; texture: GLuint); stdcall; - glBitmap: procedure (width, height: GLsizei; xorig, yorig: GLfloat; xmove, ymove: GLfloat; const bitmap: PGLubyte); stdcall; - glBlendFunc: procedure(sfactor, dfactor: GLenum); stdcall; - glCallList: procedure(list: GLuint); stdcall; - glCallLists: procedure(n: GLsizei; atype: GLenum; const lists: Pointer); stdcall; - glClear: procedure(mask: GLbitfield); stdcall; - glClearAccum: procedure(red, green, blue, alpha: GLfloat); stdcall; - glClearColor: procedure(red, green, blue, alpha: GLclampf); stdcall; - glClearDepth: procedure(depth: GLclampd); stdcall; - glClearIndex: procedure(c: GLfloat); stdcall; - glClearStencil: procedure(s: GLint); stdcall; - glClipPlane: procedure(plane: GLenum; const equation: PGLdouble); stdcall; - glColor3b: procedure(red, green, blue: GLbyte); stdcall; - glColor3bv: procedure(const v: PGLbyte); stdcall; - glColor3d: procedure(red, green, blue: GLdouble); stdcall; - glColor3dv: procedure(const v: PGLdouble); stdcall; - glColor3f: procedure(red, green, blue: GLfloat); stdcall; - glColor3fv: procedure(const v: PGLfloat); stdcall; - glColor3i: procedure(red, green, blue: GLint); stdcall; - glColor3iv: procedure(const v: PGLint); stdcall; - glColor3s: procedure(red, green, blue: GLshort); stdcall; - glColor3sv: procedure(const v: PGLshort); stdcall; - glColor3ub: procedure(red, green, blue: GLubyte); stdcall; - glColor3ubv: procedure(const v: PGLubyte); stdcall; - glColor3ui: procedure(red, green, blue: GLuint); stdcall; - glColor3uiv: procedure(const v: PGLuint); stdcall; - glColor3us: procedure(red, green, blue: GLushort); stdcall; - glColor3usv: procedure(const v: PGLushort); stdcall; - glColor4b: procedure(red, green, blue, alpha: GLbyte); stdcall; - glColor4bv: procedure(const v: PGLbyte); stdcall; - glColor4d: procedure(red, green, blue, alpha: GLdouble); stdcall; - glColor4dv: procedure(const v: PGLdouble); stdcall; - glColor4f: procedure(red, green, blue, alpha: GLfloat); stdcall; - glColor4fv: procedure(const v: PGLfloat); stdcall; - glColor4i: procedure(red, green, blue, alpha: GLint); stdcall; - glColor4iv: procedure(const v: PGLint); stdcall; - glColor4s: procedure(red, green, blue, alpha: GLshort); stdcall; - glColor4sv: procedure(const v: PGLshort); stdcall; - glColor4ub: procedure(red, green, blue, alpha: GLubyte); stdcall; - glColor4ubv: procedure(const v: PGLubyte); stdcall; - glColor4ui: procedure(red, green, blue, alpha: GLuint); stdcall; - glColor4uiv: procedure(const v: PGLuint); stdcall; - glColor4us: procedure(red, green, blue, alpha: GLushort); stdcall; - glColor4usv: procedure(const v: PGLushort); stdcall; - glColorMask: procedure(red, green, blue, alpha: GLboolean); stdcall; - glColorMaterial: procedure(face, mode: GLenum); stdcall; - glColorPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); stdcall; - glCopyPixels: procedure(x, y: GLint; width, height: GLsizei; atype: GLenum); stdcall; - glCopyTexImage1D: procedure (target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width: GLsizei; border: GLint); stdcall; - glCopyTexImage2D: procedure(target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width, height: GLsizei; border: GLint); stdcall; - glCopyTexSubImage1D: procedure(target: GLenum; level, xoffset, x, y: GLint; width: GLsizei); stdcall; - glCopyTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset, x, y: GLint; width, height: GLsizei); stdcall; - glCullFace: procedure(mode: GLenum); stdcall; - glDeleteLists: procedure(list: GLuint; range: GLsizei); stdcall; - glDeleteTextures: procedure(n: GLsizei; const textures: PGLuint); stdcall; - glDepthFunc: procedure(func: GLenum); stdcall; - glDepthMask: procedure(flag: GLboolean); stdcall; - glDepthRange: procedure(zNear, zFar: GLclampd); stdcall; - glDisable: procedure(cap: GLenum); stdcall; - glDisableClientState: procedure(aarray: GLenum); stdcall; - glDrawArrays: procedure(mode: GLenum; first: GLint; count: GLsizei); stdcall; - glDrawBuffer: procedure(mode: GLenum); stdcall; - glDrawElements: procedure(mode: GLenum; count: GLsizei; atype: GLenum; const indices: Pointer); stdcall; - glDrawPixels: procedure(width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); stdcall; - glEdgeFlag: procedure(flag: GLboolean); stdcall; - glEdgeFlagPointer: procedure(stride: GLsizei; const pointer: Pointer); stdcall; - glEdgeFlagv: procedure(const flag: PGLboolean); stdcall; - glEnable: procedure(cap: GLenum); stdcall; - glEnableClientState: procedure(aarray: GLenum); stdcall; - glEnd: procedure; stdcall; - glEndList: procedure; stdcall; - glEvalCoord1d: procedure(u: GLdouble); stdcall; - glEvalCoord1dv: procedure(const u: PGLdouble); stdcall; - glEvalCoord1f: procedure(u: GLfloat); stdcall; - glEvalCoord1fv: procedure(const u: PGLfloat); stdcall; - glEvalCoord2d: procedure(u, v: GLdouble); stdcall; - glEvalCoord2dv: procedure(const u: PGLdouble); stdcall; - glEvalCoord2f: procedure(u, v: GLfloat); stdcall; - glEvalCoord2fv: procedure(const u: PGLfloat); stdcall; - glEvalMesh1: procedure(mode: GLenum; i1, i2: GLint); stdcall; - glEvalMesh2: procedure(mode: GLenum; i1, i2, j1, j2: GLint); stdcall; - glEvalPoint1: procedure(i: GLint); stdcall; - glEvalPoint2: procedure(i, j: GLint); stdcall; - glFeedbackBuffer: procedure(size: GLsizei; atype: GLenum; buffer: PGLfloat); stdcall; - glFinish: procedure; stdcall; - glFlush: procedure; stdcall; - glFogf: procedure(pname: GLenum; param: GLfloat); stdcall; - glFogfv: procedure(pname: GLenum; const params: PGLfloat); stdcall; - glFogi: procedure(pname: GLenum; param: GLint); stdcall; - glFogiv: procedure(pname: GLenum; const params: PGLint); stdcall; - glFrontFace: procedure(mode: GLenum); stdcall; - glFrustum: procedure(left, right, bottom, top, zNear, zFar: GLdouble); stdcall; - glGenLists: function(range: GLsizei): GLuint; stdcall; - glGenTextures: procedure(n: GLsizei; textures: PGLuint); stdcall; - glGetBooleanv: procedure(pname: GLenum; params: PGLboolean); stdcall; - glGetClipPlane: procedure(plane: GLenum; equation: PGLdouble); stdcall; - glGetDoublev: procedure(pname: GLenum; params: PGLdouble); stdcall; - glGetError: function: GLenum; stdcall; - glGetFloatv: procedure(pname: GLenum; params: PGLfloat); stdcall; - glGetIntegerv: procedure(pname: GLenum; params: PGLint); stdcall; - glGetLightfv: procedure(light, pname: GLenum; params: PGLfloat); stdcall; - glGetLightiv: procedure(light, pname: GLenum; params: PGLint); stdcall; - glGetMapdv: procedure(target, query: GLenum; v: PGLdouble); stdcall; - glGetMapfv: procedure(target, query: GLenum; v: PGLfloat); stdcall; - glGetMapiv: procedure(target, query: GLenum; v: GLint); stdcall; - glGetMaterialfv: procedure(face, pname: GLenum; params: PGLfloat); stdcall; - glGetMaterialiv: procedure(face, pname: GLenum; params: GLint); stdcall; - glGetPixelMapfv: procedure(map: GLenum; values: PGLfloat); stdcall; - glGetPixelMapuiv: procedure(map: GLenum; values: PGLuint); stdcall; - glGetPixelMapusv: procedure(map: GLenum; values: PGLushort); stdcall; - glGetPointerv: procedure(pname: GLenum; params: Pointer); stdcall; - glGetPolygonStipple: procedure(mask: PGLubyte); stdcall; - glGetString: function(name: GLenum): PGLubyte; stdcall; - glGetTexEnvfv: procedure(target, pname: GLenum; params: PGLfloat); stdcall; - glGetTexEnviv: procedure(target, pname: GLenum; params: PGLint); stdcall; - glGetTexGendv: procedure(coord, pname: GLenum; params: PGLdouble); stdcall; - glGetTexGenfv: procedure(coord, pname: GLenum; params: PGLfloat); stdcall; - glGetTexGeniv: procedure(coord, pname: GLenum; params: PGLint); stdcall; - glGetTexImage: procedure(target: GLenum; level: GLint; format: GLenum; atype: GLenum; pixels: Pointer); stdcall; - glGetTexLevelParameterfv: procedure(target: GLenum; level: GLint; pname: GLenum; params: Pointer); stdcall; - glGetTexLevelParameteriv: procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); stdcall; - glGetTexParameterfv: procedure(target, pname: GLenum; params: PGLfloat); stdcall; - glGetTexParameteriv: procedure(target, pname: GLenum; params: PGLint); stdcall; - glHint: procedure(target, mode: GLenum); stdcall; - glIndexMask: procedure(mask: GLuint); stdcall; - glIndexPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); stdcall; - glIndexd: procedure(c: GLdouble); stdcall; - glIndexdv: procedure(const c: PGLdouble); stdcall; - glIndexf: procedure(c: GLfloat); stdcall; - glIndexfv: procedure(const c: PGLfloat); stdcall; - glIndexi: procedure(c: GLint); stdcall; - glIndexiv: procedure(const c: PGLint); stdcall; - glIndexs: procedure(c: GLshort); stdcall; - glIndexsv: procedure(const c: PGLshort); stdcall; - glIndexub: procedure(c: GLubyte); stdcall; - glIndexubv: procedure(const c: PGLubyte); stdcall; - glInitNames: procedure; stdcall; - glInterleavedArrays: procedure(format: GLenum; stride: GLsizei; const pointer: Pointer); stdcall; - glIsEnabled: function(cap: GLenum): GLboolean; stdcall; - glIsList: function(list: GLuint): GLboolean; stdcall; - glIsTexture: function(texture: GLuint): GLboolean; stdcall; - glLightModelf: procedure(pname: GLenum; param: GLfloat); stdcall; - glLightModelfv: procedure(pname: GLenum; const params: PGLfloat); stdcall; - glLightModeli: procedure(pname: GLenum; param: GLint); stdcall; - glLightModeliv: procedure(pname: GLenum; const params: PGLint); stdcall; - glLightf: procedure(light, pname: GLenum; param: GLfloat); stdcall; - glLightfv: procedure(light, pname: GLenum; const params: PGLfloat); stdcall; - glLighti: procedure(light, pname: GLenum; param: GLint); stdcall; - glLightiv: procedure(light, pname: GLenum; const params: GLint); stdcall; - glLineStipple: procedure(factor: GLint; pattern: GLushort); stdcall; - glLineWidth: procedure(width: GLfloat); stdcall; - glListBase: procedure(base: GLuint); stdcall; - glLoadIdentity: procedure; stdcall; - glLoadMatrixd: procedure(const m: PGLdouble); stdcall; - glLoadMatrixf: procedure(const m: PGLfloat); stdcall; - glLoadName: procedure(name: GLuint); stdcall; - glLogicOp: procedure(opcode: GLenum); stdcall; - glMap1d: procedure(target: GLenum; u1, u2: GLdouble; stride, order: GLint; const points: PGLdouble); stdcall; - glMap1f: procedure(target: GLenum; u1, u2: GLfloat; stride, order: GLint; const points: PGLfloat); stdcall; - glMap2d: procedure(target: GLenum; u1, u2: GLdouble; ustride, uorder: GLint; v1, v2: GLdouble; vstride, vorder: GLint; const points: PGLdouble); stdcall; - glMap2f: procedure(target: GLenum; u1, u2: GLfloat; ustride, uorder: GLint; v1, v2: GLfloat; vstride, vorder: GLint; const points: PGLfloat); stdcall; - glMapGrid1d: procedure(un: GLint; u1, u2: GLdouble); stdcall; - glMapGrid1f: procedure(un: GLint; u1, u2: GLfloat); stdcall; - glMapGrid2d: procedure(un: GLint; u1, u2: GLdouble; vn: GLint; v1, v2: GLdouble); stdcall; - glMapGrid2f: procedure(un: GLint; u1, u2: GLfloat; vn: GLint; v1, v2: GLfloat); stdcall; - glMaterialf: procedure(face, pname: GLenum; param: GLfloat); stdcall; - glMaterialfv: procedure(face, pname: GLenum; const params: PGLfloat); stdcall; - glMateriali: procedure(face, pname: GLenum; param: GLint); stdcall; - glMaterialiv: procedure(face, pname: GLenum; const params: PGLint); stdcall; - glMatrixMode: procedure(mode: GLenum); stdcall; - glMultMatrixd: procedure(const m: PGLdouble); stdcall; - glMultMatrixf: procedure(const m: PGLfloat); stdcall; - glNewList: procedure(list: GLuint; mode: GLenum); stdcall; - glNormal3b: procedure(nx, ny, nz: GLbyte); stdcall; - glNormal3bv: procedure(const v: PGLbyte); stdcall; - glNormal3d: procedure(nx, ny, nz: GLdouble); stdcall; - glNormal3dv: procedure(const v: PGLdouble); stdcall; - glNormal3f: procedure(nx, ny, nz: GLfloat); stdcall; - glNormal3fv: procedure(const v: PGLfloat); stdcall; - glNormal3i: procedure(nx, ny, nz: GLint); stdcall; - glNormal3iv: procedure(const v: PGLint); stdcall; - glNormal3s: procedure(nx, ny, nz: GLshort); stdcall; - glNormal3sv: procedure(const v: PGLshort); stdcall; - glNormalPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); stdcall; - glOrtho: procedure(left, right, bottom, top, zNear, zFar: GLdouble); stdcall; - glPassThrough: procedure(token: GLfloat); stdcall; - glPixelMapfv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLfloat); stdcall; - glPixelMapuiv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLuint); stdcall; - glPixelMapusv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLushort); stdcall; - glPixelStoref: procedure(pname: GLenum; param: GLfloat); stdcall; - glPixelStorei: procedure(pname: GLenum; param: GLint); stdcall; - glPixelTransferf: procedure(pname: GLenum; param: GLfloat); stdcall; - glPixelTransferi: procedure(pname: GLenum; param: GLint); stdcall; - glPixelZoom: procedure(xfactor, yfactor: GLfloat); stdcall; - glPointSize: procedure(size: GLfloat); stdcall; - glPolygonMode: procedure(face, mode: GLenum); stdcall; - glPolygonOffset: procedure(factor, units: GLfloat); stdcall; - glPolygonStipple: procedure(const mask: PGLubyte); stdcall; - glPopAttrib: procedure; stdcall; - glPopClientAttrib: procedure; stdcall; - glPopMatrix: procedure; stdcall; - glPopName: procedure; stdcall; - glPrioritizeTextures: procedure(n: GLsizei; const textures: PGLuint; const priorities: PGLclampf); stdcall; - glPushAttrib: procedure(mask: GLbitfield); stdcall; - glPushClientAttrib: procedure(mask: GLbitfield); stdcall; - glPushMatrix: procedure; stdcall; - glPushName: procedure(name: GLuint); stdcall; - glRasterPos2d: procedure(x, y: GLdouble); stdcall; - glRasterPos2dv: procedure(const v: PGLdouble); stdcall; - glRasterPos2f: procedure(x, y: GLfloat); stdcall; - glRasterPos2fv: procedure(const v: PGLfloat); stdcall; - glRasterPos2i: procedure(x, y: GLint); stdcall; - glRasterPos2iv: procedure(const v: PGLint); stdcall; - glRasterPos2s: procedure(x, y: GLshort); stdcall; - glRasterPos2sv: procedure(const v: PGLshort); stdcall; - glRasterPos3d: procedure(x, y, z: GLdouble); stdcall; - glRasterPos3dv: procedure(const v: PGLdouble); stdcall; - glRasterPos3f: procedure(x, y, z: GLfloat); stdcall; - glRasterPos3fv: procedure(const v: PGLfloat); stdcall; - glRasterPos3i: procedure(x, y, z: GLint); stdcall; - glRasterPos3iv: procedure(const v: PGLint); stdcall; - glRasterPos3s: procedure(x, y, z: GLshort); stdcall; - glRasterPos3sv: procedure(const v: PGLshort); stdcall; - glRasterPos4d: procedure(x, y, z, w: GLdouble); stdcall; - glRasterPos4dv: procedure(const v: PGLdouble); stdcall; - glRasterPos4f: procedure(x, y, z, w: GLfloat); stdcall; - glRasterPos4fv: procedure(const v: PGLfloat); stdcall; - glRasterPos4i: procedure(x, y, z, w: GLint); stdcall; - glRasterPos4iv: procedure(const v: PGLint); stdcall; - glRasterPos4s: procedure(x, y, z, w: GLshort); stdcall; - glRasterPos4sv: procedure(const v: PGLshort); stdcall; - glReadBuffer: procedure(mode: GLenum); stdcall; - glReadPixels: procedure(x, y: GLint; width, height: GLsizei; format, atype: GLenum; pixels: Pointer); stdcall; - glRectd: procedure(x1, y1, x2, y2: GLdouble); stdcall; - glRectdv: procedure(const v1: PGLdouble; const v2: PGLdouble); stdcall; - glRectf: procedure(x1, y1, x2, y2: GLfloat); stdcall; - glRectfv: procedure(const v1: PGLfloat; const v2: PGLfloat); stdcall; - glRecti: procedure(x1, y1, x2, y2: GLint); stdcall; - glRectiv: procedure(const v1: PGLint; const v2: PGLint); stdcall; - glRects: procedure(x1, y1, x2, y2: GLshort); stdcall; - glRectsv: procedure(const v1: PGLshort; const v2: PGLshort); stdcall; - glRenderMode: function(mode: GLint): GLint; stdcall; - glRotated: procedure(angle, x, y, z: GLdouble); stdcall; - glRotatef: procedure(angle, x, y, z: GLfloat); stdcall; - glScaled: procedure(x, y, z: GLdouble); stdcall; - glScalef: procedure(x, y, z: GLfloat); stdcall; - glScissor: procedure(x, y: GLint; width, height: GLsizei); stdcall; - glSelectBuffer: procedure(size: GLsizei; buffer: PGLuint); stdcall; - glShadeModel: procedure(mode: GLenum); stdcall; - glStencilFunc: procedure(func: GLenum; ref: GLint; mask: GLuint); stdcall; - glStencilMask: procedure(mask: GLuint); stdcall; - glStencilOp: procedure(fail, zfail, zpass: GLenum); stdcall; - glTexCoord1d: procedure(s: GLdouble); stdcall; - glTexCoord1dv: procedure(const v: PGLdouble); stdcall; - glTexCoord1f: procedure(s: GLfloat); stdcall; - glTexCoord1fv: procedure(const v: PGLfloat); stdcall; - glTexCoord1i: procedure(s: GLint); stdcall; - glTexCoord1iv: procedure(const v: PGLint); stdcall; - glTexCoord1s: procedure(s: GLshort); stdcall; - glTexCoord1sv: procedure(const v: PGLshort); stdcall; - glTexCoord2d: procedure(s, t: GLdouble); stdcall; - glTexCoord2dv: procedure(const v: PGLdouble); stdcall; - glTexCoord2f: procedure(s, t: GLfloat); stdcall; - glTexCoord2fv: procedure(const v: PGLfloat); stdcall; - glTexCoord2i: procedure(s, t: GLint); stdcall; - glTexCoord2iv: procedure(const v: PGLint); stdcall; - glTexCoord2s: procedure(s, t: GLshort); stdcall; - glTexCoord2sv: procedure(const v: PGLshort); stdcall; - glTexCoord3d: procedure(s, t, r: GLdouble); stdcall; - glTexCoord3dv: procedure(const v: PGLdouble); stdcall; - glTexCoord3f: procedure(s, t, r: GLfloat); stdcall; - glTexCoord3fv: procedure(const v: PGLfloat); stdcall; - glTexCoord3i: procedure(s, t, r: GLint); stdcall; - glTexCoord3iv: procedure(const v: PGLint); stdcall; - glTexCoord3s: procedure(s, t, r: GLshort); stdcall; - glTexCoord3sv: procedure(const v: PGLshort); stdcall; - glTexCoord4d: procedure(s, t, r, q: GLdouble); stdcall; - glTexCoord4dv: procedure(const v: PGLdouble); stdcall; - glTexCoord4f: procedure(s, t, r, q: GLfloat); stdcall; - glTexCoord4fv: procedure(const v: PGLfloat); stdcall; - glTexCoord4i: procedure(s, t, r, q: GLint); stdcall; - glTexCoord4iv: procedure(const v: PGLint); stdcall; - glTexCoord4s: procedure(s, t, r, q: GLshort); stdcall; - glTexCoord4sv: procedure(const v: PGLshort); stdcall; - glTexCoordPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); stdcall; - glTexEnvf: procedure(target: GLenum; pname: GLenum; param: GLfloat); stdcall; - glTexEnvfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); stdcall; - glTexEnvi: procedure(target: GLenum; pname: GLenum; param: GLint); stdcall; - glTexEnviv: procedure(target: GLenum; pname: GLenum; const params: PGLint); stdcall; - glTexGend: procedure(coord: GLenum; pname: GLenum; param: GLdouble); stdcall; - glTexGendv: procedure(coord: GLenum; pname: GLenum; const params: PGLdouble); stdcall; - glTexGenf: procedure(coord: GLenum; pname: GLenum; param: GLfloat); stdcall; - glTexGenfv: procedure(coord: GLenum; pname: GLenum; const params: PGLfloat); stdcall; - glTexGeni: procedure(coord: GLenum; pname: GLenum; param: GLint); stdcall; - glTexGeniv: procedure(coord: GLenum; pname: GLenum; const params: PGLint); stdcall; - glTexImage1D: procedure(target: GLenum; level, internalformat: GLint; width: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); stdcall; - glTexImage2D: procedure(target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); stdcall; - glTexParameterf: procedure(target: GLenum; pname: GLenum; param: GLfloat); stdcall; - glTexParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); stdcall; - glTexParameteri: procedure(target: GLenum; pname: GLenum; param: GLint); stdcall; - glTexParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); stdcall; - glTexSubImage1D: procedure(target: GLenum; level, xoffset: GLint; width: GLsizei; format, atype: GLenum; const pixels: Pointer); stdcall; - glTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset: GLint; width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); stdcall; - glTranslated: procedure(x, y, z: GLdouble); stdcall; - glTranslatef: procedure(x, y, z: GLfloat); stdcall; - glVertex2d: procedure(x, y: GLdouble); stdcall; - glVertex2dv: procedure(const v: PGLdouble); stdcall; - glVertex2f: procedure(x, y: GLfloat); stdcall; - glVertex2fv: procedure(const v: PGLfloat); stdcall; - glVertex2i: procedure(x, y: GLint); stdcall; - glVertex2iv: procedure(const v: PGLint); stdcall; - glVertex2s: procedure(x, y: GLshort); stdcall; - glVertex2sv: procedure(const v: PGLshort); stdcall; - glVertex3d: procedure(x, y, z: GLdouble); stdcall; - glVertex3dv: procedure(const v: PGLdouble); stdcall; - glVertex3f: procedure(x, y, z: GLfloat); stdcall; - glVertex3fv: procedure(const v: PGLfloat); stdcall; - glVertex3i: procedure(x, y, z: GLint); stdcall; - glVertex3iv: procedure(const v: PGLint); stdcall; - glVertex3s: procedure(x, y, z: GLshort); stdcall; - glVertex3sv: procedure(const v: PGLshort); stdcall; - glVertex4d: procedure(x, y, z, w: GLdouble); stdcall; - glVertex4dv: procedure(const v: PGLdouble); stdcall; - glVertex4f: procedure(x, y, z, w: GLfloat); stdcall; - glVertex4fv: procedure(const v: PGLfloat); stdcall; - glVertex4i: procedure(x, y, z, w: GLint); stdcall; - glVertex4iv: procedure(const v: PGLint); stdcall; - glVertex4s: procedure(x, y, z, w: GLshort); stdcall; - glVertex4sv: procedure(const v: PGLshort); stdcall; - glVertexPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); stdcall; - glViewport: procedure(x, y: GLint; width, height: GLsizei); stdcall; - ChoosePixelFormat: function(DC: HDC; p2: PPixelFormatDescriptor): Integer; stdcall; - -type - // EXT_vertex_array - PFNGLARRAYELEMENTEXTPROC = procedure(i: GLint); stdcall; - PFNGLDRAWARRAYSEXTPROC = procedure(mode: GLenum; first: GLint; count: GLsizei); stdcall; - PFNGLVERTEXPOINTEREXTPROC = procedure(size: GLint; atype: GLenum; - stride, count: GLsizei; const pointer: Pointer); stdcall; - PFNGLNORMALPOINTEREXTPROC = procedure(atype: GLenum; stride, count: GLsizei; - const pointer: Pointer); stdcall; - PFNGLCOLORPOINTEREXTPROC = procedure(size: GLint; atype: GLenum; stride, count: GLsizei; - const pointer: Pointer); stdcall; - PFNGLINDEXPOINTEREXTPROC = procedure(atype: GLenum; stride, count: GLsizei; - const pointer: Pointer); stdcall; - PFNGLTEXCOORDPOINTEREXTPROC = procedure(size: GLint; atype: GLenum; - stride, count: GLsizei; const pointer: Pointer); stdcall; - PFNGLEDGEFLAGPOINTEREXTPROC = procedure(stride, count: GLsizei; - const pointer: PGLboolean); stdcall; - PFNGLGETPOINTERVEXTPROC = procedure(pname: GLenum; params: Pointer); stdcall; - PFNGLARRAYELEMENTARRAYEXTPROC = procedure(mode: GLenum; count: GLsizei; - const pi: Pointer); stdcall; - - // WIN_swap_hint - PFNGLADDSWAPHINTRECTWINPROC = procedure(x, y: GLint; width, height: GLsizei); stdcall; - - // EXT_paletted_texture - PFNGLCOLORTABLEEXTPROC = procedure(target, internalFormat: GLenum; width: GLsizei; - format, atype: GLenum; const data: Pointer); stdcall; - PFNGLCOLORSUBTABLEEXTPROC = procedure(target: GLenum; start, count: GLsizei; - format, atype: GLenum; const data: Pointer); stdcall; - PFNGLGETCOLORTABLEEXTPROC = procedure(target, format, atype: GLenum; data: Pointer); stdcall; - PFNGLGETCOLORTABLEPARAMETERIVEXTPROC = procedure(target, pname: GLenum; params: PGLint); stdcall; - PFNGLGETCOLORTABLEPARAMETERFVEXTPROC = procedure(target, pname: GLenum; params: PGLfloat); stdcall; - -procedure LoadOpenGL(const dll: String); -procedure FreeOpenGL; - -implementation - -var - hDLL: THandle; - -procedure FreeOpenGL; -begin - - @glAccum := nil; - @glAlphaFunc := nil; - @glAreTexturesResident := nil; - @glArrayElement := nil; - @glBegin := nil; - @glBindTexture := nil; - @glBitmap := nil; - @glBlendFunc := nil; - @glCallList := nil; - @glCallLists := nil; - @glClear := nil; - @glClearAccum := nil; - @glClearColor := nil; - @glClearDepth := nil; - @glClearIndex := nil; - @glClearStencil := nil; - @glClipPlane := nil; - @glColor3b := nil; - @glColor3bv := nil; - @glColor3d := nil; - @glColor3dv := nil; - @glColor3f := nil; - @glColor3fv := nil; - @glColor3i := nil; - @glColor3iv := nil; - @glColor3s := nil; - @glColor3sv := nil; - @glColor3ub := nil; - @glColor3ubv := nil; - @glColor3ui := nil; - @glColor3uiv := nil; - @glColor3us := nil; - @glColor3usv := nil; - @glColor4b := nil; - @glColor4bv := nil; - @glColor4d := nil; - @glColor4dv := nil; - @glColor4f := nil; - @glColor4fv := nil; - @glColor4i := nil; - @glColor4iv := nil; - @glColor4s := nil; - @glColor4sv := nil; - @glColor4ub := nil; - @glColor4ubv := nil; - @glColor4ui := nil; - @glColor4uiv := nil; - @glColor4us := nil; - @glColor4usv := nil; - @glColorMask := nil; - @glColorMaterial := nil; - @glColorPointer := nil; - @glCopyPixels := nil; - @glCopyTexImage1D := nil; - @glCopyTexImage2D := nil; - @glCopyTexSubImage1D := nil; - @glCopyTexSubImage2D := nil; - @glCullFace := nil; - @glDeleteLists := nil; - @glDeleteTextures := nil; - @glDepthFunc := nil; - @glDepthMask := nil; - @glDepthRange := nil; - @glDisable := nil; - @glDisableClientState := nil; - @glDrawArrays := nil; - @glDrawBuffer := nil; - @glDrawElements := nil; - @glDrawPixels := nil; - @glEdgeFlag := nil; - @glEdgeFlagPointer := nil; - @glEdgeFlagv := nil; - @glEnable := nil; - @glEnableClientState := nil; - @glEnd := nil; - @glEndList := nil; - @glEvalCoord1d := nil; - @glEvalCoord1dv := nil; - @glEvalCoord1f := nil; - @glEvalCoord1fv := nil; - @glEvalCoord2d := nil; - @glEvalCoord2dv := nil; - @glEvalCoord2f := nil; - @glEvalCoord2fv := nil; - @glEvalMesh1 := nil; - @glEvalMesh2 := nil; - @glEvalPoint1 := nil; - @glEvalPoint2 := nil; - @glFeedbackBuffer := nil; - @glFinish := nil; - @glFlush := nil; - @glFogf := nil; - @glFogfv := nil; - @glFogi := nil; - @glFogiv := nil; - @glFrontFace := nil; - @glFrustum := nil; - @glGenLists := nil; - @glGenTextures := nil; - @glGetBooleanv := nil; - @glGetClipPlane := nil; - @glGetDoublev := nil; - @glGetError := nil; - @glGetFloatv := nil; - @glGetIntegerv := nil; - @glGetLightfv := nil; - @glGetLightiv := nil; - @glGetMapdv := nil; - @glGetMapfv := nil; - @glGetMapiv := nil; - @glGetMaterialfv := nil; - @glGetMaterialiv := nil; - @glGetPixelMapfv := nil; - @glGetPixelMapuiv := nil; - @glGetPixelMapusv := nil; - @glGetPointerv := nil; - @glGetPolygonStipple := nil; - @glGetString := nil; - @glGetTexEnvfv := nil; - @glGetTexEnviv := nil; - @glGetTexGendv := nil; - @glGetTexGenfv := nil; - @glGetTexGeniv := nil; - @glGetTexImage := nil; - @glGetTexLevelParameterfv := nil; - @glGetTexLevelParameteriv := nil; - @glGetTexParameterfv := nil; - @glGetTexParameteriv := nil; - @glHint := nil; - @glIndexMask := nil; - @glIndexPointer := nil; - @glIndexd := nil; - @glIndexdv := nil; - @glIndexf := nil; - @glIndexfv := nil; - @glIndexi := nil; - @glIndexiv := nil; - @glIndexs := nil; - @glIndexsv := nil; - @glIndexub := nil; - @glIndexubv := nil; - @glInitNames := nil; - @glInterleavedArrays := nil; - @glIsEnabled := nil; - @glIsList := nil; - @glIsTexture := nil; - @glLightModelf := nil; - @glLightModelfv := nil; - @glLightModeli := nil; - @glLightModeliv := nil; - @glLightf := nil; - @glLightfv := nil; - @glLighti := nil; - @glLightiv := nil; - @glLineStipple := nil; - @glLineWidth := nil; - @glListBase := nil; - @glLoadIdentity := nil; - @glLoadMatrixd := nil; - @glLoadMatrixf := nil; - @glLoadName := nil; - @glLogicOp := nil; - @glMap1d := nil; - @glMap1f := nil; - @glMap2d := nil; - @glMap2f := nil; - @glMapGrid1d := nil; - @glMapGrid1f := nil; - @glMapGrid2d := nil; - @glMapGrid2f := nil; - @glMaterialf := nil; - @glMaterialfv := nil; - @glMateriali := nil; - @glMaterialiv := nil; - @glMatrixMode := nil; - @glMultMatrixd := nil; - @glMultMatrixf := nil; - @glNewList := nil; - @glNormal3b := nil; - @glNormal3bv := nil; - @glNormal3d := nil; - @glNormal3dv := nil; - @glNormal3f := nil; - @glNormal3fv := nil; - @glNormal3i := nil; - @glNormal3iv := nil; - @glNormal3s := nil; - @glNormal3sv := nil; - @glNormalPointer := nil; - @glOrtho := nil; - @glPassThrough := nil; - @glPixelMapfv := nil; - @glPixelMapuiv := nil; - @glPixelMapusv := nil; - @glPixelStoref := nil; - @glPixelStorei := nil; - @glPixelTransferf := nil; - @glPixelTransferi := nil; - @glPixelZoom := nil; - @glPointSize := nil; - @glPolygonMode := nil; - @glPolygonOffset := nil; - @glPolygonStipple := nil; - @glPopAttrib := nil; - @glPopClientAttrib := nil; - @glPopMatrix := nil; - @glPopName := nil; - @glPrioritizeTextures := nil; - @glPushAttrib := nil; - @glPushClientAttrib := nil; - @glPushMatrix := nil; - @glPushName := nil; - @glRasterPos2d := nil; - @glRasterPos2dv := nil; - @glRasterPos2f := nil; - @glRasterPos2fv := nil; - @glRasterPos2i := nil; - @glRasterPos2iv := nil; - @glRasterPos2s := nil; - @glRasterPos2sv := nil; - @glRasterPos3d := nil; - @glRasterPos3dv := nil; - @glRasterPos3f := nil; - @glRasterPos3fv := nil; - @glRasterPos3i := nil; - @glRasterPos3iv := nil; - @glRasterPos3s := nil; - @glRasterPos3sv := nil; - @glRasterPos4d := nil; - @glRasterPos4dv := nil; - @glRasterPos4f := nil; - @glRasterPos4fv := nil; - @glRasterPos4i := nil; - @glRasterPos4iv := nil; - @glRasterPos4s := nil; - @glRasterPos4sv := nil; - @glReadBuffer := nil; - @glReadPixels := nil; - @glRectd := nil; - @glRectdv := nil; - @glRectf := nil; - @glRectfv := nil; - @glRecti := nil; - @glRectiv := nil; - @glRects := nil; - @glRectsv := nil; - @glRenderMode := nil; - @glRotated := nil; - @glRotatef := nil; - @glScaled := nil; - @glScalef := nil; - @glScissor := nil; - @glSelectBuffer := nil; - @glShadeModel := nil; - @glStencilFunc := nil; - @glStencilMask := nil; - @glStencilOp := nil; - @glTexCoord1d := nil; - @glTexCoord1dv := nil; - @glTexCoord1f := nil; - @glTexCoord1fv := nil; - @glTexCoord1i := nil; - @glTexCoord1iv := nil; - @glTexCoord1s := nil; - @glTexCoord1sv := nil; - @glTexCoord2d := nil; - @glTexCoord2dv := nil; - @glTexCoord2f := nil; - @glTexCoord2fv := nil; - @glTexCoord2i := nil; - @glTexCoord2iv := nil; - @glTexCoord2s := nil; - @glTexCoord2sv := nil; - @glTexCoord3d := nil; - @glTexCoord3dv := nil; - @glTexCoord3f := nil; - @glTexCoord3fv := nil; - @glTexCoord3i := nil; - @glTexCoord3iv := nil; - @glTexCoord3s := nil; - @glTexCoord3sv := nil; - @glTexCoord4d := nil; - @glTexCoord4dv := nil; - @glTexCoord4f := nil; - @glTexCoord4fv := nil; - @glTexCoord4i := nil; - @glTexCoord4iv := nil; - @glTexCoord4s := nil; - @glTexCoord4sv := nil; - @glTexCoordPointer := nil; - @glTexEnvf := nil; - @glTexEnvfv := nil; - @glTexEnvi := nil; - @glTexEnviv := nil; - @glTexGend := nil; - @glTexGendv := nil; - @glTexGenf := nil; - @glTexGenfv := nil; - @glTexGeni := nil; - @glTexGeniv := nil; - @glTexImage1D := nil; - @glTexImage2D := nil; - @glTexParameterf := nil; - @glTexParameterfv := nil; - @glTexParameteri := nil; - @glTexParameteriv := nil; - @glTexSubImage1D := nil; - @glTexSubImage2D := nil; - @glTranslated := nil; - @glTranslatef := nil; - @glVertex2d := nil; - @glVertex2dv := nil; - @glVertex2f := nil; - @glVertex2fv := nil; - @glVertex2i := nil; - @glVertex2iv := nil; - @glVertex2s := nil; - @glVertex2sv := nil; - @glVertex3d := nil; - @glVertex3dv := nil; - @glVertex3f := nil; - @glVertex3fv := nil; - @glVertex3i := nil; - @glVertex3iv := nil; - @glVertex3s := nil; - @glVertex3sv := nil; - @glVertex4d := nil; - @glVertex4dv := nil; - @glVertex4f := nil; - @glVertex4fv := nil; - @glVertex4i := nil; - @glVertex4iv := nil; - @glVertex4s := nil; - @glVertex4sv := nil; - @glVertexPointer := nil; - @glViewport := nil; - @ChoosePixelFormat := nil; - - FreeLibrary(hDLL); - -end; - -procedure LoadOpenGL(const dll: String); -begin - - FreeOpenGL; - - hDLL := LoadLibrary(PChar(dll)); - if hDLL = 0 then raise Exception.Create('Could not load OpenGL from ' + dll); - - @glAccum := GetProcAddress(hDLL, 'glAccum'); - @glAlphaFunc := GetProcAddress(hDLL, 'glAlphaFunc'); - @glAreTexturesResident := GetProcAddress(hDLL, 'glAreTexturesResident'); - @glArrayElement := GetProcAddress(hDLL, 'glArrayElement'); - @glBegin := GetProcAddress(hDLL, 'glBegin'); - @glBindTexture := GetProcAddress(hDLL, 'glBindTexture'); - @glBitmap := GetProcAddress(hDLL, 'glBitmap'); - @glBlendFunc := GetProcAddress(hDLL, 'glBlendFunc'); - @glCallList := GetProcAddress(hDLL, 'glCallList'); - @glCallLists := GetProcAddress(hDLL, 'glCallLists'); - @glClear := GetProcAddress(hDLL, 'glClear'); - @glClearAccum := GetProcAddress(hDLL, 'glClearAccum'); - @glClearColor := GetProcAddress(hDLL, 'glClearColor'); - @glClearDepth := GetProcAddress(hDLL, 'glClearDepth'); - @glClearIndex := GetProcAddress(hDLL, 'glClearIndex'); - @glClearStencil := GetProcAddress(hDLL, 'glClearStencil'); - @glClipPlane := GetProcAddress(hDLL, 'glClipPlane'); - @glColor3b := GetProcAddress(hDLL, 'glColor3b'); - @glColor3bv := GetProcAddress(hDLL, 'glColor3bv'); - @glColor3d := GetProcAddress(hDLL, 'glColor3d'); - @glColor3dv := GetProcAddress(hDLL, 'glColor3dv'); - @glColor3f := GetProcAddress(hDLL, 'glColor3f'); - @glColor3fv := GetProcAddress(hDLL, 'glColor3fv'); - @glColor3i := GetProcAddress(hDLL, 'glColor3i'); - @glColor3iv := GetProcAddress(hDLL, 'glColor3iv'); - @glColor3s := GetProcAddress(hDLL, 'glColor3s'); - @glColor3sv := GetProcAddress(hDLL, 'glColor3sv'); - @glColor3ub := GetProcAddress(hDLL, 'glColor3ub'); - @glColor3ubv := GetProcAddress(hDLL, 'glColor3ubv'); - @glColor3ui := GetProcAddress(hDLL, 'glColor3ui'); - @glColor3uiv := GetProcAddress(hDLL, 'glColor3uiv'); - @glColor3us := GetProcAddress(hDLL, 'glColor3us'); - @glColor3usv := GetProcAddress(hDLL, 'glColor3usv'); - @glColor4b := GetProcAddress(hDLL, 'glColor4b'); - @glColor4bv := GetProcAddress(hDLL, 'glColor4bv'); - @glColor4d := GetProcAddress(hDLL, 'glColor4d'); - @glColor4dv := GetProcAddress(hDLL, 'glColor4dv'); - @glColor4f := GetProcAddress(hDLL, 'glColor4f'); - @glColor4fv := GetProcAddress(hDLL, 'glColor4fv'); - @glColor4i := GetProcAddress(hDLL, 'glColor4i'); - @glColor4iv := GetProcAddress(hDLL, 'glColor4iv'); - @glColor4s := GetProcAddress(hDLL, 'glColor4s'); - @glColor4sv := GetProcAddress(hDLL, 'glColor4sv'); - @glColor4ub := GetProcAddress(hDLL, 'glColor4ub'); - @glColor4ubv := GetProcAddress(hDLL, 'glColor4ubv'); - @glColor4ui := GetProcAddress(hDLL, 'glColor4ui'); - @glColor4uiv := GetProcAddress(hDLL, 'glColor4uiv'); - @glColor4us := GetProcAddress(hDLL, 'glColor4us'); - @glColor4usv := GetProcAddress(hDLL, 'glColor4usv'); - @glColorMask := GetProcAddress(hDLL, 'glColorMask'); - @glColorMaterial := GetProcAddress(hDLL, 'glColorMaterial'); - @glColorPointer := GetProcAddress(hDLL, 'glColorPointer'); - @glCopyPixels := GetProcAddress(hDLL, 'glCopyPixels'); - @glCopyTexImage1D := GetProcAddress(hDLL, 'glCopyTexImage1D'); - @glCopyTexImage2D := GetProcAddress(hDLL, 'glCopyTexImage2D'); - @glCopyTexSubImage1D := GetProcAddress(hDLL, 'glCopyTexSubImage1D'); - @glCopyTexSubImage2D := GetProcAddress(hDLL, 'glCopyTexSubImage2D'); - @glCullFace := GetProcAddress(hDLL, 'glCullFace'); - @glDeleteLists := GetProcAddress(hDLL, 'glDeleteLists'); - @glDeleteTextures := GetProcAddress(hDLL, 'glDeleteTextures'); - @glDepthFunc := GetProcAddress(hDLL, 'glDepthFunc'); - @glDepthMask := GetProcAddress(hDLL, 'glDepthMask'); - @glDepthRange := GetProcAddress(hDLL, 'glDepthRange'); - @glDisable := GetProcAddress(hDLL, 'glDisable'); - @glDisableClientState := GetProcAddress(hDLL, 'glDisableClientState'); - @glDrawArrays := GetProcAddress(hDLL, 'glDrawArrays'); - @glDrawBuffer := GetProcAddress(hDLL, 'glDrawBuffer'); - @glDrawElements := GetProcAddress(hDLL, 'glDrawElements'); - @glDrawPixels := GetProcAddress(hDLL, 'glDrawPixels'); - @glEdgeFlag := GetProcAddress(hDLL, 'glEdgeFlag'); - @glEdgeFlagPointer := GetProcAddress(hDLL, 'glEdgeFlagPointer'); - @glEdgeFlagv := GetProcAddress(hDLL, 'glEdgeFlagv'); - @glEnable := GetProcAddress(hDLL, 'glEnable'); - @glEnableClientState := GetProcAddress(hDLL, 'glEnableClientState'); - @glEnd := GetProcAddress(hDLL, 'glEnd'); - @glEndList := GetProcAddress(hDLL, 'glEndList'); - @glEvalCoord1d := GetProcAddress(hDLL, 'glEvalCoord1d'); - @glEvalCoord1dv := GetProcAddress(hDLL, 'glEvalCoord1dv'); - @glEvalCoord1f := GetProcAddress(hDLL, 'glEvalCoord1f'); - @glEvalCoord1fv := GetProcAddress(hDLL, 'glEvalCoord1fv'); - @glEvalCoord2d := GetProcAddress(hDLL, 'glEvalCoord2d'); - @glEvalCoord2dv := GetProcAddress(hDLL, 'glEvalCoord2dv'); - @glEvalCoord2f := GetProcAddress(hDLL, 'glEvalCoord2f'); - @glEvalCoord2fv := GetProcAddress(hDLL, 'glEvalCoord2fv'); - @glEvalMesh1 := GetProcAddress(hDLL, 'glEvalMesh1'); - @glEvalMesh2 := GetProcAddress(hDLL, 'glEvalMesh2'); - @glEvalPoint1 := GetProcAddress(hDLL, 'glEvalPoint1'); - @glEvalPoint2 := GetProcAddress(hDLL, 'glEvalPoint2'); - @glFeedbackBuffer := GetProcAddress(hDLL, 'glFeedbackBuffer'); - @glFinish := GetProcAddress(hDLL, 'glFinish'); - @glFlush := GetProcAddress(hDLL, 'glFlush'); - @glFogf := GetProcAddress(hDLL, 'glFogf'); - @glFogfv := GetProcAddress(hDLL, 'glFogfv'); - @glFogi := GetProcAddress(hDLL, 'glFogi'); - @glFogiv := GetProcAddress(hDLL, 'glFogiv'); - @glFrontFace := GetProcAddress(hDLL, 'glFrontFace'); - @glFrustum := GetProcAddress(hDLL, 'glFrustum'); - @glGenLists := GetProcAddress(hDLL, 'glGenLists'); - @glGenTextures := GetProcAddress(hDLL, 'glGenTextures'); - @glGetBooleanv := GetProcAddress(hDLL, 'glGetBooleanv'); - @glGetClipPlane := GetProcAddress(hDLL, 'glGetClipPlane'); - @glGetDoublev := GetProcAddress(hDLL, 'glGetDoublev'); - @glGetError := GetProcAddress(hDLL, 'glGetError'); - @glGetFloatv := GetProcAddress(hDLL, 'glGetFloatv'); - @glGetIntegerv := GetProcAddress(hDLL, 'glGetIntegerv'); - @glGetLightfv := GetProcAddress(hDLL, 'glGetLightfv'); - @glGetLightiv := GetProcAddress(hDLL, 'glGetLightiv'); - @glGetMapdv := GetProcAddress(hDLL, 'glGetMapdv'); - @glGetMapfv := GetProcAddress(hDLL, 'glGetMapfv'); - @glGetMapiv := GetProcAddress(hDLL, 'glGetMapiv'); - @glGetMaterialfv := GetProcAddress(hDLL, 'glGetMaterialfv'); - @glGetMaterialiv := GetProcAddress(hDLL, 'glGetMaterialiv'); - @glGetPixelMapfv := GetProcAddress(hDLL, 'glGetPixelMapfv'); - @glGetPixelMapuiv := GetProcAddress(hDLL, 'glGetPixelMapuiv'); - @glGetPixelMapusv := GetProcAddress(hDLL, 'glGetPixelMapusv'); - @glGetPointerv := GetProcAddress(hDLL, 'glGetPointerv'); - @glGetPolygonStipple := GetProcAddress(hDLL, 'glGetPolygonStipple'); - @glGetString := GetProcAddress(hDLL, 'glGetString'); - @glGetTexEnvfv := GetProcAddress(hDLL, 'glGetTexEnvfv'); - @glGetTexEnviv := GetProcAddress(hDLL, 'glGetTexEnviv'); - @glGetTexGendv := GetProcAddress(hDLL, 'glGetTexGendv'); - @glGetTexGenfv := GetProcAddress(hDLL, 'glGetTexGenfv'); - @glGetTexGeniv := GetProcAddress(hDLL, 'glGetTexGeniv'); - @glGetTexImage := GetProcAddress(hDLL, 'glGetTexImage'); - @glGetTexLevelParameterfv := GetProcAddress(hDLL, 'glGetTexLevelParameterfv'); - @glGetTexLevelParameteriv := GetProcAddress(hDLL, 'glGetTexLevelParameteriv'); - @glGetTexParameterfv := GetProcAddress(hDLL, 'glGetTexParameterfv'); - @glGetTexParameteriv := GetProcAddress(hDLL, 'glGetTexParameteriv'); - @glHint := GetProcAddress(hDLL, 'glHint'); - @glIndexMask := GetProcAddress(hDLL, 'glIndexMask'); - @glIndexPointer := GetProcAddress(hDLL, 'glIndexPointer'); - @glIndexd := GetProcAddress(hDLL, 'glIndexd'); - @glIndexdv := GetProcAddress(hDLL, 'glIndexdv'); - @glIndexf := GetProcAddress(hDLL, 'glIndexf'); - @glIndexfv := GetProcAddress(hDLL, 'glIndexfv'); - @glIndexi := GetProcAddress(hDLL, 'glIndexi'); - @glIndexiv := GetProcAddress(hDLL, 'glIndexiv'); - @glIndexs := GetProcAddress(hDLL, 'glIndexs'); - @glIndexsv := GetProcAddress(hDLL, 'glIndexsv'); - @glIndexub := GetProcAddress(hDLL, 'glIndexub'); - @glIndexubv := GetProcAddress(hDLL, 'glIndexubv'); - @glInitNames := GetProcAddress(hDLL, 'glInitNames'); - @glInterleavedArrays := GetProcAddress(hDLL, 'glInterleavedArrays'); - @glIsEnabled := GetProcAddress(hDLL, 'glIsEnabled'); - @glIsList := GetProcAddress(hDLL, 'glIsList'); - @glIsTexture := GetProcAddress(hDLL, 'glIsTexture'); - @glLightModelf := GetProcAddress(hDLL, 'glLightModelf'); - @glLightModelfv := GetProcAddress(hDLL, 'glLightModelfv'); - @glLightModeli := GetProcAddress(hDLL, 'glLightModeli'); - @glLightModeliv := GetProcAddress(hDLL, 'glLightModeliv'); - @glLightf := GetProcAddress(hDLL, 'glLightf'); - @glLightfv := GetProcAddress(hDLL, 'glLightfv'); - @glLighti := GetProcAddress(hDLL, 'glLighti'); - @glLightiv := GetProcAddress(hDLL, 'glLightiv'); - @glLineStipple := GetProcAddress(hDLL, 'glLineStipple'); - @glLineWidth := GetProcAddress(hDLL, 'glLineWidth'); - @glListBase := GetProcAddress(hDLL, 'glListBase'); - @glLoadIdentity := GetProcAddress(hDLL, 'glLoadIdentity'); - @glLoadMatrixd := GetProcAddress(hDLL, 'glLoadMatrixd'); - @glLoadMatrixf := GetProcAddress(hDLL, 'glLoadMatrixf'); - @glLoadName := GetProcAddress(hDLL, 'glLoadName'); - @glLogicOp := GetProcAddress(hDLL, 'glLogicOp'); - @glMap1d := GetProcAddress(hDLL, 'glMap1d'); - @glMap1f := GetProcAddress(hDLL, 'glMap1f'); - @glMap2d := GetProcAddress(hDLL, 'glMap2d'); - @glMap2f := GetProcAddress(hDLL, 'glMap2f'); - @glMapGrid1d := GetProcAddress(hDLL, 'glMapGrid1d'); - @glMapGrid1f := GetProcAddress(hDLL, 'glMapGrid1f'); - @glMapGrid2d := GetProcAddress(hDLL, 'glMapGrid2d'); - @glMapGrid2f := GetProcAddress(hDLL, 'glMapGrid2f'); - @glMaterialf := GetProcAddress(hDLL, 'glMaterialf'); - @glMaterialfv := GetProcAddress(hDLL, 'glMaterialfv'); - @glMateriali := GetProcAddress(hDLL, 'glMateriali'); - @glMaterialiv := GetProcAddress(hDLL, 'glMaterialiv'); - @glMatrixMode := GetProcAddress(hDLL, 'glMatrixMode'); - @glMultMatrixd := GetProcAddress(hDLL, 'glMultMatrixd'); - @glMultMatrixf := GetProcAddress(hDLL, 'glMultMatrixf'); - @glNewList := GetProcAddress(hDLL, 'glNewList'); - @glNormal3b := GetProcAddress(hDLL, 'glNormal3b'); - @glNormal3bv := GetProcAddress(hDLL, 'glNormal3bv'); - @glNormal3d := GetProcAddress(hDLL, 'glNormal3d'); - @glNormal3dv := GetProcAddress(hDLL, 'glNormal3dv'); - @glNormal3f := GetProcAddress(hDLL, 'glNormal3f'); - @glNormal3fv := GetProcAddress(hDLL, 'glNormal3fv'); - @glNormal3i := GetProcAddress(hDLL, 'glNormal3i'); - @glNormal3iv := GetProcAddress(hDLL, 'glNormal3iv'); - @glNormal3s := GetProcAddress(hDLL, 'glNormal3s'); - @glNormal3sv := GetProcAddress(hDLL, 'glNormal3sv'); - @glNormalPointer := GetProcAddress(hDLL, 'glNormalPointer'); - @glOrtho := GetProcAddress(hDLL, 'glOrtho'); - @glPassThrough := GetProcAddress(hDLL, 'glPassThrough'); - @glPixelMapfv := GetProcAddress(hDLL, 'glPixelMapfv'); - @glPixelMapuiv := GetProcAddress(hDLL, 'glPixelMapuiv'); - @glPixelMapusv := GetProcAddress(hDLL, 'glPixelMapusv'); - @glPixelStoref := GetProcAddress(hDLL, 'glPixelStoref'); - @glPixelStorei := GetProcAddress(hDLL, 'glPixelStorei'); - @glPixelTransferf := GetProcAddress(hDLL, 'glPixelTransferf'); - @glPixelTransferi := GetProcAddress(hDLL, 'glPixelTransferi'); - @glPixelZoom := GetProcAddress(hDLL, 'glPixelZoom'); - @glPointSize := GetProcAddress(hDLL, 'glPointSize'); - @glPolygonMode := GetProcAddress(hDLL, 'glPolygonMode'); - @glPolygonOffset := GetProcAddress(hDLL, 'glPolygonOffset'); - @glPolygonStipple := GetProcAddress(hDLL, 'glPolygonStipple'); - @glPopAttrib := GetProcAddress(hDLL, 'glPopAttrib'); - @glPopClientAttrib := GetProcAddress(hDLL, 'glPopClientAttrib'); - @glPopMatrix := GetProcAddress(hDLL, 'glPopMatrix'); - @glPopName := GetProcAddress(hDLL, 'glPopName'); - @glPrioritizeTextures := GetProcAddress(hDLL, 'glPrioritizeTextures'); - @glPushAttrib := GetProcAddress(hDLL, 'glPushAttrib'); - @glPushClientAttrib := GetProcAddress(hDLL, 'glPushClientAttrib'); - @glPushMatrix := GetProcAddress(hDLL, 'glPushMatrix'); - @glPushName := GetProcAddress(hDLL, 'glPushName'); - @glRasterPos2d := GetProcAddress(hDLL, 'glRasterPos2d'); - @glRasterPos2dv := GetProcAddress(hDLL, 'glRasterPos2dv'); - @glRasterPos2f := GetProcAddress(hDLL, 'glRasterPos2f'); - @glRasterPos2fv := GetProcAddress(hDLL, 'glRasterPos2fv'); - @glRasterPos2i := GetProcAddress(hDLL, 'glRasterPos2i'); - @glRasterPos2iv := GetProcAddress(hDLL, 'glRasterPos2iv'); - @glRasterPos2s := GetProcAddress(hDLL, 'glRasterPos2s'); - @glRasterPos2sv := GetProcAddress(hDLL, 'glRasterPos2sv'); - @glRasterPos3d := GetProcAddress(hDLL, 'glRasterPos3d'); - @glRasterPos3dv := GetProcAddress(hDLL, 'glRasterPos3dv'); - @glRasterPos3f := GetProcAddress(hDLL, 'glRasterPos3f'); - @glRasterPos3fv := GetProcAddress(hDLL, 'glRasterPos3fv'); - @glRasterPos3i := GetProcAddress(hDLL, 'glRasterPos3i'); - @glRasterPos3iv := GetProcAddress(hDLL, 'glRasterPos3iv'); - @glRasterPos3s := GetProcAddress(hDLL, 'glRasterPos3s'); - @glRasterPos3sv := GetProcAddress(hDLL, 'glRasterPos3sv'); - @glRasterPos4d := GetProcAddress(hDLL, 'glRasterPos4d'); - @glRasterPos4dv := GetProcAddress(hDLL, 'glRasterPos4dv'); - @glRasterPos4f := GetProcAddress(hDLL, 'glRasterPos4f'); - @glRasterPos4fv := GetProcAddress(hDLL, 'glRasterPos4fv'); - @glRasterPos4i := GetProcAddress(hDLL, 'glRasterPos4i'); - @glRasterPos4iv := GetProcAddress(hDLL, 'glRasterPos4iv'); - @glRasterPos4s := GetProcAddress(hDLL, 'glRasterPos4s'); - @glRasterPos4sv := GetProcAddress(hDLL, 'glRasterPos4sv'); - @glReadBuffer := GetProcAddress(hDLL, 'glReadBuffer'); - @glReadPixels := GetProcAddress(hDLL, 'glReadPixels'); - @glRectd := GetProcAddress(hDLL, 'glRectd'); - @glRectdv := GetProcAddress(hDLL, 'glRectdv'); - @glRectf := GetProcAddress(hDLL, 'glRectf'); - @glRectfv := GetProcAddress(hDLL, 'glRectfv'); - @glRecti := GetProcAddress(hDLL, 'glRecti'); - @glRectiv := GetProcAddress(hDLL, 'glRectiv'); - @glRects := GetProcAddress(hDLL, 'glRects'); - @glRectsv := GetProcAddress(hDLL, 'glRectsv'); - @glRenderMode := GetProcAddress(hDLL, 'glRenderMode'); - @glRotated := GetProcAddress(hDLL, 'glRotated'); - @glRotatef := GetProcAddress(hDLL, 'glRotatef'); - @glScaled := GetProcAddress(hDLL, 'glScaled'); - @glScalef := GetProcAddress(hDLL, 'glScalef'); - @glScissor := GetProcAddress(hDLL, 'glScissor'); - @glSelectBuffer := GetProcAddress(hDLL, 'glSelectBuffer'); - @glShadeModel := GetProcAddress(hDLL, 'glShadeModel'); - @glStencilFunc := GetProcAddress(hDLL, 'glStencilFunc'); - @glStencilMask := GetProcAddress(hDLL, 'glStencilMask'); - @glStencilOp := GetProcAddress(hDLL, 'glStencilOp'); - @glTexCoord1d := GetProcAddress(hDLL, 'glTexCoord1d'); - @glTexCoord1dv := GetProcAddress(hDLL, 'glTexCoord1dv'); - @glTexCoord1f := GetProcAddress(hDLL, 'glTexCoord1f'); - @glTexCoord1fv := GetProcAddress(hDLL, 'glTexCoord1fv'); - @glTexCoord1i := GetProcAddress(hDLL, 'glTexCoord1i'); - @glTexCoord1iv := GetProcAddress(hDLL, 'glTexCoord1iv'); - @glTexCoord1s := GetProcAddress(hDLL, 'glTexCoord1s'); - @glTexCoord1sv := GetProcAddress(hDLL, 'glTexCoord1sv'); - @glTexCoord2d := GetProcAddress(hDLL, 'glTexCoord2d'); - @glTexCoord2dv := GetProcAddress(hDLL, 'glTexCoord2dv'); - @glTexCoord2f := GetProcAddress(hDLL, 'glTexCoord2f'); - @glTexCoord2fv := GetProcAddress(hDLL, 'glTexCoord2fv'); - @glTexCoord2i := GetProcAddress(hDLL, 'glTexCoord2i'); - @glTexCoord2iv := GetProcAddress(hDLL, 'glTexCoord2iv'); - @glTexCoord2s := GetProcAddress(hDLL, 'glTexCoord2s'); - @glTexCoord2sv := GetProcAddress(hDLL, 'glTexCoord2sv'); - @glTexCoord3d := GetProcAddress(hDLL, 'glTexCoord3d'); - @glTexCoord3dv := GetProcAddress(hDLL, 'glTexCoord3dv'); - @glTexCoord3f := GetProcAddress(hDLL, 'glTexCoord3f'); - @glTexCoord3fv := GetProcAddress(hDLL, 'glTexCoord3fv'); - @glTexCoord3i := GetProcAddress(hDLL, 'glTexCoord3i'); - @glTexCoord3iv := GetProcAddress(hDLL, 'glTexCoord3iv'); - @glTexCoord3s := GetProcAddress(hDLL, 'glTexCoord3s'); - @glTexCoord3sv := GetProcAddress(hDLL, 'glTexCoord3sv'); - @glTexCoord4d := GetProcAddress(hDLL, 'glTexCoord4d'); - @glTexCoord4dv := GetProcAddress(hDLL, 'glTexCoord4dv'); - @glTexCoord4f := GetProcAddress(hDLL, 'glTexCoord4f'); - @glTexCoord4fv := GetProcAddress(hDLL, 'glTexCoord4fv'); - @glTexCoord4i := GetProcAddress(hDLL, 'glTexCoord4i'); - @glTexCoord4iv := GetProcAddress(hDLL, 'glTexCoord4iv'); - @glTexCoord4s := GetProcAddress(hDLL, 'glTexCoord4s'); - @glTexCoord4sv := GetProcAddress(hDLL, 'glTexCoord4sv'); - @glTexCoordPointer := GetProcAddress(hDLL, 'glTexCoordPointer'); - @glTexEnvf := GetProcAddress(hDLL, 'glTexEnvf'); - @glTexEnvfv := GetProcAddress(hDLL, 'glTexEnvfv'); - @glTexEnvi := GetProcAddress(hDLL, 'glTexEnvi'); - @glTexEnviv := GetProcAddress(hDLL, 'glTexEnviv'); - @glTexGend := GetProcAddress(hDLL, 'glTexGend'); - @glTexGendv := GetProcAddress(hDLL, 'glTexGendv'); - @glTexGenf := GetProcAddress(hDLL, 'glTexGenf'); - @glTexGenfv := GetProcAddress(hDLL, 'glTexGenfv'); - @glTexGeni := GetProcAddress(hDLL, 'glTexGeni'); - @glTexGeniv := GetProcAddress(hDLL, 'glTexGeniv'); - @glTexImage1D := GetProcAddress(hDLL, 'glTexImage1D'); - @glTexImage2D := GetProcAddress(hDLL, 'glTexImage2D'); - @glTexParameterf := GetProcAddress(hDLL, 'glTexParameterf'); - @glTexParameterfv := GetProcAddress(hDLL, 'glTexParameterfv'); - @glTexParameteri := GetProcAddress(hDLL, 'glTexParameteri'); - @glTexParameteriv := GetProcAddress(hDLL, 'glTexParameteriv'); - @glTexSubImage1D := GetProcAddress(hDLL, 'glTexSubImage1D'); - @glTexSubImage2D := GetProcAddress(hDLL, 'glTexSubImage2D'); - @glTranslated := GetProcAddress(hDLL, 'glTranslated'); - @glTranslatef := GetProcAddress(hDLL, 'glTranslatef'); - @glVertex2d := GetProcAddress(hDLL, 'glVertex2d'); - @glVertex2dv := GetProcAddress(hDLL, 'glVertex2dv'); - @glVertex2f := GetProcAddress(hDLL, 'glVertex2f'); - @glVertex2fv := GetProcAddress(hDLL, 'glVertex2fv'); - @glVertex2i := GetProcAddress(hDLL, 'glVertex2i'); - @glVertex2iv := GetProcAddress(hDLL, 'glVertex2iv'); - @glVertex2s := GetProcAddress(hDLL, 'glVertex2s'); - @glVertex2sv := GetProcAddress(hDLL, 'glVertex2sv'); - @glVertex3d := GetProcAddress(hDLL, 'glVertex3d'); - @glVertex3dv := GetProcAddress(hDLL, 'glVertex3dv'); - @glVertex3f := GetProcAddress(hDLL, 'glVertex3f'); - @glVertex3fv := GetProcAddress(hDLL, 'glVertex3fv'); - @glVertex3i := GetProcAddress(hDLL, 'glVertex3i'); - @glVertex3iv := GetProcAddress(hDLL, 'glVertex3iv'); - @glVertex3s := GetProcAddress(hDLL, 'glVertex3s'); - @glVertex3sv := GetProcAddress(hDLL, 'glVertex3sv'); - @glVertex4d := GetProcAddress(hDLL, 'glVertex4d'); - @glVertex4dv := GetProcAddress(hDLL, 'glVertex4dv'); - @glVertex4f := GetProcAddress(hDLL, 'glVertex4f'); - @glVertex4fv := GetProcAddress(hDLL, 'glVertex4fv'); - @glVertex4i := GetProcAddress(hDLL, 'glVertex4i'); - @glVertex4iv := GetProcAddress(hDLL, 'glVertex4iv'); - @glVertex4s := GetProcAddress(hDLL, 'glVertex4s'); - @glVertex4sv := GetProcAddress(hDLL, 'glVertex4sv'); - @glVertexPointer := GetProcAddress(hDLL, 'glVertexPointer'); - @glViewport := GetProcAddress(hDLL, 'glViewport'); - - @ChoosePixelFormat := GetProcAddress(hDLL, 'ChoosePixelFormat'); - if not Assigned(ChoosePixelFormat) then - @ChoosePixelFormat := @Windows.ChoosePixelFormat; - -end; - -initialization - - Set8087CW($133F); - - try - LoadOpenGL('opengl32.dll'); - except end; - -finalization - - FreeOpenGL; - -end. diff --git a/src/lib/dgl/dglOpenGL.pas b/src/lib/dgl/dglOpenGL.pas deleted file mode 100644 index 80c8231..0000000 --- a/src/lib/dgl/dglOpenGL.pas +++ /dev/null @@ -1,15296 +0,0 @@ -{==============================================================================} -{ } -{ OpenGL 3.2 - Headertranslation } -{ Version 3.2.1 } -{ Date : 15.09.2009 } -{ } -{ Works with : } -{ - Delphi 3 and up } -{ - FreePascal (1.9.3 and up) } -{ } -{==============================================================================} -{ } -{ Containts the translations of glext.h, gl_1_1.h, glu.h and weglext.h. } -{ It also contains some helperfunctions that were inspired by those } -{ found in Mike Lischke's OpenGL12.pas. } -{ } -{ Copyright (C) DGL-OpenGL2-Portteam } -{ All Rights Reserved } -{ } -{ Obtained through: } -{ Delphi OpenGL Community(DGL) - www.delphigl.com } -{ } -{ Converted and maintained by DGL's GL2.0-Team : } -{ - Sascha Willems - http://www.delphigl.de } -{ - Steffen Xonna (Lossy eX) - http://www.dev-center.de } -{ - Lars Middendorf - http://www.3d-seite.de } -{ Additional input : } -{ - Martin Waldegger (Mars) - http://www.basegraph.com } -{ - Benjamin Rosseaux (BeRo) - http://www.0ok.de } -{ Additional thanks: } -{ sigsegv (libdl.so) } -{ } -{ } -{==============================================================================} -{ You may retrieve the latest version of this file at the Delphi OpenGL } -{ Community home page, located at http://www.delphigl.com/ } -{ } -{ The contents of this file are used with permission, subject to } -{ the Mozilla Public License Version 1.1 (the "License"); you may } -{ not use this file except in compliance with the License. You may } -{ obtain a copy of the License at } -{ http://www.mozilla.org/MPL/MPL-1.1.html } -{ } -{ Software distributed under the License is distributed on an } -{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or } -{ implied. See the License for the specific language governing } -{ rights and limitations under the License. } -{ } -{==============================================================================} -{ History : } -{ Version 1.0 Initial Release } -{ Version 1.1 Added PPointer in Tpyessection for compatiblity with Delphi } -{ versions lower than 7 (SW) } -{ Added a function named RaiseLastOSError including a comment } -{ on how to make it run under Delphi versions lower than 7 (SW) } -{ Added some data types according to the GL-Syntax (SW) } -{ Version 1.2 Fixed some problems with getting the addresses of some } -{ Extensions (e.g. glTexImage3D) where the EXT/ARB did work } -{ but not the core-functions (SW) } -{ Version 1.3 A second call to ReadimplementationProperties won't } -{ revert to the default libs anymore (MW) } -{ Libraries now will be released if necessary (MW) } -{ Version 1.3a Small fixes for glSlang-functions (SW) } -{ Version 1.3b Fixed a small bug with GL_ARB_shader_objects, that lead } -{ lead to that extension not loaded correctly (SW) } -{ Version 1.3c more GL 1.5 compliance by FOG_COORD_xx and } -{ ARB less VBO and occlusion query routines (MW) } -{ Version 1.3d Fixed linebreaks (should now be corrected under D5) (SW) } -{ Version 1.4 Changed header to correspond to the OpenGL-Shading } -{ Language specification 1.10 : } -{ - Added new GL_SAMPLER_*-Constants } -{ - Added Constant GL_SHADING_LANGUAGE_VERSION_ARB } -{ - Added Constant GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB } -{ - Added Constant GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB (SW) } -{ Version 1.4a Fixed a missing stdcall for glBindAttribLocationARB (SW) } -{ Version 1.4b Fixed declaration for glUniform*(f/i)vARB (added count) (MW) } -{ glCompileShaderARB changed from function to procedure (MW) } -{ Version 1.5 Added support for FreePascal (BR) } -{ Added type TGLVectorf3/TGLVector3f (SW) } -{ Version 1.6 Added Extension GL_EXT_framebuffer_object (SX) } -{ Version 1.7 Added Extension GL_ARB_fragment_program_shadow (SX) } -{ Added Extension GL_ARB_draw_buffers (SX) } -{ Added Extension GL_ARB_texture_rectangle (SX) } -{ Added Extension GL_ARB_color_buffer_float (SX) } -{ Added Extension GL_ARB_half_float_pixel (SX) } -{ Added Extension GL_ARB_texture_float (SX) } -{ Added Extension GL_ARB_pixel_buffer_object (SX) } -{ Added Extension GL_EXT_depth_bounds_test (SX) } -{ Added Extension GL_EXT_texture_mirror_clamp (SX) } -{ Added Extension GL_EXT_blend_equation_separate (SX) } -{ Added Extension GL_EXT_pixel_buffer_object (SX) } -{ Added Extension GL_EXT_texture_compression_dxt1 (SX) } -{ Added Extension GL_NV_fragment_program_option (SX) } -{ Added Extension GL_NV_fragment_program2 (SX) } -{ Added Extension GL_NV_vertex_program2_option (SX) } -{ Added Extension GL_NV_vertex_program3 (SX) } -{ Version 1.8 Added explicit delegate type definitions (LM) } -{ Added .Net 1.1 Support (LM) } -{ Added .Net overloaded functions (LM) } -{ Added delayed extension loading and stubs (LM) } -{ Added automatic InitOpenGL call in CreateRenderingContext(LM) } -{ Added extra Read_* function (LM) } -{ Version 2.0 fixed some Problem with version string and damn drivers. } -{ String 1.15 identified as OpenGL 1.5 not as OpenGL 1.1 (SX) } -{ Removed unexisting extension GL_ARB_texture_mirror_repeat(SX) } -{ Added Extension WGL_ARB_pixel_format_float (SX) } -{ Added Extension GL_EXT_stencil_clear_tag (SX) } -{ Added Extension GL_EXT_texture_rectangle (SX) } -{ Added Extension GL_EXT_texture_edge_clamp (SX) } -{ Some 1.5 Core Consts added (now completed) (SX) } -{ gluProject need pointer for not .net (SX) } -{ gluUnProject need pointer for not .net (SX) } -{ wglUseFontOutlines* need pointer for not .net (SX) } -{ wglSwapMultipleBuffers need pointer for not .net (SX) } -{ Bug with wglGetExtensionsStringEXT removed } -{ different type for .net (SX) } -{ Added OpenGL 2.0 Core (SX) } -{ Version 2.0.1 fixed some problems with glGetActiveAttrib in 2.0 Core (SX) } -{ fixes some problems with gluProject (SX) } -{ fixes some problems with gluUnProject (SX) } -{ fixes some problems with gluTessVertex (SX) } -{ fixes some problems with gluLoadSamplingMatrices (SX) } -{ Version 2.1 Removed .NET Support (SX) } -{ Better support for Linux (SX) } -{ Better Codeformation (SX) } -{ Added some more Vector/Matrix types (SX) } -{ Added OpenGL 2.1 Core (SX) } -{ Added Extension GL_EXT_packed_depth_stencil (SX) } -{ Added Extension GL_EXT_texture_sRGB (SX) } -{ Added Extension GL_EXT_framebuffer_blit (SX) } -{ Added Extension GL_EXT_framebuffer_multisample (SX) } -{ Added Extension GL_EXT_timer_query (SX) } -{ Added Extension GL_EXT_gpu_program_parameters (SX) } -{ Added Extension GL_EXT_bindable_uniform (SX) } -{ Added Extension GL_EXT_draw_buffers2 (SX) } -{ Added Extension GL_EXT_draw_instanced (SX) } -{ Added Extension GL_EXT_framebuffer_sRGB (SX) } -{ Added Extension GL_EXT_geometry_shader4 (SX) } -{ Added Extension GL_EXT_gpu_shader4 (SX) } -{ Added Extension GL_EXT_packed_float (SX) } -{ Added Extension GL_EXT_texture_array (SX) } -{ Added Extension GL_EXT_texture_buffer_object (SX) } -{ Added Extension GL_EXT_texture_compression_latc (SX) } -{ Added Extension GL_EXT_texture_compression_rgtc (SX) } -{ Added Extension GL_EXT_texture_integer (SX) } -{ Added Extension GL_EXT_texture_shared_exponent (SX) } -{ Added Extension GL_NV_depth_buffer_float (SX) } -{ Added Extension GL_NV_fragment_program4 (SX) } -{ Added Extension GL_NV_framebuffer_multisample_coverage (SX) } -{ Added Extension GL_NV_geometry_program4 (SX) } -{ Added Extension GL_NV_gpu_program4 (SX) } -{ Added Extension GL_NV_parameter_buffer_object (SX) } -{ Added Extension GL_NV_transform_feedback (SX) } -{ Added Extension GL_NV_vertex_program4 (SX) } -{ Version 3.0 fixed some const of GL_EXT_texture_shared_exponent (SX) } -{ possible better support for mac (SX) } -{ Added OpenGL 3.0 Core (SX) } -{ Added Extension GL_ARB_depth_buffer_float (SX) } -{ Added Extension GL_ARB_draw_instanced (SX) } -{ Added Extension GL_ARB_framebuffer_object (SX) } -{ Added Extension GL_ARB_framebuffer_sRGB (SX) } -{ Added Extension GL_ARB_geometry_shader4 (SX) } -{ Added Extension GL_ARB_half_float_vertex (SX) } -{ Added Extension GL_ARB_instanced_arrays (SX) } -{ Added Extension GL_ARB_map_buffer_range (SX) } -{ Added Extension GL_ARB_texture_buffer_object (SX) } -{ Added Extension GL_ARB_texture_compression_rgtc (SX) } -{ Added Extension GL_ARB_texture_rg (SX) } -{ Added Extension GL_ARB_vertex_array_object (SX) } -{ Added Extension GL_NV_conditional_render (SX) } -{ Added Extension GL_NV_present_video (SX) } -{ Added Extension GL_EXT_transform_feedback (SX) } -{ Added Extension GL_EXT_direct_state_access (SX) } -{ Added Extension GL_EXT_vertex_array_bgra (SX) } -{ Added Extension GL_EXT_texture_swizzle (SX) } -{ Added Extension GL_NV_explicit_multisample (SX) } -{ Added Extension GL_NV_transform_feedback2 (SX) } -{ Added Extension WGL_ARB_create_context (SX) } -{ Added Extension WGL_NV_present_video (SX) } -{ Added Extension WGL_NV_video_out (SX) } -{ Added Extension WGL_NV_swap_group (SX) } -{ Added Extension WGL_NV_gpu_affinity (SX) } -{ Added define DGL_TINY_HEADER to suppress automatic } -{ function loading (SX) } -{ glProcedure renamed to dglGetProcAddress and now it's } -{ visible from outside the unit to custom load functions (SX) } -{ dglCheckExtension added to check if an extension exists (SX) } -{ Read_GL_ARB_buffer_object renamed to } -{ Read_GL_ARB_vertex_buffer_object (SX) } -{ Version 3.0.1 fixed an problem with fpc (SX) } -{ Version 3.0.2 fixed an problem with WGL_ARB_create_context (SX) } -{ Version 3.2 Functions from GL_VERSION_3_0 where updated (SX) } -{ Functions from GL_ARB_map_buffer_range where updated (SX) } -{ Functions from GL_NV_present_video where added (SX) } -{ Added consts of GL_ARB_instanced_arrays (SX) } -{ Defines to identify Delphi was changed (prevent for } -{ feature maintenance) (SX) } -{ Added Extension GL_ATI_meminfo (SX) } -{ Added Extension GL_AMD_performance_monitor (SX) } -{ Added Extension GL_AMD_texture_texture4 (SX) } -{ Added Extension GL_AMD_vertex_shader_tesselator (SX) } -{ Added Extension GL_EXT_provoking_vertex (SX) } -{ Added Extension WGL_AMD_gpu_association (SX) } -{ Added OpenGL 3.1 Core (SX) } -{ All deprecated stuff can be disabled if you undef the } -{ define DGL_DEPRECATED (SX) } -{ Added Extension GL_ARB_uniform_buffer_object (SX) } -{ Added Extension GL_ARB_compatibility (SX) } -{ Added Extension GL_ARB_copy_buffer (SX) } -{ Added Extension GL_ARB_shader_texture_lod (SX) } -{ Remove function from GL_NV_present_video (SX) } -{ Added Extension WGL_3DL_stereo_control (SX) } -{ Added Extension GL_EXT_texture_snorm (SX) } -{ Added Extension GL_AMD_draw_buffers_blend (SX) } -{ Added Extension GL_APPLE_texture_range (SX) } -{ Added Extension GL_APPLE_float_pixels (SX) } -{ Added Extension GL_APPLE_vertex_program_evaluators (SX) } -{ Added Extension GL_APPLE_aux_depth_stencil (SX) } -{ Added Extension GL_APPLE_object_purgeable (SX) } -{ Added Extension GL_APPLE_row_bytes (SX) } -{ Added OpenGL 3.2 Core (SX) } -{ Added Extension GL_ARB_depth_clamp (SX) } -{ Added Extension GL_ARB_draw_elements_base_vertex (SX) } -{ Added Extension GL_ARB_fragment_coord_conventions (SX) } -{ Added Extension GL_ARB_provoking_vertex (SX) } -{ Added Extension GL_ARB_seamless_cube_map (SX) } -{ Added Extension GL_ARB_sync (SX) } -{ Added Extension GL_ARB_texture_multisample (SX) } -{ Added Extension GL_ARB_vertex_array_bgra (SX) } -{ Added Extension GL_ARB_draw_buffers_blend (SX) } -{ Added Extension GL_ARB_sample_shading (SX) } -{ Added Extension GL_ARB_texture_cube_map_array (SX) } -{ Added Extension GL_ARB_texture_gather (SX) } -{ Added Extension GL_ARB_texture_query_lod (SX) } -{ Added Extension WGL_ARB_create_context_profile (SX) } -{ Added GLX Core up to Version 1.4 (SX) } -{ Added Extension GLX_ARB_multisample (SX) } -{ Added Extension GLX_ARB_fbconfig_float (SX) } -{ Added Extension GLX_ARB_get_proc_address (SX) } -{ Added Extension GLX_ARB_create_context (SX) } -{ Added Extension GLX_ARB_create_context_profile (SX) } -{ Added Extension GLX_EXT_visual_info (SX) } -{ Added Extension GLX_EXT_visual_rating (SX) } -{ Added Extension GLX_EXT_import_context (SX) } -{ Added Extension GLX_EXT_fbconfig_packed_float (SX) } -{ Added Extension GLX_EXT_framebuffer_sRGB (SX) } -{ Added Extension GLX_EXT_texture_from_pixmap (SX) } -{ Version 3.2.1 Fixed some problems with Delphi < 6 (SX) } - - -{==============================================================================} -{ Header based on glext.h rev 54 (2009-08-03) } -{ This is an important notice for maintaining. Dont remove it. And make sure } -{ to keep him up to date } -{==============================================================================} - - -{$define DGL_DEPRECATED} -{ - This define defines if the header should use deprecated ARB stuff or not. - per Default the Header use deprecated Stuff. -} - - -{.$define DGL_TINY_HEADER} -{ - If you enable the define DGL_TINY_HEADER no function automatically will be loaded if you - call ActivateRenderingContext. This may some bit faster and the smart linker can delete - all non used functions. This will reduce the filesize of your binary file. But in this - case you have to load the functions by yourself. There are two ways to do this. - - 1. You can load whole extension by calling the func Read_Extensionname. But if you do - this it's possible to load functions you dont use. So you have the same "problem" - like before. But it's only an bit smaler. - > Read_GL_ARB_multitexture; - - 2. You are able to load only the functions you exactly need. In this case you are able - to use the variables of the dglOpenGL.pas. So you only need to load the functions - and you can use the header like before. - To do this you have to created and activated an opengl context and than you can load - the needed functions. - > ActivateRenderingContext(fDC, fRC); - > glActiveTextureARB := dglGetProcAddress('glActiveTextureARB'); - > glMultiTexCoord2fARB := dglGetProcAddress('glMultiTexCoord2fARB'); - - So only the function "glActiveTextureARB" and "glMultiTexCoord2fARB" will be loaded. - - - Please notice that the extension variables won't be loaded if this define is active. But - you can call dglCheckExtension to check if any extension exists. You can assign them to - the variables of the dglOpenGL.pas so all code they use this will find them. - - > GL_ARB_shading_language_100 := dglCheckExtension('GL_ARB_shading_language_100'); -} - - -unit dglOpenGL; - -interface - -// defines to configure freepascal -{$IFDEF FPC} - {$MODE Delphi} - - {$IFNDEF WINDOWS} - {$LINKLIB c} - {$ENDIF} -{$ENDIF} - -// known delphi versions -{$IFNDEF FPC} // if freepascal isnt defined - {$IFDEF VER140} // Delphi 6 - {$DEFINE DELPHI6_AND_DOWN} - {$ENDIF} - - {$IFDEF VER130} // Delphi 5 - {$DEFINE DELPHI6_AND_DOWN} - {$ENDIF} - - {$IFDEF VER120} // Delphi 4 - {$DEFINE DELPHI6_AND_DOWN} - {$ENDIF} - - {$IFDEF VER110} // C++ Builder 3 - {$DEFINE DELPHI6_AND_DOWN} - {$ENDIF} - - {$IFDEF VER100} // Delphi 3 - {$DEFINE DELPHI6_AND_DOWN} - {$ENDIF} -{$ENDIF} - -// Options for Delphi < 5 -{$IFDEF DELPHI6_AND_DOWN} - {$A+} -{$ELSE} - {$A4} -{$ENDIF} - -// generell options -{$H+,O+,X+} - -// detecting Windows -{$IFDEF Win32} // Delphi and fpc of 32 Bit Windows - {$DEFINE DGL_WIN} -{$ENDIF} - -{$IFDEF Win64} // Delphi and fpc of 32 Bit Windows - {$DEFINE DGL_WIN} -{$ENDIF} - -// detecting Linux -{$IFDEF linux} // Linux - {$DEFINE DGL_LINUX} -{$ENDIF} - -// detecting 64 Bit CPU -{$IFDEF CPU64} // fpc on 64 bit cpus - {$DEFINE DGL_64BIT} // dgl define for 64 bit -{$ENDIF} - - - -uses - SysUtils - {$IFDEF DGL_WIN}, Windows{$ENDIF} - {$IFDEF DGL_LINUX}, X, XLib, XUtil{$ENDIF} - ; - -type - // Needed for Delphi 6 and less (defined in system.pas for Delphi 7) - PPointer = ^Pointer; - PCardinal = ^Cardinal; - - GLenum = Cardinal; - GLboolean = BYTEBOOL; - GLbitfield = Cardinal; - GLbyte = Shortint; - GLshort = SmallInt; - GLint = Integer; - GLsizei = Integer; - GLubyte = Byte; - GLushort = Word; - GLuint = Cardinal; - GLfloat = Single; - GLclampf = Single; - GLdouble = Double; - GLclampd = Double; - GLvoid = Pointer; - GLint64 = Int64; - GLuint64 = {$IFDEF DELPHI6_AND_DOWN} Int64 {$ELSE} UInt64 {$ENDIF}; - - TGLenum = GLenum; - TGLboolean = GLboolean; - TGLbitfield = GLbitfield; - TGLbyte = GLbyte; - TGLshort = GLshort; - TGLint = GLint; - TGLsizei = GLsizei; - TGLubyte = GLubyte; - TGLushort = GLushort; - TGLuint = GLuint; - TGLfloat = GLfloat; - TGLclampf = GLclampf; - TGLdouble = GLdouble; - TGLclampd = GLclampd; - TGLvoid = GLvoid; - TGLint64 = GLint64; - TGLuint64 = GLuint64; - - PGLboolean = ^GLboolean; - PGLbyte = ^GLbyte; - PGLshort = ^GLshort; - PGLint = ^GLint; - PGLsizei = ^GLsizei; - PGLubyte = ^GLubyte; - PGLushort = ^GLushort; - PGLuint = ^GLuint; - PGLclampf = ^GLclampf; - PGLfloat = ^GLfloat; - PGLdouble = ^GLdouble; - PGLclampd = ^GLclampd; - PGLenum = ^GLenum; - PGLvoid = Pointer; - PPGLvoid = ^PGLvoid; - PGLint64 = ^GLint64; - - // GL_NV_half_float - GLhalfNV = WORD; - TGLhalfNV = GLhalfNV; - PGLhalfNV = ^GLhalfNV; - - // GL_ARB_shader_objects - PGLHandleARB = ^GLHandleARB; - GLHandleARB = Integer; - GLcharARB = AnsiChar; - PGLcharARB = PAnsiChar; - PPGLcharARB = ^PGLcharARB; - - // GL_VERSION_2_0 - GLHandle = Integer; - PGLchar = PAnsiChar; - PPGLchar = ^PGLChar; - - // GL_EXT_timer_query - GLint64EXT = Int64; - TGLint64EXT = GLint64EXT; - PGLint64EXT = ^TGLint64EXT; - - GLuint64EXT = TGLuint64; - TGLuint64EXT = GLuint64EXT; - PGLuint64EXT = ^TGLuint64EXT; - - // WGL_ARB_pbuffer - HPBUFFERARB = THandle; - - // WGL_EXT_pbuffer - HPBUFFEREXT = THandle; - - // WGL_NV_present_video - PHVIDEOOUTPUTDEVICENV = ^HVIDEOOUTPUTDEVICENV; - HVIDEOOUTPUTDEVICENV = THandle; - - // WGL_NV_video_out - PHPVIDEODEV = ^HPVIDEODEV; - HPVIDEODEV = THandle; - - // WGL_NV_gpu_affinity - PHPGPUNV = ^HPGPUNV; - PHGPUNV = ^HGPUNV; - - HPGPUNV = THandle; - HGPUNV = THandle; - - // ARB_sync - GLsync = Pointer; - - // GLX - {$IFDEF DGL_LINUX} - GLXContext = Pointer; - GLXContextID = TXID; - GLXDrawable = TXID; - GLXFBConfig = Pointer; - GLXPbuffer = TXID; - GLXPixmap = TXID; - GLXWindow = TXID; - - Window = TXID; - Colormap = TXID; - Pixmap = TXID; - Font = TXID; - {$ENDIF} - - // Datatypes corresponding to GL's types TGL(name)(type)(count) - TGLVectorub2 = array[0..1] of TGLubyte; - TGLVectori2 = array[0..1] of TGLint; - TGLVectorf2 = array[0..1] of TGLfloat; - TGLVectord2 = array[0..1] of TGLdouble; - TGLVectorp2 = array[0..1] of Pointer; - - TGLVectorub3 = array[0..2] of TGLubyte; - TGLVectori3 = array[0..2] of TGLint; - TGLVectorf3 = array[0..2] of TGLfloat; - TGLVectord3 = array[0..2] of TGLdouble; - TGLVectorp3 = array[0..2] of Pointer; - - TGLVectorub4 = array[0..3] of TGLubyte; - TGLVectori4 = array[0..3] of TGLint; - TGLVectorf4 = array[0..3] of TGLfloat; - TGLVectord4 = array[0..3] of TGLdouble; - TGLVectorp4 = array[0..3] of Pointer; - - TGLArrayf4 = TGLVectorf4; - TGLArrayf3 = TGLVectorf3; - TGLArrayd3 = TGLVectord3; - TGLArrayi4 = TGLVectori4; - TGLArrayp4 = TGLVectorp4; - - TGlMatrixub3 = array[0..2, 0..2] of TGLubyte; - TGlMatrixi3 = array[0..2, 0..2] of TGLint; - TGLMatrixf3 = array[0..2, 0..2] of TGLfloat; - TGLMatrixd3 = array[0..2, 0..2] of TGLdouble; - - TGlMatrixub4 = array[0..3, 0..3] of TGLubyte; - TGlMatrixi4 = array[0..3, 0..3] of TGLint; - TGLMatrixf4 = array[0..3, 0..3] of TGLfloat; - TGLMatrixd4 = array[0..3, 0..3] of TGLdouble; - - TGLVector3f = TGLVectorf3; - - // Datatypes corresponding to OpenGL12.pas for easy porting - TVector3d = TGLVectord3; - - TVector4i = TGLVectori4; - TVector4f = TGLVectorf4; - TVector4p = TGLVectorp4; - - TMatrix4f = TGLMatrixf4; - TMatrix4d = TGLMatrixd4; - - PGLMatrixd4 = ^TGLMatrixd4; - PVector4i = ^TVector4i; - - - -{$IFDEF FPC} - TRect = packed record - Left, Top, Right, Bottom: Longint; - end; -{$ENDIF} - - - PGPU_DEVICE = ^GPU_DEVICE; - GPU_DEVICE = record - cb: DWORD; - DeviceName: array [0..31] of AnsiChar; - DeviceString: array [0..127] of AnsiChar; - Flags: DWORD; - rcVirtualScreen: TRect; - end; - - -type -{$IFDEF FPC} - {$IFDEF DGL_WIN} - PWGLSwap = ^TWGLSwap; - {$EXTERNALSYM _WGLSWAP} - _WGLSWAP = packed record - hdc: HDC; - uiFlags: UINT; - end; - - TWGLSwap = _WGLSWAP; - {$EXTERNALSYM WGLSWAP} - WGLSWAP = _WGLSWAP; - - {$ENDIF} -{$ENDIF} - - // GLU types - TGLUNurbs = record - end; - TGLUQuadric = record - end; - TGLUTesselator = record - end; - PGLUNurbs = ^TGLUNurbs; - PGLUQuadric = ^TGLUQuadric; - PGLUTesselator = ^TGLUTesselator; - // backwards compatibility - TGLUNurbsObj = TGLUNurbs; - TGLUQuadricObj = TGLUQuadric; - TGLUTesselatorObj = TGLUTesselator; - TGLUTriangulatorObj = TGLUTesselator; - PGLUNurbsObj = PGLUNurbs; - PGLUQuadricObj = PGLUQuadric; - PGLUTesselatorObj = PGLUTesselator; - PGLUTriangulatorObj = PGLUTesselator; - - // GLUQuadricCallback - TGLUQuadricErrorProc = procedure(errorCode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - // GLUTessCallback - TGLUTessBeginProc = procedure(AType: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessEdgeFlagProc = procedure(Flag: GLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessVertexProc = procedure(VertexData: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessEndProc = procedure; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessErrorProc = procedure(ErrNo: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessCombineProc = procedure(Coords: TGLArrayd3; VertexData: TGLArrayp4; Weight: TGLArrayf4; OutData: PPointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessBeginDataProc = procedure(AType: GLenum; UserData: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessEdgeFlagDataProc = procedure(Flag: GLboolean; UserData: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessVertexDataProc = procedure(VertexData: Pointer; UserData: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessEndDataProc = procedure(UserData: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessErrorDataProc = procedure(ErrNo: GLenum; UserData: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TGLUTessCombineDataProc = procedure(Coords: TGLArrayd3; VertexData: TGLArrayp4; Weight: TGLArrayf4; OutData: PPointer; UserData: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - // GLUNurbsCallback - TGLUNurbsErrorProc = procedure(ErrorCode: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - -var - GL_VERSION_1_0, - GL_VERSION_1_1, - GL_VERSION_1_2, - GL_VERSION_1_3, - GL_VERSION_1_4, - GL_VERSION_1_5, - GL_VERSION_2_0, - GL_VERSION_2_1, - GL_VERSION_3_0, - GL_VERSION_3_1, - GL_VERSION_3_2, - GLU_VERSION_1_1, - GLU_VERSION_1_2, - GLU_VERSION_1_3, - GL_3DFX_multisample, - GL_3DFX_tbuffer, - GL_3DFX_texture_compression_FXT1, - GL_APPLE_client_storage, - GL_APPLE_element_array, - GL_APPLE_fence, - GL_APPLE_specular_vector, - GL_APPLE_transform_hint, - GL_APPLE_vertex_array_object, - GL_APPLE_vertex_array_range, - GL_APPLE_ycbcr_422, - GL_APPLE_texture_range, - GL_APPLE_float_pixels, - GL_APPLE_vertex_program_evaluators, - GL_APPLE_aux_depth_stencil, - GL_APPLE_object_purgeable, - GL_APPLE_row_bytes, - GL_ARB_depth_texture, - GL_ARB_fragment_program, - GL_ARB_imaging, - GL_ARB_matrix_palette, - GL_ARB_multisample, - GL_ARB_multitexture, - GL_ARB_point_parameters, - GL_ARB_shadow, - GL_ARB_shadow_ambient, - GL_ARB_texture_border_clamp, - GL_ARB_texture_compression, - GL_ARB_texture_cube_map, - GL_ARB_texture_env_add, - GL_ARB_texture_env_combine, - GL_ARB_texture_env_crossbar, - GL_ARB_texture_env_dot3, - GL_ARB_texture_mirrored_repeat, - GL_ARB_transpose_matrix, - GL_ARB_vertex_blend, - GL_ARB_vertex_buffer_object, - GL_ARB_vertex_program, - GL_ARB_window_pos, - GL_ARB_shader_objects, - GL_ARB_vertex_shader, - GL_ARB_fragment_shader, - GL_ARB_shading_language_100, - GL_ARB_occlusion_query, - GL_ARB_texture_non_power_of_two, - GL_ARB_point_sprite, - GL_ARB_fragment_program_shadow, - GL_ARB_draw_buffers, - GL_ARB_texture_rectangle, - GL_ARB_color_buffer_float, - GL_ARB_half_float_pixel, - GL_ARB_texture_float, - GL_ARB_pixel_buffer_object, - GL_ARB_depth_buffer_float, - GL_ARB_draw_instanced, - GL_ARB_framebuffer_object, - GL_ARB_framebuffer_sRGB, - GL_ARB_geometry_shader4, - GL_ARB_half_float_vertex, - GL_ARB_instanced_arrays, - GL_ARB_map_buffer_range, - GL_ARB_texture_buffer_object, - GL_ARB_texture_compression_rgtc, - GL_ARB_texture_rg, - GL_ARB_vertex_array_object, - GL_ARB_uniform_buffer_object, - GL_ARB_compatibility, - GL_ARB_copy_buffer, - GL_ARB_shader_texture_lod, - GL_ARB_depth_clamp, - GL_ARB_draw_elements_base_vertex, - GL_ARB_fragment_coord_conventions, - GL_ARB_provoking_vertex, - GL_ARB_seamless_cube_map, - GL_ARB_sync, - GL_ARB_texture_multisample, - GL_ARB_vertex_array_bgra, - GL_ARB_draw_buffers_blend, - GL_ARB_sample_shading, - GL_ARB_texture_cube_map_array, - GL_ARB_texture_gather, - GL_ARB_texture_query_lod, - GL_ATI_draw_buffers, - GL_ATI_element_array, - GL_ATI_envmap_bumpmap, - GL_ATI_fragment_shader, - GL_ATI_map_object_buffer, - GL_ATI_pn_triangles, - GL_ATI_separate_stencil, - GL_ATI_text_fragment_shader, - GL_ATI_texture_env_combine3, - GL_ATI_texture_float, - GL_ATI_texture_mirror_once, - GL_ATI_vertex_array_object, - GL_ATI_vertex_attrib_array_object, - GL_ATI_vertex_streams, - GL_ATI_meminfo, - GL_AMD_performance_monitor, - GL_AMD_texture_texture4, - GL_AMD_vertex_shader_tesselator, - GL_AMD_draw_buffers_blend, - GL_EXT_422_pixels, - GL_EXT_abgr, - GL_EXT_bgra, - GL_EXT_blend_color, - GL_EXT_blend_func_separate, - GL_EXT_blend_logic_op, - GL_EXT_blend_minmax, - GL_EXT_blend_subtract, - GL_EXT_clip_volume_hint, - GL_EXT_cmyka, - GL_EXT_color_matrix, - GL_EXT_color_subtable, - GL_EXT_compiled_vertex_array, - GL_EXT_convolution, - GL_EXT_coordinate_frame, - GL_EXT_copy_texture, - GL_EXT_cull_vertex, - GL_EXT_draw_range_elements, - GL_EXT_fog_coord, - GL_EXT_framebuffer_object, - GL_EXT_histogram, - GL_EXT_index_array_formats, - GL_EXT_index_func, - GL_EXT_index_material, - GL_EXT_index_texture, - GL_EXT_light_texture, - GL_EXT_misc_attribute, - GL_EXT_multi_draw_arrays, - GL_EXT_multisample, - GL_EXT_packed_pixels, - GL_EXT_paletted_texture, - GL_EXT_pixel_transform, - GL_EXT_pixel_transform_color_table, - GL_EXT_point_parameters, - GL_EXT_polygon_offset, - GL_EXT_rescale_normal, - GL_EXT_secondary_color, - GL_EXT_separate_specular_color, - GL_EXT_shadow_funcs, - GL_EXT_shared_texture_palette, - GL_EXT_stencil_two_side, - GL_EXT_stencil_wrap, - GL_EXT_subtexture, - GL_EXT_texture, - GL_EXT_texture3D, - GL_EXT_texture_compression_s3tc, - GL_EXT_texture_cube_map, - GL_EXT_texture_edge_clamp, - GL_EXT_texture_env_add, - GL_EXT_texture_env_combine, - GL_EXT_texture_env_dot3, - GL_EXT_texture_filter_anisotropic, - GL_EXT_texture_lod_bias, - GL_EXT_texture_object, - GL_EXT_texture_perturb_normal, - GL_EXT_texture_rectangle, - GL_EXT_vertex_array, - GL_EXT_vertex_shader, - GL_EXT_vertex_weighting, - GL_EXT_depth_bounds_test, - GL_EXT_texture_mirror_clamp, - GL_EXT_blend_equation_separate, - GL_EXT_pixel_buffer_object, - GL_EXT_texture_compression_dxt1, - GL_EXT_stencil_clear_tag, - GL_EXT_packed_depth_stencil, - GL_EXT_texture_sRGB, - GL_EXT_framebuffer_blit, - GL_EXT_framebuffer_multisample, - GL_EXT_timer_query, - GL_EXT_gpu_program_parameters, - GL_EXT_bindable_uniform, - GL_EXT_draw_buffers2, - GL_EXT_draw_instanced, - GL_EXT_framebuffer_sRGB, - GL_EXT_geometry_shader4, - GL_EXT_gpu_shader4, - GL_EXT_packed_float, - GL_EXT_texture_array, - GL_EXT_texture_buffer_object, - GL_EXT_texture_compression_latc, - GL_EXT_texture_compression_rgtc, - GL_EXT_texture_integer, - GL_EXT_texture_shared_exponent, - GL_EXT_transform_feedback, - GL_EXT_direct_state_access, - GL_EXT_vertex_array_bgra, - GL_EXT_texture_swizzle, - GL_EXT_provoking_vertex, - GL_EXT_texture_snorm, - GL_FfdMaskSGIX, - GL_HP_convolution_border_modes, - GL_HP_image_transform, - GL_HP_occlusion_test, - GL_HP_texture_lighting, - GL_IBM_cull_vertex, - GL_IBM_multimode_draw_arrays, - GL_IBM_rasterpos_clip, - GL_IBM_texture_mirrored_repeat, - GL_IBM_vertex_array_lists, - GL_INGR_blend_func_separate, - GL_INGR_color_clamp, - GL_INGR_interlace_read, - GL_INGR_palette_buffer, - GL_INTEL_parallel_arrays, - GL_INTEL_texture_scissor, - GL_MESA_resize_buffers, - GL_MESA_window_pos, - GL_NV_blend_square, - GL_NV_copy_depth_to_color, - GL_NV_depth_clamp, - GL_NV_evaluators, - GL_NV_fence, - GL_NV_float_buffer, - GL_NV_fog_distance, - GL_NV_fragment_program, - GL_NV_half_float, - GL_NV_light_max_exponent, - GL_NV_multisample_filter_hint, - GL_NV_occlusion_query, - GL_NV_packed_depth_stencil, - GL_NV_pixel_data_range, - GL_NV_point_sprite, - GL_NV_primitive_restart, - GL_NV_register_combiners, - GL_NV_register_combiners2, - GL_NV_texgen_emboss, - GL_NV_texgen_reflection, - GL_NV_texture_compression_vtc, - GL_NV_texture_env_combine4, - GL_NV_texture_expand_normal, - GL_NV_texture_rectangle, - GL_NV_texture_shader, - GL_NV_texture_shader2, - GL_NV_texture_shader3, - GL_NV_vertex_array_range, - GL_NV_vertex_array_range2, - GL_NV_vertex_program, - GL_NV_vertex_program1_1, - GL_NV_vertex_program2, - GL_NV_fragment_program_option, - GL_NV_fragment_program2, - GL_NV_vertex_program2_option, - GL_NV_vertex_program3, - GL_NV_depth_buffer_float, - GL_NV_fragment_program4, - GL_NV_framebuffer_multisample_coverage, - GL_NV_geometry_program4, - GL_NV_gpu_program4, - GL_NV_parameter_buffer_object, - GL_NV_transform_feedback, - GL_NV_vertex_program4, - GL_NV_conditional_render, - GL_NV_present_video, - GL_NV_explicit_multisample, - GL_NV_transform_feedback2, - GL_OML_interlace, - GL_OML_resample, - GL_OML_subsample, - GL_PGI_misc_hints, - GL_PGI_vertex_hints, - GL_REND_screen_coordinates, - GL_S3_s3tc, - GL_SGIS_detail_texture, - GL_SGIS_fog_function, - GL_SGIS_generate_mipmap, - GL_SGIS_multisample, - GL_SGIS_pixel_texture, - GL_SGIS_point_line_texgen, - GL_SGIS_point_parameters, - GL_SGIS_sharpen_texture, - GL_SGIS_texture4D, - GL_SGIS_texture_border_clamp, - GL_SGIS_texture_color_mask, - GL_SGIS_texture_edge_clamp, - GL_SGIS_texture_filter4, - GL_SGIS_texture_lod, - GL_SGIS_texture_select, - GL_SGIX_async, - GL_SGIX_async_histogram, - GL_SGIX_async_pixel, - GL_SGIX_blend_alpha_minmax, - GL_SGIX_calligraphic_fragment, - GL_SGIX_clipmap, - GL_SGIX_convolution_accuracy, - GL_SGIX_depth_pass_instrument, - GL_SGIX_depth_texture, - GL_SGIX_flush_raster, - GL_SGIX_fog_offset, - GL_SGIX_fog_scale, - GL_SGIX_fragment_lighting, - GL_SGIX_framezoom, - GL_SGIX_igloo_interface, - GL_SGIX_impact_pixel_texture, - GL_SGIX_instruments, - GL_SGIX_interlace, - GL_SGIX_ir_instrument1, - GL_SGIX_list_priority, - GL_SGIX_pixel_texture, - GL_SGIX_pixel_tiles, - GL_SGIX_polynomial_ffd, - GL_SGIX_reference_plane, - GL_SGIX_resample, - GL_SGIX_scalebias_hint, - GL_SGIX_shadow, - GL_SGIX_shadow_ambient, - GL_SGIX_sprite, - GL_SGIX_subsample, - GL_SGIX_tag_sample_buffer, - GL_SGIX_texture_add_env, - GL_SGIX_texture_coordinate_clamp, - GL_SGIX_texture_lod_bias, - GL_SGIX_texture_multi_buffer, - GL_SGIX_texture_scale_bias, - GL_SGIX_texture_select, - GL_SGIX_vertex_preclip, - GL_SGIX_ycrcb, - GL_SGIX_ycrcb_subsample, - GL_SGIX_ycrcba, - GL_SGI_color_matrix, - GL_SGI_color_table, - GL_SGI_depth_pass_instrument, - GL_SGI_texture_color_table, - GL_SUNX_constant_data, - GL_SUN_convolution_border_modes, - GL_SUN_global_alpha, - GL_SUN_mesh_array, - GL_SUN_slice_accum, - GL_SUN_triangle_list, - GL_SUN_vertex, - - GL_WIN_phong_shading, - GL_WIN_specular_fog, - WGL_3DFX_multisample, - WGL_ARB_buffer_region, - WGL_ARB_extensions_string, - WGL_ARB_make_current_read, - WGL_ARB_multisample, - WGL_ARB_pbuffer, - WGL_ARB_pixel_format, - WGL_ARB_pixel_format_float, - WGL_ARB_render_texture, - WGL_ARB_create_context, - WGL_ARB_create_context_profile, - WGL_ATI_pixel_format_float, - WGL_AMD_gpu_association, - WGL_EXT_depth_float, - WGL_EXT_display_color_table, - WGL_EXT_extensions_string, - WGL_EXT_make_current_read, - WGL_EXT_multisample, - WGL_EXT_pbuffer, - WGL_EXT_pixel_format, - WGL_EXT_swap_control, - WGL_I3D_digital_video_control, - WGL_I3D_gamma, - WGL_I3D_genlock, - WGL_I3D_image_buffer, - WGL_I3D_swap_frame_lock, - WGL_I3D_swap_frame_usage, - WGL_NV_float_buffer, - WGL_NV_render_depth_texture, - WGL_NV_render_texture_rectangle, - WGL_NV_vertex_array_range, - WGL_NV_present_video, - WGL_NV_video_out, - WGL_NV_swap_group, - WGL_NV_gpu_affinity, - WGL_OML_sync_control, - WGL_3DL_stereo_control, - WIN_draw_range_elements, - WIN_swap_hint, - -// GLX_VERSION_1_0, - GLX_VERSION_1_3, - GLX_VERSION_1_4, - GLX_ARB_multisample, - GLX_ARB_fbconfig_float, - GLX_ARB_get_proc_address, - GLX_ARB_create_context, - GLX_ARB_create_context_profile, - GLX_EXT_visual_info, - GLX_EXT_visual_rating, - GLX_EXT_import_context, - GLX_EXT_fbconfig_packed_float, - GLX_EXT_framebuffer_sRGB, - GLX_EXT_texture_from_pixmap: Boolean; - -const - // GL_VERSION_1_1 - { AttribMask } - GL_DEPTH_BUFFER_BIT = $00000100; - GL_STENCIL_BUFFER_BIT = $00000400; - GL_COLOR_BUFFER_BIT = $00004000; - { Boolean } - GL_TRUE = 1; - GL_FALSE = 0; - { BeginMode } - GL_POINTS = $0000; - GL_LINES = $0001; - GL_LINE_LOOP = $0002; - GL_LINE_STRIP = $0003; - GL_TRIANGLES = $0004; - GL_TRIANGLE_STRIP = $0005; - GL_TRIANGLE_FAN = $0006; - { AlphaFunction } - GL_NEVER = $0200; - GL_LESS = $0201; - GL_EQUAL = $0202; - GL_LEQUAL = $0203; - GL_GREATER = $0204; - GL_NOTEQUAL = $0205; - GL_GEQUAL = $0206; - GL_ALWAYS = $0207; - { BlendingFactorDest } - GL_ZERO = 0; - GL_ONE = 1; - GL_SRC_COLOR = $0300; - GL_ONE_MINUS_SRC_COLOR = $0301; - GL_SRC_ALPHA = $0302; - GL_ONE_MINUS_SRC_ALPHA = $0303; - GL_DST_ALPHA = $0304; - GL_ONE_MINUS_DST_ALPHA = $0305; - { BlendingFactorSrc } - GL_DST_COLOR = $0306; - GL_ONE_MINUS_DST_COLOR = $0307; - GL_SRC_ALPHA_SATURATE = $0308; - { DrawBufferMode } - GL_NONE = 0; - GL_FRONT_LEFT = $0400; - GL_FRONT_RIGHT = $0401; - GL_BACK_LEFT = $0402; - GL_BACK_RIGHT = $0403; - GL_FRONT = $0404; - GL_BACK = $0405; - GL_LEFT = $0406; - GL_RIGHT = $0407; - GL_FRONT_AND_BACK = $0408; - { ErrorCode } - GL_NO_ERROR = 0; - GL_INVALID_ENUM = $0500; - GL_INVALID_VALUE = $0501; - GL_INVALID_OPERATION = $0502; - GL_OUT_OF_MEMORY = $0505; - { FrontFaceDirection } - GL_CW = $0900; - GL_CCW = $0901; - { GetPName } - GL_POINT_SIZE = $0B11; - GL_POINT_SIZE_RANGE = $0B12; - GL_POINT_SIZE_GRANULARITY = $0B13; - GL_LINE_SMOOTH = $0B20; - GL_LINE_WIDTH = $0B21; - GL_LINE_WIDTH_RANGE = $0B22; - GL_LINE_WIDTH_GRANULARITY = $0B23; - GL_POLYGON_SMOOTH = $0B41; - GL_CULL_FACE = $0B44; - GL_CULL_FACE_MODE = $0B45; - GL_FRONT_FACE = $0B46; - GL_DEPTH_RANGE = $0B70; - GL_DEPTH_TEST = $0B71; - GL_DEPTH_WRITEMASK = $0B72; - GL_DEPTH_CLEAR_VALUE = $0B73; - GL_DEPTH_FUNC = $0B74; - GL_STENCIL_TEST = $0B90; - GL_STENCIL_CLEAR_VALUE = $0B91; - GL_STENCIL_FUNC = $0B92; - GL_STENCIL_VALUE_MASK = $0B93; - GL_STENCIL_FAIL = $0B94; - GL_STENCIL_PASS_DEPTH_FAIL = $0B95; - GL_STENCIL_PASS_DEPTH_PASS = $0B96; - GL_STENCIL_REF = $0B97; - GL_STENCIL_WRITEMASK = $0B98; - GL_VIEWPORT = $0BA2; - GL_DITHER = $0BD0; - GL_BLEND_DST = $0BE0; - GL_BLEND_SRC = $0BE1; - GL_BLEND = $0BE2; - GL_LOGIC_OP_MODE = $0BF0; - GL_COLOR_LOGIC_OP = $0BF2; - GL_DRAW_BUFFER = $0C01; - GL_READ_BUFFER = $0C02; - GL_SCISSOR_BOX = $0C10; - GL_SCISSOR_TEST = $0C11; - GL_COLOR_CLEAR_VALUE = $0C22; - GL_COLOR_WRITEMASK = $0C23; - GL_DOUBLEBUFFER = $0C32; - GL_STEREO = $0C33; - GL_LINE_SMOOTH_HINT = $0C52; - GL_POLYGON_SMOOTH_HINT = $0C53; - GL_UNPACK_SWAP_BYTES = $0CF0; - GL_UNPACK_LSB_FIRST = $0CF1; - GL_UNPACK_ROW_LENGTH = $0CF2; - GL_UNPACK_SKIP_ROWS = $0CF3; - GL_UNPACK_SKIP_PIXELS = $0CF4; - GL_UNPACK_ALIGNMENT = $0CF5; - GL_PACK_SWAP_BYTES = $0D00; - GL_PACK_LSB_FIRST = $0D01; - GL_PACK_ROW_LENGTH = $0D02; - GL_PACK_SKIP_ROWS = $0D03; - GL_PACK_SKIP_PIXELS = $0D04; - GL_PACK_ALIGNMENT = $0D05; - GL_MAX_TEXTURE_SIZE = $0D33; - GL_MAX_VIEWPORT_DIMS = $0D3A; - GL_SUBPIXEL_BITS = $0D50; - GL_TEXTURE_1D = $0DE0; - GL_TEXTURE_2D = $0DE1; - GL_POLYGON_OFFSET_UNITS = $2A00; - GL_POLYGON_OFFSET_POINT = $2A01; - GL_POLYGON_OFFSET_LINE = $2A02; - GL_POLYGON_OFFSET_FILL = $8037; - GL_POLYGON_OFFSET_FACTOR = $8038; - GL_TEXTURE_BINDING_1D = $8068; - GL_TEXTURE_BINDING_2D = $8069; - { GetTextureParameter } - GL_TEXTURE_WIDTH = $1000; - GL_TEXTURE_HEIGHT = $1001; - GL_TEXTURE_INTERNAL_FORMAT = $1003; - GL_TEXTURE_BORDER_COLOR = $1004; - GL_TEXTURE_BORDER = $1005; - GL_TEXTURE_RED_SIZE = $805C; - GL_TEXTURE_GREEN_SIZE = $805D; - GL_TEXTURE_BLUE_SIZE = $805E; - GL_TEXTURE_ALPHA_SIZE = $805F; - { HintMode } - GL_DONT_CARE = $1100; - GL_FASTEST = $1101; - GL_NICEST = $1102; - { DataType } - GL_BYTE = $1400; - GL_UNSIGNED_BYTE = $1401; - GL_SHORT = $1402; - GL_UNSIGNED_SHORT = $1403; - GL_INT = $1404; - GL_UNSIGNED_INT = $1405; - GL_FLOAT = $1406; - GL_DOUBLE = $140A; - { LogicOp } - GL_CLEAR = $1500; - GL_AND = $1501; - GL_AND_REVERSE = $1502; - GL_COPY = $1503; - GL_AND_INVERTED = $1504; - GL_NOOP = $1505; - GL_XOR = $1506; - GL_OR = $1507; - GL_NOR = $1508; - GL_EQUIV = $1509; - GL_INVERT = $150A; - GL_OR_REVERSE = $150B; - GL_COPY_INVERTED = $150C; - GL_OR_INVERTED = $150D; - GL_NAND = $150E; - GL_SET = $150F; - { MatrixMode (for gl3.h, FBO attachment type) } - GL_TEXTURE = $1702; - { PixelCopyType } - GL_COLOR = $1800; - GL_DEPTH = $1801; - GL_STENCIL = $1802; - { PixelFormat } - GL_STENCIL_INDEX = $1901; - GL_DEPTH_COMPONENT = $1902; - GL_RED = $1903; - GL_GREEN = $1904; - GL_BLUE = $1905; - GL_ALPHA = $1906; - GL_RGB = $1907; - GL_RGBA = $1908; - { PolygonMode } - GL_POINT = $1B00; - GL_LINE = $1B01; - GL_FILL = $1B02; - { StencilOp } - GL_KEEP = $1E00; - GL_REPLACE = $1E01; - GL_INCR = $1E02; - GL_DECR = $1E03; - { StringName } - GL_VENDOR = $1F00; - GL_RENDERER = $1F01; - GL_VERSION = $1F02; - GL_EXTENSIONS = $1F03; - { TextureMagFilter } - GL_NEAREST = $2600; - GL_LINEAR = $2601; - { TextureMinFilter } - GL_NEAREST_MIPMAP_NEAREST = $2700; - GL_LINEAR_MIPMAP_NEAREST = $2701; - GL_NEAREST_MIPMAP_LINEAR = $2702; - GL_LINEAR_MIPMAP_LINEAR = $2703; - { TextureParameterName } - GL_TEXTURE_MAG_FILTER = $2800; - GL_TEXTURE_MIN_FILTER = $2801; - GL_TEXTURE_WRAP_S = $2802; - GL_TEXTURE_WRAP_T = $2803; - { TextureTarget } - GL_PROXY_TEXTURE_1D = $8063; - GL_PROXY_TEXTURE_2D = $8064; - { TextureWrapMode } - GL_REPEAT = $2901; - { PixelInternalFormat } - GL_R3_G3_B2 = $2A10; - GL_RGB4 = $804F; - GL_RGB5 = $8050; - GL_RGB8 = $8051; - GL_RGB10 = $8052; - GL_RGB12 = $8053; - GL_RGB16 = $8054; - GL_RGBA2 = $8055; - GL_RGBA4 = $8056; - GL_RGB5_A1 = $8057; - GL_RGBA8 = $8058; - GL_RGB10_A2 = $8059; - GL_RGBA12 = $805A; - GL_RGBA16 = $805B; -{$ifdef DGL_DEPRECATED} - GL_ACCUM = $0100; - GL_LOAD = $0101; - GL_RETURN = $0102; - GL_MULT = $0103; - GL_ADD = $0104; - GL_CURRENT_BIT = $00000001; - GL_POINT_BIT = $00000002; - GL_LINE_BIT = $00000004; - GL_POLYGON_BIT = $00000008; - GL_POLYGON_STIPPLE_BIT = $00000010; - GL_PIXEL_MODE_BIT = $00000020; - GL_LIGHTING_BIT = $00000040; - GL_FOG_BIT = $00000080; - GL_ACCUM_BUFFER_BIT = $00000200; - GL_VIEWPORT_BIT = $00000800; - GL_TRANSFORM_BIT = $00001000; - GL_ENABLE_BIT = $00002000; - GL_HINT_BIT = $00008000; - GL_EVAL_BIT = $00010000; - GL_LIST_BIT = $00020000; - GL_TEXTURE_BIT = $00040000; - GL_SCISSOR_BIT = $00080000; - GL_ALL_ATTRIB_BITS = $000FFFFF; - GL_QUADS = $0007; - GL_QUAD_STRIP = $0008; - GL_POLYGON = $0009; - GL_CLIP_PLANE0 = $3000; - GL_CLIP_PLANE1 = $3001; - GL_CLIP_PLANE2 = $3002; - GL_CLIP_PLANE3 = $3003; - GL_CLIP_PLANE4 = $3004; - GL_CLIP_PLANE5 = $3005; - GL_2_BYTES = $1407; - GL_3_BYTES = $1408; - GL_4_BYTES = $1409; - GL_AUX0 = $0409; - GL_AUX1 = $040A; - GL_AUX2 = $040B; - GL_AUX3 = $040C; - GL_STACK_OVERFLOW = $0503; - GL_STACK_UNDERFLOW = $0504; - GL_2D = $0600; - GL_3D = $0601; - GL_3D_COLOR = $0602; - GL_3D_COLOR_TEXTURE = $0603; - GL_4D_COLOR_TEXTURE = $0604; - GL_PASS_THROUGH_TOKEN = $0700; - GL_POINT_TOKEN = $0701; - GL_LINE_TOKEN = $0702; - GL_POLYGON_TOKEN = $0703; - GL_BITMAP_TOKEN = $0704; - GL_DRAW_PIXEL_TOKEN = $0705; - GL_COPY_PIXEL_TOKEN = $0706; - GL_LINE_RESET_TOKEN = $0707; - GL_EXP = $0800; - GL_EXP2 = $0801; - GL_COEFF = $0A00; - GL_ORDER = $0A01; - GL_DOMAIN = $0A02; - GL_CURRENT_COLOR = $0B00; - GL_CURRENT_INDEX = $0B01; - GL_CURRENT_NORMAL = $0B02; - GL_CURRENT_TEXTURE_COORDS = $0B03; - GL_CURRENT_RASTER_COLOR = $0B04; - GL_CURRENT_RASTER_INDEX = $0B05; - GL_CURRENT_RASTER_TEXTURE_COORDS = $0B06; - GL_CURRENT_RASTER_POSITION = $0B07; - GL_CURRENT_RASTER_POSITION_VALID = $0B08; - GL_CURRENT_RASTER_DISTANCE = $0B09; - GL_POINT_SMOOTH = $0B10; - GL_LINE_STIPPLE = $0B24; - GL_LINE_STIPPLE_PATTERN = $0B25; - GL_LINE_STIPPLE_REPEAT = $0B26; - GL_LIST_MODE = $0B30; - GL_MAX_LIST_NESTING = $0B31; - GL_LIST_BASE = $0B32; - GL_LIST_INDEX = $0B33; - GL_POLYGON_MODE = $0B40; - GL_POLYGON_STIPPLE = $0B42; - GL_EDGE_FLAG = $0B43; - GL_LIGHTING = $0B50; - GL_LIGHT_MODEL_LOCAL_VIEWER = $0B51; - GL_LIGHT_MODEL_TWO_SIDE = $0B52; - GL_LIGHT_MODEL_AMBIENT = $0B53; - GL_SHADE_MODEL = $0B54; - GL_COLOR_MATERIAL_FACE = $0B55; - GL_COLOR_MATERIAL_PARAMETER = $0B56; - GL_COLOR_MATERIAL = $0B57; - GL_FOG = $0B60; - GL_FOG_INDEX = $0B61; - GL_FOG_DENSITY = $0B62; - GL_FOG_START = $0B63; - GL_FOG_END = $0B64; - GL_FOG_MODE = $0B65; - GL_FOG_COLOR = $0B66; - GL_ACCUM_CLEAR_VALUE = $0B80; - GL_MATRIX_MODE = $0BA0; - GL_NORMALIZE = $0BA1; - GL_MODELVIEW_STACK_DEPTH = $0BA3; - GL_PROJECTION_STACK_DEPTH = $0BA4; - GL_TEXTURE_STACK_DEPTH = $0BA5; - GL_MODELVIEW_MATRIX = $0BA6; - GL_PROJECTION_MATRIX = $0BA7; - GL_TEXTURE_MATRIX = $0BA8; - GL_ATTRIB_STACK_DEPTH = $0BB0; - GL_CLIENT_ATTRIB_STACK_DEPTH = $0BB1; - GL_ALPHA_TEST = $0BC0; - GL_ALPHA_TEST_FUNC = $0BC1; - GL_ALPHA_TEST_REF = $0BC2; - GL_INDEX_LOGIC_OP = $0BF1; - GL_AUX_BUFFERS = $0C00; - GL_INDEX_CLEAR_VALUE = $0C20; - GL_INDEX_WRITEMASK = $0C21; - GL_INDEX_MODE = $0C30; - GL_RGBA_MODE = $0C31; - GL_RENDER_MODE = $0C40; - GL_PERSPECTIVE_CORRECTION_HINT = $0C50; - GL_POINT_SMOOTH_HINT = $0C51; - GL_FOG_HINT = $0C54; - GL_TEXTURE_GEN_S = $0C60; - GL_TEXTURE_GEN_T = $0C61; - GL_TEXTURE_GEN_R = $0C62; - GL_TEXTURE_GEN_Q = $0C63; - GL_PIXEL_MAP_I_TO_I = $0C70; - GL_PIXEL_MAP_S_TO_S = $0C71; - GL_PIXEL_MAP_I_TO_R = $0C72; - GL_PIXEL_MAP_I_TO_G = $0C73; - GL_PIXEL_MAP_I_TO_B = $0C74; - GL_PIXEL_MAP_I_TO_A = $0C75; - GL_PIXEL_MAP_R_TO_R = $0C76; - GL_PIXEL_MAP_G_TO_G = $0C77; - GL_PIXEL_MAP_B_TO_B = $0C78; - GL_PIXEL_MAP_A_TO_A = $0C79; - GL_PIXEL_MAP_I_TO_I_SIZE = $0CB0; - GL_PIXEL_MAP_S_TO_S_SIZE = $0CB1; - GL_PIXEL_MAP_I_TO_R_SIZE = $0CB2; - GL_PIXEL_MAP_I_TO_G_SIZE = $0CB3; - GL_PIXEL_MAP_I_TO_B_SIZE = $0CB4; - GL_PIXEL_MAP_I_TO_A_SIZE = $0CB5; - GL_PIXEL_MAP_R_TO_R_SIZE = $0CB6; - GL_PIXEL_MAP_G_TO_G_SIZE = $0CB7; - GL_PIXEL_MAP_B_TO_B_SIZE = $0CB8; - GL_PIXEL_MAP_A_TO_A_SIZE = $0CB9; - GL_MAP_COLOR = $0D10; - GL_MAP_STENCIL = $0D11; - GL_INDEX_SHIFT = $0D12; - GL_INDEX_OFFSET = $0D13; - GL_RED_SCALE = $0D14; - GL_RED_BIAS = $0D15; - GL_ZOOM_X = $0D16; - GL_ZOOM_Y = $0D17; - GL_GREEN_SCALE = $0D18; - GL_GREEN_BIAS = $0D19; - GL_BLUE_SCALE = $0D1A; - GL_BLUE_BIAS = $0D1B; - GL_ALPHA_SCALE = $0D1C; - GL_ALPHA_BIAS = $0D1D; - GL_DEPTH_SCALE = $0D1E; - GL_DEPTH_BIAS = $0D1F; - GL_MAX_EVAL_ORDER = $0D30; - GL_MAX_LIGHTS = $0D31; - GL_MAX_CLIP_PLANES = $0D32; - GL_MAX_PIXEL_MAP_TABLE = $0D34; - GL_MAX_ATTRIB_STACK_DEPTH = $0D35; - GL_MAX_MODELVIEW_STACK_DEPTH = $0D36; - GL_MAX_NAME_STACK_DEPTH = $0D37; - GL_MAX_PROJECTION_STACK_DEPTH = $0D38; - GL_MAX_TEXTURE_STACK_DEPTH = $0D39; - GL_MAX_CLIENT_ATTRIB_STACK_DEPTH = $0D3B; - GL_INDEX_BITS = $0D51; - GL_RED_BITS = $0D52; - GL_GREEN_BITS = $0D53; - GL_BLUE_BITS = $0D54; - GL_ALPHA_BITS = $0D55; - GL_DEPTH_BITS = $0D56; - GL_STENCIL_BITS = $0D57; - GL_ACCUM_RED_BITS = $0D58; - GL_ACCUM_GREEN_BITS = $0D59; - GL_ACCUM_BLUE_BITS = $0D5A; - GL_ACCUM_ALPHA_BITS = $0D5B; - GL_NAME_STACK_DEPTH = $0D70; - GL_AUTO_NORMAL = $0D80; - GL_MAP1_COLOR_4 = $0D90; - GL_MAP1_INDEX = $0D91; - GL_MAP1_NORMAL = $0D92; - GL_MAP1_TEXTURE_COORD_1 = $0D93; - GL_MAP1_TEXTURE_COORD_2 = $0D94; - GL_MAP1_TEXTURE_COORD_3 = $0D95; - GL_MAP1_TEXTURE_COORD_4 = $0D96; - GL_MAP1_VERTEX_3 = $0D97; - GL_MAP1_VERTEX_4 = $0D98; - GL_MAP2_COLOR_4 = $0DB0; - GL_MAP2_INDEX = $0DB1; - GL_MAP2_NORMAL = $0DB2; - GL_MAP2_TEXTURE_COORD_1 = $0DB3; - GL_MAP2_TEXTURE_COORD_2 = $0DB4; - GL_MAP2_TEXTURE_COORD_3 = $0DB5; - GL_MAP2_TEXTURE_COORD_4 = $0DB6; - GL_MAP2_VERTEX_3 = $0DB7; - GL_MAP2_VERTEX_4 = $0DB8; - GL_MAP1_GRID_DOMAIN = $0DD0; - GL_MAP1_GRID_SEGMENTS = $0DD1; - GL_MAP2_GRID_DOMAIN = $0DD2; - GL_MAP2_GRID_SEGMENTS = $0DD3; - GL_FEEDBACK_BUFFER_POINTER = $0DF0; - GL_FEEDBACK_BUFFER_SIZE = $0DF1; - GL_FEEDBACK_BUFFER_TYPE = $0DF2; - GL_SELECTION_BUFFER_POINTER = $0DF3; - GL_SELECTION_BUFFER_SIZE = $0DF4; - GL_LIGHT0 = $4000; - GL_LIGHT1 = $4001; - GL_LIGHT2 = $4002; - GL_LIGHT3 = $4003; - GL_LIGHT4 = $4004; - GL_LIGHT5 = $4005; - GL_LIGHT6 = $4006; - GL_LIGHT7 = $4007; - GL_AMBIENT = $1200; - GL_DIFFUSE = $1201; - GL_SPECULAR = $1202; - GL_POSITION = $1203; - GL_SPOT_DIRECTION = $1204; - GL_SPOT_EXPONENT = $1205; - GL_SPOT_CUTOFF = $1206; - GL_CONSTANT_ATTENUATION = $1207; - GL_LINEAR_ATTENUATION = $1208; - GL_QUADRATIC_ATTENUATION = $1209; - GL_COMPILE = $1300; - GL_COMPILE_AND_EXECUTE = $1301; - GL_EMISSION = $1600; - GL_SHININESS = $1601; - GL_AMBIENT_AND_DIFFUSE = $1602; - GL_COLOR_INDEXES = $1603; - GL_MODELVIEW = $1700; - GL_PROJECTION = $1701; - GL_COLOR_INDEX = $1900; - GL_LUMINANCE = $1909; - GL_LUMINANCE_ALPHA = $190A; - GL_BITMAP = $1A00; - GL_RENDER = $1C00; - GL_FEEDBACK = $1C01; - GL_SELECT = $1C02; - GL_FLAT = $1D00; - GL_SMOOTH = $1D01; - GL_S = $2000; - GL_T = $2001; - GL_R = $2002; - GL_Q = $2003; - GL_MODULATE = $2100; - GL_DECAL = $2101; - GL_TEXTURE_ENV_MODE = $2200; - GL_TEXTURE_ENV_COLOR = $2201; - GL_TEXTURE_ENV = $2300; - GL_EYE_LINEAR = $2400; - GL_OBJECT_LINEAR = $2401; - GL_SPHERE_MAP = $2402; - GL_TEXTURE_GEN_MODE = $2500; - GL_OBJECT_PLANE = $2501; - GL_EYE_PLANE = $2502; - GL_CLAMP = $2900; - GL_CLIENT_PIXEL_STORE_BIT = $00000001; - GL_CLIENT_VERTEX_ARRAY_BIT = $00000002; - GL_CLIENT_ALL_ATTRIB_BITS = $FFFFFFFF; - GL_ALPHA4 = $803B; - GL_ALPHA8 = $803C; - GL_ALPHA12 = $803D; - GL_ALPHA16 = $803E; - GL_LUMINANCE4 = $803F; - GL_LUMINANCE8 = $8040; - GL_LUMINANCE12 = $8041; - GL_LUMINANCE16 = $8042; - GL_LUMINANCE4_ALPHA4 = $8043; - GL_LUMINANCE6_ALPHA2 = $8044; - GL_LUMINANCE8_ALPHA8 = $8045; - GL_LUMINANCE12_ALPHA4 = $8046; - GL_LUMINANCE12_ALPHA12 = $8047; - GL_LUMINANCE16_ALPHA16 = $8048; - GL_INTENSITY = $8049; - GL_INTENSITY4 = $804A; - GL_INTENSITY8 = $804B; - GL_INTENSITY12 = $804C; - GL_INTENSITY16 = $804D; - GL_TEXTURE_LUMINANCE_SIZE = $8060; - GL_TEXTURE_INTENSITY_SIZE = $8061; - GL_TEXTURE_PRIORITY = $8066; - GL_TEXTURE_RESIDENT = $8067; - GL_VERTEX_ARRAY = $8074; - GL_NORMAL_ARRAY = $8075; - GL_COLOR_ARRAY = $8076; - GL_INDEX_ARRAY = $8077; - GL_TEXTURE_COORD_ARRAY = $8078; - GL_EDGE_FLAG_ARRAY = $8079; - GL_VERTEX_ARRAY_SIZE = $807A; - GL_VERTEX_ARRAY_TYPE = $807B; - GL_VERTEX_ARRAY_STRIDE = $807C; - GL_NORMAL_ARRAY_TYPE = $807E; - GL_NORMAL_ARRAY_STRIDE = $807F; - GL_COLOR_ARRAY_SIZE = $8081; - GL_COLOR_ARRAY_TYPE = $8082; - GL_COLOR_ARRAY_STRIDE = $8083; - GL_INDEX_ARRAY_TYPE = $8085; - GL_INDEX_ARRAY_STRIDE = $8086; - GL_TEXTURE_COORD_ARRAY_SIZE = $8088; - GL_TEXTURE_COORD_ARRAY_TYPE = $8089; - GL_TEXTURE_COORD_ARRAY_STRIDE = $808A; - GL_EDGE_FLAG_ARRAY_STRIDE = $808C; - GL_VERTEX_ARRAY_POINTER = $808E; - GL_NORMAL_ARRAY_POINTER = $808F; - GL_COLOR_ARRAY_POINTER = $8090; - GL_INDEX_ARRAY_POINTER = $8091; - GL_TEXTURE_COORD_ARRAY_POINTER = $8092; - GL_EDGE_FLAG_ARRAY_POINTER = $8093; - GL_V2F = $2A20; - GL_V3F = $2A21; - GL_C4UB_V2F = $2A22; - GL_C4UB_V3F = $2A23; - GL_C3F_V3F = $2A24; - GL_N3F_V3F = $2A25; - GL_C4F_N3F_V3F = $2A26; - GL_T2F_V3F = $2A27; - GL_T4F_V4F = $2A28; - GL_T2F_C4UB_V3F = $2A29; - GL_T2F_C3F_V3F = $2A2A; - GL_T2F_N3F_V3F = $2A2B; - GL_T2F_C4F_N3F_V3F = $2A2C; - GL_T4F_C4F_N3F_V4F = $2A2D; - GL_COLOR_TABLE_FORMAT_EXT = $80D8; - GL_COLOR_TABLE_WIDTH_EXT = $80D9; - GL_COLOR_TABLE_RED_SIZE_EXT = $80DA; - GL_COLOR_TABLE_GREEN_SIZE_EXT = $80DB; - GL_COLOR_TABLE_BLUE_SIZE_EXT = $80DC; - GL_COLOR_TABLE_ALPHA_SIZE_EXT = $80DD; - GL_COLOR_TABLE_LUMINANCE_SIZE_EXT = $80DE; - GL_COLOR_TABLE_INTENSITY_SIZE_EXT = $80DF; - GL_LOGIC_OP = GL_INDEX_LOGIC_OP; - GL_TEXTURE_COMPONENTS = GL_TEXTURE_INTERNAL_FORMAT; -{$endif} - - // GL_VERSION_1_2 - GL_UNSIGNED_BYTE_3_3_2 = $8032; - GL_UNSIGNED_SHORT_4_4_4_4 = $8033; - GL_UNSIGNED_SHORT_5_5_5_1 = $8034; - GL_UNSIGNED_INT_8_8_8_8 = $8035; - GL_UNSIGNED_INT_10_10_10_2 = $8036; - GL_TEXTURE_BINDING_3D = $806A; - GL_PACK_SKIP_IMAGES = $806B; - GL_PACK_IMAGE_HEIGHT = $806C; - GL_UNPACK_SKIP_IMAGES = $806D; - GL_UNPACK_IMAGE_HEIGHT = $806E; - GL_TEXTURE_3D = $806F; - GL_PROXY_TEXTURE_3D = $8070; - GL_TEXTURE_DEPTH = $8071; - GL_TEXTURE_WRAP_R = $8072; - GL_MAX_3D_TEXTURE_SIZE = $8073; - GL_UNSIGNED_BYTE_2_3_3_REV = $8362; - GL_UNSIGNED_SHORT_5_6_5 = $8363; - GL_UNSIGNED_SHORT_5_6_5_REV = $8364; - GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365; - GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366; - GL_UNSIGNED_INT_8_8_8_8_REV = $8367; - GL_UNSIGNED_INT_2_10_10_10_REV = $8368; - GL_BGR = $80E0; - GL_BGRA = $80E1; - GL_MAX_ELEMENTS_VERTICES = $80E8; - GL_MAX_ELEMENTS_INDICES = $80E9; - GL_CLAMP_TO_EDGE = $812F; - GL_TEXTURE_MIN_LOD = $813A; - GL_TEXTURE_MAX_LOD = $813B; - GL_TEXTURE_BASE_LEVEL = $813C; - GL_TEXTURE_MAX_LEVEL = $813D; - GL_SMOOTH_POINT_SIZE_RANGE = $0B12; - GL_SMOOTH_POINT_SIZE_GRANULARITY = $0B13; - GL_SMOOTH_LINE_WIDTH_RANGE = $0B22; - GL_SMOOTH_LINE_WIDTH_GRANULARITY = $0B23; - GL_ALIASED_LINE_WIDTH_RANGE = $846E; -{$ifdef DGL_DEPRECATED} - GL_RESCALE_NORMAL = $803A; - GL_LIGHT_MODEL_COLOR_CONTROL = $81F8; - GL_SINGLE_COLOR = $81F9; - GL_SEPARATE_SPECULAR_COLOR = $81FA; - GL_ALIASED_POINT_SIZE_RANGE = $846D; -{$endif} - - // GL_VERSION_1_3 - GL_TEXTURE0 = $84C0; - GL_TEXTURE1 = $84C1; - GL_TEXTURE2 = $84C2; - GL_TEXTURE3 = $84C3; - GL_TEXTURE4 = $84C4; - GL_TEXTURE5 = $84C5; - GL_TEXTURE6 = $84C6; - GL_TEXTURE7 = $84C7; - GL_TEXTURE8 = $84C8; - GL_TEXTURE9 = $84C9; - GL_TEXTURE10 = $84CA; - GL_TEXTURE11 = $84CB; - GL_TEXTURE12 = $84CC; - GL_TEXTURE13 = $84CD; - GL_TEXTURE14 = $84CE; - GL_TEXTURE15 = $84CF; - GL_TEXTURE16 = $84D0; - GL_TEXTURE17 = $84D1; - GL_TEXTURE18 = $84D2; - GL_TEXTURE19 = $84D3; - GL_TEXTURE20 = $84D4; - GL_TEXTURE21 = $84D5; - GL_TEXTURE22 = $84D6; - GL_TEXTURE23 = $84D7; - GL_TEXTURE24 = $84D8; - GL_TEXTURE25 = $84D9; - GL_TEXTURE26 = $84DA; - GL_TEXTURE27 = $84DB; - GL_TEXTURE28 = $84DC; - GL_TEXTURE29 = $84DD; - GL_TEXTURE30 = $84DE; - GL_TEXTURE31 = $84DF; - GL_ACTIVE_TEXTURE = $84E0; - GL_MULTISAMPLE = $809D; - GL_SAMPLE_ALPHA_TO_COVERAGE = $809E; - GL_SAMPLE_ALPHA_TO_ONE = $809F; - GL_SAMPLE_COVERAGE = $80A0; - GL_SAMPLE_BUFFERS = $80A8; - GL_SAMPLES = $80A9; - GL_SAMPLE_COVERAGE_VALUE = $80AA; - GL_SAMPLE_COVERAGE_INVERT = $80AB; - GL_TEXTURE_CUBE_MAP = $8513; - GL_TEXTURE_BINDING_CUBE_MAP = $8514; - GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515; - GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516; - GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518; - GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A; - GL_PROXY_TEXTURE_CUBE_MAP = $851B; - GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C; - GL_COMPRESSED_RGB = $84ED; - GL_COMPRESSED_RGBA = $84EE; - GL_TEXTURE_COMPRESSION_HINT = $84EF; - GL_TEXTURE_COMPRESSED_IMAGE_SIZE = $86A0; - GL_TEXTURE_COMPRESSED = $86A1; - GL_NUM_COMPRESSED_TEXTURE_FORMATS = $86A2; - GL_COMPRESSED_TEXTURE_FORMATS = $86A3; - GL_CLAMP_TO_BORDER = $812D; -{$ifdef DGL_DEPRECATED} - GL_CLIENT_ACTIVE_TEXTURE = $84E1; - GL_MAX_TEXTURE_UNITS = $84E2; - GL_TRANSPOSE_MODELVIEW_MATRIX = $84E3; - GL_TRANSPOSE_PROJECTION_MATRIX = $84E4; - GL_TRANSPOSE_TEXTURE_MATRIX = $84E5; - GL_TRANSPOSE_COLOR_MATRIX = $84E6; - GL_MULTISAMPLE_BIT = $20000000; - GL_NORMAL_MAP = $8511; - GL_REFLECTION_MAP = $8512; - GL_COMPRESSED_ALPHA = $84E9; - GL_COMPRESSED_LUMINANCE = $84EA; - GL_COMPRESSED_LUMINANCE_ALPHA = $84EB; - GL_COMPRESSED_INTENSITY = $84EC; - GL_COMBINE = $8570; - GL_COMBINE_RGB = $8571; - GL_COMBINE_ALPHA = $8572; - GL_SOURCE0_RGB = $8580; - GL_SOURCE1_RGB = $8581; - GL_SOURCE2_RGB = $8582; - GL_SOURCE0_ALPHA = $8588; - GL_SOURCE1_ALPHA = $8589; - GL_SOURCE2_ALPHA = $858A; - GL_OPERAND0_RGB = $8590; - GL_OPERAND1_RGB = $8591; - GL_OPERAND2_RGB = $8592; - GL_OPERAND0_ALPHA = $8598; - GL_OPERAND1_ALPHA = $8599; - GL_OPERAND2_ALPHA = $859A; - GL_RGB_SCALE = $8573; - GL_ADD_SIGNED = $8574; - GL_INTERPOLATE = $8575; - GL_SUBTRACT = $84E7; - GL_CONSTANT = $8576; - GL_PRIMARY_COLOR = $8577; - GL_PREVIOUS = $8578; - GL_DOT3_RGB = $86AE; - GL_DOT3_RGBA = $86AF; -{$endif} - - // GL_VERSION_1_4 - GL_BLEND_DST_RGB = $80C8; - GL_BLEND_SRC_RGB = $80C9; - GL_BLEND_DST_ALPHA = $80CA; - GL_BLEND_SRC_ALPHA = $80CB; - GL_POINT_FADE_THRESHOLD_SIZE = $8128; - GL_DEPTH_COMPONENT16 = $81A5; - GL_DEPTH_COMPONENT24 = $81A6; - GL_DEPTH_COMPONENT32 = $81A7; - GL_MIRRORED_REPEAT = $8370; - GL_MAX_TEXTURE_LOD_BIAS = $84FD; - GL_TEXTURE_LOD_BIAS = $8501; - GL_INCR_WRAP = $8507; - GL_DECR_WRAP = $8508; - GL_TEXTURE_DEPTH_SIZE = $884A; - GL_TEXTURE_COMPARE_MODE = $884C; - GL_TEXTURE_COMPARE_FUNC = $884D; -{$ifdef DGL_DEPRECATED} - GL_POINT_SIZE_MIN = $8126; - GL_POINT_SIZE_MAX = $8127; - GL_POINT_DISTANCE_ATTENUATION = $8129; - GL_GENERATE_MIPMAP = $8191; - GL_GENERATE_MIPMAP_HINT = $8192; - GL_FOG_COORDINATE_SOURCE = $8450; - GL_FOG_COORDINATE = $8451; - GL_FRAGMENT_DEPTH = $8452; - GL_CURRENT_FOG_COORDINATE = $8453; - GL_FOG_COORDINATE_ARRAY_TYPE = $8454; - GL_FOG_COORDINATE_ARRAY_STRIDE = $8455; - GL_FOG_COORDINATE_ARRAY_POINTER = $8456; - GL_FOG_COORDINATE_ARRAY = $8457; - GL_COLOR_SUM = $8458; - GL_CURRENT_SECONDARY_COLOR = $8459; - GL_SECONDARY_COLOR_ARRAY_SIZE = $845A; - GL_SECONDARY_COLOR_ARRAY_TYPE = $845B; - GL_SECONDARY_COLOR_ARRAY_STRIDE = $845C; - GL_SECONDARY_COLOR_ARRAY_POINTER = $845D; - GL_SECONDARY_COLOR_ARRAY = $845E; - GL_TEXTURE_FILTER_CONTROL = $8500; - GL_DEPTH_TEXTURE_MODE = $884B; - GL_COMPARE_R_TO_TEXTURE = $884E; -{$endif} - - // GL_VERSION_1_5 - GL_BUFFER_SIZE = $8764; - GL_BUFFER_USAGE = $8765; - GL_QUERY_COUNTER_BITS = $8864; - GL_CURRENT_QUERY = $8865; - GL_QUERY_RESULT = $8866; - GL_QUERY_RESULT_AVAILABLE = $8867; - GL_ARRAY_BUFFER = $8892; - GL_ELEMENT_ARRAY_BUFFER = $8893; - GL_ARRAY_BUFFER_BINDING = $8894; - GL_ELEMENT_ARRAY_BUFFER_BINDING = $8895; - GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = $889F; - GL_READ_ONLY = $88B8; - GL_WRITE_ONLY = $88B9; - GL_READ_WRITE = $88BA; - GL_BUFFER_ACCESS = $88BB; - GL_BUFFER_MAPPED = $88BC; - GL_BUFFER_MAP_POINTER = $88BD; - GL_STREAM_DRAW = $88E0; - GL_STREAM_READ = $88E1; - GL_STREAM_COPY = $88E2; - GL_STATIC_DRAW = $88E4; - GL_STATIC_READ = $88E5; - GL_STATIC_COPY = $88E6; - GL_DYNAMIC_DRAW = $88E8; - GL_DYNAMIC_READ = $88E9; - GL_DYNAMIC_COPY = $88EA; - GL_SAMPLES_PASSED = $8914; -{$ifdef DGL_DEPRECATED} - GL_VERTEX_ARRAY_BUFFER_BINDING = $8896; - GL_NORMAL_ARRAY_BUFFER_BINDING = $8897; - GL_COLOR_ARRAY_BUFFER_BINDING = $8898; - GL_INDEX_ARRAY_BUFFER_BINDING = $8899; - GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING = $889A; - GL_EDGE_FLAG_ARRAY_BUFFER_BINDING = $889B; - GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING = $889C; - GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING = $889D; - GL_WEIGHT_ARRAY_BUFFER_BINDING = $889E; - GL_FOG_COORD_SRC = $8450; - GL_FOG_COORD = $8451; - GL_CURRENT_FOG_COORD = $8453; - GL_FOG_COORD_ARRAY_TYPE = $8454; - GL_FOG_COORD_ARRAY_STRIDE = $8455; - GL_FOG_COORD_ARRAY_POINTER = $8456; - GL_FOG_COORD_ARRAY = $8457; - GL_FOG_COORD_ARRAY_BUFFER_BINDING = $889D; - GL_SRC0_RGB = $8580; - GL_SRC1_RGB = $8581; - GL_SRC2_RGB = $8582; - GL_SRC0_ALPHA = $8588; - GL_SRC1_ALPHA = $8589; - GL_SRC2_ALPHA = $858A; -{$endif} - - // GL_VERSION_2_0 - GL_BLEND_EQUATION_RGB = $8009; - GL_VERTEX_ATTRIB_ARRAY_ENABLED = $8622; - GL_VERTEX_ATTRIB_ARRAY_SIZE = $8623; - GL_VERTEX_ATTRIB_ARRAY_STRIDE = $8624; - GL_VERTEX_ATTRIB_ARRAY_TYPE = $8625; - GL_CURRENT_VERTEX_ATTRIB = $8626; - GL_VERTEX_PROGRAM_POINT_SIZE = $8642; - GL_VERTEX_ATTRIB_ARRAY_POINTER = $8645; - GL_STENCIL_BACK_FUNC = $8800; - GL_STENCIL_BACK_FAIL = $8801; - GL_STENCIL_BACK_PASS_DEPTH_FAIL = $8802; - GL_STENCIL_BACK_PASS_DEPTH_PASS = $8803; - GL_MAX_DRAW_BUFFERS = $8824; - GL_DRAW_BUFFER0 = $8825; - GL_DRAW_BUFFER1 = $8826; - GL_DRAW_BUFFER2 = $8827; - GL_DRAW_BUFFER3 = $8828; - GL_DRAW_BUFFER4 = $8829; - GL_DRAW_BUFFER5 = $882A; - GL_DRAW_BUFFER6 = $882B; - GL_DRAW_BUFFER7 = $882C; - GL_DRAW_BUFFER8 = $882D; - GL_DRAW_BUFFER9 = $882E; - GL_DRAW_BUFFER10 = $882F; - GL_DRAW_BUFFER11 = $8830; - GL_DRAW_BUFFER12 = $8831; - GL_DRAW_BUFFER13 = $8832; - GL_DRAW_BUFFER14 = $8833; - GL_DRAW_BUFFER15 = $8834; - GL_BLEND_EQUATION_ALPHA = $883D; - GL_MAX_VERTEX_ATTRIBS = $8869; - GL_VERTEX_ATTRIB_ARRAY_NORMALIZED = $886A; - GL_MAX_TEXTURE_IMAGE_UNITS = $8872; - GL_FRAGMENT_SHADER = $8B30; - GL_VERTEX_SHADER = $8B31; - GL_MAX_FRAGMENT_UNIFORM_COMPONENTS = $8B49; - GL_MAX_VERTEX_UNIFORM_COMPONENTS = $8B4A; - GL_MAX_VARYING_FLOATS = $8B4B; - GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = $8B4C; - GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = $8B4D; - GL_SHADER_TYPE = $8B4F; - GL_FLOAT_VEC2 = $8B50; - GL_FLOAT_VEC3 = $8B51; - GL_FLOAT_VEC4 = $8B52; - GL_INT_VEC2 = $8B53; - GL_INT_VEC3 = $8B54; - GL_INT_VEC4 = $8B55; - GL_BOOL = $8B56; - GL_BOOL_VEC2 = $8B57; - GL_BOOL_VEC3 = $8B58; - GL_BOOL_VEC4 = $8B59; - GL_FLOAT_MAT2 = $8B5A; - GL_FLOAT_MAT3 = $8B5B; - GL_FLOAT_MAT4 = $8B5C; - GL_SAMPLER_1D = $8B5D; - GL_SAMPLER_2D = $8B5E; - GL_SAMPLER_3D = $8B5F; - GL_SAMPLER_CUBE = $8B60; - GL_SAMPLER_1D_SHADOW = $8B61; - GL_SAMPLER_2D_SHADOW = $8B62; - GL_DELETE_STATUS = $8B80; - GL_COMPILE_STATUS = $8B81; - GL_LINK_STATUS = $8B82; - GL_VALIDATE_STATUS = $8B83; - GL_INFO_LOG_LENGTH = $8B84; - GL_ATTACHED_SHADERS = $8B85; - GL_ACTIVE_UNIFORMS = $8B86; - GL_ACTIVE_UNIFORM_MAX_LENGTH = $8B87; - GL_SHADER_SOURCE_LENGTH = $8B88; - GL_ACTIVE_ATTRIBUTES = $8B89; - GL_ACTIVE_ATTRIBUTE_MAX_LENGTH = $8B8A; - GL_FRAGMENT_SHADER_DERIVATIVE_HINT = $8B8B; - GL_SHADING_LANGUAGE_VERSION = $8B8C; - GL_CURRENT_PROGRAM = $8B8D; - GL_POINT_SPRITE_COORD_ORIGIN = $8CA0; - GL_LOWER_LEFT = $8CA1; - GL_UPPER_LEFT = $8CA2; - GL_STENCIL_BACK_REF = $8CA3; - GL_STENCIL_BACK_VALUE_MASK = $8CA4; - GL_STENCIL_BACK_WRITEMASK = $8CA5; -{$ifdef DGL_DEPRECATED} - GL_VERTEX_PROGRAM_TWO_SIDE = $8643; - GL_POINT_SPRITE = $8861; - GL_COORD_REPLACE = $8862; - GL_MAX_TEXTURE_COORDS = $8871; -{$endif} - - // GL_VERSION_2_1 - GL_PIXEL_PACK_BUFFER = $88EB; - GL_PIXEL_UNPACK_BUFFER = $88EC; - GL_PIXEL_PACK_BUFFER_BINDING = $88ED; - GL_PIXEL_UNPACK_BUFFER_BINDING = $88EF; - GL_FLOAT_MAT2x3 = $8B65; - GL_FLOAT_MAT2x4 = $8B66; - GL_FLOAT_MAT3x2 = $8B67; - GL_FLOAT_MAT3x4 = $8B68; - GL_FLOAT_MAT4x2 = $8B69; - GL_FLOAT_MAT4x3 = $8B6A; - GL_SRGB = $8C40; - GL_SRGB8 = $8C41; - GL_SRGB_ALPHA = $8C42; - GL_SRGB8_ALPHA8 = $8C43; - GL_COMPRESSED_SRGB = $8C48; - GL_COMPRESSED_SRGB_ALPHA = $8C49; -{$ifdef DGL_DEPRECATED} - GL_CURRENT_RASTER_SECONDARY_COLOR = $845F; - GL_SLUMINANCE_ALPHA = $8C44; - GL_SLUMINANCE8_ALPHA8 = $8C45; - GL_SLUMINANCE = $8C46; - GL_SLUMINANCE8 = $8C47; - GL_COMPRESSED_SLUMINANCE = $8C4A; - GL_COMPRESSED_SLUMINANCE_ALPHA = $8C4B; -{$endif} - - // GL_VERSION_3_0 - GL_COMPARE_REF_TO_TEXTURE = $884E; - GL_CLIP_DISTANCE0 = $3000; - GL_CLIP_DISTANCE1 = $3001; - GL_CLIP_DISTANCE2 = $3002; - GL_CLIP_DISTANCE3 = $3003; - GL_CLIP_DISTANCE4 = $3004; - GL_CLIP_DISTANCE5 = $3005; - GL_CLIP_DISTANCE6 = $3006; - GL_CLIP_DISTANCE7 = $3007; - GL_MAX_CLIP_DISTANCES = $0D32; - GL_MAJOR_VERSION = $821B; - GL_MINOR_VERSION = $821C; - GL_NUM_EXTENSIONS = $821D; - GL_CONTEXT_FLAGS = $821E; - GL_DEPTH_BUFFER = $8223; - GL_STENCIL_BUFFER = $8224; - GL_COMPRESSED_RED = $8225; - GL_COMPRESSED_RG = $8226; - GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT = $0001; - GL_RGBA32F = $8814; - GL_RGB32F = $8815; - GL_RGBA16F = $881A; - GL_RGB16F = $881B; - GL_VERTEX_ATTRIB_ARRAY_INTEGER = $88FD; - GL_MAX_ARRAY_TEXTURE_LAYERS = $88FF; - GL_MIN_PROGRAM_TEXEL_OFFSET = $8904; - GL_MAX_PROGRAM_TEXEL_OFFSET = $8905; - GL_CLAMP_READ_COLOR = $891C; - GL_FIXED_ONLY = $891D; - GL_MAX_VARYING_COMPONENTS = $8B4B; - GL_TEXTURE_1D_ARRAY = $8C18; - GL_PROXY_TEXTURE_1D_ARRAY = $8C19; - GL_TEXTURE_2D_ARRAY = $8C1A; - GL_PROXY_TEXTURE_2D_ARRAY = $8C1B; - GL_TEXTURE_BINDING_1D_ARRAY = $8C1C; - GL_TEXTURE_BINDING_2D_ARRAY = $8C1D; - GL_R11F_G11F_B10F = $8C3A; - GL_UNSIGNED_INT_10F_11F_11F_REV = $8C3B; - GL_RGB9_E5 = $8C3D; - GL_UNSIGNED_INT_5_9_9_9_REV = $8C3E; - GL_TEXTURE_SHARED_SIZE = $8C3F; - GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH = $8C76; - GL_TRANSFORM_FEEDBACK_BUFFER_MODE = $8C7F; - GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = $8C80; - GL_TRANSFORM_FEEDBACK_VARYINGS = $8C83; - GL_TRANSFORM_FEEDBACK_BUFFER_START = $8C84; - GL_TRANSFORM_FEEDBACK_BUFFER_SIZE = $8C85; - GL_PRIMITIVES_GENERATED = $8C87; - GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = $8C88; - GL_RASTERIZER_DISCARD = $8C89; - GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = $8C8A; - GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = $8C8B; - GL_INTERLEAVED_ATTRIBS = $8C8C; - GL_SEPARATE_ATTRIBS = $8C8D; - GL_TRANSFORM_FEEDBACK_BUFFER = $8C8E; - GL_TRANSFORM_FEEDBACK_BUFFER_BINDING = $8C8F; - GL_RGBA32UI = $8D70; - GL_RGB32UI = $8D71; - GL_RGBA16UI = $8D76; - GL_RGB16UI = $8D77; - GL_RGBA8UI = $8D7C; - GL_RGB8UI = $8D7D; - GL_RGBA32I = $8D82; - GL_RGB32I = $8D83; - GL_RGBA16I = $8D88; - GL_RGB16I = $8D89; - GL_RGBA8I = $8D8E; - GL_RGB8I = $8D8F; - GL_RED_INTEGER = $8D94; - GL_GREEN_INTEGER = $8D95; - GL_BLUE_INTEGER = $8D96; - GL_RGB_INTEGER = $8D98; - GL_RGBA_INTEGER = $8D99; - GL_BGR_INTEGER = $8D9A; - GL_BGRA_INTEGER = $8D9B; - GL_SAMPLER_1D_ARRAY = $8DC0; - GL_SAMPLER_2D_ARRAY = $8DC1; - GL_SAMPLER_1D_ARRAY_SHADOW = $8DC3; - GL_SAMPLER_2D_ARRAY_SHADOW = $8DC4; - GL_SAMPLER_CUBE_SHADOW = $8DC5; - GL_UNSIGNED_INT_VEC2 = $8DC6; - GL_UNSIGNED_INT_VEC3 = $8DC7; - GL_UNSIGNED_INT_VEC4 = $8DC8; - GL_INT_SAMPLER_1D = $8DC9; - GL_INT_SAMPLER_2D = $8DCA; - GL_INT_SAMPLER_3D = $8DCB; - GL_INT_SAMPLER_CUBE = $8DCC; - GL_INT_SAMPLER_1D_ARRAY = $8DCE; - GL_INT_SAMPLER_2D_ARRAY = $8DCF; - GL_UNSIGNED_INT_SAMPLER_1D = $8DD1; - GL_UNSIGNED_INT_SAMPLER_2D = $8DD2; - GL_UNSIGNED_INT_SAMPLER_3D = $8DD3; - GL_UNSIGNED_INT_SAMPLER_CUBE = $8DD4; - GL_UNSIGNED_INT_SAMPLER_1D_ARRAY = $8DD6; - GL_UNSIGNED_INT_SAMPLER_2D_ARRAY = $8DD7; - GL_QUERY_WAIT = $8E13; - GL_QUERY_NO_WAIT = $8E14; - GL_QUERY_BY_REGION_WAIT = $8E15; - GL_QUERY_BY_REGION_NO_WAIT = $8E16; - GL_BUFFER_ACCESS_FLAGS = $911F; - GL_BUFFER_MAP_LENGTH = $9120; - GL_BUFFER_MAP_OFFSET = $9121; - { Reuse tokens from ARB_depth_buffer_float } - { reuse GL_DEPTH_COMPONENT32F } - { reuse GL_DEPTH32F_STENCIL8 } - { reuse GL_FLOAT_32_UNSIGNED_INT_24_8_REV } - { Reuse tokens from ARB_framebuffer_object } - { reuse GL_INVALID_FRAMEBUFFER_OPERATION } - { reuse GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING } - { reuse GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE } - { reuse GL_FRAMEBUFFER_DEFAULT } - { reuse GL_FRAMEBUFFER_UNDEFINED } - { reuse GL_DEPTH_STENCIL_ATTACHMENT } - { reuse GL_INDEX } - { reuse GL_MAX_RENDERBUFFER_SIZE } - { reuse GL_DEPTH_STENCIL } - { reuse GL_UNSIGNED_INT_24_8 } - { reuse GL_DEPTH24_STENCIL8 } - { reuse GL_TEXTURE_STENCIL_SIZE } - { reuse GL_TEXTURE_RED_TYPE } - { reuse GL_TEXTURE_GREEN_TYPE } - { reuse GL_TEXTURE_BLUE_TYPE } - { reuse GL_TEXTURE_ALPHA_TYPE } - { reuse GL_TEXTURE_DEPTH_TYPE } - { reuse GL_UNSIGNED_NORMALIZED } - { reuse GL_FRAMEBUFFER_BINDING } - { reuse GL_DRAW_FRAMEBUFFER_BINDING } - { reuse GL_RENDERBUFFER_BINDING } - { reuse GL_READ_FRAMEBUFFER } - { reuse GL_DRAW_FRAMEBUFFER } - { reuse GL_READ_FRAMEBUFFER_BINDING } - { reuse GL_RENDERBUFFER_SAMPLES } - { reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME } - { reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL } - { reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE } - { reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER } - { reuse GL_FRAMEBUFFER_COMPLETE } - { reuse GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT } - { reuse GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT } - { reuse GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER } - { reuse GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER } - { reuse GL_FRAMEBUFFER_UNSUPPORTED } - { reuse GL_MAX_COLOR_ATTACHMENTS } - { reuse GL_COLOR_ATTACHMENT0 } - { reuse GL_COLOR_ATTACHMENT1 } - { reuse GL_COLOR_ATTACHMENT2 } - { reuse GL_COLOR_ATTACHMENT3 } - { reuse GL_COLOR_ATTACHMENT4 } - { reuse GL_COLOR_ATTACHMENT5 } - { reuse GL_COLOR_ATTACHMENT6 } - { reuse GL_COLOR_ATTACHMENT7 } - { reuse GL_COLOR_ATTACHMENT8 } - { reuse GL_COLOR_ATTACHMENT9 } - { reuse GL_COLOR_ATTACHMENT10 } - { reuse GL_COLOR_ATTACHMENT11 } - { reuse GL_COLOR_ATTACHMENT12 } - { reuse GL_COLOR_ATTACHMENT13 } - { reuse GL_COLOR_ATTACHMENT14 } - { reuse GL_COLOR_ATTACHMENT15 } - { reuse GL_DEPTH_ATTACHMENT } - { reuse GL_STENCIL_ATTACHMENT } - { reuse GL_FRAMEBUFFER } - { reuse GL_RENDERBUFFER } - { reuse GL_RENDERBUFFER_WIDTH } - { reuse GL_RENDERBUFFER_HEIGHT } - { reuse GL_RENDERBUFFER_INTERNAL_FORMAT } - { reuse GL_STENCIL_INDEX1 } - { reuse GL_STENCIL_INDEX4 } - { reuse GL_STENCIL_INDEX8 } - { reuse GL_STENCIL_INDEX16 } - { reuse GL_RENDERBUFFER_RED_SIZE } - { reuse GL_RENDERBUFFER_GREEN_SIZE } - { reuse GL_RENDERBUFFER_BLUE_SIZE } - { reuse GL_RENDERBUFFER_ALPHA_SIZE } - { reuse GL_RENDERBUFFER_DEPTH_SIZE } - { reuse GL_RENDERBUFFER_STENCIL_SIZE } - { reuse GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE } - { reuse GL_MAX_SAMPLES } - { Reuse tokens from ARB_framebuffer_sRGB } - { reuse GL_FRAMEBUFFER_SRGB } - { Reuse tokens from ARB_half_float_vertex } - { reuse GL_HALF_FLOAT } - { Reuse tokens from ARB_map_buffer_range } - { reuse GL_MAP_READ_BIT } - { reuse GL_MAP_WRITE_BIT } - { reuse GL_MAP_INVALIDATE_RANGE_BIT } - { reuse GL_MAP_INVALIDATE_BUFFER_BIT } - { reuse GL_MAP_FLUSH_EXPLICIT_BIT } - { reuse GL_MAP_UNSYNCHRONIZED_BIT } - { Reuse tokens from ARB_texture_compression_rgtc } - { reuse GL_COMPRESSED_RED_RGTC1 } - { reuse GL_COMPRESSED_SIGNED_RED_RGTC1 } - { reuse GL_COMPRESSED_RG_RGTC2 } - { reuse GL_COMPRESSED_SIGNED_RG_RGTC2 } - { Reuse tokens from ARB_texture_rg } - { reuse GL_RG } - { reuse GL_RG_INTEGER } - { reuse GL_R8 } - { reuse GL_R16 } - { reuse GL_RG8 } - { reuse GL_RG16 } - { reuse GL_R16F } - { reuse GL_R32F } - { reuse GL_RG16F } - { reuse GL_RG32F } - { reuse GL_R8I } - { reuse GL_R8UI } - { reuse GL_R16I } - { reuse GL_R16UI } - { reuse GL_R32I } - { reuse GL_R32UI } - { reuse GL_RG8I } - { reuse GL_RG8UI } - { reuse GL_RG16I } - { reuse GL_RG16UI } - { reuse GL_RG32I } - { reuse GL_RG32UI } - { Reuse tokens from ARB_vertex_array_object } - { reuse GL_VERTEX_ARRAY_BINDING } -{$ifdef DGL_DEPRECATED} - GL_CLAMP_VERTEX_COLOR = $891A; - GL_CLAMP_FRAGMENT_COLOR = $891B; - GL_ALPHA_INTEGER = $8D97; - { Reuse tokens from ARB_framebuffer_object } - { reuse GL_TEXTURE_LUMINANCE_TYPE } - { reuse GL_TEXTURE_INTENSITY_TYPE } -{$endif} - - // GL_VERSION_3_1 - GL_SAMPLER_2D_RECT = $8B63; - GL_SAMPLER_2D_RECT_SHADOW = $8B64; - GL_SAMPLER_BUFFER = $8DC2; - GL_INT_SAMPLER_2D_RECT = $8DCD; - GL_INT_SAMPLER_BUFFER = $8DD0; - GL_UNSIGNED_INT_SAMPLER_2D_RECT = $8DD5; - GL_UNSIGNED_INT_SAMPLER_BUFFER = $8DD8; - GL_TEXTURE_BUFFER = $8C2A; - GL_MAX_TEXTURE_BUFFER_SIZE = $8C2B; - GL_TEXTURE_BINDING_BUFFER = $8C2C; - GL_TEXTURE_BUFFER_DATA_STORE_BINDING = $8C2D; - GL_TEXTURE_BUFFER_FORMAT = $8C2E; - GL_TEXTURE_RECTANGLE = $84F5; - GL_TEXTURE_BINDING_RECTANGLE = $84F6; - GL_PROXY_TEXTURE_RECTANGLE = $84F7; - GL_MAX_RECTANGLE_TEXTURE_SIZE = $84F8; - GL_RED_SNORM = $8F90; - GL_RG_SNORM = $8F91; - GL_RGB_SNORM = $8F92; - GL_RGBA_SNORM = $8F93; - GL_R8_SNORM = $8F94; - GL_RG8_SNORM = $8F95; - GL_RGB8_SNORM = $8F96; - GL_RGBA8_SNORM = $8F97; - GL_R16_SNORM = $8F98; - GL_RG16_SNORM = $8F99; - GL_RGB16_SNORM = $8F9A; - GL_RGBA16_SNORM = $8F9B; - GL_SIGNED_NORMALIZED = $8F9C; - GL_PRIMITIVE_RESTART = $8F9D; - GL_PRIMITIVE_RESTART_INDEX = $8F9E; - { Reuse tokens from ARB_copy_buffer } - { reuse GL_COPY_READ_BUFFER } - { reuse GL_COPY_WRITE_BUFFER } - { Would reuse tokens from ARB_draw_instanced, but it has none } - { Reuse tokens from ARB_uniform_buffer_object } - { reuse GL_UNIFORM_BUFFER } - { reuse GL_UNIFORM_BUFFER_BINDING } - { reuse GL_UNIFORM_BUFFER_START } - { reuse GL_UNIFORM_BUFFER_SIZE } - { reuse GL_MAX_VERTEX_UNIFORM_BLOCKS } - { reuse GL_MAX_FRAGMENT_UNIFORM_BLOCKS } - { reuse GL_MAX_COMBINED_UNIFORM_BLOCKS } - { reuse GL_MAX_UNIFORM_BUFFER_BINDINGS } - { reuse GL_MAX_UNIFORM_BLOCK_SIZE } - { reuse GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS } - { reuse GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS } - { reuse GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT } - { reuse GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH } - { reuse GL_ACTIVE_UNIFORM_BLOCKS } - { reuse GL_UNIFORM_TYPE } - { reuse GL_UNIFORM_SIZE } - { reuse GL_UNIFORM_NAME_LENGTH } - { reuse GL_UNIFORM_BLOCK_INDEX } - { reuse GL_UNIFORM_OFFSET } - { reuse GL_UNIFORM_ARRAY_STRIDE } - { reuse GL_UNIFORM_MATRIX_STRIDE } - { reuse GL_UNIFORM_IS_ROW_MAJOR } - { reuse GL_UNIFORM_BLOCK_BINDING } - { reuse GL_UNIFORM_BLOCK_DATA_SIZE } - { reuse GL_UNIFORM_BLOCK_NAME_LENGTH } - { reuse GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS } - { reuse GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES } - { reuse GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER } - { reuse GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER } - { reuse GL_INVALID_INDEX } - - // GL_VERSION_3_2 - GL_CONTEXT_CORE_PROFILE_BIT = $00000001; - GL_CONTEXT_COMPATIBILITY_PROFILE_BIT = $00000002; - GL_LINES_ADJACENCY = $000A; - GL_LINE_STRIP_ADJACENCY = $000B; - GL_TRIANGLES_ADJACENCY = $000C; - GL_TRIANGLE_STRIP_ADJACENCY = $000D; - GL_PROGRAM_POINT_SIZE = $8642; - GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS = $8C29; - GL_FRAMEBUFFER_ATTACHMENT_LAYERED = $8DA7; - GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS = $8DA8; - GL_GEOMETRY_SHADER = $8DD9; - GL_GEOMETRY_VERTICES_OUT = $8916; - GL_GEOMETRY_INPUT_TYPE = $8917; - GL_GEOMETRY_OUTPUT_TYPE = $8918; - GL_MAX_GEOMETRY_UNIFORM_COMPONENTS = $8DDF; - GL_MAX_GEOMETRY_OUTPUT_VERTICES = $8DE0; - GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = $8DE1; - GL_MAX_VERTEX_OUTPUT_COMPONENTS = $9122; - GL_MAX_GEOMETRY_INPUT_COMPONENTS = $9123; - GL_MAX_GEOMETRY_OUTPUT_COMPONENTS = $9124; - GL_MAX_FRAGMENT_INPUT_COMPONENTS = $9125; - GL_CONTEXT_PROFILE_MASK = $9126; - { reuse GL_MAX_VARYING_COMPONENTS } - { reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER } - { Reuse tokens from ARB_depth_clamp } - { reuse GL_DEPTH_CLAMP } - { Would reuse tokens from ARB_draw_elements_base_vertex, but it has none } - { Would reuse tokens from ARB_fragment_coord_conventions, but it has none } - { Reuse tokens from ARB_provoking_vertex } - { reuse GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION } - { reuse GL_FIRST_VERTEX_CONVENTION } - { reuse GL_LAST_VERTEX_CONVENTION } - { reuse GL_PROVOKING_VERTEX } - { Reuse tokens from ARB_seamless_cube_map } - { reuse GL_TEXTURE_CUBE_MAP_SEAMLESS } - { Reuse tokens from ARB_sync } - { reuse GL_MAX_SERVER_WAIT_TIMEOUT } - { reuse GL_OBJECT_TYPE } - { reuse GL_SYNC_CONDITION } - { reuse GL_SYNC_STATUS } - { reuse GL_SYNC_FLAGS } - { reuse GL_SYNC_FENCE } - { reuse GL_SYNC_GPU_COMMANDS_COMPLETE } - { reuse GL_UNSIGNALED } - { reuse GL_SIGNALED } - { reuse GL_ALREADY_SIGNALED } - { reuse GL_TIMEOUT_EXPIRED } - { reuse GL_CONDITION_SATISFIED } - { reuse GL_WAIT_FAILED } - { reuse GL_TIMEOUT_IGNORED } - { reuse GL_SYNC_FLUSH_COMMANDS_BIT } - { reuse GL_TIMEOUT_IGNORED } - { Reuse tokens from ARB_texture_multisample } - { reuse GL_SAMPLE_POSITION } - { reuse GL_SAMPLE_MASK } - { reuse GL_SAMPLE_MASK_VALUE } - { reuse GL_MAX_SAMPLE_MASK_WORDS } - { reuse GL_TEXTURE_2D_MULTISAMPLE } - { reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE } - { reuse GL_TEXTURE_2D_MULTISAMPLE_ARRAY } - { reuse GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY } - { reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE } - { reuse GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY } - { reuse GL_TEXTURE_SAMPLES } - { reuse GL_TEXTURE_FIXED_SAMPLE_LOCATIONS } - { reuse GL_SAMPLER_2D_MULTISAMPLE } - { reuse GL_INT_SAMPLER_2D_MULTISAMPLE } - { reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE } - { reuse GL_SAMPLER_2D_MULTISAMPLE_ARRAY } - { reuse GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY } - { reuse GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY } - { reuse GL_MAX_COLOR_TEXTURE_SAMPLES } - { reuse GL_MAX_DEPTH_TEXTURE_SAMPLES } - { reuse GL_MAX_INTEGER_SAMPLES } - { Don't need to reuse tokens from ARB_vertex_array_bgra since they're already in 1.2 core } - - // GL_3DFX_multisample - GL_MULTISAMPLE_3DFX = $86B2; - GL_SAMPLE_BUFFERS_3DFX = $86B3; - GL_SAMPLES_3DFX = $86B4; - GL_MULTISAMPLE_BIT_3DFX = $20000000; - - // GL_3DFX_texture_compression_FXT1 - GL_COMPRESSED_RGB_FXT1_3DFX = $86B0; - GL_COMPRESSED_RGBA_FXT1_3DFX = $86B1; - - // GL_APPLE_client_storage - GL_UNPACK_CLIENT_STORAGE_APPLE = $85B2; - - // GL_APPLE_element_array - GL_ELEMENT_ARRAY_APPLE = $8768; - GL_ELEMENT_ARRAY_TYPE_APPLE = $8769; - GL_ELEMENT_ARRAY_POINTER_APPLE = $876A; - - // GL_APPLE_fence - GL_DRAW_PIXELS_APPLE = $8A0A; - GL_FENCE_APPLE = $8A0B; - - // GL_APPLE_specular_vector - GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE = $85B0; - - // GL_APPLE_transform_hint - GL_TRANSFORM_HINT_APPLE = $85B1; - - // GL_APPLE_vertex_array_object - GL_VERTEX_ARRAY_BINDING_APPLE = $85B5; - - // GL_APPLE_vertex_array_range - GL_VERTEX_ARRAY_RANGE_APPLE = $851D; - GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE = $851E; - GL_VERTEX_ARRAY_STORAGE_HINT_APPLE = $851F; - GL_VERTEX_ARRAY_RANGE_POINTER_APPLE = $8521; - GL_STORAGE_CACHED_APPLE = $85BE; - GL_STORAGE_SHARED_APPLE = $85BF; - - // GL_APPLE_ycbcr_422 - GL_YCBCR_422_APPLE = $85B9; - GL_UNSIGNED_SHORT_8_8_APPLE = $85BA; - GL_UNSIGNED_SHORT_8_8_REV_APPLE = $85BB; - - // GL_APPLE_texture_range - GL_TEXTURE_RANGE_LENGTH_APPLE = $85B7; - GL_TEXTURE_RANGE_POINTER_APPLE = $85B8; - GL_TEXTURE_STORAGE_HINT_APPLE = $85BC; - GL_STORAGE_PRIVATE_APPLE = $85BD; - { reuse GL_STORAGE_CACHED_APPLE } - { reuse GL_STORAGE_SHARED_APPLE } - - // GL_APPLE_float_pixels - GL_HALF_APPLE = $140B; - GL_RGBA_FLOAT32_APPLE = $8814; - GL_RGB_FLOAT32_APPLE = $8815; - GL_ALPHA_FLOAT32_APPLE = $8816; - GL_INTENSITY_FLOAT32_APPLE = $8817; - GL_LUMINANCE_FLOAT32_APPLE = $8818; - GL_LUMINANCE_ALPHA_FLOAT32_APPLE = $8819; - GL_RGBA_FLOAT16_APPLE = $881A; - GL_RGB_FLOAT16_APPLE = $881B; - GL_ALPHA_FLOAT16_APPLE = $881C; - GL_INTENSITY_FLOAT16_APPLE = $881D; - GL_LUMINANCE_FLOAT16_APPLE = $881E; - GL_LUMINANCE_ALPHA_FLOAT16_APPLE = $881F; - GL_COLOR_FLOAT_APPLE = $8A0F; - - // GL_APPLE_vertex_program_evaluators - GL_VERTEX_ATTRIB_MAP1_APPLE = $8A00; - GL_VERTEX_ATTRIB_MAP2_APPLE = $8A01; - GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE = $8A02; - GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE = $8A03; - GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE = $8A04; - GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE = $8A05; - GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE = $8A06; - GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE = $8A07; - GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE = $8A08; - GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE = $8A09; - - // GL_APPLE_aux_depth_stencil - GL_AUX_DEPTH_STENCIL_APPLE = $8A14; - - // GL_APPLE_object_purgeable - GL_BUFFER_OBJECT_APPLE = $85B3; - GL_RELEASED_APPLE = $8A19; - GL_VOLATILE_APPLE = $8A1A; - GL_RETAINED_APPLE = $8A1B; - GL_UNDEFINED_APPLE = $8A1C; - GL_PURGEABLE_APPLE = $8A1D; - - // GL_APPLE_row_bytes - GL_PACK_ROW_BYTES_APPLE = $8A15; - GL_UNPACK_ROW_BYTES_APPLE = $8A16; - - - // GL_ARB_depth_texture - GL_DEPTH_COMPONENT16_ARB = $81A5; - GL_DEPTH_COMPONENT24_ARB = $81A6; - GL_DEPTH_COMPONENT32_ARB = $81A7; - GL_TEXTURE_DEPTH_SIZE_ARB = $884A; - GL_DEPTH_TEXTURE_MODE_ARB = $884B; - - // GL_ARB_fragment_program - GL_FRAGMENT_PROGRAM_ARB = $8804; - GL_PROGRAM_ALU_INSTRUCTIONS_ARB = $8805; - GL_PROGRAM_TEX_INSTRUCTIONS_ARB = $8806; - GL_PROGRAM_TEX_INDIRECTIONS_ARB = $8807; - GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = $8808; - GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = $8809; - GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = $880A; - GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB = $880B; - GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB = $880C; - GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB = $880D; - GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = $880E; - GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = $880F; - GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = $8810; - GL_MAX_TEXTURE_COORDS_ARB = $8871; - GL_MAX_TEXTURE_IMAGE_UNITS_ARB = $8872; - - // GL_ARB_imaging - GL_CONSTANT_COLOR_ARB = $8001; - GL_ONE_MINUS_CONSTANT_COLOR = $8002; - GL_CONSTANT_ALPHA = $8003; - GL_ONE_MINUS_CONSTANT_ALPHA = $8004; - GL_BLEND_COLOR = $8005; - GL_FUNC_ADD = $8006; - GL_MIN = $8007; - GL_MAX = $8008; - GL_BLEND_EQUATION = $8009; - GL_FUNC_SUBTRACT = $800A; - GL_FUNC_REVERSE_SUBTRACT = $800B; -{$ifdef DGL_DEPRECATED} - GL_CONVOLUTION_1D = $8010; - GL_CONVOLUTION_2D = $8011; - GL_SEPARABLE_2D = $8012; - GL_CONVOLUTION_BORDER_MODE = $8013; - GL_CONVOLUTION_FILTER_SCALE = $8014; - GL_CONVOLUTION_FILTER_BIAS = $8015; - GL_REDUCE = $8016; - GL_CONVOLUTION_FORMAT = $8017; - GL_CONVOLUTION_WIDTH = $8018; - GL_CONVOLUTION_HEIGHT = $8019; - GL_MAX_CONVOLUTION_WIDTH = $801A; - GL_MAX_CONVOLUTION_HEIGHT = $801B; - GL_POST_CONVOLUTION_RED_SCALE = $801C; - GL_POST_CONVOLUTION_GREEN_SCALE = $801D; - GL_POST_CONVOLUTION_BLUE_SCALE = $801E; - GL_POST_CONVOLUTION_ALPHA_SCALE = $801F; - GL_POST_CONVOLUTION_RED_BIAS = $8020; - GL_POST_CONVOLUTION_GREEN_BIAS = $8021; - GL_POST_CONVOLUTION_BLUE_BIAS = $8022; - GL_POST_CONVOLUTION_ALPHA_BIAS = $8023; - GL_HISTOGRAM = $8024; - GL_PROXY_HISTOGRAM = $8025; - GL_HISTOGRAM_WIDTH = $8026; - GL_HISTOGRAM_FORMAT = $8027; - GL_HISTOGRAM_RED_SIZE = $8028; - GL_HISTOGRAM_GREEN_SIZE = $8029; - GL_HISTOGRAM_BLUE_SIZE = $802A; - GL_HISTOGRAM_ALPHA_SIZE = $802B; - GL_HISTOGRAM_LUMINANCE_SIZE = $802C; - GL_HISTOGRAM_SINK = $802D; - GL_MINMAX = $802E; - GL_MINMAX_FORMAT = $802F; - GL_MINMAX_SINK = $8030; - GL_TABLE_TOO_LARGE = $8031; - GL_COLOR_MATRIX = $80B1; - GL_COLOR_MATRIX_STACK_DEPTH = $80B2; - GL_MAX_COLOR_MATRIX_STACK_DEPTH = $80B3; - GL_POST_COLOR_MATRIX_RED_SCALE = $80B4; - GL_POST_COLOR_MATRIX_GREEN_SCALE = $80B5; - GL_POST_COLOR_MATRIX_BLUE_SCALE = $80B6; - GL_POST_COLOR_MATRIX_ALPHA_SCALE = $80B7; - GL_POST_COLOR_MATRIX_RED_BIAS = $80B8; - GL_POST_COLOR_MATRIX_GREEN_BIAS = $80B9; - GL_POST_COLOR_MATRIX_BLUE_BIAS = $80BA; - GL_POST_COLOR_MATRIX_ALPHA_BIAS = $80BB; - GL_COLOR_TABLE = $80D0; - GL_POST_CONVOLUTION_COLOR_TABLE = $80D1; - GL_POST_COLOR_MATRIX_COLOR_TABLE = $80D2; - GL_PROXY_COLOR_TABLE = $80D3; - GL_PROXY_POST_CONVOLUTION_COLOR_TABLE = $80D4; - GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE = $80D5; - GL_COLOR_TABLE_SCALE = $80D6; - GL_COLOR_TABLE_BIAS = $80D7; - GL_COLOR_TABLE_FORMAT = $80D8; - GL_COLOR_TABLE_WIDTH = $80D9; - GL_COLOR_TABLE_RED_SIZE = $80DA; - GL_COLOR_TABLE_GREEN_SIZE = $80DB; - GL_COLOR_TABLE_BLUE_SIZE = $80DC; - GL_COLOR_TABLE_ALPHA_SIZE = $80DD; - GL_COLOR_TABLE_LUMINANCE_SIZE = $80DE; - GL_COLOR_TABLE_INTENSITY_SIZE = $80DF; - GL_CONSTANT_BORDER = $8151; - GL_REPLICATE_BORDER = $8153; - GL_CONVOLUTION_BORDER_COLOR = $8154; -{$endif} - - // GL_ARB_matrix_palette - GL_MATRIX_PALETTE_ARB = $8840; - GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB = $8841; - GL_MAX_PALETTE_MATRICES_ARB = $8842; - GL_CURRENT_PALETTE_MATRIX_ARB = $8843; - GL_MATRIX_INDEX_ARRAY_ARB = $8844; - GL_CURRENT_MATRIX_INDEX_ARB = $8845; - GL_MATRIX_INDEX_ARRAY_SIZE_ARB = $8846; - GL_MATRIX_INDEX_ARRAY_TYPE_ARB = $8847; - GL_MATRIX_INDEX_ARRAY_STRIDE_ARB = $8848; - GL_MATRIX_INDEX_ARRAY_POINTER_ARB = $8849; - - // GL_ARB_multisample - GL_MULTISAMPLE_ARB = $809D; - GL_SAMPLE_ALPHA_TO_COVERAGE_ARB = $809E; - GL_SAMPLE_ALPHA_TO_ONE_ARB = $809F; - GL_SAMPLE_COVERAGE_ARB = $80A0; - GL_SAMPLE_BUFFERS_ARB = $80A8; - GL_SAMPLES_ARB = $80A9; - GL_SAMPLE_COVERAGE_VALUE_ARB = $80AA; - GL_SAMPLE_COVERAGE_INVERT_ARB = $80AB; - GL_MULTISAMPLE_BIT_ARB = $20000000; - - // GL_ARB_multitexture - GL_TEXTURE0_ARB = $84C0; - GL_TEXTURE1_ARB = $84C1; - GL_TEXTURE2_ARB = $84C2; - GL_TEXTURE3_ARB = $84C3; - GL_TEXTURE4_ARB = $84C4; - GL_TEXTURE5_ARB = $84C5; - GL_TEXTURE6_ARB = $84C6; - GL_TEXTURE7_ARB = $84C7; - GL_TEXTURE8_ARB = $84C8; - GL_TEXTURE9_ARB = $84C9; - GL_TEXTURE10_ARB = $84CA; - GL_TEXTURE11_ARB = $84CB; - GL_TEXTURE12_ARB = $84CC; - GL_TEXTURE13_ARB = $84CD; - GL_TEXTURE14_ARB = $84CE; - GL_TEXTURE15_ARB = $84CF; - GL_TEXTURE16_ARB = $84D0; - GL_TEXTURE17_ARB = $84D1; - GL_TEXTURE18_ARB = $84D2; - GL_TEXTURE19_ARB = $84D3; - GL_TEXTURE20_ARB = $84D4; - GL_TEXTURE21_ARB = $84D5; - GL_TEXTURE22_ARB = $84D6; - GL_TEXTURE23_ARB = $84D7; - GL_TEXTURE24_ARB = $84D8; - GL_TEXTURE25_ARB = $84D9; - GL_TEXTURE26_ARB = $84DA; - GL_TEXTURE27_ARB = $84DB; - GL_TEXTURE28_ARB = $84DC; - GL_TEXTURE29_ARB = $84DD; - GL_TEXTURE30_ARB = $84DE; - GL_TEXTURE31_ARB = $84DF; - GL_ACTIVE_TEXTURE_ARB = $84E0; - GL_CLIENT_ACTIVE_TEXTURE_ARB = $84E1; - GL_MAX_TEXTURE_UNITS_ARB = $84E2; - - // GL_ARB_point_parameters - GL_POINT_SIZE_MIN_ARB = $8126; - GL_POINT_SIZE_MAX_ARB = $8127; - GL_POINT_FADE_THRESHOLD_SIZE_ARB = $8128; - GL_POINT_DISTANCE_ATTENUATION_ARB = $8129; - - // GL_ARB_shadow - GL_TEXTURE_COMPARE_MODE_ARB = $884C; - GL_TEXTURE_COMPARE_FUNC_ARB = $884D; - GL_COMPARE_R_TO_TEXTURE_ARB = $884E; - - // GL_ARB_shadow_ambient - GL_TEXTURE_COMPARE_FAIL_VALUE_ARB = $80BF; - - // GL_ARB_texture_border_clamp - GL_CLAMP_TO_BORDER_ARB = $812D; - - // GL_ARB_texture_compression - GL_COMPRESSED_ALPHA_ARB = $84E9; - GL_COMPRESSED_LUMINANCE_ARB = $84EA; - GL_COMPRESSED_LUMINANCE_ALPHA_ARB = $84EB; - GL_COMPRESSED_INTENSITY_ARB = $84EC; - GL_COMPRESSED_RGB_ARB = $84ED; - GL_COMPRESSED_RGBA_ARB = $84EE; - GL_TEXTURE_COMPRESSION_HINT_ARB = $84EF; - GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB = $86A0; - GL_TEXTURE_COMPRESSED_ARB = $86A1; - GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB = $86A2; - GL_COMPRESSED_TEXTURE_FORMATS_ARB = $86A3; - - // GL_ARB_texture_cube_map - GL_NORMAL_MAP_ARB = $8511; - GL_REFLECTION_MAP_ARB = $8512; - GL_TEXTURE_CUBE_MAP_ARB = $8513; - GL_TEXTURE_BINDING_CUBE_MAP_ARB = $8514; - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB = $8515; - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB = $8516; - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB = $8517; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB = $8518; - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB = $8519; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB = $851A; - GL_PROXY_TEXTURE_CUBE_MAP_ARB = $851B; - GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB = $851C; - - // GL_ARB_texture_env_combine - GL_COMBINE_ARB = $8570; - GL_COMBINE_RGB_ARB = $8571; - GL_COMBINE_ALPHA_ARB = $8572; - GL_SOURCE0_RGB_ARB = $8580; - GL_SOURCE1_RGB_ARB = $8581; - GL_SOURCE2_RGB_ARB = $8582; - GL_SOURCE0_ALPHA_ARB = $8588; - GL_SOURCE1_ALPHA_ARB = $8589; - GL_SOURCE2_ALPHA_ARB = $858A; - GL_OPERAND0_RGB_ARB = $8590; - GL_OPERAND1_RGB_ARB = $8591; - GL_OPERAND2_RGB_ARB = $8592; - GL_OPERAND0_ALPHA_ARB = $8598; - GL_OPERAND1_ALPHA_ARB = $8599; - GL_OPERAND2_ALPHA_ARB = $859A; - GL_RGB_SCALE_ARB = $8573; - GL_ADD_SIGNED_ARB = $8574; - GL_INTERPOLATE_ARB = $8575; - GL_SUBTRACT_ARB = $84E7; - GL_CONSTANT_ARB = $8576; - GL_PRIMARY_COLOR_ARB = $8577; - GL_PREVIOUS_ARB = $8578; - - // GL_ARB_texture_env_dot3 - GL_DOT3_RGB_ARB = $86AE; - GL_DOT3_RGBA_ARB = $86AF; - - // GL_ARB_texture_mirrored_repeat - GL_MIRRORED_REPEAT_ARB = $8370; - - // GL_ARB_transpose_matrix - GL_TRANSPOSE_MODELVIEW_MATRIX_ARB = $84E3; - GL_TRANSPOSE_PROJECTION_MATRIX_ARB = $84E4; - GL_TRANSPOSE_TEXTURE_MATRIX_ARB = $84E5; - GL_TRANSPOSE_COLOR_MATRIX_ARB = $84E6; - - // GL_ARB_vertex_blend - GL_MAX_VERTEX_UNITS_ARB = $86A4; - GL_ACTIVE_VERTEX_UNITS_ARB = $86A5; - GL_WEIGHT_SUM_UNITY_ARB = $86A6; - GL_VERTEX_BLEND_ARB = $86A7; - GL_CURRENT_WEIGHT_ARB = $86A8; - GL_WEIGHT_ARRAY_TYPE_ARB = $86A9; - GL_WEIGHT_ARRAY_STRIDE_ARB = $86AA; - GL_WEIGHT_ARRAY_SIZE_ARB = $86AB; - GL_WEIGHT_ARRAY_POINTER_ARB = $86AC; - GL_WEIGHT_ARRAY_ARB = $86AD; - GL_MODELVIEW0_ARB = $1700; - GL_MODELVIEW1_ARB = $850A; - GL_MODELVIEW2_ARB = $8722; - GL_MODELVIEW3_ARB = $8723; - GL_MODELVIEW4_ARB = $8724; - GL_MODELVIEW5_ARB = $8725; - GL_MODELVIEW6_ARB = $8726; - GL_MODELVIEW7_ARB = $8727; - GL_MODELVIEW8_ARB = $8728; - GL_MODELVIEW9_ARB = $8729; - GL_MODELVIEW10_ARB = $872A; - GL_MODELVIEW11_ARB = $872B; - GL_MODELVIEW12_ARB = $872C; - GL_MODELVIEW13_ARB = $872D; - GL_MODELVIEW14_ARB = $872E; - GL_MODELVIEW15_ARB = $872F; - GL_MODELVIEW16_ARB = $8730; - GL_MODELVIEW17_ARB = $8731; - GL_MODELVIEW18_ARB = $8732; - GL_MODELVIEW19_ARB = $8733; - GL_MODELVIEW20_ARB = $8734; - GL_MODELVIEW21_ARB = $8735; - GL_MODELVIEW22_ARB = $8736; - GL_MODELVIEW23_ARB = $8737; - GL_MODELVIEW24_ARB = $8738; - GL_MODELVIEW25_ARB = $8739; - GL_MODELVIEW26_ARB = $873A; - GL_MODELVIEW27_ARB = $873B; - GL_MODELVIEW28_ARB = $873C; - GL_MODELVIEW29_ARB = $873D; - GL_MODELVIEW30_ARB = $873E; - GL_MODELVIEW31_ARB = $873F; - - // GL_ARB_vertex_buffer_object - GL_BUFFER_SIZE_ARB = $8764; - GL_BUFFER_USAGE_ARB = $8765; - GL_ARRAY_BUFFER_ARB = $8892; - GL_ELEMENT_ARRAY_BUFFER_ARB = $8893; - GL_ARRAY_BUFFER_BINDING_ARB = $8894; - GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB = $8895; - GL_VERTEX_ARRAY_BUFFER_BINDING_ARB = $8896; - GL_NORMAL_ARRAY_BUFFER_BINDING_ARB = $8897; - GL_COLOR_ARRAY_BUFFER_BINDING_ARB = $8898; - GL_INDEX_ARRAY_BUFFER_BINDING_ARB = $8899; - GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB = $889A; - GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB = $889B; - GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB = $889C; - GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB = $889D; - GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB = $889E; - GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB = $889F; - GL_READ_ONLY_ARB = $88B8; - GL_WRITE_ONLY_ARB = $88B9; - GL_READ_WRITE_ARB = $88BA; - GL_BUFFER_ACCESS_ARB = $88BB; - GL_BUFFER_MAPPED_ARB = $88BC; - GL_BUFFER_MAP_POINTER_ARB = $88BD; - GL_STREAM_DRAW_ARB = $88E0; - GL_STREAM_READ_ARB = $88E1; - GL_STREAM_COPY_ARB = $88E2; - GL_STATIC_DRAW_ARB = $88E4; - GL_STATIC_READ_ARB = $88E5; - GL_STATIC_COPY_ARB = $88E6; - GL_DYNAMIC_DRAW_ARB = $88E8; - GL_DYNAMIC_READ_ARB = $88E9; - GL_DYNAMIC_COPY_ARB = $88EA; - - // GL_ARB_vertex_program - GL_COLOR_SUM_ARB = $8458; - GL_VERTEX_PROGRAM_ARB = $8620; - GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB = $8622; - GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB = $8623; - GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB = $8624; - GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB = $8625; - GL_CURRENT_VERTEX_ATTRIB_ARB = $8626; - GL_PROGRAM_LENGTH_ARB = $8627; - GL_PROGRAM_STRING_ARB = $8628; - GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB = $862E; - GL_MAX_PROGRAM_MATRICES_ARB = $862F; - GL_CURRENT_MATRIX_STACK_DEPTH_ARB = $8640; - GL_CURRENT_MATRIX_ARB = $8641; - GL_VERTEX_PROGRAM_POINT_SIZE_ARB = $8642; - GL_VERTEX_PROGRAM_TWO_SIDE_ARB = $8643; - GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB = $8645; - GL_PROGRAM_ERROR_POSITION_ARB = $864B; - GL_PROGRAM_BINDING_ARB = $8677; - GL_MAX_VERTEX_ATTRIBS_ARB = $8869; - GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB = $886A; - GL_PROGRAM_ERROR_STRING_ARB = $8874; - GL_PROGRAM_FORMAT_ASCII_ARB = $8875; - GL_PROGRAM_FORMAT_ARB = $8876; - GL_PROGRAM_INSTRUCTIONS_ARB = $88A0; - GL_MAX_PROGRAM_INSTRUCTIONS_ARB = $88A1; - GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB = $88A2; - GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB = $88A3; - GL_PROGRAM_TEMPORARIES_ARB = $88A4; - GL_MAX_PROGRAM_TEMPORARIES_ARB = $88A5; - GL_PROGRAM_NATIVE_TEMPORARIES_ARB = $88A6; - GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB = $88A7; - GL_PROGRAM_PARAMETERS_ARB = $88A8; - GL_MAX_PROGRAM_PARAMETERS_ARB = $88A9; - GL_PROGRAM_NATIVE_PARAMETERS_ARB = $88AA; - GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB = $88AB; - GL_PROGRAM_ATTRIBS_ARB = $88AC; - GL_MAX_PROGRAM_ATTRIBS_ARB = $88AD; - GL_PROGRAM_NATIVE_ATTRIBS_ARB = $88AE; - GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB = $88AF; - GL_PROGRAM_ADDRESS_REGISTERS_ARB = $88B0; - GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB = $88B1; - GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = $88B2; - GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = $88B3; - GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB = $88B4; - GL_MAX_PROGRAM_ENV_PARAMETERS_ARB = $88B5; - GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB = $88B6; - GL_TRANSPOSE_CURRENT_MATRIX_ARB = $88B7; - GL_MATRIX0_ARB = $88C0; - GL_MATRIX1_ARB = $88C1; - GL_MATRIX2_ARB = $88C2; - GL_MATRIX3_ARB = $88C3; - GL_MATRIX4_ARB = $88C4; - GL_MATRIX5_ARB = $88C5; - GL_MATRIX6_ARB = $88C6; - GL_MATRIX7_ARB = $88C7; - GL_MATRIX8_ARB = $88C8; - GL_MATRIX9_ARB = $88C9; - GL_MATRIX10_ARB = $88CA; - GL_MATRIX11_ARB = $88CB; - GL_MATRIX12_ARB = $88CC; - GL_MATRIX13_ARB = $88CD; - GL_MATRIX14_ARB = $88CE; - GL_MATRIX15_ARB = $88CF; - GL_MATRIX16_ARB = $88D0; - GL_MATRIX17_ARB = $88D1; - GL_MATRIX18_ARB = $88D2; - GL_MATRIX19_ARB = $88D3; - GL_MATRIX20_ARB = $88D4; - GL_MATRIX21_ARB = $88D5; - GL_MATRIX22_ARB = $88D6; - GL_MATRIX23_ARB = $88D7; - GL_MATRIX24_ARB = $88D8; - GL_MATRIX25_ARB = $88D9; - GL_MATRIX26_ARB = $88DA; - GL_MATRIX27_ARB = $88DB; - GL_MATRIX28_ARB = $88DC; - GL_MATRIX29_ARB = $88DD; - GL_MATRIX30_ARB = $88DE; - GL_MATRIX31_ARB = $88DF; - - // GL_ARB_draw_buffers - GL_MAX_DRAW_BUFFERS_ARB = $8824; - GL_DRAW_BUFFER0_ARB = $8825; - GL_DRAW_BUFFER1_ARB = $8826; - GL_DRAW_BUFFER2_ARB = $8827; - GL_DRAW_BUFFER3_ARB = $8828; - GL_DRAW_BUFFER4_ARB = $8829; - GL_DRAW_BUFFER5_ARB = $882A; - GL_DRAW_BUFFER6_ARB = $882B; - GL_DRAW_BUFFER7_ARB = $882C; - GL_DRAW_BUFFER8_ARB = $882D; - GL_DRAW_BUFFER9_ARB = $882E; - GL_DRAW_BUFFER10_ARB = $882F; - GL_DRAW_BUFFER11_ARB = $8830; - GL_DRAW_BUFFER12_ARB = $8831; - GL_DRAW_BUFFER13_ARB = $8832; - GL_DRAW_BUFFER14_ARB = $8833; - GL_DRAW_BUFFER15_ARB = $8834; - - // GL_ARB_texture_rectangle - GL_TEXTURE_RECTANGLE_ARB = $84F5; - GL_TEXTURE_BINDING_RECTANGLE_ARB = $84F6; - GL_PROXY_TEXTURE_RECTANGLE_ARB = $84F7; - GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB = $84F8; - - // GL_ARB_color_buffer_float - GL_RGBA_FLOAT_MODE_ARB = $8820; - GL_CLAMP_VERTEX_COLOR_ARB = $891A; - GL_CLAMP_FRAGMENT_COLOR_ARB = $891B; - GL_CLAMP_READ_COLOR_ARB = $891C; - GL_FIXED_ONLY_ARB = $891D; - WGL_TYPE_RGBA_FLOAT_ARB = $21A0; - GLX_RGBA_FLOAT_TYPE = $20B9; - GLX_RGBA_FLOAT_BIT = $00000004; - - // GL_ARB_half_float_pixel - GL_HALF_FLOAT_ARB = $140B; - - // GL_ARB_texture_float - GL_TEXTURE_RED_TYPE_ARB = $8C10; - GL_TEXTURE_GREEN_TYPE_ARB = $8C11; - GL_TEXTURE_BLUE_TYPE_ARB = $8C12; - GL_TEXTURE_ALPHA_TYPE_ARB = $8C13; - GL_TEXTURE_LUMINANCE_TYPE_ARB = $8C14; - GL_TEXTURE_INTENSITY_TYPE_ARB = $8C15; - GL_TEXTURE_DEPTH_TYPE_ARB = $8C16; - GL_UNSIGNED_NORMALIZED_ARB = $8C17; - GL_RGBA32F_ARB = $8814; - GL_RGB32F_ARB = $8815; - GL_ALPHA32F_ARB = $8816; - GL_INTENSITY32F_ARB = $8817; - GL_LUMINANCE32F_ARB = $8818; - GL_LUMINANCE_ALPHA32F_ARB = $8819; - GL_RGBA16F_ARB = $881A; - GL_RGB16F_ARB = $881B; - GL_ALPHA16F_ARB = $881C; - GL_INTENSITY16F_ARB = $881D; - GL_LUMINANCE16F_ARB = $881E; - GL_LUMINANCE_ALPHA16F_ARB = $881F; - - // GL_ARB_pixel_buffer_object - GL_PIXEL_PACK_BUFFER_ARB = $88EB; - GL_PIXEL_UNPACK_BUFFER_ARB = $88EC; - GL_PIXEL_PACK_BUFFER_BINDING_ARB = $88ED; - GL_PIXEL_UNPACK_BUFFER_BINDING_ARB = $88EF; - - // GL_ARB_depth_buffer_float - GL_DEPTH_COMPONENT32F = $8CAC; - GL_DEPTH32F_STENCIL8 = $8CAD; - GL_FLOAT_32_UNSIGNED_INT_24_8_REV = $8DAD; - - // GL_ARB_framebuffer_object - GL_INVALID_FRAMEBUFFER_OPERATION = $0506; - GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = $8210; - GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE = $8211; - GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE = $8212; - GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE = $8213; - GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE = $8214; - GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE = $8215; - GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE = $8216; - GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE = $8217; - GL_FRAMEBUFFER_DEFAULT = $8218; - GL_FRAMEBUFFER_UNDEFINED = $8219; - GL_DEPTH_STENCIL_ATTACHMENT = $821A; - GL_MAX_RENDERBUFFER_SIZE = $84E8; - GL_DEPTH_STENCIL = $84F9; - GL_UNSIGNED_INT_24_8 = $84FA; - GL_DEPTH24_STENCIL8 = $88F0; - GL_TEXTURE_STENCIL_SIZE = $88F1; - GL_TEXTURE_RED_TYPE = $8C10; - GL_TEXTURE_GREEN_TYPE = $8C11; - GL_TEXTURE_BLUE_TYPE = $8C12; - GL_TEXTURE_ALPHA_TYPE = $8C13; - GL_TEXTURE_DEPTH_TYPE = $8C16; - GL_UNSIGNED_NORMALIZED = $8C17; - GL_FRAMEBUFFER_BINDING = $8CA6; - GL_DRAW_FRAMEBUFFER_BINDING = GL_FRAMEBUFFER_BINDING; - GL_RENDERBUFFER_BINDING = $8CA7; - GL_READ_FRAMEBUFFER = $8CA8; - GL_DRAW_FRAMEBUFFER = $8CA9; - GL_READ_FRAMEBUFFER_BINDING = $8CAA; - GL_RENDERBUFFER_SAMPLES = $8CAB; - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = $8CD0; - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = $8CD1; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = $8CD2; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = $8CD3; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = $8CD4; - GL_FRAMEBUFFER_COMPLETE = $8CD5; - GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = $8CD6; - GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = $8CD7; - GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = $8CDB; - GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER = $8CDC; - GL_FRAMEBUFFER_UNSUPPORTED = $8CDD; - GL_MAX_COLOR_ATTACHMENTS = $8CDF; - GL_COLOR_ATTACHMENT0 = $8CE0; - GL_COLOR_ATTACHMENT1 = $8CE1; - GL_COLOR_ATTACHMENT2 = $8CE2; - GL_COLOR_ATTACHMENT3 = $8CE3; - GL_COLOR_ATTACHMENT4 = $8CE4; - GL_COLOR_ATTACHMENT5 = $8CE5; - GL_COLOR_ATTACHMENT6 = $8CE6; - GL_COLOR_ATTACHMENT7 = $8CE7; - GL_COLOR_ATTACHMENT8 = $8CE8; - GL_COLOR_ATTACHMENT9 = $8CE9; - GL_COLOR_ATTACHMENT10 = $8CEA; - GL_COLOR_ATTACHMENT11 = $8CEB; - GL_COLOR_ATTACHMENT12 = $8CEC; - GL_COLOR_ATTACHMENT13 = $8CED; - GL_COLOR_ATTACHMENT14 = $8CEE; - GL_COLOR_ATTACHMENT15 = $8CEF; - GL_DEPTH_ATTACHMENT = $8D00; - GL_STENCIL_ATTACHMENT = $8D20; - GL_FRAMEBUFFER = $8D40; - GL_RENDERBUFFER = $8D41; - GL_RENDERBUFFER_WIDTH = $8D42; - GL_RENDERBUFFER_HEIGHT = $8D43; - GL_RENDERBUFFER_INTERNAL_FORMAT = $8D44; - GL_STENCIL_INDEX1 = $8D46; - GL_STENCIL_INDEX4 = $8D47; - GL_STENCIL_INDEX8 = $8D48; - GL_STENCIL_INDEX16 = $8D49; - GL_RENDERBUFFER_RED_SIZE = $8D50; - GL_RENDERBUFFER_GREEN_SIZE = $8D51; - GL_RENDERBUFFER_BLUE_SIZE = $8D52; - GL_RENDERBUFFER_ALPHA_SIZE = $8D53; - GL_RENDERBUFFER_DEPTH_SIZE = $8D54; - GL_RENDERBUFFER_STENCIL_SIZE = $8D55; - GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = $8D56; - GL_MAX_SAMPLES = $8D57; -{$ifdef DGL_DEPRECATED} - GL_INDEX = $8222; - GL_TEXTURE_LUMINANCE_TYPE = $8C14; - GL_TEXTURE_INTENSITY_TYPE = $8C15; -{$endif} - - // GL_ARB_framebuffer_sRGB - GL_FRAMEBUFFER_SRGB = $8DB9; - - // GL_ARB_geometry_shader4 - GL_LINES_ADJACENCY_ARB = $000A; - GL_LINE_STRIP_ADJACENCY_ARB = $000B; - GL_TRIANGLES_ADJACENCY_ARB = $000C; - GL_TRIANGLE_STRIP_ADJACENCY_ARB = $000D; - GL_PROGRAM_POINT_SIZE_ARB = $8642; - GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB = $8C29; - GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB = $8DA7; - GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB = $8DA8; - GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB = $8DA9; - GL_GEOMETRY_SHADER_ARB = $8DD9; - GL_GEOMETRY_VERTICES_OUT_ARB = $8DDA; - GL_GEOMETRY_INPUT_TYPE_ARB = $8DDB; - GL_GEOMETRY_OUTPUT_TYPE_ARB = $8DDC; - GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB = $8DDD; - GL_MAX_VERTEX_VARYING_COMPONENTS_ARB = $8DDE; - GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB = $8DDF; - GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB = $8DE0; - GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB = $8DE1; - { reuse GL_MAX_VARYING_COMPONENTS } - { reuse GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER } - - // GL_ARB_half_float_vertex - GL_HALF_FLOAT = $140B; - - // GL_ARB_instanced_arrays - GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB = $88FE; - - // GL_ARB_map_buffer_range - GL_MAP_READ_BIT = $0001; - GL_MAP_WRITE_BIT = $0002; - GL_MAP_INVALIDATE_RANGE_BIT = $0004; - GL_MAP_INVALIDATE_BUFFER_BIT = $0008; - GL_MAP_FLUSH_EXPLICIT_BIT = $0010; - GL_MAP_UNSYNCHRONIZED_BIT = $0020; - - // GL_ARB_texture_buffer_object - GL_TEXTURE_BUFFER_ARB = $8C2A; - GL_MAX_TEXTURE_BUFFER_SIZE_ARB = $8C2B; - GL_TEXTURE_BINDING_BUFFER_ARB = $8C2C; - GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB = $8C2D; - GL_TEXTURE_BUFFER_FORMAT_ARB = $8C2E; - - // GL_ARB_texture_compression_rgtc - GL_COMPRESSED_RED_RGTC1 = $8DBB; - GL_COMPRESSED_SIGNED_RED_RGTC1 = $8DBC; - GL_COMPRESSED_RG_RGTC2 = $8DBD; - GL_COMPRESSED_SIGNED_RG_RGTC2 = $8DBE; - - // GL_ARB_texture_rg - GL_RG = $8227; - GL_RG_INTEGER = $8228; - GL_R8 = $8229; - GL_R16 = $822A; - GL_RG8 = $822B; - GL_RG16 = $822C; - GL_R16F = $822D; - GL_R32F = $822E; - GL_RG16F = $822F; - GL_RG32F = $8230; - GL_R8I = $8231; - GL_R8UI = $8232; - GL_R16I = $8233; - GL_R16UI = $8234; - GL_R32I = $8235; - GL_R32UI = $8236; - GL_RG8I = $8237; - GL_RG8UI = $8238; - GL_RG16I = $8239; - GL_RG16UI = $823A; - GL_RG32I = $823B; - GL_RG32UI = $823C; - - // GL_ARB_vertex_array_object - GL_VERTEX_ARRAY_BINDING = $85B5; - - // GL_ARB_uniform_buffer_object - GL_UNIFORM_BUFFER = $8A11; - GL_UNIFORM_BUFFER_BINDING = $8A28; - GL_UNIFORM_BUFFER_START = $8A29; - GL_UNIFORM_BUFFER_SIZE = $8A2A; - GL_MAX_VERTEX_UNIFORM_BLOCKS = $8A2B; - GL_MAX_GEOMETRY_UNIFORM_BLOCKS = $8A2C; - GL_MAX_FRAGMENT_UNIFORM_BLOCKS = $8A2D; - GL_MAX_COMBINED_UNIFORM_BLOCKS = $8A2E; - GL_MAX_UNIFORM_BUFFER_BINDINGS = $8A2F; - GL_MAX_UNIFORM_BLOCK_SIZE = $8A30; - GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = $8A31; - GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS = $8A32; - GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = $8A33; - GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = $8A34; - GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH = $8A35; - GL_ACTIVE_UNIFORM_BLOCKS = $8A36; - GL_UNIFORM_TYPE = $8A37; - GL_UNIFORM_SIZE = $8A38; - GL_UNIFORM_NAME_LENGTH = $8A39; - GL_UNIFORM_BLOCK_INDEX = $8A3A; - GL_UNIFORM_OFFSET = $8A3B; - GL_UNIFORM_ARRAY_STRIDE = $8A3C; - GL_UNIFORM_MATRIX_STRIDE = $8A3D; - GL_UNIFORM_IS_ROW_MAJOR = $8A3E; - GL_UNIFORM_BLOCK_BINDING = $8A3F; - GL_UNIFORM_BLOCK_DATA_SIZE = $8A40; - GL_UNIFORM_BLOCK_NAME_LENGTH = $8A41; - GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS = $8A42; - GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = $8A43; - GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = $8A44; - GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER = $8A45; - GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = $8A46; - GL_INVALID_INDEX = $FFFFFFFF; - - // GL_ARB_compatibility - { ARB_compatibility just defines tokens from core 3.0 } - - // GL_ARB_copy_buffer - GL_COPY_READ_BUFFER = $8F36; - GL_COPY_WRITE_BUFFER = $8F37; - - // GL_ARB_depth_clamp - GL_DEPTH_CLAMP = $864F; - - // GL_ARB_provoking_vertex - GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION = $8E4C; - GL_FIRST_VERTEX_CONVENTION = $8E4D; - GL_LAST_VERTEX_CONVENTION = $8E4E; - GL_PROVOKING_VERTEX = $8E4F; - - // GL_ARB_seamless_cube_map - GL_TEXTURE_CUBE_MAP_SEAMLESS = $884F; - - // GL_ARB_sync - GL_MAX_SERVER_WAIT_TIMEOUT = $9111; - GL_OBJECT_TYPE = $9112; - GL_SYNC_CONDITION = $9113; - GL_SYNC_STATUS = $9114; - GL_SYNC_FLAGS = $9115; - GL_SYNC_FENCE = $9116; - GL_SYNC_GPU_COMMANDS_COMPLETE = $9117; - GL_UNSIGNALED = $9118; - GL_SIGNALED = $9119; - GL_ALREADY_SIGNALED = $911A; - GL_TIMEOUT_EXPIRED = $911B; - GL_CONDITION_SATISFIED = $911C; - GL_WAIT_FAILED = $911D; - GL_SYNC_FLUSH_COMMANDS_BIT = $00000001; - GL_TIMEOUT_IGNORED = $FFFFFFFFFFFFFFFF; - - // GL_ARB_texture_multisample - GL_SAMPLE_POSITION = $8E50; - GL_SAMPLE_MASK = $8E51; - GL_SAMPLE_MASK_VALUE = $8E52; - GL_MAX_SAMPLE_MASK_WORDS = $8E59; - GL_TEXTURE_2D_MULTISAMPLE = $9100; - GL_PROXY_TEXTURE_2D_MULTISAMPLE = $9101; - GL_TEXTURE_2D_MULTISAMPLE_ARRAY = $9102; - GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY = $9103; - GL_TEXTURE_BINDING_2D_MULTISAMPLE = $9104; - GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY = $9105; - GL_TEXTURE_SAMPLES = $9106; - GL_TEXTURE_FIXED_SAMPLE_LOCATIONS = $9107; - GL_SAMPLER_2D_MULTISAMPLE = $9108; - GL_INT_SAMPLER_2D_MULTISAMPLE = $9109; - GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = $910A; - GL_SAMPLER_2D_MULTISAMPLE_ARRAY = $910B; - GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY = $910C; - GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY = $910D; - GL_MAX_COLOR_TEXTURE_SAMPLES = $910E; - GL_MAX_DEPTH_TEXTURE_SAMPLES = $910F; - GL_MAX_INTEGER_SAMPLES = $9110; - - // GL_ARB_vertex_array_bgra - { reuse GL_BGRA } - - // GL_ARB_sample_shading - GL_SAMPLE_SHADING = $8C36; - GL_MIN_SAMPLE_SHADING_VALUE = $8C37; - - // GL_ARB_texture_cube_map_array - GL_TEXTURE_CUBE_MAP_ARRAY = $9009; - GL_TEXTURE_BINDING_CUBE_MAP_ARRAY = $900A; - GL_PROXY_TEXTURE_CUBE_MAP_ARRAY = $900B; - GL_SAMPLER_CUBE_MAP_ARRAY = $900C; - GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW = $900D; - GL_INT_SAMPLER_CUBE_MAP_ARRAY = $900E; - GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY = $900F; - - // GL_ARB_texture_gather - GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET = $8E5E; - GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET = $8E5F; - GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS = $8F9F; - - // GL_ATI_draw_buffers - GL_MAX_DRAW_BUFFERS_ATI = $8824; - GL_DRAW_BUFFER0_ATI = $8825; - GL_DRAW_BUFFER1_ATI = $8826; - GL_DRAW_BUFFER2_ATI = $8827; - GL_DRAW_BUFFER3_ATI = $8828; - GL_DRAW_BUFFER4_ATI = $8829; - GL_DRAW_BUFFER5_ATI = $882A; - GL_DRAW_BUFFER6_ATI = $882B; - GL_DRAW_BUFFER7_ATI = $882C; - GL_DRAW_BUFFER8_ATI = $882D; - GL_DRAW_BUFFER9_ATI = $882E; - GL_DRAW_BUFFER10_ATI = $882F; - GL_DRAW_BUFFER11_ATI = $8830; - GL_DRAW_BUFFER12_ATI = $8831; - GL_DRAW_BUFFER13_ATI = $8832; - GL_DRAW_BUFFER14_ATI = $8833; - GL_DRAW_BUFFER15_ATI = $8834; - - // GL_ATI_element_array - GL_ELEMENT_ARRAY_ATI = $8768; - GL_ELEMENT_ARRAY_TYPE_ATI = $8769; - GL_ELEMENT_ARRAY_POINTER_ATI = $876A; - - // GL_ATI_envmap_bumpmap - GL_BUMP_ROT_MATRIX_ATI = $8775; - GL_BUMP_ROT_MATRIX_SIZE_ATI = $8776; - GL_BUMP_NUM_TEX_UNITS_ATI = $8777; - GL_BUMP_TEX_UNITS_ATI = $8778; - GL_DUDV_ATI = $8779; - GL_DU8DV8_ATI = $877A; - GL_BUMP_ENVMAP_ATI = $877B; - GL_BUMP_TARGET_ATI = $877C; - - // GL_ATI_fragment_shader - GL_FRAGMENT_SHADER_ATI = $8920; - GL_REG_0_ATI = $8921; - GL_REG_1_ATI = $8922; - GL_REG_2_ATI = $8923; - GL_REG_3_ATI = $8924; - GL_REG_4_ATI = $8925; - GL_REG_5_ATI = $8926; - GL_REG_6_ATI = $8927; - GL_REG_7_ATI = $8928; - GL_REG_8_ATI = $8929; - GL_REG_9_ATI = $892A; - GL_REG_10_ATI = $892B; - GL_REG_11_ATI = $892C; - GL_REG_12_ATI = $892D; - GL_REG_13_ATI = $892E; - GL_REG_14_ATI = $892F; - GL_REG_15_ATI = $8930; - GL_REG_16_ATI = $8931; - GL_REG_17_ATI = $8932; - GL_REG_18_ATI = $8933; - GL_REG_19_ATI = $8934; - GL_REG_20_ATI = $8935; - GL_REG_21_ATI = $8936; - GL_REG_22_ATI = $8937; - GL_REG_23_ATI = $8938; - GL_REG_24_ATI = $8939; - GL_REG_25_ATI = $893A; - GL_REG_26_ATI = $893B; - GL_REG_27_ATI = $893C; - GL_REG_28_ATI = $893D; - GL_REG_29_ATI = $893E; - GL_REG_30_ATI = $893F; - GL_REG_31_ATI = $8940; - GL_CON_0_ATI = $8941; - GL_CON_1_ATI = $8942; - GL_CON_2_ATI = $8943; - GL_CON_3_ATI = $8944; - GL_CON_4_ATI = $8945; - GL_CON_5_ATI = $8946; - GL_CON_6_ATI = $8947; - GL_CON_7_ATI = $8948; - GL_CON_8_ATI = $8949; - GL_CON_9_ATI = $894A; - GL_CON_10_ATI = $894B; - GL_CON_11_ATI = $894C; - GL_CON_12_ATI = $894D; - GL_CON_13_ATI = $894E; - GL_CON_14_ATI = $894F; - GL_CON_15_ATI = $8950; - GL_CON_16_ATI = $8951; - GL_CON_17_ATI = $8952; - GL_CON_18_ATI = $8953; - GL_CON_19_ATI = $8954; - GL_CON_20_ATI = $8955; - GL_CON_21_ATI = $8956; - GL_CON_22_ATI = $8957; - GL_CON_23_ATI = $8958; - GL_CON_24_ATI = $8959; - GL_CON_25_ATI = $895A; - GL_CON_26_ATI = $895B; - GL_CON_27_ATI = $895C; - GL_CON_28_ATI = $895D; - GL_CON_29_ATI = $895E; - GL_CON_30_ATI = $895F; - GL_CON_31_ATI = $8960; - GL_MOV_ATI = $8961; - GL_ADD_ATI = $8963; - GL_MUL_ATI = $8964; - GL_SUB_ATI = $8965; - GL_DOT3_ATI = $8966; - GL_DOT4_ATI = $8967; - GL_MAD_ATI = $8968; - GL_LERP_ATI = $8969; - GL_CND_ATI = $896A; - GL_CND0_ATI = $896B; - GL_DOT2_ADD_ATI = $896C; - GL_SECONDARY_INTERPOLATOR_ATI = $896D; - GL_NUM_FRAGMENT_REGISTERS_ATI = $896E; - GL_NUM_FRAGMENT_CONSTANTS_ATI = $896F; - GL_NUM_PASSES_ATI = $8970; - GL_NUM_INSTRUCTIONS_PER_PASS_ATI = $8971; - GL_NUM_INSTRUCTIONS_TOTAL_ATI = $8972; - GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI = $8973; - GL_NUM_LOOPBACK_COMPONENTS_ATI = $8974; - GL_COLOR_ALPHA_PAIRING_ATI = $8975; - GL_SWIZZLE_STR_ATI = $8976; - GL_SWIZZLE_STQ_ATI = $8977; - GL_SWIZZLE_STR_DR_ATI = $8978; - GL_SWIZZLE_STQ_DQ_ATI = $8979; - GL_SWIZZLE_STRQ_ATI = $897A; - GL_SWIZZLE_STRQ_DQ_ATI = $897B; - GL_RED_BIT_ATI = $00000001; - GL_GREEN_BIT_ATI = $00000002; - GL_BLUE_BIT_ATI = $00000004; - GL_2X_BIT_ATI = $00000001; - GL_4X_BIT_ATI = $00000002; - GL_8X_BIT_ATI = $00000004; - GL_HALF_BIT_ATI = $00000008; - GL_QUARTER_BIT_ATI = $00000010; - GL_EIGHTH_BIT_ATI = $00000020; - GL_SATURATE_BIT_ATI = $00000040; - GL_COMP_BIT_ATI = $00000002; - GL_NEGATE_BIT_ATI = $00000004; - GL_BIAS_BIT_ATI = $00000008; - - // GL_ATI_pn_triangles - GL_PN_TRIANGLES_ATI = $87F0; - GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI = $87F1; - GL_PN_TRIANGLES_POINT_MODE_ATI = $87F2; - GL_PN_TRIANGLES_NORMAL_MODE_ATI = $87F3; - GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI = $87F4; - GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI = $87F5; - GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI = $87F6; - GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI = $87F7; - GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI = $87F8; - - // GL_ATI_separate_stencil - GL_STENCIL_BACK_FUNC_ATI = $8800; - GL_STENCIL_BACK_FAIL_ATI = $8801; - GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI = $8802; - GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI = $8803; - - // GL_ATI_text_fragment_shader - GL_TEXT_FRAGMENT_SHADER_ATI = $8200; - - // GL_ATI_texture_env_combine3 - GL_MODULATE_ADD_ATI = $8744; - GL_MODULATE_SIGNED_ADD_ATI = $8745; - GL_MODULATE_SUBTRACT_ATI = $8746; - - // GL_ATI_texture_float - GL_RGBA_FLOAT32_ATI = $8814; - GL_RGB_FLOAT32_ATI = $8815; - GL_ALPHA_FLOAT32_ATI = $8816; - GL_INTENSITY_FLOAT32_ATI = $8817; - GL_LUMINANCE_FLOAT32_ATI = $8818; - GL_LUMINANCE_ALPHA_FLOAT32_ATI = $8819; - GL_RGBA_FLOAT16_ATI = $881A; - GL_RGB_FLOAT16_ATI = $881B; - GL_ALPHA_FLOAT16_ATI = $881C; - GL_INTENSITY_FLOAT16_ATI = $881D; - GL_LUMINANCE_FLOAT16_ATI = $881E; - GL_LUMINANCE_ALPHA_FLOAT16_ATI = $881F; - - // GL_ATI_texture_mirror_once - GL_MIRROR_CLAMP_ATI = $8742; - GL_MIRROR_CLAMP_TO_EDGE_ATI = $8743; - - // GL_ATI_vertex_array_object - GL_STATIC_ATI = $8760; - GL_DYNAMIC_ATI = $8761; - GL_PRESERVE_ATI = $8762; - GL_DISCARD_ATI = $8763; - GL_OBJECT_BUFFER_SIZE_ATI = $8764; - GL_OBJECT_BUFFER_USAGE_ATI = $8765; - GL_ARRAY_OBJECT_BUFFER_ATI = $8766; - GL_ARRAY_OBJECT_OFFSET_ATI = $8767; - - // GL_ATI_vertex_streams - GL_MAX_VERTEX_STREAMS_ATI = $876B; - GL_VERTEX_STREAM0_ATI = $876C; - GL_VERTEX_STREAM1_ATI = $876D; - GL_VERTEX_STREAM2_ATI = $876E; - GL_VERTEX_STREAM3_ATI = $876F; - GL_VERTEX_STREAM4_ATI = $8770; - GL_VERTEX_STREAM5_ATI = $8771; - GL_VERTEX_STREAM6_ATI = $8772; - GL_VERTEX_STREAM7_ATI = $8773; - GL_VERTEX_SOURCE_ATI = $8774; - - // GL_ATI_meminfo - GL_VBO_FREE_MEMORY_ATI = $87FB; - GL_TEXTURE_FREE_MEMORY_ATI = $87FC; - GL_RENDERBUFFER_FREE_MEMORY_ATI = $87FD; - - // GL_AMD_performance_monitor - GL_COUNTER_TYPE_AMD = $8BC0; - GL_COUNTER_RANGE_AMD = $8BC1; - GL_UNSIGNED_INT64_AMD = $8BC2; - GL_PERCENTAGE_AMD = $8BC3; - GL_PERFMON_RESULT_AVAILABLE_AMD = $8BC4; - GL_PERFMON_RESULT_SIZE_AMD = $8BC5; - GL_PERFMON_RESULT_AMD = $8BC6; - - // GL_AMD_vertex_shader_tesselator - GL_SAMPLER_BUFFER_AMD = $9001; - GL_INT_SAMPLER_BUFFER_AMD = $9002; - GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD = $9003; - GL_TESSELLATION_MODE_AMD = $9004; - GL_TESSELLATION_FACTOR_AMD = $9005; - GL_DISCRETE_AMD = $9006; - GL_CONTINUOUS_AMD = $9007; - - // GL_EXT_422_pixels - GL_422_EXT = $80CC; - GL_422_REV_EXT = $80CD; - GL_422_AVERAGE_EXT = $80CE; - GL_422_REV_AVERAGE_EXT = $80CF; - - // GL_EXT_abgr - GL_ABGR_EXT = $8000; - - // GL_EXT_bgra - GL_BGR_EXT = $80E0; - GL_BGRA_EXT = $80E1; - - // GL_EXT_blend_color - GL_CONSTANT_COLOR_EXT = $8001; - GL_ONE_MINUS_CONSTANT_COLOR_EXT = $8002; - GL_CONSTANT_ALPHA_EXT = $8003; - GL_ONE_MINUS_CONSTANT_ALPHA_EXT = $8004; - GL_BLEND_COLOR_EXT = $8005; - - // GL_EXT_blend_func_separate - GL_BLEND_DST_RGB_EXT = $80C8; - GL_BLEND_SRC_RGB_EXT = $80C9; - GL_BLEND_DST_ALPHA_EXT = $80CA; - GL_BLEND_SRC_ALPHA_EXT = $80CB; - - // GL_EXT_blend_minmax - GL_FUNC_ADD_EXT = $8006; - GL_MIN_EXT = $8007; - GL_MAX_EXT = $8008; - GL_BLEND_EQUATION_EXT = $8009; - - // GL_EXT_blend_subtract - GL_FUNC_SUBTRACT_EXT = $800A; - GL_FUNC_REVERSE_SUBTRACT_EXT = $800B; - - // GL_EXT_clip_volume_hint - GL_CLIP_VOLUME_CLIPPING_HINT_EXT = $80F0; - - // GL_EXT_cmyka - GL_CMYK_EXT = $800C; - GL_CMYKA_EXT = $800D; - GL_PACK_CMYK_HINT_EXT = $800E; - GL_UNPACK_CMYK_HINT_EXT = $800F; - - // GL_EXT_compiled_vertex_array - GL_ARRAY_ELEMENT_LOCK_FIRST_EXT = $81A8; - GL_ARRAY_ELEMENT_LOCK_COUNT_EXT = $81A9; - - // GL_EXT_convolution - GL_CONVOLUTION_1D_EXT = $8010; - GL_CONVOLUTION_2D_EXT = $8011; - GL_SEPARABLE_2D_EXT = $8012; - GL_CONVOLUTION_BORDER_MODE_EXT = $8013; - GL_CONVOLUTION_FILTER_SCALE_EXT = $8014; - GL_CONVOLUTION_FILTER_BIAS_EXT = $8015; - GL_REDUCE_EXT = $8016; - GL_CONVOLUTION_FORMAT_EXT = $8017; - GL_CONVOLUTION_WIDTH_EXT = $8018; - GL_CONVOLUTION_HEIGHT_EXT = $8019; - GL_MAX_CONVOLUTION_WIDTH_EXT = $801A; - GL_MAX_CONVOLUTION_HEIGHT_EXT = $801B; - GL_POST_CONVOLUTION_RED_SCALE_EXT = $801C; - GL_POST_CONVOLUTION_GREEN_SCALE_EXT = $801D; - GL_POST_CONVOLUTION_BLUE_SCALE_EXT = $801E; - GL_POST_CONVOLUTION_ALPHA_SCALE_EXT = $801F; - GL_POST_CONVOLUTION_RED_BIAS_EXT = $8020; - GL_POST_CONVOLUTION_GREEN_BIAS_EXT = $8021; - GL_POST_CONVOLUTION_BLUE_BIAS_EXT = $8022; - GL_POST_CONVOLUTION_ALPHA_BIAS_EXT = $8023; - - // GL_EXT_coordinate_frame - GL_TANGENT_ARRAY_EXT = $8439; - GL_BINORMAL_ARRAY_EXT = $843A; - GL_CURRENT_TANGENT_EXT = $843B; - GL_CURRENT_BINORMAL_EXT = $843C; - GL_TANGENT_ARRAY_TYPE_EXT = $843E; - GL_TANGENT_ARRAY_STRIDE_EXT = $843F; - GL_BINORMAL_ARRAY_TYPE_EXT = $8440; - GL_BINORMAL_ARRAY_STRIDE_EXT = $8441; - GL_TANGENT_ARRAY_POINTER_EXT = $8442; - GL_BINORMAL_ARRAY_POINTER_EXT = $8443; - GL_MAP1_TANGENT_EXT = $8444; - GL_MAP2_TANGENT_EXT = $8445; - GL_MAP1_BINORMAL_EXT = $8446; - GL_MAP2_BINORMAL_EXT = $8447; - - // GL_EXT_cull_vertex - GL_CULL_VERTEX_EXT = $81AA; - GL_CULL_VERTEX_EYE_POSITION_EXT = $81AB; - GL_CULL_VERTEX_OBJECT_POSITION_EXT = $81AC; - - // GL_EXT_draw_range_elements - GL_MAX_ELEMENTS_VERTICES_EXT = $80E8; - GL_MAX_ELEMENTS_INDICES_EXT = $80E9; - - // GL_EXT_fog_coord - GL_FOG_COORDINATE_SOURCE_EXT = $8450; - GL_FOG_COORDINATE_EXT = $8451; - GL_FRAGMENT_DEPTH_EXT = $8452; - GL_CURRENT_FOG_COORDINATE_EXT = $8453; - GL_FOG_COORDINATE_ARRAY_TYPE_EXT = $8454; - GL_FOG_COORDINATE_ARRAY_STRIDE_EXT = $8455; - GL_FOG_COORDINATE_ARRAY_POINTER_EXT = $8456; - GL_FOG_COORDINATE_ARRAY_EXT = $8457; - - // GL_EXT_framebuffer_object - GL_FRAMEBUFFER_EXT = $8D40; - GL_RENDERBUFFER_EXT = $8D41; - GL_STENCIL_INDEX_EXT = $8D45; - GL_STENCIL_INDEX1_EXT = $8D46; - GL_STENCIL_INDEX4_EXT = $8D47; - GL_STENCIL_INDEX8_EXT = $8D48; - GL_STENCIL_INDEX16_EXT = $8D49; - GL_RENDERBUFFER_WIDTH_EXT = $8D42; - GL_RENDERBUFFER_HEIGHT_EXT = $8D43; - GL_RENDERBUFFER_INTERNAL_FORMAT_EXT = $8D44; - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT = $8CD0; - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT = $8CD1; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT = $8CD2; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT = $8CD3; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT = $8CD4; - GL_COLOR_ATTACHMENT0_EXT = $8CE0; - GL_COLOR_ATTACHMENT1_EXT = $8CE1; - GL_COLOR_ATTACHMENT2_EXT = $8CE2; - GL_COLOR_ATTACHMENT3_EXT = $8CE3; - GL_COLOR_ATTACHMENT4_EXT = $8CE4; - GL_COLOR_ATTACHMENT5_EXT = $8CE5; - GL_COLOR_ATTACHMENT6_EXT = $8CE6; - GL_COLOR_ATTACHMENT7_EXT = $8CE7; - GL_COLOR_ATTACHMENT8_EXT = $8CE8; - GL_COLOR_ATTACHMENT9_EXT = $8CE9; - GL_COLOR_ATTACHMENT10_EXT = $8CEA; - GL_COLOR_ATTACHMENT11_EXT = $8CEB; - GL_COLOR_ATTACHMENT12_EXT = $8CEC; - GL_COLOR_ATTACHMENT13_EXT = $8CED; - GL_COLOR_ATTACHMENT14_EXT = $8CEE; - GL_COLOR_ATTACHMENT15_EXT = $8CEF; - GL_DEPTH_ATTACHMENT_EXT = $8D00; - GL_STENCIL_ATTACHMENT_EXT = $8D20; - GL_FRAMEBUFFER_COMPLETE_EXT = $8CD5; - GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT = $8CD6; - GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT = $8CD7; - GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT = $8CD8; - GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT = $8CD9; - GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT = $8CDA; - GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT = $8CDB; - GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT = $8CDC; - GL_FRAMEBUFFER_UNSUPPORTED_EXT = $8CDD; - GL_FRAMEBUFFER_STATUS_ERROR_EXT = $8CDE; - GL_FRAMEBUFFER_BINDING_EXT = $8CA6; - GL_RENDERBUFFER_BINDING_EXT = $8CA7; - GL_MAX_COLOR_ATTACHMENTS_EXT = $8CDF; - GL_MAX_RENDERBUFFER_SIZE_EXT = $84E8; - GL_INVALID_FRAMEBUFFER_OPERATION_EXT = $0506; - - // GL_EXT_histogram - GL_HISTOGRAM_EXT = $8024; - GL_PROXY_HISTOGRAM_EXT = $8025; - GL_HISTOGRAM_WIDTH_EXT = $8026; - GL_HISTOGRAM_FORMAT_EXT = $8027; - GL_HISTOGRAM_RED_SIZE_EXT = $8028; - GL_HISTOGRAM_GREEN_SIZE_EXT = $8029; - GL_HISTOGRAM_BLUE_SIZE_EXT = $802A; - GL_HISTOGRAM_ALPHA_SIZE_EXT = $802B; - GL_HISTOGRAM_LUMINANCE_SIZE_EXT = $802C; - GL_HISTOGRAM_SINK_EXT = $802D; - GL_MINMAX_EXT = $802E; - GL_MINMAX_FORMAT_EXT = $802F; - GL_MINMAX_SINK_EXT = $8030; - GL_TABLE_TOO_LARGE_EXT = $8031; - - // GL_EXT_index_array_formats - GL_IUI_V2F_EXT = $81AD; - GL_IUI_V3F_EXT = $81AE; - GL_IUI_N3F_V2F_EXT = $81AF; - GL_IUI_N3F_V3F_EXT = $81B0; - GL_T2F_IUI_V2F_EXT = $81B1; - GL_T2F_IUI_V3F_EXT = $81B2; - GL_T2F_IUI_N3F_V2F_EXT = $81B3; - GL_T2F_IUI_N3F_V3F_EXT = $81B4; - - // GL_EXT_index_func - GL_INDEX_TEST_EXT = $81B5; - GL_INDEX_TEST_FUNC_EXT = $81B6; - GL_INDEX_TEST_REF_EXT = $81B7; - - // GL_EXT_index_material - GL_INDEX_MATERIAL_EXT = $81B8; - GL_INDEX_MATERIAL_PARAMETER_EXT = $81B9; - GL_INDEX_MATERIAL_FACE_EXT = $81BA; - - // GL_EXT_light_texture - GL_FRAGMENT_MATERIAL_EXT = $8349; - GL_FRAGMENT_NORMAL_EXT = $834A; - GL_FRAGMENT_COLOR_EXT = $834C; - GL_ATTENUATION_EXT = $834D; - GL_SHADOW_ATTENUATION_EXT = $834E; - GL_TEXTURE_APPLICATION_MODE_EXT = $834F; - GL_TEXTURE_LIGHT_EXT = $8350; - GL_TEXTURE_MATERIAL_FACE_EXT = $8351; - GL_TEXTURE_MATERIAL_PARAMETER_EXT = $8352; - - // GL_EXT_multisample - GL_MULTISAMPLE_EXT = $809D; - GL_SAMPLE_ALPHA_TO_MASK_EXT = $809E; - GL_SAMPLE_ALPHA_TO_ONE_EXT = $809F; - GL_SAMPLE_MASK_EXT = $80A0; - GL_1PASS_EXT = $80A1; - GL_2PASS_0_EXT = $80A2; - GL_2PASS_1_EXT = $80A3; - GL_4PASS_0_EXT = $80A4; - GL_4PASS_1_EXT = $80A5; - GL_4PASS_2_EXT = $80A6; - GL_4PASS_3_EXT = $80A7; - GL_SAMPLE_BUFFERS_EXT = $80A8; - GL_SAMPLES_EXT = $80A9; - GL_SAMPLE_MASK_VALUE_EXT = $80AA; - GL_SAMPLE_MASK_INVERT_EXT = $80AB; - GL_SAMPLE_PATTERN_EXT = $80AC; - GL_MULTISAMPLE_BIT_EXT = $20000000; - - // GL_EXT_packed_pixels - GL_UNSIGNED_BYTE_3_3_2_EXT = $8032; - GL_UNSIGNED_SHORT_4_4_4_4_EXT = $8033; - GL_UNSIGNED_SHORT_5_5_5_1_EXT = $8034; - GL_UNSIGNED_INT_8_8_8_8_EXT = $8035; - GL_UNSIGNED_INT_10_10_10_2_EXT = $8036; - - // GL_EXT_paletted_texture - GL_COLOR_INDEX1_EXT = $80E2; - GL_COLOR_INDEX2_EXT = $80E3; - GL_COLOR_INDEX4_EXT = $80E4; - GL_COLOR_INDEX8_EXT = $80E5; - GL_COLOR_INDEX12_EXT = $80E6; - GL_COLOR_INDEX16_EXT = $80E7; - GL_TEXTURE_INDEX_SIZE_EXT = $80ED; - - // GL_EXT_pixel_transform - GL_PIXEL_TRANSFORM_2D_EXT = $8330; - GL_PIXEL_MAG_FILTER_EXT = $8331; - GL_PIXEL_MIN_FILTER_EXT = $8332; - GL_PIXEL_CUBIC_WEIGHT_EXT = $8333; - GL_CUBIC_EXT = $8334; - GL_AVERAGE_EXT = $8335; - GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT = $8336; - GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT = $8337; - GL_PIXEL_TRANSFORM_2D_MATRIX_EXT = $8338; - - // GL_EXT_point_parameters - GL_POINT_SIZE_MIN_EXT = $8126; - GL_POINT_SIZE_MAX_EXT = $8127; - GL_POINT_FADE_THRESHOLD_SIZE_EXT = $8128; - GL_DISTANCE_ATTENUATION_EXT = $8129; - - // GL_EXT_polygon_offset - GL_POLYGON_OFFSET_EXT = $8037; - GL_POLYGON_OFFSET_FACTOR_EXT = $8038; - GL_POLYGON_OFFSET_BIAS_EXT = $8039; - - // GL_EXT_rescale_normal - GL_RESCALE_NORMAL_EXT = $803A; - - // GL_EXT_secondary_color - GL_COLOR_SUM_EXT = $8458; - GL_CURRENT_SECONDARY_COLOR_EXT = $8459; - GL_SECONDARY_COLOR_ARRAY_SIZE_EXT = $845A; - GL_SECONDARY_COLOR_ARRAY_TYPE_EXT = $845B; - GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT = $845C; - GL_SECONDARY_COLOR_ARRAY_POINTER_EXT = $845D; - GL_SECONDARY_COLOR_ARRAY_EXT = $845E; - - // GL_EXT_separate_specular_color - GL_LIGHT_MODEL_COLOR_CONTROL_EXT = $81F8; - GL_SINGLE_COLOR_EXT = $81F9; - GL_SEPARATE_SPECULAR_COLOR_EXT = $81FA; - - // GL_EXT_shared_texture_palette - GL_SHARED_TEXTURE_PALETTE_EXT = $81FB; - - // GL_EXT_stencil_two_side - GL_STENCIL_TEST_TWO_SIDE_EXT = $8910; - GL_ACTIVE_STENCIL_FACE_EXT = $8911; - - // GL_EXT_stencil_wrap - GL_INCR_WRAP_EXT = $8507; - GL_DECR_WRAP_EXT = $8508; - - // GL_EXT_texture - GL_ALPHA4_EXT = $803B; - GL_ALPHA8_EXT = $803C; - GL_ALPHA12_EXT = $803D; - GL_ALPHA16_EXT = $803E; - GL_LUMINANCE4_EXT = $803F; - GL_LUMINANCE8_EXT = $8040; - GL_LUMINANCE12_EXT = $8041; - GL_LUMINANCE16_EXT = $8042; - GL_LUMINANCE4_ALPHA4_EXT = $8043; - GL_LUMINANCE6_ALPHA2_EXT = $8044; - GL_LUMINANCE8_ALPHA8_EXT = $8045; - GL_LUMINANCE12_ALPHA4_EXT = $8046; - GL_LUMINANCE12_ALPHA12_EXT = $8047; - GL_LUMINANCE16_ALPHA16_EXT = $8048; - GL_INTENSITY_EXT = $8049; - GL_INTENSITY4_EXT = $804A; - GL_INTENSITY8_EXT = $804B; - GL_INTENSITY12_EXT = $804C; - GL_INTENSITY16_EXT = $804D; - GL_RGB2_EXT = $804E; - GL_RGB4_EXT = $804F; - GL_RGB5_EXT = $8050; - GL_RGB8_EXT = $8051; - GL_RGB10_EXT = $8052; - GL_RGB12_EXT = $8053; - GL_RGB16_EXT = $8054; - GL_RGBA2_EXT = $8055; - GL_RGBA4_EXT = $8056; - GL_RGB5_A1_EXT = $8057; - GL_RGBA8_EXT = $8058; - GL_RGB10_A2_EXT = $8059; - GL_RGBA12_EXT = $805A; - GL_RGBA16_EXT = $805B; - GL_TEXTURE_RED_SIZE_EXT = $805C; - GL_TEXTURE_GREEN_SIZE_EXT = $805D; - GL_TEXTURE_BLUE_SIZE_EXT = $805E; - GL_TEXTURE_ALPHA_SIZE_EXT = $805F; - GL_TEXTURE_LUMINANCE_SIZE_EXT = $8060; - GL_TEXTURE_INTENSITY_SIZE_EXT = $8061; - GL_REPLACE_EXT = $8062; - GL_PROXY_TEXTURE_1D_EXT = $8063; - GL_PROXY_TEXTURE_2D_EXT = $8064; - GL_TEXTURE_TOO_LARGE_EXT = $8065; - - // GL_EXT_texture3D - GL_PACK_SKIP_IMAGES_EXT = $806B; - GL_PACK_IMAGE_HEIGHT_EXT = $806C; - GL_UNPACK_SKIP_IMAGES_EXT = $806D; - GL_UNPACK_IMAGE_HEIGHT_EXT = $806E; - GL_TEXTURE_3D_EXT = $806F; - GL_PROXY_TEXTURE_3D_EXT = $8070; - GL_TEXTURE_DEPTH_EXT = $8071; - GL_TEXTURE_WRAP_R_EXT = $8072; - GL_MAX_3D_TEXTURE_SIZE_EXT = $8073; - - // GL_EXT_texture_compression_s3tc - GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0; - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1; - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2; - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3; - - // GL_EXT_texture_cube_map - GL_NORMAL_MAP_EXT = $8511; - GL_REFLECTION_MAP_EXT = $8512; - GL_TEXTURE_CUBE_MAP_EXT = $8513; - GL_TEXTURE_BINDING_CUBE_MAP_EXT = $8514; - GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT = $8515; - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT = $8516; - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT = $8517; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT = $8518; - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT = $8519; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT = $851A; - GL_PROXY_TEXTURE_CUBE_MAP_EXT = $851B; - GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT = $851C; - - // GL_EXT_texture_edge_clamp - GL_CLAMP_TO_EDGE_EXT = $812F; - - // GL_EXT_texture_env_combine - GL_COMBINE_EXT = $8570; - GL_COMBINE_RGB_EXT = $8571; - GL_COMBINE_ALPHA_EXT = $8572; - GL_RGB_SCALE_EXT = $8573; - GL_ADD_SIGNED_EXT = $8574; - GL_INTERPOLATE_EXT = $8575; - GL_CONSTANT_EXT = $8576; - GL_PRIMARY_COLOR_EXT = $8577; - GL_PREVIOUS_EXT = $8578; - GL_SOURCE0_RGB_EXT = $8580; - GL_SOURCE1_RGB_EXT = $8581; - GL_SOURCE2_RGB_EXT = $8582; - GL_SOURCE0_ALPHA_EXT = $8588; - GL_SOURCE1_ALPHA_EXT = $8589; - GL_SOURCE2_ALPHA_EXT = $858A; - GL_OPERAND0_RGB_EXT = $8590; - GL_OPERAND1_RGB_EXT = $8591; - GL_OPERAND2_RGB_EXT = $8592; - GL_OPERAND0_ALPHA_EXT = $8598; - GL_OPERAND1_ALPHA_EXT = $8599; - GL_OPERAND2_ALPHA_EXT = $859A; - - // GL_EXT_texture_env_dot3 - GL_DOT3_RGB_EXT = $8740; - GL_DOT3_RGBA_EXT = $8741; - - // GL_EXT_texture_filter_anisotropic - GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE; - GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF; - - // GL_EXT_texture_lod_bias - GL_MAX_TEXTURE_LOD_BIAS_EXT = $84FD; - GL_TEXTURE_FILTER_CONTROL_EXT = $8500; - GL_TEXTURE_LOD_BIAS_EXT = $8501; - - // GL_EXT_texture_object - GL_TEXTURE_PRIORITY_EXT = $8066; - GL_TEXTURE_RESIDENT_EXT = $8067; - GL_TEXTURE_1D_BINDING_EXT = $8068; - GL_TEXTURE_2D_BINDING_EXT = $8069; - GL_TEXTURE_3D_BINDING_EXT = $806A; - - // GL_EXT_texture_perturb_normal - GL_PERTURB_EXT = $85AE; - GL_TEXTURE_NORMAL_EXT = $85AF; - - // GL_EXT_texture_rectangle - GL_TEXTURE_RECTANGLE_EXT = $84F5; - GL_TEXTURE_BINDING_RECTANGLE_EXT = $84F6; - GL_PROXY_TEXTURE_RECTANGLE_EXT = $84F7; - GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT = $84F8; - - // GL_EXT_vertex_array - GL_VERTEX_ARRAY_EXT = $8074; - GL_NORMAL_ARRAY_EXT = $8075; - GL_COLOR_ARRAY_EXT = $8076; - GL_INDEX_ARRAY_EXT = $8077; - GL_TEXTURE_COORD_ARRAY_EXT = $8078; - GL_EDGE_FLAG_ARRAY_EXT = $8079; - GL_VERTEX_ARRAY_SIZE_EXT = $807A; - GL_VERTEX_ARRAY_TYPE_EXT = $807B; - GL_VERTEX_ARRAY_STRIDE_EXT = $807C; - GL_VERTEX_ARRAY_COUNT_EXT = $807D; - GL_NORMAL_ARRAY_TYPE_EXT = $807E; - GL_NORMAL_ARRAY_STRIDE_EXT = $807F; - GL_NORMAL_ARRAY_COUNT_EXT = $8080; - GL_COLOR_ARRAY_SIZE_EXT = $8081; - GL_COLOR_ARRAY_TYPE_EXT = $8082; - GL_COLOR_ARRAY_STRIDE_EXT = $8083; - GL_COLOR_ARRAY_COUNT_EXT = $8084; - GL_INDEX_ARRAY_TYPE_EXT = $8085; - GL_INDEX_ARRAY_STRIDE_EXT = $8086; - GL_INDEX_ARRAY_COUNT_EXT = $8087; - GL_TEXTURE_COORD_ARRAY_SIZE_EXT = $8088; - GL_TEXTURE_COORD_ARRAY_TYPE_EXT = $8089; - GL_TEXTURE_COORD_ARRAY_STRIDE_EXT = $808A; - GL_TEXTURE_COORD_ARRAY_COUNT_EXT = $808B; - GL_EDGE_FLAG_ARRAY_STRIDE_EXT = $808C; - GL_EDGE_FLAG_ARRAY_COUNT_EXT = $808D; - GL_VERTEX_ARRAY_POINTER_EXT = $808E; - GL_NORMAL_ARRAY_POINTER_EXT = $808F; - GL_COLOR_ARRAY_POINTER_EXT = $8090; - GL_INDEX_ARRAY_POINTER_EXT = $8091; - GL_TEXTURE_COORD_ARRAY_POINTER_EXT = $8092; - GL_EDGE_FLAG_ARRAY_POINTER_EXT = $8093; - - // GL_EXT_vertex_shader - GL_VERTEX_SHADER_EXT = $8780; - GL_VERTEX_SHADER_BINDING_EXT = $8781; - GL_OP_INDEX_EXT = $8782; - GL_OP_NEGATE_EXT = $8783; - GL_OP_DOT3_EXT = $8784; - GL_OP_DOT4_EXT = $8785; - GL_OP_MUL_EXT = $8786; - GL_OP_ADD_EXT = $8787; - GL_OP_MADD_EXT = $8788; - GL_OP_FRAC_EXT = $8789; - GL_OP_MAX_EXT = $878A; - GL_OP_MIN_EXT = $878B; - GL_OP_SET_GE_EXT = $878C; - GL_OP_SET_LT_EXT = $878D; - GL_OP_CLAMP_EXT = $878E; - GL_OP_FLOOR_EXT = $878F; - GL_OP_ROUND_EXT = $8790; - GL_OP_EXP_BASE_2_EXT = $8791; - GL_OP_LOG_BASE_2_EXT = $8792; - GL_OP_POWER_EXT = $8793; - GL_OP_RECIP_EXT = $8794; - GL_OP_RECIP_SQRT_EXT = $8795; - GL_OP_SUB_EXT = $8796; - GL_OP_CROSS_PRODUCT_EXT = $8797; - GL_OP_MULTIPLY_MATRIX_EXT = $8798; - GL_OP_MOV_EXT = $8799; - GL_OUTPUT_VERTEX_EXT = $879A; - GL_OUTPUT_COLOR0_EXT = $879B; - GL_OUTPUT_COLOR1_EXT = $879C; - GL_OUTPUT_TEXTURE_COORD0_EXT = $879D; - GL_OUTPUT_TEXTURE_COORD1_EXT = $879E; - GL_OUTPUT_TEXTURE_COORD2_EXT = $879F; - GL_OUTPUT_TEXTURE_COORD3_EXT = $87A0; - GL_OUTPUT_TEXTURE_COORD4_EXT = $87A1; - GL_OUTPUT_TEXTURE_COORD5_EXT = $87A2; - GL_OUTPUT_TEXTURE_COORD6_EXT = $87A3; - GL_OUTPUT_TEXTURE_COORD7_EXT = $87A4; - GL_OUTPUT_TEXTURE_COORD8_EXT = $87A5; - GL_OUTPUT_TEXTURE_COORD9_EXT = $87A6; - GL_OUTPUT_TEXTURE_COORD10_EXT = $87A7; - GL_OUTPUT_TEXTURE_COORD11_EXT = $87A8; - GL_OUTPUT_TEXTURE_COORD12_EXT = $87A9; - GL_OUTPUT_TEXTURE_COORD13_EXT = $87AA; - GL_OUTPUT_TEXTURE_COORD14_EXT = $87AB; - GL_OUTPUT_TEXTURE_COORD15_EXT = $87AC; - GL_OUTPUT_TEXTURE_COORD16_EXT = $87AD; - GL_OUTPUT_TEXTURE_COORD17_EXT = $87AE; - GL_OUTPUT_TEXTURE_COORD18_EXT = $87AF; - GL_OUTPUT_TEXTURE_COORD19_EXT = $87B0; - GL_OUTPUT_TEXTURE_COORD20_EXT = $87B1; - GL_OUTPUT_TEXTURE_COORD21_EXT = $87B2; - GL_OUTPUT_TEXTURE_COORD22_EXT = $87B3; - GL_OUTPUT_TEXTURE_COORD23_EXT = $87B4; - GL_OUTPUT_TEXTURE_COORD24_EXT = $87B5; - GL_OUTPUT_TEXTURE_COORD25_EXT = $87B6; - GL_OUTPUT_TEXTURE_COORD26_EXT = $87B7; - GL_OUTPUT_TEXTURE_COORD27_EXT = $87B8; - GL_OUTPUT_TEXTURE_COORD28_EXT = $87B9; - GL_OUTPUT_TEXTURE_COORD29_EXT = $87BA; - GL_OUTPUT_TEXTURE_COORD30_EXT = $87BB; - GL_OUTPUT_TEXTURE_COORD31_EXT = $87BC; - GL_OUTPUT_FOG_EXT = $87BD; - GL_SCALAR_EXT = $87BE; - GL_VECTOR_EXT = $87BF; - GL_MATRIX_EXT = $87C0; - GL_VARIANT_EXT = $87C1; - GL_INVARIANT_EXT = $87C2; - GL_LOCAL_CONSTANT_EXT = $87C3; - GL_LOCAL_EXT = $87C4; - GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT = $87C5; - GL_MAX_VERTEX_SHADER_VARIANTS_EXT = $87C6; - GL_MAX_VERTEX_SHADER_INVARIANTS_EXT = $87C7; - GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87C8; - GL_MAX_VERTEX_SHADER_LOCALS_EXT = $87C9; - GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT = $87CA; - GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT = $87CB; - GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87CC; - GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT = $87CD; - GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT = $87CE; - GL_VERTEX_SHADER_INSTRUCTIONS_EXT = $87CF; - GL_VERTEX_SHADER_VARIANTS_EXT = $87D0; - GL_VERTEX_SHADER_INVARIANTS_EXT = $87D1; - GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87D2; - GL_VERTEX_SHADER_LOCALS_EXT = $87D3; - GL_VERTEX_SHADER_OPTIMIZED_EXT = $87D4; - GL_X_EXT = $87D5; - GL_Y_EXT = $87D6; - GL_Z_EXT = $87D7; - GL_W_EXT = $87D8; - GL_NEGATIVE_X_EXT = $87D9; - GL_NEGATIVE_Y_EXT = $87DA; - GL_NEGATIVE_Z_EXT = $87DB; - GL_NEGATIVE_W_EXT = $87DC; - GL_ZERO_EXT = $87DD; - GL_ONE_EXT = $87DE; - GL_NEGATIVE_ONE_EXT = $87DF; - GL_NORMALIZED_RANGE_EXT = $87E0; - GL_FULL_RANGE_EXT = $87E1; - GL_CURRENT_VERTEX_EXT = $87E2; - GL_MVP_MATRIX_EXT = $87E3; - GL_VARIANT_VALUE_EXT = $87E4; - GL_VARIANT_DATATYPE_EXT = $87E5; - GL_VARIANT_ARRAY_STRIDE_EXT = $87E6; - GL_VARIANT_ARRAY_TYPE_EXT = $87E7; - GL_VARIANT_ARRAY_EXT = $87E8; - GL_VARIANT_ARRAY_POINTER_EXT = $87E9; - GL_INVARIANT_VALUE_EXT = $87EA; - GL_INVARIANT_DATATYPE_EXT = $87EB; - GL_LOCAL_CONSTANT_VALUE_EXT = $87EC; - GL_LOCAL_CONSTANT_DATATYPE_EXT = $87ED; - - // GL_EXT_vertex_weighting - GL_MODELVIEW0_STACK_DEPTH_EXT = $0BA3; - GL_MODELVIEW1_STACK_DEPTH_EXT = $8502; - GL_MODELVIEW0_MATRIX_EXT = $0BA6; - GL_MODELVIEW1_MATRIX_EXT = $8506; - GL_VERTEX_WEIGHTING_EXT = $8509; - GL_MODELVIEW0_EXT = $1700; - GL_MODELVIEW1_EXT = $850A; - GL_CURRENT_VERTEX_WEIGHT_EXT = $850B; - GL_VERTEX_WEIGHT_ARRAY_EXT = $850C; - GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT = $850D; - GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT = $850E; - GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT = $850F; - GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT = $8510; - - // GL_EXT_depth_bounds_test - GL_DEPTH_BOUNDS_TEST_EXT = $8890; - GL_DEPTH_BOUNDS_EXT = $8891; - - // GL_EXT_texture_mirror_clamp - GL_MIRROR_CLAMP_EXT = $8742; - GL_MIRROR_CLAMP_TO_EDGE_EXT = $8743; - GL_MIRROR_CLAMP_TO_BORDER_EXT = $8912; - - // GL_EXT_blend_equation_separate - GL_BLEND_EQUATION_RGB_EXT = $8009; - GL_BLEND_EQUATION_ALPHA_EXT = $883D; - - // GL_EXT_pixel_buffer_object - GL_PIXEL_PACK_BUFFER_EXT = $88EB; - GL_PIXEL_UNPACK_BUFFER_EXT = $88EC; - GL_PIXEL_PACK_BUFFER_BINDING_EXT = $88ED; - GL_PIXEL_UNPACK_BUFFER_BINDING_EXT = $88EF; - - // GL_EXT_stencil_clear_tag - GL_STENCIL_TAG_BITS_EXT = $88F2; - GL_STENCIL_CLEAR_TAG_VALUE_EXT = $88F3; - - // GL_EXT_packed_depth_stencil - GL_DEPTH_STENCIL_EXT = $84F9; - GL_UNSIGNED_INT_24_8_EXT = $84FA; - GL_DEPTH24_STENCIL8_EXT = $88F0; - GL_TEXTURE_STENCIL_SIZE_EXT = $88F1; - - // GL_EXT_texture_sRGB - GL_SRGB_EXT = $8C40; - GL_SRGB8_EXT = $8C41; - GL_SRGB_ALPHA_EXT = $8C42; - GL_SRGB8_ALPHA8_EXT = $8C43; - GL_SLUMINANCE_ALPHA_EXT = $8C44; - GL_SLUMINANCE8_ALPHA8_EXT = $8C45; - GL_SLUMINANCE_EXT = $8C46; - GL_SLUMINANCE8_EXT = $8C47; - GL_COMPRESSED_SRGB_EXT = $8C48; - GL_COMPRESSED_SRGB_ALPHA_EXT = $8C49; - GL_COMPRESSED_SLUMINANCE_EXT = $8C4A; - GL_COMPRESSED_SLUMINANCE_ALPHA_EXT = $8C4B; - GL_COMPRESSED_SRGB_S3TC_DXT1_EXT = $8C4C; - GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT = $8C4D; - GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT = $8C4E; - GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT = $8C4F; - - // GL_EXT_framebuffer_blit - GL_READ_FRAMEBUFFER_EXT = $8CA8; - GL_DRAW_FRAMEBUFFER_EXT = $8CA9; - GL_READ_FRAMEBUFFER_BINDING_EXT = GL_FRAMEBUFFER_BINDING_EXT; - GL_DRAW_FRAMEBUFFER_BINDING_EXT = $8CAA; - - // GL_EXT_framebuffer_multisample - GL_RENDERBUFFER_SAMPLES_EXT = $8CAB; - GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT = $8D56; - GL_MAX_SAMPLES_EXT = $8D57; - - // GL_EXT_timer_query - GL_TIME_ELAPSED_EXT = $88BF; - - // GL_EXT_bindable_uniform - GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT = $8DE2; - GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT = $8DE3; - GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT = $8DE4; - GL_MAX_BINDABLE_UNIFORM_SIZE_EXT = $8DED; - GL_UNIFORM_BUFFER_BINDING_EXT = $8DEF; - - // GL_EXT_framebuffer_sRGB - GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT = $20B2; - WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT = $20A9; - GL_FRAMEBUFFER_SRGB_EXT = $8DB9; - GL_FRAMEBUFFER_SRGB_CAPABLE_EXT = $8DBA; - - // GL_EXT_geometry_shader4 - GL_GEOMETRY_SHADER_EXT = $8DD9; - GL_GEOMETRY_VERTICES_OUT_EXT = $8DDA; - GL_GEOMETRY_INPUT_TYPE_EXT = $8DDB; - GL_GEOMETRY_OUTPUT_TYPE_EXT = $8DDC; - GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT = $8C29; - GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT = $8DDD; - GL_MAX_VERTEX_VARYING_COMPONENTS_EXT = $8DDE; - GL_MAX_VARYING_COMPONENTS_EXT = $8B4B; - GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT = $8DDF; - GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT = $8DE0; - GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT = $8DE1; - GL_LINES_ADJACENCY_EXT = $A; - GL_LINE_STRIP_ADJACENCY_EXT = $B; - GL_TRIANGLES_ADJACENCY_EXT = $C; - GL_TRIANGLE_STRIP_ADJACENCY_EXT = $D; - GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT = $8DA8; - GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT = $8DA9; - GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT = $8DA7; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT = $8CD4; - GL_PROGRAM_POINT_SIZE_EXT = $8642; - - // GL_EXT_gpu_shader4 - GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT = $88FD; - GL_SAMPLER_1D_ARRAY_EXT = $8DC0; - GL_SAMPLER_2D_ARRAY_EXT = $8DC1; - GL_SAMPLER_BUFFER_EXT = $8DC2; - GL_SAMPLER_1D_ARRAY_SHADOW_EXT = $8DC3; - GL_SAMPLER_2D_ARRAY_SHADOW_EXT = $8DC4; - GL_SAMPLER_CUBE_SHADOW_EXT = $8DC5; - GL_UNSIGNED_INT_VEC2_EXT = $8DC6; - GL_UNSIGNED_INT_VEC3_EXT = $8DC7; - GL_UNSIGNED_INT_VEC4_EXT = $8DC8; - GL_INT_SAMPLER_1D_EXT = $8DC9; - GL_INT_SAMPLER_2D_EXT = $8DCA; - GL_INT_SAMPLER_3D_EXT = $8DCB; - GL_INT_SAMPLER_CUBE_EXT = $8DCC; - GL_INT_SAMPLER_2D_RECT_EXT = $8DCD; - GL_INT_SAMPLER_1D_ARRAY_EXT = $8DCE; - GL_INT_SAMPLER_2D_ARRAY_EXT = $8DCF; - GL_INT_SAMPLER_BUFFER_EXT = $8DD0; - GL_UNSIGNED_INT_SAMPLER_1D_EXT = $8DD1; - GL_UNSIGNED_INT_SAMPLER_2D_EXT = $8DD2; - GL_UNSIGNED_INT_SAMPLER_3D_EXT = $8DD3; - GL_UNSIGNED_INT_SAMPLER_CUBE_EXT = $8DD4; - GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT = $8DD5; - GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT = $8DD6; - GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT = $8DD7; - GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT = $8DD8; - GL_MIN_PROGRAM_TEXEL_OFFSET_EXT = $8904; - GL_MAX_PROGRAM_TEXEL_OFFSET_EXT = $8905; - - // GL_EXT_packed_float - GL_R11F_G11F_B10F_EXT = $8C3A; - GL_UNSIGNED_INT_10F_11F_11F_REV_EXT = $8C3B; - RGBA_SIGNED_COMPONENTS_EXT = $8C3C; - WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT = $20A8; - GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT = $20B1; - GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT = $00000008; - - // GL_EXT_texture_array - GL_TEXTURE_1D_ARRAY_EXT = $8C18; - GL_TEXTURE_2D_ARRAY_EXT = $8C1A; - GL_PROXY_TEXTURE_2D_ARRAY_EXT = $8C1B; - GL_PROXY_TEXTURE_1D_ARRAY_EXT = $8C19; - GL_TEXTURE_BINDING_1D_ARRAY_EXT = $8C1C; - GL_TEXTURE_BINDING_2D_ARRAY_EXT = $8C1D; - GL_MAX_ARRAY_TEXTURE_LAYERS_EXT = $88FF; - GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT = $884E; - - // GL_EXT_texture_buffer_object - GL_TEXTURE_BUFFER_EXT = $8C2A; - GL_MAX_TEXTURE_BUFFER_SIZE_EXT = $8C2B; - GL_TEXTURE_BINDING_BUFFER_EXT = $8C2C; - GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT = $8C2D; - GL_TEXTURE_BUFFER_FORMAT_EXT = $8C2E; - - // GL_EXT_texture_compression_latc - GL_COMPRESSED_LUMINANCE_LATC1_EXT = $8C70; - GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT = $8C71; - GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT = $8C72; - GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT = $8C73; - - // GL_EXT_texture_compression_rgtc - GL_COMPRESSED_RED_RGTC1_EXT = $8DBB; - GL_COMPRESSED_SIGNED_RED_RGTC1_EXT = $8DBC; - GL_COMPRESSED_RED_GREEN_RGTC2_EXT = $8DBD; - GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT = $8DBE; - - // GL_EXT_texture_integer - GL_RGBA_INTEGER_MODE_EXT = $8D9E; - GL_RGBA32UI_EXT = $8D70; - GL_RGB32UI_EXT = $8D71; - GL_ALPHA32UI_EXT = $8D72; - GL_INTENSITY32UI_EXT = $8D73; - GL_LUMINANCE32UI_EXT = $8D74; - GL_LUMINANCE_ALPHA32UI_EXT = $8D75; - GL_RGBA16UI_EXT = $8D76; - GL_RGB16UI_EXT = $8D77; - GL_ALPHA16UI_EXT = $8D78; - GL_INTENSITY16UI_EXT = $8D79; - GL_LUMINANCE16UI_EXT = $8D7A; - GL_LUMINANCE_ALPHA16UI_EXT = $8D7B; - GL_RGBA8UI_EXT = $8D7C; - GL_RGB8UI_EXT = $8D7D; - GL_ALPHA8UI_EXT = $8D7E; - GL_INTENSITY8UI_EXT = $8D7F; - GL_LUMINANCE8UI_EXT = $8D80; - GL_LUMINANCE_ALPHA8UI_EXT = $8D81; - GL_RGBA32I_EXT = $8D82; - GL_RGB32I_EXT = $8D83; - GL_ALPHA32I_EXT = $8D84; - GL_INTENSITY32I_EXT = $8D85; - GL_LUMINANCE32I_EXT = $8D86; - GL_LUMINANCE_ALPHA32I_EXT = $8D87; - GL_RGBA16I_EXT = $8D88; - GL_RGB16I_EXT = $8D89; - GL_ALPHA16I_EXT = $8D8A; - GL_INTENSITY16I_EXT = $8D8B; - GL_LUMINANCE16I_EXT = $8D8C; - GL_LUMINANCE_ALPHA16I_EXT = $8D8D; - GL_RGBA8I_EXT = $8D8E; - GL_RGB8I_EXT = $8D8F; - GL_ALPHA8I_EXT = $8D90; - GL_INTENSITY8I_EXT = $8D91; - GL_LUMINANCE8I_EXT = $8D92; - GL_LUMINANCE_ALPHA8I_EXT = $8D93; - GL_RED_INTEGER_EXT = $8D94; - GL_GREEN_INTEGER_EXT = $8D95; - GL_BLUE_INTEGER_EXT = $8D96; - GL_ALPHA_INTEGER_EXT = $8D97; - GL_RGB_INTEGER_EXT = $8D98; - GL_RGBA_INTEGER_EXT = $8D99; - GL_BGR_INTEGER_EXT = $8D9A; - GL_BGRA_INTEGER_EXT = $8D9B; - GL_LUMINANCE_INTEGER_EXT = $8D9C; - GL_LUMINANCE_ALPHA_INTEGER_EXT = $8D9D; - - // GL_EXT_texture_shared_exponent - GL_RGB9_E5_EXT = $8C3D; - GL_UNSIGNED_INT_5_9_9_9_REV_EXT = $8C3E; - GL_TEXTURE_SHARED_SIZE_EXT = $8C3F; - - // GL_EXT_transform_feedback - GL_TRANSFORM_FEEDBACK_BUFFER_EXT = $8C8E; - GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT = $8C84; - GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT = $8C85; - GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT = $8C8F; - GL_INTERLEAVED_ATTRIBS_EXT = $8C8C; - GL_SEPARATE_ATTRIBS_EXT = $8C8D; - GL_PRIMITIVES_GENERATED_EXT = $8C87; - GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT = $8C88; - GL_RASTERIZER_DISCARD_EXT = $8C89; - GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT = $8C8A; - GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT = $8C8B; - GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT = $8C80; - GL_TRANSFORM_FEEDBACK_VARYINGS_EXT = $8C83; - GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT = $8C7F; - GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT = $8C76; - - // GL_EXT_direct_state_access - GL_PROGRAM_MATRIX_EXT = $8E2D; - GL_TRANSPOSE_PROGRAM_MATRIX_EXT = $8E2E; - GL_PROGRAM_MATRIX_STACK_DEPTH_EXT = $8E2F; - - // GL_EXT_texture_swizzle - GL_TEXTURE_SWIZZLE_R_EXT = $8E42; - GL_TEXTURE_SWIZZLE_G_EXT = $8E43; - GL_TEXTURE_SWIZZLE_B_EXT = $8E44; - GL_TEXTURE_SWIZZLE_A_EXT = $8E45; - GL_TEXTURE_SWIZZLE_RGBA_EXT = $8E46; - - // GL_EXT_provoking_vertex - GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT = $8E4C; - GL_FIRST_VERTEX_CONVENTION_EXT = $8E4D; - GL_LAST_VERTEX_CONVENTION_EXT = $8E4E; - GL_PROVOKING_VERTEX_EXT = $8E4F; - - // GL_EXT_texture_snorm - GL_ALPHA_SNORM = $9010; - GL_LUMINANCE_SNORM = $9011; - GL_LUMINANCE_ALPHA_SNORM = $9012; - GL_INTENSITY_SNORM = $9013; - GL_ALPHA8_SNORM = $9014; - GL_LUMINANCE8_SNORM = $9015; - GL_LUMINANCE8_ALPHA8_SNORM = $9016; - GL_INTENSITY8_SNORM = $9017; - GL_ALPHA16_SNORM = $9018; - GL_LUMINANCE16_SNORM = $9019; - GL_LUMINANCE16_ALPHA16_SNORM = $901A; - GL_INTENSITY16_SNORM = $901B; - { reuse GL_R_SNORM } - { reuse GL_RG_SNORM } - { reuse GL_RGB_SNORM } - { reuse GL_RGBA_SNORM } - { reuse GL_R8_SNORM } - { reuse GL_RG8_SNORM } - { reuse GL_RGB8_SNORM } - { reuse GL_RGBA8_SNORM } - { reuse GL_R16_SNORM } - { reuse GL_RG16_SNORM } - { reuse GL_RGB16_SNORM } - { reuse GL_RGBA16_SNORM } - { reuse GL_SIGNED_NORMALIZED } - - // GL_FfdMaskSGIX - GL_TEXTURE_DEFORMATION_BIT_SGIX = $00000001; - GL_GEOMETRY_DEFORMATION_BIT_SGIX = $00000002; - - // GL_HP_convolution_border_modes - GL_IGNORE_BORDER_HP = $8150; - GL_CONSTANT_BORDER_HP = $8151; - GL_REPLICATE_BORDER_HP = $8153; - GL_CONVOLUTION_BORDER_COLOR_HP = $8154; - - // GL_HP_image_transform - GL_IMAGE_SCALE_X_HP = $8155; - GL_IMAGE_SCALE_Y_HP = $8156; - GL_IMAGE_TRANSLATE_X_HP = $8157; - GL_IMAGE_TRANSLATE_Y_HP = $8158; - GL_IMAGE_ROTATE_ANGLE_HP = $8159; - GL_IMAGE_ROTATE_ORIGIN_X_HP = $815A; - GL_IMAGE_ROTATE_ORIGIN_Y_HP = $815B; - GL_IMAGE_MAG_FILTER_HP = $815C; - GL_IMAGE_MIN_FILTER_HP = $815D; - GL_IMAGE_CUBIC_WEIGHT_HP = $815E; - GL_CUBIC_HP = $815F; - GL_AVERAGE_HP = $8160; - GL_IMAGE_TRANSFORM_2D_HP = $8161; - GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP = $8162; - GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP = $8163; - - // GL_HP_occlusion_test - GL_OCCLUSION_TEST_HP = $8165; - GL_OCCLUSION_TEST_RESULT_HP = $8166; - - // GL_HP_texture_lighting - GL_TEXTURE_LIGHTING_MODE_HP = $8167; - GL_TEXTURE_POST_SPECULAR_HP = $8168; - GL_TEXTURE_PRE_SPECULAR_HP = $8169; - - // GL_IBM_cull_vertex - GL_CULL_VERTEX_IBM = 103050; - - // GL_IBM_rasterpos_clip - GL_RASTER_POSITION_UNCLIPPED_IBM = $19262; - - // GL_IBM_texture_mirrored_repeat - GL_MIRRORED_REPEAT_IBM = $8370; - - // GL_IBM_vertex_array_lists - GL_VERTEX_ARRAY_LIST_IBM = 103070; - GL_NORMAL_ARRAY_LIST_IBM = 103071; - GL_COLOR_ARRAY_LIST_IBM = 103072; - GL_INDEX_ARRAY_LIST_IBM = 103073; - GL_TEXTURE_COORD_ARRAY_LIST_IBM = 103074; - GL_EDGE_FLAG_ARRAY_LIST_IBM = 103075; - GL_FOG_COORDINATE_ARRAY_LIST_IBM = 103076; - GL_SECONDARY_COLOR_ARRAY_LIST_IBM = 103077; - GL_VERTEX_ARRAY_LIST_STRIDE_IBM = 103080; - GL_NORMAL_ARRAY_LIST_STRIDE_IBM = 103081; - GL_COLOR_ARRAY_LIST_STRIDE_IBM = 103082; - GL_INDEX_ARRAY_LIST_STRIDE_IBM = 103083; - GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM = 103084; - GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM = 103085; - GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM = 103086; - GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM = 103087; - - // GL_INGR_color_clamp - GL_RED_MIN_CLAMP_INGR = $8560; - GL_GREEN_MIN_CLAMP_INGR = $8561; - GL_BLUE_MIN_CLAMP_INGR = $8562; - GL_ALPHA_MIN_CLAMP_INGR = $8563; - GL_RED_MAX_CLAMP_INGR = $8564; - GL_GREEN_MAX_CLAMP_INGR = $8565; - GL_BLUE_MAX_CLAMP_INGR = $8566; - GL_ALPHA_MAX_CLAMP_INGR = $8567; - - // GL_INGR_interlace_read - GL_INTERLACE_READ_INGR = $8568; - - // GL_INTEL_parallel_arrays - GL_PARALLEL_ARRAYS_INTEL = $83F4; - GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL = $83F5; - GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL = $83F6; - GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL = $83F7; - GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL = $83F8; - - // GL_NV_copy_depth_to_color - GL_DEPTH_STENCIL_TO_RGBA_NV = $886E; - GL_DEPTH_STENCIL_TO_BGRA_NV = $886F; - - // GL_NV_depth_clamp - GL_DEPTH_CLAMP_NV = $864F; - - // GL_NV_evaluators - GL_EVAL_2D_NV = $86C0; - GL_EVAL_TRIANGULAR_2D_NV = $86C1; - GL_MAP_TESSELLATION_NV = $86C2; - GL_MAP_ATTRIB_U_ORDER_NV = $86C3; - GL_MAP_ATTRIB_V_ORDER_NV = $86C4; - GL_EVAL_FRACTIONAL_TESSELLATION_NV = $86C5; - GL_EVAL_VERTEX_ATTRIB0_NV = $86C6; - GL_EVAL_VERTEX_ATTRIB1_NV = $86C7; - GL_EVAL_VERTEX_ATTRIB2_NV = $86C8; - GL_EVAL_VERTEX_ATTRIB3_NV = $86C9; - GL_EVAL_VERTEX_ATTRIB4_NV = $86CA; - GL_EVAL_VERTEX_ATTRIB5_NV = $86CB; - GL_EVAL_VERTEX_ATTRIB6_NV = $86CC; - GL_EVAL_VERTEX_ATTRIB7_NV = $86CD; - GL_EVAL_VERTEX_ATTRIB8_NV = $86CE; - GL_EVAL_VERTEX_ATTRIB9_NV = $86CF; - GL_EVAL_VERTEX_ATTRIB10_NV = $86D0; - GL_EVAL_VERTEX_ATTRIB11_NV = $86D1; - GL_EVAL_VERTEX_ATTRIB12_NV = $86D2; - GL_EVAL_VERTEX_ATTRIB13_NV = $86D3; - GL_EVAL_VERTEX_ATTRIB14_NV = $86D4; - GL_EVAL_VERTEX_ATTRIB15_NV = $86D5; - GL_MAX_MAP_TESSELLATION_NV = $86D6; - GL_MAX_RATIONAL_EVAL_ORDER_NV = $86D7; - - // GL_NV_fence - GL_ALL_COMPLETED_NV = $84F2; - GL_FENCE_STATUS_NV = $84F3; - GL_FENCE_CONDITION_NV = $84F4; - - // GL_NV_float_buffer - GL_FLOAT_R_NV = $8880; - GL_FLOAT_RG_NV = $8881; - GL_FLOAT_RGB_NV = $8882; - GL_FLOAT_RGBA_NV = $8883; - GL_FLOAT_R16_NV = $8884; - GL_FLOAT_R32_NV = $8885; - GL_FLOAT_RG16_NV = $8886; - GL_FLOAT_RG32_NV = $8887; - GL_FLOAT_RGB16_NV = $8888; - GL_FLOAT_RGB32_NV = $8889; - GL_FLOAT_RGBA16_NV = $888A; - GL_FLOAT_RGBA32_NV = $888B; - GL_TEXTURE_FLOAT_COMPONENTS_NV = $888C; - GL_FLOAT_CLEAR_COLOR_VALUE_NV = $888D; - GL_FLOAT_RGBA_MODE_NV = $888E; - - // GL_NV_fog_distance - GL_FOG_DISTANCE_MODE_NV = $855A; - GL_EYE_RADIAL_NV = $855B; - GL_EYE_PLANE_ABSOLUTE_NV = $855C; - - // GL_NV_fragment_program - GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV = $8868; - GL_FRAGMENT_PROGRAM_NV = $8870; - GL_MAX_TEXTURE_COORDS_NV = $8871; - GL_MAX_TEXTURE_IMAGE_UNITS_NV = $8872; - GL_FRAGMENT_PROGRAM_BINDING_NV = $8873; - GL_PROGRAM_ERROR_STRING_NV = $8874; - - // GL_NV_half_float - GL_HALF_FLOAT_NV = $140B; - - // GL_NV_light_max_exponent - GL_MAX_SHININESS_NV = $8504; - GL_MAX_SPOT_EXPONENT_NV = $8505; - - // GL_NV_multisample_filter_hint - GL_MULTISAMPLE_FILTER_HINT_NV = $8534; - - // GL_NV_occlusion_query - GL_PIXEL_COUNTER_BITS_NV = $8864; - GL_CURRENT_OCCLUSION_QUERY_ID_NV = $8865; - GL_PIXEL_COUNT_NV = $8866; - GL_PIXEL_COUNT_AVAILABLE_NV = $8867; - - // GL_NV_packed_depth_stencil - GL_DEPTH_STENCIL_NV = $84F9; - GL_UNSIGNED_INT_24_8_NV = $84FA; - - // GL_NV_pixel_data_range - GL_WRITE_PIXEL_DATA_RANGE_NV = $8878; - GL_READ_PIXEL_DATA_RANGE_NV = $8879; - GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV = $887A; - GL_READ_PIXEL_DATA_RANGE_LENGTH_NV = $887B; - GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV = $887C; - GL_READ_PIXEL_DATA_RANGE_POINTER_NV = $887D; - - // GL_NV_point_sprite - GL_POINT_SPRITE_NV = $8861; - GL_COORD_REPLACE_NV = $8862; - GL_POINT_SPRITE_R_MODE_NV = $8863; - - // GL_NV_primitive_restart - GL_PRIMITIVE_RESTART_NV = $8558; - GL_PRIMITIVE_RESTART_INDEX_NV = $8559; - - // GL_NV_register_combiners - GL_REGISTER_COMBINERS_NV = $8522; - GL_VARIABLE_A_NV = $8523; - GL_VARIABLE_B_NV = $8524; - GL_VARIABLE_C_NV = $8525; - GL_VARIABLE_D_NV = $8526; - GL_VARIABLE_E_NV = $8527; - GL_VARIABLE_F_NV = $8528; - GL_VARIABLE_G_NV = $8529; - GL_CONSTANT_COLOR0_NV = $852A; - GL_CONSTANT_COLOR1_NV = $852B; - GL_PRIMARY_COLOR_NV = $852C; - GL_SECONDARY_COLOR_NV = $852D; - GL_SPARE0_NV = $852E; - GL_SPARE1_NV = $852F; - GL_DISCARD_NV = $8530; - GL_E_TIMES_F_NV = $8531; - GL_SPARE0_PLUS_SECONDARY_COLOR_NV = $8532; - GL_UNSIGNED_IDENTITY_NV = $8536; - GL_UNSIGNED_INVERT_NV = $8537; - GL_EXPAND_NORMAL_NV = $8538; - GL_EXPAND_NEGATE_NV = $8539; - GL_HALF_BIAS_NORMAL_NV = $853A; - GL_HALF_BIAS_NEGATE_NV = $853B; - GL_SIGNED_IDENTITY_NV = $853C; - GL_SIGNED_NEGATE_NV = $853D; - GL_SCALE_BY_TWO_NV = $853E; - GL_SCALE_BY_FOUR_NV = $853F; - GL_SCALE_BY_ONE_HALF_NV = $8540; - GL_BIAS_BY_NEGATIVE_ONE_HALF_NV = $8541; - GL_COMBINER_INPUT_NV = $8542; - GL_COMBINER_MAPPING_NV = $8543; - GL_COMBINER_COMPONENT_USAGE_NV = $8544; - GL_COMBINER_AB_DOT_PRODUCT_NV = $8545; - GL_COMBINER_CD_DOT_PRODUCT_NV = $8546; - GL_COMBINER_MUX_SUM_NV = $8547; - GL_COMBINER_SCALE_NV = $8548; - GL_COMBINER_BIAS_NV = $8549; - GL_COMBINER_AB_OUTPUT_NV = $854A; - GL_COMBINER_CD_OUTPUT_NV = $854B; - GL_COMBINER_SUM_OUTPUT_NV = $854C; - GL_MAX_GENERAL_COMBINERS_NV = $854D; - GL_NUM_GENERAL_COMBINERS_NV = $854E; - GL_COLOR_SUM_CLAMP_NV = $854F; - GL_COMBINER0_NV = $8550; - GL_COMBINER1_NV = $8551; - GL_COMBINER2_NV = $8552; - GL_COMBINER3_NV = $8553; - GL_COMBINER4_NV = $8554; - GL_COMBINER5_NV = $8555; - GL_COMBINER6_NV = $8556; - GL_COMBINER7_NV = $8557; - - // GL_NV_register_combiners2 - GL_PER_STAGE_CONSTANTS_NV = $8535; - - // GL_NV_texgen_emboss - GL_EMBOSS_LIGHT_NV = $855D; - GL_EMBOSS_CONSTANT_NV = $855E; - GL_EMBOSS_MAP_NV = $855F; - - // GL_NV_texgen_reflection - GL_NORMAL_MAP_NV = $8511; - GL_REFLECTION_MAP_NV = $8512; - - // GL_NV_texture_env_combine4 - GL_COMBINE4_NV = $8503; - GL_SOURCE3_RGB_NV = $8583; - GL_SOURCE3_ALPHA_NV = $858B; - GL_OPERAND3_RGB_NV = $8593; - GL_OPERAND3_ALPHA_NV = $859B; - - // GL_NV_texture_expand_normal - GL_TEXTURE_UNSIGNED_REMAP_MODE_NV = $888F; - - // GL_NV_texture_rectangle - GL_TEXTURE_RECTANGLE_NV = $84F5; - GL_TEXTURE_BINDING_RECTANGLE_NV = $84F6; - GL_PROXY_TEXTURE_RECTANGLE_NV = $84F7; - GL_MAX_RECTANGLE_TEXTURE_SIZE_NV = $84F8; - - // GL_NV_texture_shader - GL_OFFSET_TEXTURE_RECTANGLE_NV = $864C; - GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV = $864D; - GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV = $864E; - GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV = $86D9; - GL_UNSIGNED_INT_S8_S8_8_8_NV = $86DA; - GL_UNSIGNED_INT_8_8_S8_S8_REV_NV = $86DB; - GL_DSDT_MAG_INTENSITY_NV = $86DC; - GL_SHADER_CONSISTENT_NV = $86DD; - GL_TEXTURE_SHADER_NV = $86DE; - GL_SHADER_OPERATION_NV = $86DF; - GL_CULL_MODES_NV = $86E0; - GL_OFFSET_TEXTURE_MATRIX_NV = $86E1; - GL_OFFSET_TEXTURE_SCALE_NV = $86E2; - GL_OFFSET_TEXTURE_BIAS_NV = $86E3; - GL_OFFSET_TEXTURE_2D_MATRIX_NV = GL_OFFSET_TEXTURE_MATRIX_NV; - GL_OFFSET_TEXTURE_2D_SCALE_NV = GL_OFFSET_TEXTURE_SCALE_NV; - GL_OFFSET_TEXTURE_2D_BIAS_NV = GL_OFFSET_TEXTURE_BIAS_NV; - GL_PREVIOUS_TEXTURE_INPUT_NV = $86E4; - GL_CONST_EYE_NV = $86E5; - GL_PASS_THROUGH_NV = $86E6; - GL_CULL_FRAGMENT_NV = $86E7; - GL_OFFSET_TEXTURE_2D_NV = $86E8; - GL_DEPENDENT_AR_TEXTURE_2D_NV = $86E9; - GL_DEPENDENT_GB_TEXTURE_2D_NV = $86EA; - GL_DOT_PRODUCT_NV = $86EC; - GL_DOT_PRODUCT_DEPTH_REPLACE_NV = $86ED; - GL_DOT_PRODUCT_TEXTURE_2D_NV = $86EE; - GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV = $86F0; - GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV = $86F1; - GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV = $86F2; - GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV = $86F3; - GL_HILO_NV = $86F4; - GL_DSDT_NV = $86F5; - GL_DSDT_MAG_NV = $86F6; - GL_DSDT_MAG_VIB_NV = $86F7; - GL_HILO16_NV = $86F8; - GL_SIGNED_HILO_NV = $86F9; - GL_SIGNED_HILO16_NV = $86FA; - GL_SIGNED_RGBA_NV = $86FB; - GL_SIGNED_RGBA8_NV = $86FC; - GL_SIGNED_RGB_NV = $86FE; - GL_SIGNED_RGB8_NV = $86FF; - GL_SIGNED_LUMINANCE_NV = $8701; - GL_SIGNED_LUMINANCE8_NV = $8702; - GL_SIGNED_LUMINANCE_ALPHA_NV = $8703; - GL_SIGNED_LUMINANCE8_ALPHA8_NV = $8704; - GL_SIGNED_ALPHA_NV = $8705; - GL_SIGNED_ALPHA8_NV = $8706; - GL_SIGNED_INTENSITY_NV = $8707; - GL_SIGNED_INTENSITY8_NV = $8708; - GL_DSDT8_NV = $8709; - GL_DSDT8_MAG8_NV = $870A; - GL_DSDT8_MAG8_INTENSITY8_NV = $870B; - GL_SIGNED_RGB_UNSIGNED_ALPHA_NV = $870C; - GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV = $870D; - GL_HI_SCALE_NV = $870E; - GL_LO_SCALE_NV = $870F; - GL_DS_SCALE_NV = $8710; - GL_DT_SCALE_NV = $8711; - GL_MAGNITUDE_SCALE_NV = $8712; - GL_VIBRANCE_SCALE_NV = $8713; - GL_HI_BIAS_NV = $8714; - GL_LO_BIAS_NV = $8715; - GL_DS_BIAS_NV = $8716; - GL_DT_BIAS_NV = $8717; - GL_MAGNITUDE_BIAS_NV = $8718; - GL_VIBRANCE_BIAS_NV = $8719; - GL_TEXTURE_BORDER_VALUES_NV = $871A; - GL_TEXTURE_HI_SIZE_NV = $871B; - GL_TEXTURE_LO_SIZE_NV = $871C; - GL_TEXTURE_DS_SIZE_NV = $871D; - GL_TEXTURE_DT_SIZE_NV = $871E; - GL_TEXTURE_MAG_SIZE_NV = $871F; - - // GL_NV_texture_shader2 - GL_DOT_PRODUCT_TEXTURE_3D_NV = $86EF; - - // GL_NV_texture_shader3 - GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV = $8850; - GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV = $8851; - GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV = $8852; - GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV = $8853; - GL_OFFSET_HILO_TEXTURE_2D_NV = $8854; - GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV = $8855; - GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV = $8856; - GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV = $8857; - GL_DEPENDENT_HILO_TEXTURE_2D_NV = $8858; - GL_DEPENDENT_RGB_TEXTURE_3D_NV = $8859; - GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV = $885A; - GL_DOT_PRODUCT_PASS_THROUGH_NV = $885B; - GL_DOT_PRODUCT_TEXTURE_1D_NV = $885C; - GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV = $885D; - GL_HILO8_NV = $885E; - GL_SIGNED_HILO8_NV = $885F; - GL_FORCE_BLUE_TO_ONE_NV = $8860; - - // GL_NV_vertex_array_range - GL_VERTEX_ARRAY_RANGE_NV = $851D; - GL_VERTEX_ARRAY_RANGE_LENGTH_NV = $851E; - GL_VERTEX_ARRAY_RANGE_VALID_NV = $851F; - GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV = $8520; - GL_VERTEX_ARRAY_RANGE_POINTER_NV = $8521; - - // GL_NV_vertex_array_range2 - GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV = $8533; - - // GL_NV_vertex_program - GL_VERTEX_PROGRAM_NV = $8620; - GL_VERTEX_STATE_PROGRAM_NV = $8621; - GL_ATTRIB_ARRAY_SIZE_NV = $8623; - GL_ATTRIB_ARRAY_STRIDE_NV = $8624; - GL_ATTRIB_ARRAY_TYPE_NV = $8625; - GL_CURRENT_ATTRIB_NV = $8626; - GL_PROGRAM_LENGTH_NV = $8627; - GL_PROGRAM_STRING_NV = $8628; - GL_MODELVIEW_PROJECTION_NV = $8629; - GL_IDENTITY_NV = $862A; - GL_INVERSE_NV = $862B; - GL_TRANSPOSE_NV = $862C; - GL_INVERSE_TRANSPOSE_NV = $862D; - GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV = $862E; - GL_MAX_TRACK_MATRICES_NV = $862F; - GL_MATRIX0_NV = $8630; - GL_MATRIX1_NV = $8631; - GL_MATRIX2_NV = $8632; - GL_MATRIX3_NV = $8633; - GL_MATRIX4_NV = $8634; - GL_MATRIX5_NV = $8635; - GL_MATRIX6_NV = $8636; - GL_MATRIX7_NV = $8637; - GL_CURRENT_MATRIX_STACK_DEPTH_NV = $8640; - GL_CURRENT_MATRIX_NV = $8641; - GL_VERTEX_PROGRAM_POINT_SIZE_NV = $8642; - GL_VERTEX_PROGRAM_TWO_SIDE_NV = $8643; - GL_PROGRAM_PARAMETER_NV = $8644; - GL_ATTRIB_ARRAY_POINTER_NV = $8645; - GL_PROGRAM_TARGET_NV = $8646; - GL_PROGRAM_RESIDENT_NV = $8647; - GL_TRACK_MATRIX_NV = $8648; - GL_TRACK_MATRIX_TRANSFORM_NV = $8649; - GL_VERTEX_PROGRAM_BINDING_NV = $864A; - GL_PROGRAM_ERROR_POSITION_NV = $864B; - GL_VERTEX_ATTRIB_ARRAY0_NV = $8650; - GL_VERTEX_ATTRIB_ARRAY1_NV = $8651; - GL_VERTEX_ATTRIB_ARRAY2_NV = $8652; - GL_VERTEX_ATTRIB_ARRAY3_NV = $8653; - GL_VERTEX_ATTRIB_ARRAY4_NV = $8654; - GL_VERTEX_ATTRIB_ARRAY5_NV = $8655; - GL_VERTEX_ATTRIB_ARRAY6_NV = $8656; - GL_VERTEX_ATTRIB_ARRAY7_NV = $8657; - GL_VERTEX_ATTRIB_ARRAY8_NV = $8658; - GL_VERTEX_ATTRIB_ARRAY9_NV = $8659; - GL_VERTEX_ATTRIB_ARRAY10_NV = $865A; - GL_VERTEX_ATTRIB_ARRAY11_NV = $865B; - GL_VERTEX_ATTRIB_ARRAY12_NV = $865C; - GL_VERTEX_ATTRIB_ARRAY13_NV = $865D; - GL_VERTEX_ATTRIB_ARRAY14_NV = $865E; - GL_VERTEX_ATTRIB_ARRAY15_NV = $865F; - GL_MAP1_VERTEX_ATTRIB0_4_NV = $8660; - GL_MAP1_VERTEX_ATTRIB1_4_NV = $8661; - GL_MAP1_VERTEX_ATTRIB2_4_NV = $8662; - GL_MAP1_VERTEX_ATTRIB3_4_NV = $8663; - GL_MAP1_VERTEX_ATTRIB4_4_NV = $8664; - GL_MAP1_VERTEX_ATTRIB5_4_NV = $8665; - GL_MAP1_VERTEX_ATTRIB6_4_NV = $8666; - GL_MAP1_VERTEX_ATTRIB7_4_NV = $8667; - GL_MAP1_VERTEX_ATTRIB8_4_NV = $8668; - GL_MAP1_VERTEX_ATTRIB9_4_NV = $8669; - GL_MAP1_VERTEX_ATTRIB10_4_NV = $866A; - GL_MAP1_VERTEX_ATTRIB11_4_NV = $866B; - GL_MAP1_VERTEX_ATTRIB12_4_NV = $866C; - GL_MAP1_VERTEX_ATTRIB13_4_NV = $866D; - GL_MAP1_VERTEX_ATTRIB14_4_NV = $866E; - GL_MAP1_VERTEX_ATTRIB15_4_NV = $866F; - GL_MAP2_VERTEX_ATTRIB0_4_NV = $8670; - GL_MAP2_VERTEX_ATTRIB1_4_NV = $8671; - GL_MAP2_VERTEX_ATTRIB2_4_NV = $8672; - GL_MAP2_VERTEX_ATTRIB3_4_NV = $8673; - GL_MAP2_VERTEX_ATTRIB4_4_NV = $8674; - GL_MAP2_VERTEX_ATTRIB5_4_NV = $8675; - GL_MAP2_VERTEX_ATTRIB6_4_NV = $8676; - GL_MAP2_VERTEX_ATTRIB7_4_NV = $8677; - GL_MAP2_VERTEX_ATTRIB8_4_NV = $8678; - GL_MAP2_VERTEX_ATTRIB9_4_NV = $8679; - GL_MAP2_VERTEX_ATTRIB10_4_NV = $867A; - GL_MAP2_VERTEX_ATTRIB11_4_NV = $867B; - GL_MAP2_VERTEX_ATTRIB12_4_NV = $867C; - GL_MAP2_VERTEX_ATTRIB13_4_NV = $867D; - GL_MAP2_VERTEX_ATTRIB14_4_NV = $867E; - GL_MAP2_VERTEX_ATTRIB15_4_NV = $867F; - - // GL_NV_fragment_program2 and GL_NV_vertex_program2_option - GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV = $88F4; - GL_MAX_PROGRAM_CALL_DEPTH_NV = $88F5; - - // GL_NV_fragment_program2 - GL_MAX_PROGRAM_IF_DEPTH_NV = $88F6; - GL_MAX_PROGRAM_LOOP_DEPTH_NV = $88F7; - GL_MAX_PROGRAM_LOOP_COUNT_NV = $88F8; - - // GL_NV_vertex_program3 - MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB = $8B4C; - - // GL_NV_depth_buffer_float - GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV = $8DAD; - GL_DEPTH_BUFFER_FLOAT_MODE_NV = $8DAF; - - // GL_NV_framebuffer_multisample_coverage - GL_RENDERBUFFER_COVERAGE_SAMPLES_NV = $8CAB; - GL_RENDERBUFFER_COLOR_SAMPLES_NV = $8E10; - - // GL_NV_geometry_program4 - GL_GEOMETRY_PROGRAM_NV = $8C26; - GL_MAX_PROGRAM_OUTPUT_VERTICES_NV = $8C27; - GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV = $8C28; - - // GL_NV_gpu_program4 - GL_PROGRAM_ATTRIB_COMPONENTS_NV = $8906; - GL_PROGRAM_RESULT_COMPONENTS_NV = $8907; - GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV = $8908; - GL_MAX_PROGRAM_RESULT_COMPONENTS_NV = $8909; - GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV = $8DA5; - GL_MAX_PROGRAM_GENERIC_RESULTS_NV = $8DA6; - - // GL_NV_parameter_buffer_object - GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV = $8DA0; - GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV = $8DA1; - GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV = $8DA2; - GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV = $8DA3; - GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV = $8DA4; - - // GL_NV_transform_feedback - GL_TRANSFORM_FEEDBACK_BUFFER_NV = $8C8E; - GL_TRANSFORM_FEEDBACK_BUFFER_START_NV = $8C84; - GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV = $8C85; - GL_TRANSFORM_FEEDBACK_RECORD_NV = $8C86; - GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV = $8C8F; - GL_INTERLEAVED_ATTRIBS_NV = $8C8C; - GL_SEPARATE_ATTRIBS_NV = $8C8D; - GL_PRIMITIVES_GENERATED_NV = $8C87; - GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV = $8C88; - GL_RASTERIZER_DISCARD_NV = $8C89; - GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV = $8C8A; - GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV = $8C8B; - GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV = $8C80; - GL_TRANSFORM_FEEDBACK_ATTRIBS_NV = $8C7E; - GL_ACTIVE_VARYINGS_NV = $8C81; - GL_ACTIVE_VARYING_MAX_LENGTH_NV = $8C82; - GL_TRANSFORM_FEEDBACK_VARYINGS_NV = $8C83; - GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV = $8C7F; - GL_BACK_PRIMARY_COLOR_NV = $8C77; - GL_BACK_SECONDARY_COLOR_NV = $8C78; - GL_TEXTURE_COORD_NV = $8C79; - GL_CLIP_DISTANCE_NV = $8C7A; - GL_VERTEX_ID_NV = $8C7B; - GL_PRIMITIVE_ID_NV = $8C7C; - GL_GENERIC_ATTRIB_NV = $8C7D; - - // GL_NV_conditional_render - GL_QUERY_WAIT_NV = $8E13; - GL_QUERY_NO_WAIT_NV = $8E14; - GL_QUERY_BY_REGION_WAIT_NV = $8E15; - GL_QUERY_BY_REGION_NO_WAIT_NV = $8E16; - - // GL_NV_present_video - GL_FRAME_NV = $8E26; - GL_FIELDS_NV = $8E27; - GL_CURRENT_TIME_NV = $8E28; - GL_NUM_FILL_STREAMS_NV = $8E29; - GL_PRESENT_TIME_NV = $8E2A; - GL_PRESENT_DURATION_NV = $8E2B; - - // GL_NV_explicit_multisample - GL_SAMPLE_POSITION_NV = $8E50; - GL_SAMPLE_MASK_NV = $8E51; - GL_SAMPLE_MASK_VALUE_NV = $8E52; - GL_TEXTURE_BINDING_RENDERBUFFER_NV = $8E53; - GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV = $8E54; - GL_TEXTURE_RENDERBUFFER_NV = $8E55; - GL_SAMPLER_RENDERBUFFER_NV = $8E56; - GL_INT_SAMPLER_RENDERBUFFER_NV = $8E57; - GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV = $8E58; - GL_MAX_SAMPLE_MASK_WORDS_NV = $8E59; - - // GL_NV_transform_feedback2 - GL_TRANSFORM_FEEDBACK_NV = $8E22; - GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV = $8E23; - GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV = $8E24; - GL_TRANSFORM_FEEDBACK_BINDING_NV = $8E25; - - // GL_OML_interlace - GL_INTERLACE_OML = $8980; - GL_INTERLACE_READ_OML = $8981; - - // GL_OML_resample - GL_PACK_RESAMPLE_OML = $8984; - GL_UNPACK_RESAMPLE_OML = $8985; - GL_RESAMPLE_REPLICATE_OML = $8986; - GL_RESAMPLE_ZERO_FILL_OML = $8987; - GL_RESAMPLE_AVERAGE_OML = $8988; - GL_RESAMPLE_DECIMATE_OML = $8989; - - // GL_OML_subsample - GL_FORMAT_SUBSAMPLE_24_24_OML = $8982; - GL_FORMAT_SUBSAMPLE_244_244_OML = $8983; - - // GL_PGI_misc_hints - GL_PREFER_DOUBLEBUFFER_HINT_PGI = $1A1F8; - GL_CONSERVE_MEMORY_HINT_PGI = $1A1FD; - GL_RECLAIM_MEMORY_HINT_PGI = $1A1FE; - GL_NATIVE_GRAPHICS_HANDLE_PGI = $1A202; - GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI = $1A203; - GL_NATIVE_GRAPHICS_END_HINT_PGI = $1A204; - GL_ALWAYS_FAST_HINT_PGI = $1A20C; - GL_ALWAYS_SOFT_HINT_PGI = $1A20D; - GL_ALLOW_DRAW_OBJ_HINT_PGI = $1A20E; - GL_ALLOW_DRAW_WIN_HINT_PGI = $1A20F; - GL_ALLOW_DRAW_FRG_HINT_PGI = $1A210; - GL_ALLOW_DRAW_MEM_HINT_PGI = $1A211; - GL_STRICT_DEPTHFUNC_HINT_PGI = $1A216; - GL_STRICT_LIGHTING_HINT_PGI = $1A217; - GL_STRICT_SCISSOR_HINT_PGI = $1A218; - GL_FULL_STIPPLE_HINT_PGI = $1A219; - GL_CLIP_NEAR_HINT_PGI = $1A220; - GL_CLIP_FAR_HINT_PGI = $1A221; - GL_WIDE_LINE_HINT_PGI = $1A222; - GL_BACK_NORMALS_HINT_PGI = $1A223; - - // GL_PGI_vertex_hints - GL_VERTEX_DATA_HINT_PGI = $1A22A; - GL_VERTEX_CONSISTENT_HINT_PGI = $1A22B; - GL_MATERIAL_SIDE_HINT_PGI = $1A22C; - GL_MAX_VERTEX_HINT_PGI = $1A22D; - GL_COLOR3_BIT_PGI = $00010000; - GL_COLOR4_BIT_PGI = $00020000; - GL_EDGEFLAG_BIT_PGI = $00040000; - GL_INDEX_BIT_PGI = $00080000; - GL_MAT_AMBIENT_BIT_PGI = $00100000; - GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI = $00200000; - GL_MAT_DIFFUSE_BIT_PGI = $00400000; - GL_MAT_EMISSION_BIT_PGI = $00800000; - GL_MAT_COLOR_INDEXES_BIT_PGI = $01000000; - GL_MAT_SHININESS_BIT_PGI = $02000000; - GL_MAT_SPECULAR_BIT_PGI = $04000000; - GL_NORMAL_BIT_PGI = $08000000; - GL_TEXCOORD1_BIT_PGI = $10000000; - GL_TEXCOORD2_BIT_PGI = $20000000; - GL_TEXCOORD3_BIT_PGI = $40000000; - GL_TEXCOORD4_BIT_PGI = $80000000; - GL_VERTEX23_BIT_PGI = $00000004; - GL_VERTEX4_BIT_PGI = $00000008; - - // GL_REND_screen_coordinates - GL_SCREEN_COORDINATES_REND = $8490; - GL_INVERTED_SCREEN_W_REND = $8491; - - // GL_S3_s3tc - GL_RGB_S3TC = $83A0; - GL_RGB4_S3TC = $83A1; - GL_RGBA_S3TC = $83A2; - GL_RGBA4_S3TC = $83A3; - - // GL_SGIS_detail_texture - GL_DETAIL_TEXTURE_2D_SGIS = $8095; - GL_DETAIL_TEXTURE_2D_BINDING_SGIS = $8096; - GL_LINEAR_DETAIL_SGIS = $8097; - GL_LINEAR_DETAIL_ALPHA_SGIS = $8098; - GL_LINEAR_DETAIL_COLOR_SGIS = $8099; - GL_DETAIL_TEXTURE_LEVEL_SGIS = $809A; - GL_DETAIL_TEXTURE_MODE_SGIS = $809B; - GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS = $809C; - - // GL_SGIS_fog_function - GL_FOG_FUNC_SGIS = $812A; - GL_FOG_FUNC_POINTS_SGIS = $812B; - GL_MAX_FOG_FUNC_POINTS_SGIS = $812C; - - // GL_SGIS_generate_mipmap - GL_GENERATE_MIPMAP_SGIS = $8191; - GL_GENERATE_MIPMAP_HINT_SGIS = $8192; - - // GL_SGIS_multisample - GL_MULTISAMPLE_SGIS = $809D; - GL_SAMPLE_ALPHA_TO_MASK_SGIS = $809E; - GL_SAMPLE_ALPHA_TO_ONE_SGIS = $809F; - GL_SAMPLE_MASK_SGIS = $80A0; - GL_1PASS_SGIS = $80A1; - GL_2PASS_0_SGIS = $80A2; - GL_2PASS_1_SGIS = $80A3; - GL_4PASS_0_SGIS = $80A4; - GL_4PASS_1_SGIS = $80A5; - GL_4PASS_2_SGIS = $80A6; - GL_4PASS_3_SGIS = $80A7; - GL_SAMPLE_BUFFERS_SGIS = $80A8; - GL_SAMPLES_SGIS = $80A9; - GL_SAMPLE_MASK_VALUE_SGIS = $80AA; - GL_SAMPLE_MASK_INVERT_SGIS = $80AB; - GL_SAMPLE_PATTERN_SGIS = $80AC; - - // GL_SGIS_pixel_texture - GL_PIXEL_TEXTURE_SGIS = $8353; - GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS = $8354; - GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS = $8355; - GL_PIXEL_GROUP_COLOR_SGIS = $8356; - - // GL_SGIS_point_line_texgen - GL_EYE_DISTANCE_TO_POINT_SGIS = $81F0; - GL_OBJECT_DISTANCE_TO_POINT_SGIS = $81F1; - GL_EYE_DISTANCE_TO_LINE_SGIS = $81F2; - GL_OBJECT_DISTANCE_TO_LINE_SGIS = $81F3; - GL_EYE_POINT_SGIS = $81F4; - GL_OBJECT_POINT_SGIS = $81F5; - GL_EYE_LINE_SGIS = $81F6; - GL_OBJECT_LINE_SGIS = $81F7; - - // GL_SGIS_point_parameters - GL_POINT_SIZE_MIN_SGIS = $8126; - GL_POINT_SIZE_MAX_SGIS = $8127; - GL_POINT_FADE_THRESHOLD_SIZE_SGIS = $8128; - GL_DISTANCE_ATTENUATION_SGIS = $8129; - - // GL_SGIS_sharpen_texture - GL_LINEAR_SHARPEN_SGIS = $80AD; - GL_LINEAR_SHARPEN_ALPHA_SGIS = $80AE; - GL_LINEAR_SHARPEN_COLOR_SGIS = $80AF; - GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS = $80B0; - - // GL_SGIS_texture4D - GL_PACK_SKIP_VOLUMES_SGIS = $8130; - GL_PACK_IMAGE_DEPTH_SGIS = $8131; - GL_UNPACK_SKIP_VOLUMES_SGIS = $8132; - GL_UNPACK_IMAGE_DEPTH_SGIS = $8133; - GL_TEXTURE_4D_SGIS = $8134; - GL_PROXY_TEXTURE_4D_SGIS = $8135; - GL_TEXTURE_4DSIZE_SGIS = $8136; - GL_TEXTURE_WRAP_Q_SGIS = $8137; - GL_MAX_4D_TEXTURE_SIZE_SGIS = $8138; - GL_TEXTURE_4D_BINDING_SGIS = $814F; - - // GL_SGIS_texture_color_mask - GL_TEXTURE_COLOR_WRITEMASK_SGIS = $81EF; - - // GL_SGIS_texture_edge_clamp - GL_CLAMP_TO_EDGE_SGIS = $812F; - - // GL_SGIS_texture_filter4 - GL_FILTER4_SGIS = $8146; - GL_TEXTURE_FILTER4_SIZE_SGIS = $8147; - - // GL_SGIS_texture_lod - GL_TEXTURE_MIN_LOD_SGIS = $813A; - GL_TEXTURE_MAX_LOD_SGIS = $813B; - GL_TEXTURE_BASE_LEVEL_SGIS = $813C; - GL_TEXTURE_MAX_LEVEL_SGIS = $813D; - - // GL_SGIS_texture_select - GL_DUAL_ALPHA4_SGIS = $8110; - GL_DUAL_ALPHA8_SGIS = $8111; - GL_DUAL_ALPHA12_SGIS = $8112; - GL_DUAL_ALPHA16_SGIS = $8113; - GL_DUAL_LUMINANCE4_SGIS = $8114; - GL_DUAL_LUMINANCE8_SGIS = $8115; - GL_DUAL_LUMINANCE12_SGIS = $8116; - GL_DUAL_LUMINANCE16_SGIS = $8117; - GL_DUAL_INTENSITY4_SGIS = $8118; - GL_DUAL_INTENSITY8_SGIS = $8119; - GL_DUAL_INTENSITY12_SGIS = $811A; - GL_DUAL_INTENSITY16_SGIS = $811B; - GL_DUAL_LUMINANCE_ALPHA4_SGIS = $811C; - GL_DUAL_LUMINANCE_ALPHA8_SGIS = $811D; - GL_QUAD_ALPHA4_SGIS = $811E; - GL_QUAD_ALPHA8_SGIS = $811F; - GL_QUAD_LUMINANCE4_SGIS = $8120; - GL_QUAD_LUMINANCE8_SGIS = $8121; - GL_QUAD_INTENSITY4_SGIS = $8122; - GL_QUAD_INTENSITY8_SGIS = $8123; - GL_DUAL_TEXTURE_SELECT_SGIS = $8124; - GL_QUAD_TEXTURE_SELECT_SGIS = $8125; - - // GL_SGIX_async - GL_ASYNC_MARKER_SGIX = $8329; - - // GL_SGIX_async_histogram - GL_ASYNC_HISTOGRAM_SGIX = $832C; - GL_MAX_ASYNC_HISTOGRAM_SGIX = $832D; - - // GL_SGIX_async_pixel - GL_ASYNC_TEX_IMAGE_SGIX = $835C; - GL_ASYNC_DRAW_PIXELS_SGIX = $835D; - GL_ASYNC_READ_PIXELS_SGIX = $835E; - GL_MAX_ASYNC_TEX_IMAGE_SGIX = $835F; - GL_MAX_ASYNC_DRAW_PIXELS_SGIX = $8360; - GL_MAX_ASYNC_READ_PIXELS_SGIX = $8361; - - // GL_SGIX_blend_alpha_minmax - GL_ALPHA_MIN_SGIX = $8320; - GL_ALPHA_MAX_SGIX = $8321; - - // GL_SGIX_calligraphic_fragment - GL_CALLIGRAPHIC_FRAGMENT_SGIX = $8183; - - // GL_SGIX_clipmap - GL_LINEAR_CLIPMAP_LINEAR_SGIX = $8170; - GL_TEXTURE_CLIPMAP_CENTER_SGIX = $8171; - GL_TEXTURE_CLIPMAP_FRAME_SGIX = $8172; - GL_TEXTURE_CLIPMAP_OFFSET_SGIX = $8173; - GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX = $8174; - GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX = $8175; - GL_TEXTURE_CLIPMAP_DEPTH_SGIX = $8176; - GL_MAX_CLIPMAP_DEPTH_SGIX = $8177; - GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX = $8178; - GL_NEAREST_CLIPMAP_NEAREST_SGIX = $844D; - GL_NEAREST_CLIPMAP_LINEAR_SGIX = $844E; - GL_LINEAR_CLIPMAP_NEAREST_SGIX = $844F; - - // GL_SGIX_convolution_accuracy - GL_CONVOLUTION_HINT_SGIX = $8316; - - // GL_SGIX_depth_texture - GL_DEPTH_COMPONENT16_SGIX = $81A5; - GL_DEPTH_COMPONENT24_SGIX = $81A6; - GL_DEPTH_COMPONENT32_SGIX = $81A7; - - // GL_SGIX_fog_offset - GL_FOG_OFFSET_SGIX = $8198; - GL_FOG_OFFSET_VALUE_SGIX = $8199; - - // GL_SGIX_fog_scale - GL_FOG_SCALE_SGIX = $81FC; - GL_FOG_SCALE_VALUE_SGIX = $81FD; - - // GL_SGIX_fragment_lighting - GL_FRAGMENT_LIGHTING_SGIX = $8400; - GL_FRAGMENT_COLOR_MATERIAL_SGIX = $8401; - GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX = $8402; - GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX = $8403; - GL_MAX_FRAGMENT_LIGHTS_SGIX = $8404; - GL_MAX_ACTIVE_LIGHTS_SGIX = $8405; - GL_CURRENT_RASTER_NORMAL_SGIX = $8406; - GL_LIGHT_ENV_MODE_SGIX = $8407; - GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX = $8408; - GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX = $8409; - GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX = $840A; - GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX = $840B; - GL_FRAGMENT_LIGHT0_SGIX = $840C; - GL_FRAGMENT_LIGHT1_SGIX = $840D; - GL_FRAGMENT_LIGHT2_SGIX = $840E; - GL_FRAGMENT_LIGHT3_SGIX = $840F; - GL_FRAGMENT_LIGHT4_SGIX = $8410; - GL_FRAGMENT_LIGHT5_SGIX = $8411; - GL_FRAGMENT_LIGHT6_SGIX = $8412; - GL_FRAGMENT_LIGHT7_SGIX = $8413; - - // GL_SGIX_framezoom - GL_FRAMEZOOM_SGIX = $818B; - GL_FRAMEZOOM_FACTOR_SGIX = $818C; - GL_MAX_FRAMEZOOM_FACTOR_SGIX = $818D; - - // GL_SGIX_impact_pixel_texture - GL_PIXEL_TEX_GEN_Q_CEILING_SGIX = $8184; - GL_PIXEL_TEX_GEN_Q_ROUND_SGIX = $8185; - GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX = $8186; - GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX = $8187; - GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX = $8188; - GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX = $8189; - GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX = $818A; - - // GL_SGIX_instruments - GL_INSTRUMENT_BUFFER_POINTER_SGIX = $8180; - GL_INSTRUMENT_MEASUREMENTS_SGIX = $8181; - - // GL_SGIX_interlace - GL_INTERLACE_SGIX = $8094; - - // GL_SGIX_ir_instrument1 - GL_IR_INSTRUMENT1_SGIX = $817F; - - // GL_SGIX_list_priority - GL_LIST_PRIORITY_SGIX = $8182; - - // GL_SGIX_pixel_texture - GL_PIXEL_TEX_GEN_SGIX = $8139; - GL_PIXEL_TEX_GEN_MODE_SGIX = $832B; - - // GL_SGIX_pixel_tiles - GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX = $813E; - GL_PIXEL_TILE_CACHE_INCREMENT_SGIX = $813F; - GL_PIXEL_TILE_WIDTH_SGIX = $8140; - GL_PIXEL_TILE_HEIGHT_SGIX = $8141; - GL_PIXEL_TILE_GRID_WIDTH_SGIX = $8142; - GL_PIXEL_TILE_GRID_HEIGHT_SGIX = $8143; - GL_PIXEL_TILE_GRID_DEPTH_SGIX = $8144; - GL_PIXEL_TILE_CACHE_SIZE_SGIX = $8145; - - // GL_SGIX_polynomial_ffd - GL_GEOMETRY_DEFORMATION_SGIX = $8194; - GL_TEXTURE_DEFORMATION_SGIX = $8195; - GL_DEFORMATIONS_MASK_SGIX = $8196; - GL_MAX_DEFORMATION_ORDER_SGIX = $8197; - - // GL_SGIX_reference_plane - GL_REFERENCE_PLANE_SGIX = $817D; - GL_REFERENCE_PLANE_EQUATION_SGIX = $817E; - - // GL_SGIX_resample - GL_PACK_RESAMPLE_SGIX = $842C; - GL_UNPACK_RESAMPLE_SGIX = $842D; - GL_RESAMPLE_REPLICATE_SGIX = $842E; - GL_RESAMPLE_ZERO_FILL_SGIX = $842F; - GL_RESAMPLE_DECIMATE_SGIX = $8430; - - // GL_SGIX_scalebias_hint - GL_SCALEBIAS_HINT_SGIX = $8322; - - // GL_SGIX_shadow - GL_TEXTURE_COMPARE_SGIX = $819A; - GL_TEXTURE_COMPARE_OPERATOR_SGIX = $819B; - GL_TEXTURE_LEQUAL_R_SGIX = $819C; - GL_TEXTURE_GEQUAL_R_SGIX = $819D; - - // GL_SGIX_shadow_ambient - GL_SHADOW_AMBIENT_SGIX = $80BF; - - // GL_SGIX_sprite - GL_SPRITE_SGIX = $8148; - GL_SPRITE_MODE_SGIX = $8149; - GL_SPRITE_AXIS_SGIX = $814A; - GL_SPRITE_TRANSLATION_SGIX = $814B; - GL_SPRITE_AXIAL_SGIX = $814C; - GL_SPRITE_OBJECT_ALIGNED_SGIX = $814D; - GL_SPRITE_EYE_ALIGNED_SGIX = $814E; - - // GL_SGIX_subsample - GL_PACK_SUBSAMPLE_RATE_SGIX = $85A0; - GL_UNPACK_SUBSAMPLE_RATE_SGIX = $85A1; - GL_PIXEL_SUBSAMPLE_4444_SGIX = $85A2; - GL_PIXEL_SUBSAMPLE_2424_SGIX = $85A3; - GL_PIXEL_SUBSAMPLE_4242_SGIX = $85A4; - - // GL_SGIX_texture_add_env - GL_TEXTURE_ENV_BIAS_SGIX = $80BE; - - // GL_SGIX_texture_coordinate_clamp - GL_TEXTURE_MAX_CLAMP_S_SGIX = $8369; - GL_TEXTURE_MAX_CLAMP_T_SGIX = $836A; - GL_TEXTURE_MAX_CLAMP_R_SGIX = $836B; - - // GL_SGIX_texture_lod_bias - GL_TEXTURE_LOD_BIAS_S_SGIX = $818E; - GL_TEXTURE_LOD_BIAS_T_SGIX = $818F; - GL_TEXTURE_LOD_BIAS_R_SGIX = $8190; - - // GL_SGIX_texture_multi_buffer - GL_TEXTURE_MULTI_BUFFER_HINT_SGIX = $812E; - - // GL_SGIX_texture_scale_bias - GL_POST_TEXTURE_FILTER_BIAS_SGIX = $8179; - GL_POST_TEXTURE_FILTER_SCALE_SGIX = $817A; - GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX = $817B; - GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX = $817C; - - // GL_SGIX_vertex_preclip - GL_VERTEX_PRECLIP_SGIX = $83EE; - GL_VERTEX_PRECLIP_HINT_SGIX = $83EF; - - // GL_SGIX_ycrcb - GL_YCRCB_422_SGIX = $81BB; - GL_YCRCB_444_SGIX = $81BC; - - // GL_SGIX_ycrcba - GL_YCRCB_SGIX = $8318; - GL_YCRCBA_SGIX = $8319; - - // GL_SGI_color_matrix - GL_COLOR_MATRIX_SGI = $80B1; - GL_COLOR_MATRIX_STACK_DEPTH_SGI = $80B2; - GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI = $80B3; - GL_POST_COLOR_MATRIX_RED_SCALE_SGI = $80B4; - GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI = $80B5; - GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI = $80B6; - GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI = $80B7; - GL_POST_COLOR_MATRIX_RED_BIAS_SGI = $80B8; - GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI = $80B9; - GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI = $80BA; - GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI = $80BB; - - // GL_SGI_color_table - GL_COLOR_TABLE_SGI = $80D0; - GL_POST_CONVOLUTION_COLOR_TABLE_SGI = $80D1; - GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI = $80D2; - GL_PROXY_COLOR_TABLE_SGI = $80D3; - GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI = $80D4; - GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI = $80D5; - GL_COLOR_TABLE_SCALE_SGI = $80D6; - GL_COLOR_TABLE_BIAS_SGI = $80D7; - GL_COLOR_TABLE_FORMAT_SGI = $80D8; - GL_COLOR_TABLE_WIDTH_SGI = $80D9; - GL_COLOR_TABLE_RED_SIZE_SGI = $80DA; - GL_COLOR_TABLE_GREEN_SIZE_SGI = $80DB; - GL_COLOR_TABLE_BLUE_SIZE_SGI = $80DC; - GL_COLOR_TABLE_ALPHA_SIZE_SGI = $80DD; - GL_COLOR_TABLE_LUMINANCE_SIZE_SGI = $80DE; - GL_COLOR_TABLE_INTENSITY_SIZE_SGI = $80DF; - - // GL_SGI_depth_pass_instrument - GL_DEPTH_PASS_INSTRUMENT_SGIX = $8310; - GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX = $8311; - GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX = $8312; - - // GL_SGI_texture_color_table - GL_TEXTURE_COLOR_TABLE_SGI = $80BC; - GL_PROXY_TEXTURE_COLOR_TABLE_SGI = $80BD; - - // GL_SUNX_constant_data - GL_UNPACK_CONSTANT_DATA_SUNX = $81D5; - GL_TEXTURE_CONSTANT_DATA_SUNX = $81D6; - - // GL_SUN_convolution_border_modes - GL_WRAP_BORDER_SUN = $81D4; - - // GL_SUN_global_alpha - GL_GLOBAL_ALPHA_SUN = $81D9; - GL_GLOBAL_ALPHA_FACTOR_SUN = $81DA; - - // GL_SUN_mesh_array - GL_QUAD_MESH_SUN = $8614; - GL_TRIANGLE_MESH_SUN = $8615; - - // GL_SUN_slice_accum - GL_SLICE_ACCUM_SUN = $85CC; - - // GL_SUN_triangle_list - GL_RESTART_SUN = $0001; - GL_REPLACE_MIDDLE_SUN = $0002; - GL_REPLACE_OLDEST_SUN = $0003; - GL_TRIANGLE_LIST_SUN = $81D7; - GL_REPLACEMENT_CODE_SUN = $81D8; - GL_REPLACEMENT_CODE_ARRAY_SUN = $85C0; - GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN = $85C1; - GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN = $85C2; - GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN = $85C3; - GL_R1UI_V3F_SUN = $85C4; - GL_R1UI_C4UB_V3F_SUN = $85C5; - GL_R1UI_C3F_V3F_SUN = $85C6; - GL_R1UI_N3F_V3F_SUN = $85C7; - GL_R1UI_C4F_N3F_V3F_SUN = $85C8; - GL_R1UI_T2F_V3F_SUN = $85C9; - GL_R1UI_T2F_N3F_V3F_SUN = $85CA; - GL_R1UI_T2F_C4F_N3F_V3F_SUN = $85CB; - - // GL_WIN_phong_shading - GL_PHONG_WIN = $80EA; - GL_PHONG_HINT_WIN = $80EB; - - // GL_WIN_specular_fog - GL_FOG_SPECULAR_TEXTURE_WIN = $80EC; - - // GL_ARB_vertex_shader - GL_VERTEX_SHADER_ARB = $8B31; - GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB = $8B4A; - GL_MAX_VARYING_FLOATS_ARB = $8B4B; - GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB = $8B4C; - GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB = $8B4D; - GL_OBJECT_ACTIVE_ATTRIBUTES_ARB = $8B89; - GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB = $8B8A; - - // GL_ARB_fragment_shader - GL_FRAGMENT_SHADER_ARB = $8B30; - GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB = $8B49; // 1.4 - GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB = $8B8B; // 1.4 - - // GL_ARB_occlusion_query - GL_SAMPLES_PASSED_ARB = $8914; - GL_QUERY_COUNTER_BITS_ARB = $8864; - GL_CURRENT_QUERY_ARB = $8865; - GL_QUERY_RESULT_ARB = $8866; - GL_QUERY_RESULT_AVAILABLE_ARB = $8867; - - // GL_ARB_point_sprite - GL_POINT_SPRITE_ARB = $8861; - GL_COORD_REPLACE_ARB = $8862; - - // GL_ARB_shading_language_100 - GL_SHADING_LANGUAGE_VERSION_ARB = $8B8C; // 1.4 - - // GL_ARB_shader_objects - GL_PROGRAM_OBJECT_ARB = $8B40; - - GL_OBJECT_TYPE_ARB = $8B4E; - GL_OBJECT_SUBTYPE_ARB = $8B4F; - GL_OBJECT_DELETE_STATUS_ARB = $8B80; - GL_OBJECT_COMPILE_STATUS_ARB = $8B81; - GL_OBJECT_LINK_STATUS_ARB = $8B82; - GL_OBJECT_VALIDATE_STATUS_ARB = $8B83; - GL_OBJECT_INFO_LOG_LENGTH_ARB = $8B84; - GL_OBJECT_ATTACHED_OBJECTS_ARB = $8B85; - GL_OBJECT_ACTIVE_UNIFORMS_ARB = $8B86; - GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB = $8B87; - GL_OBJECT_SHADER_SOURCE_LENGTH_ARB = $8B88; - - GL_SHADER_OBJECT_ARB = $8B48; - - GL_FLOAT_VEC2_ARB = $8B50; - GL_FLOAT_VEC3_ARB = $8B51; - GL_FLOAT_VEC4_ARB = $8B52; - GL_INT_VEC2_ARB = $8B53; - GL_INT_VEC3_ARB = $8B54; - GL_INT_VEC4_ARB = $8B55; - GL_BOOL_ARB = $8B56; - GL_BOOL_VEC2_ARB = $8B57; - GL_BOOL_VEC3_ARB = $8B58; - GL_BOOL_VEC4_ARB = $8B59; - GL_FLOAT_MAT2_ARB = $8B5A; - GL_FLOAT_MAT3_ARB = $8B5B; - GL_FLOAT_MAT4_ARB = $8B5C; - GL_SAMPLER_1D_ARB = $8B5D; - GL_SAMPLER_2D_ARB = $8B5E; - GL_SAMPLER_3D_ARB = $8B5F; - GL_SAMPLER_CUBE_ARB = $8B60; - GL_SAMPLER_1D_SHADOW_ARB = $8B61; - GL_SAMPLER_2D_SHADOW_ARB = $8B62; - GL_SAMPLER_2D_RECT_ARB = $8B63; - GL_SAMPLER_2D_RECT_SHADOW_ARB = $8B64; - - // WGL_3DFX_multisample - WGL_SAMPLE_BUFFERS_3DFX = $2060; - WGL_SAMPLES_3DFX = $2061; - - // WGL_ARB_buffer_region - WGL_FRONT_COLOR_BUFFER_BIT_ARB = $00000001; - WGL_BACK_COLOR_BUFFER_BIT_ARB = $00000002; - WGL_DEPTH_BUFFER_BIT_ARB = $00000004; - WGL_STENCIL_BUFFER_BIT_ARB = $00000008; - - // WGL_ARB_make_current_read - ERROR_INVALID_PIXEL_TYPE_ARB = $2043; - ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB = $2054; - - // WGL_ARB_multisample - WGL_SAMPLE_BUFFERS_ARB = $2041; - WGL_SAMPLES_ARB = $2042; - - // WGL_ARB_pbuffer - WGL_DRAW_TO_PBUFFER_ARB = $202D; - WGL_MAX_PBUFFER_PIXELS_ARB = $202E; - WGL_MAX_PBUFFER_WIDTH_ARB = $202F; - WGL_MAX_PBUFFER_HEIGHT_ARB = $2030; - WGL_PBUFFER_LARGEST_ARB = $2033; - WGL_PBUFFER_WIDTH_ARB = $2034; - WGL_PBUFFER_HEIGHT_ARB = $2035; - WGL_PBUFFER_LOST_ARB = $2036; - - // WGL_ARB_pixel_format - WGL_NUMBER_PIXEL_FORMATS_ARB = $2000; - WGL_DRAW_TO_WINDOW_ARB = $2001; - WGL_DRAW_TO_BITMAP_ARB = $2002; - WGL_ACCELERATION_ARB = $2003; - WGL_NEED_PALETTE_ARB = $2004; - WGL_NEED_SYSTEM_PALETTE_ARB = $2005; - WGL_SWAP_LAYER_BUFFERS_ARB = $2006; - WGL_SWAP_METHOD_ARB = $2007; - WGL_NUMBER_OVERLAYS_ARB = $2008; - WGL_NUMBER_UNDERLAYS_ARB = $2009; - WGL_TRANSPARENT_ARB = $200A; - WGL_TRANSPARENT_RED_VALUE_ARB = $2037; - WGL_TRANSPARENT_GREEN_VALUE_ARB = $2038; - WGL_TRANSPARENT_BLUE_VALUE_ARB = $2039; - WGL_TRANSPARENT_ALPHA_VALUE_ARB = $203A; - WGL_TRANSPARENT_INDEX_VALUE_ARB = $203B; - WGL_SHARE_DEPTH_ARB = $200C; - WGL_SHARE_STENCIL_ARB = $200D; - WGL_SHARE_ACCUM_ARB = $200E; - WGL_SUPPORT_GDI_ARB = $200F; - WGL_SUPPORT_OPENGL_ARB = $2010; - WGL_DOUBLE_BUFFER_ARB = $2011; - WGL_STEREO_ARB = $2012; - WGL_PIXEL_TYPE_ARB = $2013; - WGL_COLOR_BITS_ARB = $2014; - WGL_RED_BITS_ARB = $2015; - WGL_RED_SHIFT_ARB = $2016; - WGL_GREEN_BITS_ARB = $2017; - WGL_GREEN_SHIFT_ARB = $2018; - WGL_BLUE_BITS_ARB = $2019; - WGL_BLUE_SHIFT_ARB = $201A; - WGL_ALPHA_BITS_ARB = $201B; - WGL_ALPHA_SHIFT_ARB = $201C; - WGL_ACCUM_BITS_ARB = $201D; - WGL_ACCUM_RED_BITS_ARB = $201E; - WGL_ACCUM_GREEN_BITS_ARB = $201F; - WGL_ACCUM_BLUE_BITS_ARB = $2020; - WGL_ACCUM_ALPHA_BITS_ARB = $2021; - WGL_DEPTH_BITS_ARB = $2022; - WGL_STENCIL_BITS_ARB = $2023; - WGL_AUX_BUFFERS_ARB = $2024; - WGL_NO_ACCELERATION_ARB = $2025; - WGL_GENERIC_ACCELERATION_ARB = $2026; - WGL_FULL_ACCELERATION_ARB = $2027; - WGL_SWAP_EXCHANGE_ARB = $2028; - WGL_SWAP_COPY_ARB = $2029; - WGL_SWAP_UNDEFINED_ARB = $202A; - WGL_TYPE_RGBA_ARB = $202B; - WGL_TYPE_COLORINDEX_ARB = $202C; - - // WGL_ARB_pixel_format_float - WGL_RGBA_FLOAT_MODE_ARB = $8820; - WGL_CLAMP_VERTEX_COLOR_ARB = $891A; - WGL_CLAMP_FRAGMENT_COLOR_ARB = $891B; - WGL_CLAMP_READ_COLOR_ARB = $891C; - WGL_FIXED_ONLY_ARB = $891D; - - // WGL_ARB_render_texture - WGL_BIND_TO_TEXTURE_RGB_ARB = $2070; - WGL_BIND_TO_TEXTURE_RGBA_ARB = $2071; - WGL_TEXTURE_FORMAT_ARB = $2072; - WGL_TEXTURE_TARGET_ARB = $2073; - WGL_MIPMAP_TEXTURE_ARB = $2074; - WGL_TEXTURE_RGB_ARB = $2075; - WGL_TEXTURE_RGBA_ARB = $2076; - WGL_NO_TEXTURE_ARB = $2077; - WGL_TEXTURE_CUBE_MAP_ARB = $2078; - WGL_TEXTURE_1D_ARB = $2079; - WGL_TEXTURE_2D_ARB = $207A; - WGL_MIPMAP_LEVEL_ARB = $207B; - WGL_CUBE_MAP_FACE_ARB = $207C; - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB = $207D; - WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB = $207E; - WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB = $207F; - WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB = $2080; - WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB = $2081; - WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB = $2082; - WGL_FRONT_LEFT_ARB = $2083; - WGL_FRONT_RIGHT_ARB = $2084; - WGL_BACK_LEFT_ARB = $2085; - WGL_BACK_RIGHT_ARB = $2086; - WGL_AUX0_ARB = $2087; - WGL_AUX1_ARB = $2088; - WGL_AUX2_ARB = $2089; - WGL_AUX3_ARB = $208A; - WGL_AUX4_ARB = $208B; - WGL_AUX5_ARB = $208C; - WGL_AUX6_ARB = $208D; - WGL_AUX7_ARB = $208E; - WGL_AUX8_ARB = $208F; - WGL_AUX9_ARB = $2090; - - // WGL_ARB_create_context - WGL_CONTEXT_DEBUG_BIT_ARB = $00000001; - WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = $00000002; - WGL_CONTEXT_MAJOR_VERSION_ARB = $2091; - WGL_CONTEXT_MINOR_VERSION_ARB = $2092; - WGL_CONTEXT_LAYER_PLANE_ARB = $2093; - WGL_CONTEXT_FLAGS_ARB = $2094; - ERROR_INVALID_VERSION_ARB = $2095; - - // WGL_ARB_create_context_profile - WGL_CONTEXT_PROFILE_MASK_ARB = $9126; - WGL_CONTEXT_CORE_PROFILE_BIT_ARB = $00000001; - WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = $00000002; - ERROR_INVALID_PROFILE_ARB = $2096; - - // WGL_ATI_pixel_format_float - WGL_TYPE_RGBA_FLOAT_ATI = $21A0; - GL_TYPE_RGBA_FLOAT_ATI = $8820; - GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI = $8835; - - // WGL_AMD_gpu_association - WGL_GPU_VENDOR_AMD = $1F00; - WGL_GPU_RENDERER_STRING_AMD = $1F01; - WGL_GPU_OPENGL_VERSION_STRING_AMD = $1F02; - WGL_GPU_FASTEST_TARGET_GPUS_AMD = $21A2; - WGL_GPU_RAM_AMD = $21A3; - WGL_GPU_CLOCK_AMD = $21A4; - WGL_GPU_NUM_PIPES_AMD = $21A5; - WGL_GPU_NUM_SIMD_AMD = $21A6; - WGL_GPU_NUM_RB_AMD = $21A7; - WGL_GPU_NUM_SPI_AMD = $21A8; - - // WGL_EXT_depth_float - WGL_DEPTH_FLOAT_EXT = $2040; - - // WGL_EXT_make_current_read - ERROR_INVALID_PIXEL_TYPE_EXT = $2043; - - // WGL_EXT_multisample - WGL_SAMPLE_BUFFERS_EXT = $2041; - WGL_SAMPLES_EXT = $2042; - - // WGL_EXT_pbuffer - WGL_DRAW_TO_PBUFFER_EXT = $202D; - WGL_MAX_PBUFFER_PIXELS_EXT = $202E; - WGL_MAX_PBUFFER_WIDTH_EXT = $202F; - WGL_MAX_PBUFFER_HEIGHT_EXT = $2030; - WGL_OPTIMAL_PBUFFER_WIDTH_EXT = $2031; - WGL_OPTIMAL_PBUFFER_HEIGHT_EXT = $2032; - WGL_PBUFFER_LARGEST_EXT = $2033; - WGL_PBUFFER_WIDTH_EXT = $2034; - WGL_PBUFFER_HEIGHT_EXT = $2035; - - // WGL_EXT_pixel_format - WGL_NUMBER_PIXEL_FORMATS_EXT = $2000; - WGL_DRAW_TO_WINDOW_EXT = $2001; - WGL_DRAW_TO_BITMAP_EXT = $2002; - WGL_ACCELERATION_EXT = $2003; - WGL_NEED_PALETTE_EXT = $2004; - WGL_NEED_SYSTEM_PALETTE_EXT = $2005; - WGL_SWAP_LAYER_BUFFERS_EXT = $2006; - WGL_SWAP_METHOD_EXT = $2007; - WGL_NUMBER_OVERLAYS_EXT = $2008; - WGL_NUMBER_UNDERLAYS_EXT = $2009; - WGL_TRANSPARENT_EXT = $200A; - WGL_TRANSPARENT_VALUE_EXT = $200B; - WGL_SHARE_DEPTH_EXT = $200C; - WGL_SHARE_STENCIL_EXT = $200D; - WGL_SHARE_ACCUM_EXT = $200E; - WGL_SUPPORT_GDI_EXT = $200F; - WGL_SUPPORT_OPENGL_EXT = $2010; - WGL_DOUBLE_BUFFER_EXT = $2011; - WGL_STEREO_EXT = $2012; - WGL_PIXEL_TYPE_EXT = $2013; - WGL_COLOR_BITS_EXT = $2014; - WGL_RED_BITS_EXT = $2015; - WGL_RED_SHIFT_EXT = $2016; - WGL_GREEN_BITS_EXT = $2017; - WGL_GREEN_SHIFT_EXT = $2018; - WGL_BLUE_BITS_EXT = $2019; - WGL_BLUE_SHIFT_EXT = $201A; - WGL_ALPHA_BITS_EXT = $201B; - WGL_ALPHA_SHIFT_EXT = $201C; - WGL_ACCUM_BITS_EXT = $201D; - WGL_ACCUM_RED_BITS_EXT = $201E; - WGL_ACCUM_GREEN_BITS_EXT = $201F; - WGL_ACCUM_BLUE_BITS_EXT = $2020; - WGL_ACCUM_ALPHA_BITS_EXT = $2021; - WGL_DEPTH_BITS_EXT = $2022; - WGL_STENCIL_BITS_EXT = $2023; - WGL_AUX_BUFFERS_EXT = $2024; - WGL_NO_ACCELERATION_EXT = $2025; - WGL_GENERIC_ACCELERATION_EXT = $2026; - WGL_FULL_ACCELERATION_EXT = $2027; - WGL_SWAP_EXCHANGE_EXT = $2028; - WGL_SWAP_COPY_EXT = $2029; - WGL_SWAP_UNDEFINED_EXT = $202A; - WGL_TYPE_RGBA_EXT = $202B; - WGL_TYPE_COLORINDEX_EXT = $202C; - - // WGL_I3D_digital_video_control - WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D = $2050; - WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D = $2051; - WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D = $2052; - WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D = $2053; - - // WGL_I3D_gamma - WGL_GAMMA_TABLE_SIZE_I3D = $204E; - WGL_GAMMA_EXCLUDE_DESKTOP_I3D = $204F; - - // WGL_I3D_genlock - WGL_GENLOCK_SOURCE_MULTIVIEW_I3D = $2044; - WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D = $2045; - WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D = $2046; - WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D = $2047; - WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D = $2048; - WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D = $2049; - WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D = $204A; - WGL_GENLOCK_SOURCE_EDGE_RISING_I3D = $204B; - WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D = $204C; - - // WGL_I3D_image_buffer - WGL_IMAGE_BUFFER_MIN_ACCESS_I3D = $00000001; - WGL_IMAGE_BUFFER_LOCK_I3D = $00000002; - - // WGL_NV_float_buffer - WGL_FLOAT_COMPONENTS_NV = $20B0; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV = $20B1; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV = $20B2; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV = $20B3; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV = $20B4; - WGL_TEXTURE_FLOAT_R_NV = $20B5; - WGL_TEXTURE_FLOAT_RG_NV = $20B6; - WGL_TEXTURE_FLOAT_RGB_NV = $20B7; - WGL_TEXTURE_FLOAT_RGBA_NV = $20B8; - - // WGL_NV_render_depth_texture - WGL_BIND_TO_TEXTURE_DEPTH_NV = $20A3; - WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV = $20A4; - WGL_DEPTH_TEXTURE_FORMAT_NV = $20A5; - WGL_TEXTURE_DEPTH_COMPONENT_NV = $20A6; - WGL_DEPTH_COMPONENT_NV = $20A7; - - // WGL_NV_render_texture_rectangle - WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV = $20A0; - WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV = $20A1; - WGL_TEXTURE_RECTANGLE_NV = $20A2; - - // WGL_NV_present_video - WGL_NUM_VIDEO_SLOTS_NV = $20F0; - - // WGL_NV_video_out - WGL_BIND_TO_VIDEO_RGB_NV = $20C0; - WGL_BIND_TO_VIDEO_RGBA_NV = $20C1; - WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV = $20C2; - WGL_VIDEO_OUT_COLOR_NV = $20C3; - WGL_VIDEO_OUT_ALPHA_NV = $20C4; - WGL_VIDEO_OUT_DEPTH_NV = $20C5; - WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV = $20C6; - WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV = $20C7; - WGL_VIDEO_OUT_FRAME = $20C8; - WGL_VIDEO_OUT_FIELD_1 = $20C9; - WGL_VIDEO_OUT_FIELD_2 = $20CA; - WGL_VIDEO_OUT_STACKED_FIELDS_1_2 = $20CB; - WGL_VIDEO_OUT_STACKED_FIELDS_2_1 = $20CC; - - // WGL_NV_gpu_affinity - WGL_ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV = $20D0; - WGL_ERROR_MISSING_AFFINITY_MASK_NV = $20D1; - - // WIN_draw_range_elements - GL_MAX_ELEMENTS_VERTICES_WIN = $80E8; - GL_MAX_ELEMENTS_INDICES_WIN = $80E9; - - // GLX 1.1 and later: - GLX_VENDOR = 1; - GLX_VERSION = 2; - GLX_EXTENSIONS = 3; - - GLX_USE_GL = 1; - GLX_BUFFER_SIZE = 2; - GLX_LEVEL = 3; - GLX_RGBA = 4; - GLX_DOUBLEBUFFER = 5; - GLX_STEREO = 6; - GLX_AUX_BUFFERS = 7; - GLX_RED_SIZE = 8; - GLX_GREEN_SIZE = 9; - GLX_BLUE_SIZE = 10; - GLX_ALPHA_SIZE = 11; - GLX_DEPTH_SIZE = 12; - GLX_STENCIL_SIZE = 13; - GLX_ACCUM_RED_SIZE = 14; - GLX_ACCUM_GREEN_SIZE = 15; - GLX_ACCUM_BLUE_SIZE = 16; - GLX_ACCUM_ALPHA_SIZE = 17; - - // GLX_VERSION_1_3 - GLX_WINDOW_BIT = $00000001; - GLX_PIXMAP_BIT = $00000002; - GLX_PBUFFER_BIT = $00000004; - GLX_RGBA_BIT = $00000001; - GLX_COLOR_INDEX_BIT = $00000002; - GLX_PBUFFER_CLOBBER_MASK = $08000000; - GLX_FRONT_LEFT_BUFFER_BIT = $00000001; - GLX_FRONT_RIGHT_BUFFER_BIT = $00000002; - GLX_BACK_LEFT_BUFFER_BIT = $00000004; - GLX_BACK_RIGHT_BUFFER_BIT = $00000008; - GLX_AUX_BUFFERS_BIT = $00000010; - GLX_DEPTH_BUFFER_BIT = $00000020; - GLX_STENCIL_BUFFER_BIT = $00000040; - GLX_ACCUM_BUFFER_BIT = $00000080; - GLX_CONFIG_CAVEAT = $20; - GLX_X_VISUAL_TYPE = $22; - GLX_TRANSPARENT_TYPE = $23; - GLX_TRANSPARENT_INDEX_VALUE = $24; - GLX_TRANSPARENT_RED_VALUE = $25; - GLX_TRANSPARENT_GREEN_VALUE = $26; - GLX_TRANSPARENT_BLUE_VALUE = $27; - GLX_TRANSPARENT_ALPHA_VALUE = $28; - GLX_DONT_CARE = $FFFFFFFF; - GLX_NONE = $8000; - GLX_SLOW_CONFIG = $8001; - GLX_TRUE_COLOR = $8002; - GLX_DIRECT_COLOR = $8003; - GLX_PSEUDO_COLOR = $8004; - GLX_STATIC_COLOR = $8005; - GLX_GRAY_SCALE = $8006; - GLX_STATIC_GRAY = $8007; - GLX_TRANSPARENT_RGB = $8008; - GLX_TRANSPARENT_INDEX = $8009; - GLX_VISUAL_ID = $800B; - GLX_SCREEN = $800C; - GLX_NON_CONFORMANT_CONFIG = $800D; - GLX_DRAWABLE_TYPE = $8010; - GLX_RENDER_TYPE = $8011; - GLX_X_RENDERABLE = $8012; - GLX_FBCONFIG_ID = $8013; - GLX_RGBA_TYPE = $8014; - GLX_COLOR_INDEX_TYPE = $8015; - GLX_MAX_PBUFFER_WIDTH = $8016; - GLX_MAX_PBUFFER_HEIGHT = $8017; - GLX_MAX_PBUFFER_PIXELS = $8018; - GLX_PRESERVED_CONTENTS = $801B; - GLX_LARGEST_PBUFFER = $801C; - GLX_WIDTH = $801D; - GLX_HEIGHT = $801E; - GLX_EVENT_MASK = $801F; - GLX_DAMAGED = $8020; - GLX_SAVED = $8021; - GLX_WINDOW = $8022; - GLX_PBUFFER = $8023; - GLX_PBUFFER_HEIGHT = $8040; - GLX_PBUFFER_WIDTH = $8041; - - // GLX_VERSION_1_4 - GLX_SAMPLE_BUFFERS = 100000; - GLX_SAMPLES = 100001; - - // GLX_ARB_multisample - GLX_SAMPLE_BUFFERS_ARB = 100000; - GLX_SAMPLES_ARB = 100001; - - // GLX_ARB_fbconfig_float - GLX_RGBA_FLOAT_TYPE_ARB = $20B9; - GLX_RGBA_FLOAT_BIT_ARB = $00000004; - - // GLX_ARB_create_context - GLX_CONTEXT_DEBUG_BIT_ARB = $00000001; - GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = $00000002; - GLX_CONTEXT_MAJOR_VERSION_ARB = $2091; - GLX_CONTEXT_MINOR_VERSION_ARB = $2092; - GLX_CONTEXT_FLAGS_ARB = $2094; - - // GLX_ARB_create_context_profile - GLX_CONTEXT_CORE_PROFILE_BIT_ARB = $00000001; - GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = $00000002; - GLX_CONTEXT_PROFILE_MASK_ARB = $9126; - - // GLX_EXT_visual_info - GLX_X_VISUAL_TYPE_EXT = $22; - GLX_TRANSPARENT_TYPE_EXT = $23; - GLX_TRANSPARENT_INDEX_VALUE_EXT = $24; - GLX_TRANSPARENT_RED_VALUE_EXT = $25; - GLX_TRANSPARENT_GREEN_VALUE_EXT = $26; - GLX_TRANSPARENT_BLUE_VALUE_EXT = $27; - GLX_TRANSPARENT_ALPHA_VALUE_EXT = $28; - GLX_NONE_EXT = $8000; - GLX_TRUE_COLOR_EXT = $8002; - GLX_DIRECT_COLOR_EXT = $8003; - GLX_PSEUDO_COLOR_EXT = $8004; - GLX_STATIC_COLOR_EXT = $8005; - GLX_GRAY_SCALE_EXT = $8006; - GLX_STATIC_GRAY_EXT = $8007; - GLX_TRANSPARENT_RGB_EXT = $8008; - GLX_TRANSPARENT_INDEX_EXT = $8009; - - // GLX_EXT_visual_rating - GLX_VISUAL_CAVEAT_EXT = $20; - GLX_SLOW_VISUAL_EXT = $8001; - GLX_NON_CONFORMANT_VISUAL_EXT = $800D; - (* reuse GLX_NONE_EXT *) - - // GLX_EXT_import_context - GLX_SHARE_CONTEXT_EXT = $800A; - GLX_VISUAL_ID_EXT = $800B; - GLX_SCREEN_EXT = $800C; - - // GLX_EXT_fbconfig_packed_float -// GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT = $20B1; -// GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT = $00000008; - - // GLX_EXT_framebuffer_sRGB -// GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT = $20B2; - - // GLX_EXT_texture_from_pixmap - GLX_TEXTURE_1D_BIT_EXT = $00000001; - GLX_TEXTURE_2D_BIT_EXT = $00000002; - GLX_TEXTURE_RECTANGLE_BIT_EXT = $00000004; - GLX_BIND_TO_TEXTURE_RGB_EXT = $20D0; - GLX_BIND_TO_TEXTURE_RGBA_EXT = $20D1; - GLX_BIND_TO_MIPMAP_TEXTURE_EXT = $20D2; - GLX_BIND_TO_TEXTURE_TARGETS_EXT = $20D3; - GLX_Y_INVERTED_EXT = $20D4; - GLX_TEXTURE_FORMAT_EXT = $20D5; - GLX_TEXTURE_TARGET_EXT = $20D6; - GLX_MIPMAP_TEXTURE_EXT = $20D7; - GLX_TEXTURE_FORMAT_NONE_EXT = $20D8; - GLX_TEXTURE_FORMAT_RGB_EXT = $20D9; - GLX_TEXTURE_FORMAT_RGBA_EXT = $20DA; - GLX_TEXTURE_1D_EXT = $20DB; - GLX_TEXTURE_2D_EXT = $20DC; - GLX_TEXTURE_RECTANGLE_EXT = $20DD; - GLX_FRONT_LEFT_EXT = $20DE; - GLX_FRONT_RIGHT_EXT = $20DF; - GLX_BACK_LEFT_EXT = $20E0; - GLX_BACK_RIGHT_EXT = $20E1; - GLX_FRONT_EXT = GLX_FRONT_LEFT_EXT; - GLX_BACK_EXT = GLX_BACK_LEFT_EXT; - GLX_AUX0_EXT = $20E2; - GLX_AUX1_EXT = $20E3; - GLX_AUX2_EXT = $20E4; - GLX_AUX3_EXT = $20E5; - GLX_AUX4_EXT = $20E6; - GLX_AUX5_EXT = $20E7; - GLX_AUX6_EXT = $20E8; - GLX_AUX7_EXT = $20E9; - GLX_AUX8_EXT = $20EA; - GLX_AUX9_EXT = $20EB; - - - // GLU - GLU_INVALID_ENUM = 100900; - GLU_INVALID_VALUE = 100901; - GLU_OUT_OF_MEMORY = 100902; - GLU_INCOMPATIBLE_GL_VERSION = 100903; - GLU_VERSION = 100800; - GLU_EXTENSIONS = 100801; - GLU_TRUE = GL_TRUE; - GLU_FALSE = GL_FALSE; - GLU_SMOOTH = 100000; - GLU_FLAT = 100001; - GLU_NONE = 100002; - GLU_POINT = 100010; - GLU_LINE = 100011; - GLU_FILL = 100012; - GLU_SILHOUETTE = 100013; - GLU_OUTSIDE = 100020; - GLU_INSIDE = 100021; - GLU_TESS_MAX_COORD = 1.0E150; - GLU_TESS_WINDING_RULE = 100140; - GLU_TESS_BOUNDARY_ONLY = 100141; - GLU_TESS_TOLERANCE = 100142; - GLU_TESS_WINDING_ODD = 100130; - GLU_TESS_WINDING_NONZERO = 100131; - GLU_TESS_WINDING_POSITIVE = 100132; - GLU_TESS_WINDING_NEGATIVE = 100133; - GLU_TESS_WINDING_ABS_GEQ_TWO = 100134; - GLU_TESS_BEGIN = 100100; // TGLUTessBeginProc - GLU_TESS_VERTEX = 100101; // TGLUTessVertexProc - GLU_TESS_END = 100102; // TGLUTessEndProc - GLU_TESS_ERROR = 100103; // TGLUTessErrorProc - GLU_TESS_EDGE_FLAG = 100104; // TGLUTessEdgeFlagProc - GLU_TESS_COMBINE = 100105; // TGLUTessCombineProc - GLU_TESS_BEGIN_DATA = 100106; // TGLUTessBeginDataProc - GLU_TESS_VERTEX_DATA = 100107; // TGLUTessVertexDataProc - GLU_TESS_END_DATA = 100108; // TGLUTessEndDataProc - GLU_TESS_ERROR_DATA = 100109; // TGLUTessErrorDataProc - GLU_TESS_EDGE_FLAG_DATA = 100110; // TGLUTessEdgeFlagDataProc - GLU_TESS_COMBINE_DATA = 100111; // TGLUTessCombineDataProc - GLU_TESS_ERROR1 = 100151; - GLU_TESS_ERROR2 = 100152; - GLU_TESS_ERROR3 = 100153; - GLU_TESS_ERROR4 = 100154; - GLU_TESS_ERROR5 = 100155; - GLU_TESS_ERROR6 = 100156; - GLU_TESS_ERROR7 = 100157; - GLU_TESS_ERROR8 = 100158; - GLU_TESS_MISSING_BEGIN_POLYGON = GLU_TESS_ERROR1; - GLU_TESS_MISSING_BEGIN_CONTOUR = GLU_TESS_ERROR2; - GLU_TESS_MISSING_END_POLYGON = GLU_TESS_ERROR3; - GLU_TESS_MISSING_END_CONTOUR = GLU_TESS_ERROR4; - GLU_TESS_COORD_TOO_LARGE = GLU_TESS_ERROR5; - GLU_TESS_NEED_COMBINE_CALLBACK = GLU_TESS_ERROR6; - GLU_AUTO_LOAD_MATRIX = 100200; - GLU_CULLING = 100201; - GLU_SAMPLING_TOLERANCE = 100203; - GLU_DISPLAY_MODE = 100204; - GLU_PARAMETRIC_TOLERANCE = 100202; - GLU_SAMPLING_METHOD = 100205; - GLU_U_STEP = 100206; - GLU_V_STEP = 100207; - GLU_PATH_LENGTH = 100215; - GLU_PARAMETRIC_ERROR = 100216; - GLU_DOMAIN_DISTANCE = 100217; - GLU_MAP1_TRIM_2 = 100210; - GLU_MAP1_TRIM_3 = 100211; - GLU_OUTLINE_POLYGON = 100240; - GLU_OUTLINE_PATCH = 100241; - GLU_NURBS_ERROR1 = 100251; - GLU_NURBS_ERROR2 = 100252; - GLU_NURBS_ERROR3 = 100253; - GLU_NURBS_ERROR4 = 100254; - GLU_NURBS_ERROR5 = 100255; - GLU_NURBS_ERROR6 = 100256; - GLU_NURBS_ERROR7 = 100257; - GLU_NURBS_ERROR8 = 100258; - GLU_NURBS_ERROR9 = 100259; - GLU_NURBS_ERROR10 = 100260; - GLU_NURBS_ERROR11 = 100261; - GLU_NURBS_ERROR12 = 100262; - GLU_NURBS_ERROR13 = 100263; - GLU_NURBS_ERROR14 = 100264; - GLU_NURBS_ERROR15 = 100265; - GLU_NURBS_ERROR16 = 100266; - GLU_NURBS_ERROR17 = 100267; - GLU_NURBS_ERROR18 = 100268; - GLU_NURBS_ERROR19 = 100269; - GLU_NURBS_ERROR20 = 100270; - GLU_NURBS_ERROR21 = 100271; - GLU_NURBS_ERROR22 = 100272; - GLU_NURBS_ERROR23 = 100273; - GLU_NURBS_ERROR24 = 100274; - GLU_NURBS_ERROR25 = 100275; - GLU_NURBS_ERROR26 = 100276; - GLU_NURBS_ERROR27 = 100277; - GLU_NURBS_ERROR28 = 100278; - GLU_NURBS_ERROR29 = 100279; - GLU_NURBS_ERROR30 = 100280; - GLU_NURBS_ERROR31 = 100281; - GLU_NURBS_ERROR32 = 100282; - GLU_NURBS_ERROR33 = 100283; - GLU_NURBS_ERROR34 = 100284; - GLU_NURBS_ERROR35 = 100285; - GLU_NURBS_ERROR36 = 100286; - GLU_NURBS_ERROR37 = 100287; - GLU_CW = 100120; - GLU_CCW = 100121; - GLU_INTERIOR = 100122; - GLU_EXTERIOR = 100123; - GLU_UNKNOWN = 100124; - GLU_BEGIN = GLU_TESS_BEGIN; - GLU_VERTEX = GLU_TESS_VERTEX; - GLU_END = GLU_TESS_END; - GLU_ERROR = GLU_TESS_ERROR; - GLU_EDGE_FLAG = GLU_TESS_EDGE_FLAG; - -type - // GL_VERSION_1_0 - TglCullFace = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFrontFace = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglHint = procedure(target: TGLenum; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLineWidth = procedure(width: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointSize = procedure(size: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPolygonMode = procedure(face: TGLenum; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglScissor = procedure(x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameterf = procedure(target: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameterfv = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameteri = procedure(target: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameteriv = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexImage1D = procedure(target: TGLenum; level: TGLint; internalformat: TGLint; width: TGLsizei; border: TGLint; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexImage2D = procedure(target: TGLenum; level: TGLint; internalformat: TGLint; width: TGLsizei; height: TGLsizei; border: TGLint; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawBuffer = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClear = procedure(mask: TGLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearColor = procedure(red: TGLclampf; green: TGLclampf; blue: TGLclampf; alpha: TGLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearStencil = procedure(s: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearDepth = procedure(depth: TGLclampd); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStencilMask = procedure(mask: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorMask = procedure(red: TGLboolean; green: TGLboolean; blue: TGLboolean; alpha: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDepthMask = procedure(flag: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisable = procedure(cap: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnable = procedure(cap: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFinish = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFlush = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBlendFunc = procedure(sfactor: TGLenum; dfactor: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLogicOp = procedure(opcode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStencilFunc = procedure(func: TGLenum; ref: TGLint; mask: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStencilOp = procedure(fail: TGLenum; zfail: TGLenum; zpass: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDepthFunc = procedure(func: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelStoref = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelStorei = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReadBuffer = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReadPixels = procedure(x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBooleanv = procedure(pname: TGLenum; params: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetDoublev = procedure(pname: TGLenum; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetError = function(): TGLenum; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFloatv = procedure(pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetIntegerv = procedure(pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetString = function(name: TGLenum): PAnsiChar; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexImage = procedure(target: TGLenum; level: TGLint; format: TGLenum; _type: TGLenum; pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexParameteriv = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexParameterfv = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexLevelParameterfv = procedure(target: TGLenum; level: TGLint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexLevelParameteriv = procedure(target: TGLenum; level: TGLint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsEnabled = function(cap: TGLenum): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDepthRange = procedure(zNear: TGLclampd; zFar: TGLclampd); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglViewport = procedure(x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_VERSION_1_1 - TglDrawArrays = procedure(mode: TGLenum; first: TGLint; count: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawElements = procedure(mode: TGLenum; count: TGLsizei; _type: TGLenum; const indices: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPointerv = procedure(pname: TGLenum; params: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPolygonOffset = procedure(factor: TGLfloat; units: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexImage1D = procedure(target: TGLenum; level: TGLint; internalFormat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei; border: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexImage2D = procedure(target: TGLenum; level: TGLint; internalFormat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei; border: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexSubImage1D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexSubImage2D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexSubImage1D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; width: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexSubImage2D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindTexture = procedure(target: TGLenum; texture: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteTextures = procedure(n: TGLsizei; const textures: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenTextures = procedure(n: TGLsizei; textures: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - -{$ifdef DGL_DEPRECATED} - TglAccum = procedure(op: TGLenum; value: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglAlphaFunc = procedure(func: TGLenum; ref: TGLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglAreTexturesResident = function(n: TGLsizei; const textures: PGLuint; residences: PGLboolean): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglArrayElement = procedure(i: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBegin = procedure(mode: TGLenum); {$IFNDEF CLR}{$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF}{$ENDIF} - TglBitmap = procedure(width: TGLsizei; height: TGLsizei; xorig: TGLfloat; yorig: TGLfloat; xmove: TGLfloat; ymove: TGLfloat; const bitmap: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCallList = procedure(list: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCallLists = procedure(n: TGLsizei; _type: TGLenum; const lists: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearAccum = procedure(red: TGLfloat; green: TGLfloat; blue: TGLfloat; alpha: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearIndex = procedure(c: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClipPlane = procedure(plane: TGLenum; const equation: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3b = procedure(red: TGLbyte; green: TGLbyte; blue: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3bv = procedure(const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3d = procedure(red: TGLdouble; green: TGLdouble; blue: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3f = procedure(red: TGLfloat; green: TGLfloat; blue: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3i = procedure(red: TGLint; green: TGLint; blue: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3s = procedure(red: TGLshort; green: TGLshort; blue: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3ub = procedure(red: TGLubyte; green: TGLubyte; blue: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3ubv = procedure(const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3ui = procedure(red: TGLuint; green: TGLuint; blue: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3uiv = procedure(const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3us = procedure(red: TGLushort; green: TGLushort; blue: TGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3usv = procedure(const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4b = procedure(red: TGLbyte; green: TGLbyte; blue: TGLbyte; alpha: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4bv = procedure(const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4d = procedure(red: TGLdouble; green: TGLdouble; blue: TGLdouble; alpha: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4f = procedure(red: TGLfloat; green: TGLfloat; blue: TGLfloat; alpha: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4i = procedure(red: TGLint; green: TGLint; blue: TGLint; alpha: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4s = procedure(red: TGLshort; green: TGLshort; blue: TGLshort; alpha: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4ub = procedure(red: TGLubyte; green: TGLubyte; blue: TGLubyte; alpha: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4ubv = procedure(const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4ui = procedure(red: TGLuint; green: TGLuint; blue: TGLuint; alpha: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4uiv = procedure(const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4us = procedure(red: TGLushort; green: TGLushort; blue: TGLushort; alpha: TGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4usv = procedure(const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorMaterial = procedure(face: TGLenum; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorPointer = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyPixels = procedure(x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei; _type: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteLists = procedure(list: TGLuint; range: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisableClientState = procedure(_array: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawPixels = procedure(width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEdgeFlag = procedure(flag: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEdgeFlagPointer = procedure(stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEdgeFlagv = procedure(const flag: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnableClientState = procedure(_array: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnd = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndList = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord1d = procedure(u: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord1dv = procedure(const u: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord1f = procedure(u: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord1fv = procedure(const u: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord2d = procedure(u: TGLdouble; v: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord2dv = procedure(const u: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord2f = procedure(u: TGLfloat; v: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalCoord2fv = procedure(const u: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalMesh1 = procedure(mode: TGLenum; i1: TGLint; i2: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalMesh2 = procedure(mode: TGLenum; i1: TGLint; i2: TGLint; j1: TGLint; j2: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalPoint1 = procedure(i: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalPoint2 = procedure(i: TGLint; j: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFeedbackBuffer = procedure(size: TGLsizei; _type: TGLenum; buffer: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogf = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogfv = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogi = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogiv = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFrustum = procedure(left: TGLdouble; right: TGLdouble; bottom: TGLdouble; top: TGLdouble; zNear: TGLdouble; zFar: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenLists = function(range: TGLsizei): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetClipPlane = procedure(plane: TGLenum; equation: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetLightfv = procedure(light: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetLightiv = procedure(light: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapdv = procedure(target: TGLenum; query: TGLenum; v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapfv = procedure(target: TGLenum; query: TGLenum; v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapiv = procedure(target: TGLenum; query: TGLenum; v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMaterialfv = procedure(face: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMaterialiv = procedure(face: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPixelMapfv = procedure(map: TGLenum; values: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPixelMapuiv = procedure(map: TGLenum; values: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPixelMapusv = procedure(map: TGLenum; values: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPolygonStipple = procedure(mask: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexEnvfv = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexEnviv = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexGendv = procedure(coord: TGLenum; pname: TGLenum; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexGenfv = procedure(coord: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexGeniv = procedure(coord: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexMask = procedure(mask: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexPointer = procedure(_type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexd = procedure(c: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexdv = procedure(const c: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexf = procedure(c: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexfv = procedure(const c: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexi = procedure(c: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexiv = procedure(const c: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexs = procedure(c: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexsv = procedure(const c: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexub = procedure(c: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexubv = procedure(const c: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglInitNames = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglInterleavedArrays = procedure(format: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsList = function(list: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsTexture = function(texture: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightModelf = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightModelfv = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightModeli = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightModeliv = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightf = procedure(light: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightfv = procedure(light: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLighti = procedure(light: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightiv = procedure(light: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLineStipple = procedure(factor: TGLint; pattern: TGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglListBase = procedure(base: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadIdentity = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadMatrixd = procedure(const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadMatrixf = procedure(const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadName = procedure(name: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMap1d = procedure(target: TGLenum; u1: TGLdouble; u2: TGLdouble; stride: TGLint; order: TGLint; const points: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMap1f = procedure(target: TGLenum; u1: TGLfloat; u2: TGLfloat; stride: TGLint; order: TGLint; const points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMap2d = procedure(target: TGLenum; u1: TGLdouble; u2: TGLdouble; ustride: TGLint; uorder: TGLint; v1: TGLdouble; v2: TGLdouble; vstride: TGLint; vorder: TGLint; const points: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMap2f = procedure(target: TGLenum; u1: TGLfloat; u2: TGLfloat; ustride: TGLint; uorder: TGLint; v1: TGLfloat; v2: TGLfloat; vstride: TGLint; vorder: TGLint; const points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapGrid1d = procedure(un: TGLint; u1: TGLdouble; u2: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapGrid1f = procedure(un: TGLint; u1: TGLfloat; u2: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapGrid2d = procedure(un: TGLint; u1: TGLdouble; u2: TGLdouble; vn: TGLint; v1: TGLdouble; v2: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapGrid2f = procedure(un: TGLint; u1: TGLfloat; u2: TGLfloat; vn: TGLint; v1: TGLfloat; v2: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMaterialf = procedure(face: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMaterialfv = procedure(face: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMateriali = procedure(face: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMaterialiv = procedure(face: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixMode = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultMatrixd = procedure(const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultMatrixf = procedure(const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNewList = procedure(list: TGLuint; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3b = procedure(nx: TGLbyte; ny: TGLbyte; nz: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3bv = procedure(const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3d = procedure(nx: TGLdouble; ny: TGLdouble; nz: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3f = procedure(nx: TGLfloat; ny: TGLfloat; nz: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3i = procedure(nx: TGLint; ny: TGLint; nz: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3s = procedure(nx: TGLshort; ny: TGLshort; nz: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalPointer = procedure(_type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglOrtho = procedure(left: TGLdouble; right: TGLdouble; bottom: TGLdouble; top: TGLdouble; zNear: TGLdouble; zFar: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPassThrough = procedure(token: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelMapfv = procedure(map: TGLenum; mapsize: TGLsizei; const values: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelMapuiv = procedure(map: TGLenum; mapsize: TGLsizei; const values: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelMapusv = procedure(map: TGLenum; mapsize: TGLsizei; const values: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTransferf = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTransferi = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelZoom = procedure(xfactor: TGLfloat; yfactor: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPolygonStipple = procedure(const mask: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPopAttrib = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPopClientAttrib = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPopMatrix = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPopName = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPrioritizeTextures = procedure(n: TGLsizei; const textures: PGLuint; const priorities: PGLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPushAttrib = procedure(mask: TGLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPushClientAttrib = procedure(mask: TGLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPushMatrix = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPushName = procedure(name: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2d = procedure(x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2f = procedure(x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2i = procedure(x: TGLint; y: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2s = procedure(x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos2sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3d = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3f = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3i = procedure(x: TGLint; y: TGLint; z: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3s = procedure(x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos3sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4d = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4f = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4i = procedure(x: TGLint; y: TGLint; z: TGLint; w: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4s = procedure(x: TGLshort; y: TGLshort; z: TGLshort; w: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRasterPos4sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRectd = procedure(x1: TGLdouble; y1: TGLdouble; x2: TGLdouble; y2: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRectdv = procedure(const v1: PGLdouble; const v2: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRectf = procedure(x1: TGLfloat; y1: TGLfloat; x2: TGLfloat; y2: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRectfv = procedure(const v1: PGLfloat; const v2: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRecti = procedure(x1: TGLint; y1: TGLint; x2: TGLint; y2: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRectiv = procedure(const v1: PGLint; const v2: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRects = procedure(x1: TGLshort; y1: TGLshort; x2: TGLshort; y2: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRectsv = procedure(const v1: PGLshort; const v2: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRenderMode = function(mode: TGLenum): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRotated = procedure(angle: TGLdouble; x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRotatef = procedure(angle: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglScaled = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglScalef = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSelectBuffer = procedure(size: TGLsizei; buffer: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglShadeModel = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1d = procedure(s: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1f = procedure(s: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1i = procedure(s: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1s = procedure(s: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2d = procedure(s: TGLdouble; t: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2f = procedure(s: TGLfloat; t: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2i = procedure(s: TGLint; t: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2s = procedure(s: TGLshort; t: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3d = procedure(s: TGLdouble; t: TGLdouble; r: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3f = procedure(s: TGLfloat; t: TGLfloat; r: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3i = procedure(s: TGLint; t: TGLint; r: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3s = procedure(s: TGLshort; t: TGLshort; r: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4d = procedure(s: TGLdouble; t: TGLdouble; r: TGLdouble; q: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4f = procedure(s: TGLfloat; t: TGLfloat; r: TGLfloat; q: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4i = procedure(s: TGLint; t: TGLint; r: TGLint; q: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4s = procedure(s: TGLshort; t: TGLshort; r: TGLshort; q: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoordPointer = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexEnvf = procedure(target: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexEnvfv = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexEnvi = procedure(target: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexEnviv = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexGend = procedure(coord: TGLenum; pname: TGLenum; param: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexGendv = procedure(coord: TGLenum; pname: TGLenum; const params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexGenf = procedure(coord: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexGenfv = procedure(coord: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexGeni = procedure(coord: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexGeniv = procedure(coord: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - - TglTranslated = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTranslatef = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2d = procedure(x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2f = procedure(x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2i = procedure(x: TGLint; y: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2s = procedure(x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3d = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3f = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3i = procedure(x: TGLint; y: TGLint; z: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3s = procedure(x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4d = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4f = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4i = procedure(x: TGLint; y: TGLint; z: TGLint; w: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4s = procedure(x: TGLshort; y: TGLshort; z: TGLshort; w: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexPointer = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -{$endif} - - // GL_VERSION_1_2 - TglBlendColor = procedure(red: TGLclampf; green: TGLclampf; blue: TGLclampf; alpha: TGLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBlendEquation = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawRangeElements = procedure(mode: TGLenum; start: TGLuint; _end: TGLuint; count: TGLsizei; _type: TGLenum; const indices: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexImage3D = procedure(target: TGLenum; level: TGLint; internalformat: TGLint; width: TGLsizei; height: TGLsizei; depth: TGLsizei; border: TGLint; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexSubImage3D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; zoffset: TGLint; width: TGLsizei; height: TGLsizei; depth: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexSubImage3D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; zoffset: TGLint; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -{$ifdef DGL_DEPRECATED} - TglColorTable = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; format: TGLenum; _type: TGLenum; const table: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorTableParameterfv = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorTableParameteriv = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyColorTable = procedure(target: TGLenum; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTable = procedure(target: TGLenum; format: TGLenum; _type: TGLenum; table: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableParameterfv = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableParameteriv = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorSubTable = procedure(target: TGLenum; start: TGLsizei; count: TGLsizei; format: TGLenum; _type: TGLenum; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyColorSubTable = procedure(target: TGLenum; start: TGLsizei; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionFilter1D = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; format: TGLenum; _type: TGLenum; const image: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionFilter2D = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; const image: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameterf = procedure(target: TGLenum; pname: TGLenum; params: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameterfv = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameteri = procedure(target: TGLenum; pname: TGLenum; params: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameteriv = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyConvolutionFilter1D = procedure(target: TGLenum; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyConvolutionFilter2D = procedure(target: TGLenum; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetConvolutionFilter = procedure(target: TGLenum; format: TGLenum; _type: TGLenum; image: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetConvolutionParameterfv = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetConvolutionParameteriv = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetSeparableFilter = procedure(target: TGLenum; format: TGLenum; _type: TGLenum; row: PGLvoid; column: PGLvoid; span: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSeparableFilter2D = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; const row: PGLvoid; const column: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetHistogram = procedure(target: TGLenum; reset: TGLboolean; format: TGLenum; _type: TGLenum; values: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetHistogramParameterfv = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetHistogramParameteriv = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMinmax = procedure(target: TGLenum; reset: TGLboolean; format: TGLenum; _type: TGLenum; values: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMinmaxParameterfv = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMinmaxParameteriv = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglHistogram = procedure(target: TGLenum; width: TGLsizei; internalformat: TGLenum; sink: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMinmax = procedure(target: TGLenum; internalformat: TGLenum; sink: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglResetHistogram = procedure(target: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglResetMinmax = procedure(target: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -{$endif} - - // GL_VERSION_1_3 - TglActiveTexture = procedure(texture: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSampleCoverage = procedure(value: TGLclampf; invert: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexImage3D = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; depth: TGLsizei; border: TGLint; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexImage2D = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; border: TGLint; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexImage1D = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; border: TGLint; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexSubImage3D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; zoffset: TGLint; width: TGLsizei; height: TGLsizei; depth: TGLsizei; format: TGLenum; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexSubImage2D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; width: TGLsizei; height: TGLsizei; format: TGLenum; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexSubImage1D = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; width: TGLsizei; format: TGLenum; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCompressedTexImage = procedure(target: TGLenum; level: TGLint; img: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -{$ifdef DGL_DEPRECATED} - TglClientActiveTexture = procedure(texture: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1d = procedure(target: TGLenum; s: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1dv = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1f = procedure(target: TGLenum; s: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1fv = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1i = procedure(target: TGLenum; s: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1iv = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1s = procedure(target: TGLenum; s: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1sv = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2d = procedure(target: TGLenum; s: TGLdouble; t: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2dv = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2f = procedure(target: TGLenum; s: TGLfloat; t: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2fv = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2i = procedure(target: TGLenum; s: TGLint; t: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2iv = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2s = procedure(target: TGLenum; s: TGLshort; t: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2sv = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3d = procedure(target: TGLenum; s: TGLdouble; t: TGLdouble; r: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3dv = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3f = procedure(target: TGLenum; s: TGLfloat; t: TGLfloat; r: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3fv = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3i = procedure(target: TGLenum; s: TGLint; t: TGLint; r: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3iv = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3s = procedure(target: TGLenum; s: TGLshort; t: TGLshort; r: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3sv = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4d = procedure(target: TGLenum; s: TGLdouble; t: TGLdouble; r: TGLdouble; q: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4dv = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4f = procedure(target: TGLenum; s: TGLfloat; t: TGLfloat; r: TGLfloat; q: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4fv = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4i = procedure(target: TGLenum; s: TGLint; t: TGLint; r: TGLint; q: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4iv = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4s = procedure(target: TGLenum; s: TGLshort; t: TGLshort; r: TGLshort; q: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4sv = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadTransposeMatrixf = procedure(const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadTransposeMatrixd = procedure(const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultTransposeMatrixf = procedure(const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultTransposeMatrixd = procedure(const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -{$endif} - - // GL_VERSION_1_4 - TglBlendFuncSeparate = procedure(sfactorRGB: TGLenum; dfactorRGB: TGLenum; sfactorAlpha: TGLenum; dfactorAlpha: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiDrawArrays = procedure(mode: TGLenum; first: PGLint; count: PGLsizei; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiDrawElements = procedure(mode: TGLenum; const count: PGLsizei; _type: TGLenum; const indices: PGLvoid; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameterf = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameterfv = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameteri = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameteriv = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -{$ifdef DGL_DEPRECATED} - TglFogCoordf = procedure(coord: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordfv = procedure(const coord: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordd = procedure(coord: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoorddv = procedure(const coord: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordPointer = procedure(_type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3b = procedure(red: TGLbyte; green: TGLbyte; blue: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3bv = procedure(const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3d = procedure(red: TGLdouble; green: TGLdouble; blue: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3f = procedure(red: TGLfloat; green: TGLfloat; blue: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3i = procedure(red: TGLint; green: TGLint; blue: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3s = procedure(red: TGLshort; green: TGLshort; blue: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3ub = procedure(red: TGLubyte; green: TGLubyte; blue: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3ubv = procedure(const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3ui = procedure(red: TGLuint; green: TGLuint; blue: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3uiv = procedure(const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3us = procedure(red: TGLushort; green: TGLushort; blue: TGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3usv = procedure(const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColorPointer = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2d = procedure(x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2f = procedure(x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2i = procedure(x: TGLint; y: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2s = procedure(x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3d = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3dv = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3f = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3fv = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3i = procedure(x: TGLint; y: TGLint; z: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3iv = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3s = procedure(x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3sv = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -{$endif} - - // GL_VERSION_1_5 - TglGenQueries = procedure(n: GLsizei; ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteQueries = procedure(n: GLsizei; const ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsQuery = function(id: GLuint): boolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBeginQuery = procedure(target: GLenum; id: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndQuery = procedure(target: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetQueryiv = procedure(target, pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetQueryObjectiv = procedure(id: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetQueryObjectuiv = procedure(id: GLuint; pname: GLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBuffer = procedure(target: TGLenum; buffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteBuffers = procedure(n: TGLsizei; const buffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenBuffers = procedure(n: TGLsizei; buffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsBuffer = function(buffer: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBufferData = procedure(target: TGLenum; size: TGLsizei; const data: PGLvoid; usage: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBufferSubData = procedure(target: TGLenum; offset: TGLsizei; size: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBufferSubData = procedure(target: TGLenum; offset: TGLsizei; size: TGLsizei; data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapBuffer = function(target: TGLenum; access: TGLenum): PGLvoid; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUnmapBuffer = function(target: TGLenum): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBufferParameteriv = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBufferPointerv = procedure(target: TGLenum; pname: TGLenum; params: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_VERSION_2_0 - TglBlendEquationSeparate = procedure(modeRGB: GLenum; modeAlpha: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawBuffers = procedure(n: GLsizei; const bufs: PGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStencilOpSeparate = procedure(face: GLenum; sfail: GLenum; dpfail: GLenum; dppass: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStencilFuncSeparate = procedure(frontfunc: GLenum; backfunc: GLenum; ref: GLint; mask: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStencilMaskSeparate = procedure(face: GLenum; mask: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglAttachShader = procedure(programObj, shaderObj: GLhandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindAttribLocation = procedure(programObj: GLhandle; index: GLuint; name: PGLChar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompileShader = procedure(shaderObj: GLhandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCreateProgram = function: GLhandle; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCreateShader = function(shaderType: GLenum): GLhandle; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteProgram = procedure(programObj: GLhandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteShader = procedure(shaderObj: GLhandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDetachShader = procedure(programObj, shaderObj: GLhandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisableVertexAttribArray = procedure(index: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnableVertexAttribArray = procedure(index: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveAttrib = procedure(programObj: GLhandle; index: GLuint; maxlength: GLsizei; var length: GLint; var size: GLint; var _type: GLenum; name: PGLChar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveUniform = procedure(programObj: GLhandle; index: GLuint; maxLength: GLsizei; var length: GLsizei; var size: GLint; var _type: GLenum; name: PGLChar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetAttachedShaders = procedure(programObj: GLhandle; MaxCount: GLsizei; var Count: GLint; shaders: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetAttribLocation = function(programObj: GLhandle; char: string): glint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramiv = procedure(programObj: GLhandle; pname: TGLenum; params: PGLInt); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramInfoLog = procedure(programObj: GLHandle; maxLength: glsizei; var length: GLint; infoLog: PGLChar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetShaderiv = procedure(shaderObj: GLhandle; pname: TGLenum; params: PGLInt); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetShaderInfoLog = procedure(shaderObj: GLHandle; maxLength: glsizei; var length: glint; infoLog: PGLChar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetShaderSource = procedure(shaderObj: GLhandle; maxlength: GLsizei; var length: GLsizei; source: PGLChar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformLocation = function(programObj: GLhandle; const char: PGLChar): glint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformfv = procedure(programObj: GLhandle; location: GLint; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformiv = procedure(programObj: GLhandle; location: GLint; params: PGLInt); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribfv = procedure(index: GLuint; pname: GLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribiv = procedure(index: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribPointerv = procedure(index: GLuint; pname: GLenum; _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsProgram = function(programObj: GLhandle) : TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsShader = function(shaderObj: GLhandle) : TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLinkProgram = procedure(programObj: GLHandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglShaderSource = procedure(shaderObj: GLHandle; count: glsizei; _string: PPGLChar; lengths: pglint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUseProgram = procedure(programObj: GLhandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1f = procedure(location: GLint; v0: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2f = procedure(location: GLint; v0, v1: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3f = procedure(location: GLint; v0, v1, v2: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4f = procedure(location: GLint; v0, v1, v2, v3: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1i = procedure(location: GLint; v0: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2i = procedure(location: GLint; v0, v1: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3i = procedure(location: GLint; v0, v1, v2: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4i = procedure(location: GLint; v0, v1, v2, v3: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1fv = procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2fv = procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3fv = procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4fv = procedure(location: GLint; count: GLsizei; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1iv = procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2iv = procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3iv = procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4iv = procedure(location: GLint; count: GLsizei; value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix2fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix3fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix4fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglValidateProgram = procedure(programObj: GLhandle); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1d = procedure(index: GLuint; x: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1dv = procedure(index: GLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1f = procedure(index: GLuint; x: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1fv = procedure(index: GLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1s = procedure(index: GLuint; x: GLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1sv = procedure(index: GLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2d = procedure(index: GLuint; x: GLdouble; y: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2dv = procedure(index: GLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2f = procedure(index: GLuint; x: GLfloat; y: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2fv = procedure(index: GLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2s = procedure(index: GLuint; x: GLshort; y: GLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2sv = procedure(index: GLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3d = procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3dv = procedure(index: GLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3f = procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3fv = procedure(index: GLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3s = procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3sv = procedure(index: GLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4Nbv = procedure(index: GLuint; const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4Niv = procedure(index: GLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4Nsv = procedure(index: GLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4Nub = procedure(index: GLuint; x: GLubyte; y: GLubyte; z: GLubyte; w: GLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4Nubv = procedure(index: GLuint; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4Nuiv = procedure(index: GLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4Nusv = procedure(index: GLuint; const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4bv = procedure(index: GLuint; const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4d = procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4dv = procedure(index: GLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4f = procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4fv = procedure(index: GLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4iv = procedure(index: GLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4s = procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort; w: GLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4sv = procedure(index: GLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4ubv = procedure(index: GLuint; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4uiv = procedure(index: GLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4usv = procedure(index: GLuint; const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribPointer = procedure(index: GLuint; size: GLint; _type: GLenum; normalized: GLboolean; stride: GLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_VERSION_2_1 - TglUniformMatrix2x3fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix3x2fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix2x4fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix4x2fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix3x4fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix4x3fv = procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_VERSION_3_0 - { OpenGL 3.0 also reuses entry points from these extensions: } - { ARB_framebuffer_object } - { ARB_map_buffer_range } - { ARB_vertex_array_object } - TglColorMaski = procedure(index_: GLuint; r: GLboolean; g: GLboolean; b: GLboolean; a: GLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBooleani_v = procedure(target: GLenum; index_: GLuint; data: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetIntegeri_v = procedure(target: GLenum; index_: GLuint; data: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnablei = procedure(target: GLenum; index_: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisablei = procedure(target: GLenum; index_: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsEnabledi = function(target: GLenum; index_: GLuint): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBeginTransformFeedback = procedure(primitiveMode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndTransformFeedback = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferRange = procedure(target: GLenum; index_: GLuint; buffer: GLuint; offset: GLsizei; size: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferBase = procedure(target: GLenum; index_: GLuint; buffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTransformFeedbackVaryings = procedure(program_: GLuint; count: GLsizei; const varyings: PPGLchar; bufferMode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTransformFeedbackVarying = procedure(program_: GLuint; index_: GLuint; bufSize: GLsizei; length: PGLsizei; size: PGLsizei; type_: PGLsizei; name: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClampColor = procedure(targe: GLenum; clamp: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBeginConditionalRender = procedure(id: GLuint; mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndConditionalRender = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribIPointer = procedure(index_: GLuint; size: GLint; type_: GLenum; stride: GLsizei; const pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribIiv = procedure(index_: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribIuiv = procedure(index_: GLuint; pname: GLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI1i = procedure(index_: GLuint; x: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2i = procedure(index_: GLuint; x: GLint; y: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3i = procedure(index_: GLuint; x: GLint; y: GLint; z: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4i = procedure(index_: GLuint; x: GLint; y: GLint; z: GLint; w: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI1ui = procedure(index_: GLuint; x: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2ui = procedure(index_: GLuint; x: GLuint; y: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3ui = procedure(index_: GLuint; x: GLuint; y: GLuint; z: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4ui = procedure(index_: GLuint; x: GLuint; y: GLuint; z: GLuint; w: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI1iv = procedure(index_: GLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2iv = procedure(index_: GLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3iv = procedure(index_: GLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4iv = procedure(index_: GLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI1uiv = procedure(index_: GLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2uiv = procedure(index_: GLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3uiv = procedure(index_: GLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4uiv = procedure(index_: GLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4bv = procedure(index_: GLuint; const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4sv = procedure(index_: GLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4ubv = procedure(index_: GLuint; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4usv = procedure(index_: GLuint; const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformuiv = procedure(program_: GLuint; location: GLint; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindFragDataLocation = procedure(program_: GLuint; color: GLuint; const name: PGLChar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFragDataLocation = function(program_: GLuint; const name: PGLChar): GLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1ui = procedure(location: GLint; v0: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2ui = procedure(location: GLint; v0: GLuint; v1: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3ui = procedure(location: GLint; v0: GLuint; v1: GLuint; v2: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4ui = procedure(location: GLint; v0: GLuint; v1: GLuint; v2: GLuint; v3: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1uiv = procedure(location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2uiv = procedure(location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3uiv = procedure(location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4uiv = procedure(location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameterIiv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameterIuiv = procedure(target: GLenum; pname: GLenum; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexParameterIiv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexParameterIuiv = procedure(target: GLenum; pname: GLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearBufferiv = procedure(buffer: GLenum; drawbuffer: GLint; const value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearBufferuiv = procedure(buffer: GLenum; drawbuffer: GLint; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearBufferfv = procedure(buffer: GLenum; drawbuffer: GLint; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearBufferfi = procedure(buffer: GLenum; drawbuffer: GLint; depth: GLfloat; stencil: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetStringi = function(name: GLenum; index: GLuint): PGLubyte; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_VERSION_3_1 - { OpenGL 3.1 also reuses entry points from these extensions: } - { ARB_copy_buffer } - { ARB_uniform_buffer_object } - TglDrawArraysInstanced = procedure(mode: GLenum; first: GLint; count: GLsizei; primcount: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawElementsInstanced = procedure(mode: GLenum; count: GLsizei; type_: GLenum; const indices: PGLvoid; primcount: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexBuffer = procedure(target: GLenum; internalformat: GLenum; buffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPrimitiveRestartIndex = procedure(index_: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_VERSION_3_2 - { OpenGL 3.2 also reuses entry points from these extensions: } - { ARB_draw_elements_base_vertex } - { ARB_provoking_vertex } - { ARB_sync } - { ARB_texture_multisample } - TglGetInteger64i_v = procedure(target: GLenum; index_: GLuint; data: PGLint64); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBufferParameteri64v = procedure(target: GLenum; pname: GLenum; params: PGLint64); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramParameteri = procedure(program_: GLuint; pname: GLenum; value: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTexture = procedure(target: GLenum; attachment: GLenum; texture: GLuint; level: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTextureFace = procedure(target: GLenum; attachment: GLenum; texture: GLuint; level: GLint; face: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_3DFX_tbuffer - TglTbufferMask3DFX = procedure(mask: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_APPLE_element_array - TglElementPointerAPPLE = procedure(_type: TGLenum; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawElementArrayAPPLE = procedure(mode: TGLenum; first: TGLint; count: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawRangeElementArrayAPPLE = procedure(mode: TGLenum; start: TGLuint; _end: TGLuint; first: TGLint; count: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiDrawElementArrayAPPLE = procedure(mode: TGLenum; const first: PGLint; const count: PGLsizei; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiDrawRangeElementArrayAPPLE = procedure(mode: TGLenum; start: TGLuint; _end: TGLuint; const first: PGLint; const count: PGLsizei; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_APPLE_fence - TglGenFencesAPPLE = procedure(n: TGLsizei; fences: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteFencesAPPLE = procedure(n: TGLsizei; const fences: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSetFenceAPPLE = procedure(fence: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsFenceAPPLE = function(fence: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTestFenceAPPLE = function(fence: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFinishFenceAPPLE = procedure(fence: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTestObjectAPPLE = function(_object: TGLenum; name: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFinishObjectAPPLE = procedure(_object: TGLenum; name: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_APPLE_vertex_array_object - TglBindVertexArrayAPPLE = procedure(_array: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteVertexArraysAPPLE = procedure(n: TGLsizei; const arrays: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenVertexArraysAPPLE = procedure(n: TGLsizei; const arrays: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsVertexArrayAPPLE = function(_array: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_APPLE_vertex_array_range - TglVertexArrayRangeAPPLE = procedure(length: TGLsizei; _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFlushVertexArrayRangeAPPLE = procedure(length: TGLsizei; _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexArrayParameteriAPPLE = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_APPLE_texture_range - TglTextureRangeAPPLE = procedure(target: GLenum; length: GLsizei; const Pointer_: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexParameterPointervAPPLE = procedure(target: GLenum; pname: GLenum; params: PPGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_APPLE_vertex_program_evaluators - TglEnableVertexAttribAPPLE = procedure(index_: GLuint; pname: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisableVertexAttribAPPLE = procedure(index_: GLuint; pname: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsVertexAttribEnabledAPPLE = function(index_: GLuint; pname: GLenum): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapVertexAttrib1dAPPLE = procedure(index_: GLuint; size: GLuint; u1: GLdouble; u2: GLdouble; stride: GLint; order: GLint; const points: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapVertexAttrib1fAPPLE = procedure(index_: GLuint; size: GLuint; u1: GLfloat; u2: GLfloat; stride: GLint; order: GLint; const points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapVertexAttrib2dAPPLE = procedure(index_: GLuint; size: GLuint; u1: GLdouble; u2: GLdouble; ustride: GLint; uorder: GLint; v1: GLdouble; v2: GLdouble; vstride: GLint; vorder: GLint; const points: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapVertexAttrib2fAPPLE = procedure(index_: GLuint; size: GLuint; u1: GLfloat; u2: GLfloat; ustride: GLint; order: GLint; v1: GLfloat; v2: GLfloat; vstride: GLint; vorder: GLint; const points: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_APPLE_object_purgeable - TglObjectPurgeableAPPLE = function(objectType: GLenum; name: GLuint; option: GLenum): GLenum; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglObjectUnpurgeableAPPLE = function(objectType: GLenum; name: GLuint; option: GLenum): GLenum; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetObjectParameterivAPPLE = procedure(objectType: GLenum; name: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_matrix_palette - TglCurrentPaletteMatrixARB = procedure(index: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixIndexubvARB = procedure(size: TGLint; const indices: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixIndexusvARB = procedure(size: TGLint; const indices: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixIndexuivARB = procedure(size: TGLint; const indices: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixIndexPointerARB = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_multisample - TglSampleCoverageARB = procedure(value: TGLclampf; invert: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_multitexture - TglActiveTextureARB = procedure(texture: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClientActiveTextureARB = procedure(texture: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1dARB = procedure(target: TGLenum; s: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1dvARB = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1fARB = procedure(target: TGLenum; s: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1fvARB = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1iARB = procedure(target: TGLenum; s: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1ivARB = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1sARB = procedure(target: TGLenum; s: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1svARB = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2dARB = procedure(target: TGLenum; s: TGLdouble; t: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2dvARB = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2fARB = procedure(target: TGLenum; s: TGLfloat; t: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2fvARB = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2iARB = procedure(target: TGLenum; s: TGLint; t: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2ivARB = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2sARB = procedure(target: TGLenum; s: TGLshort; t: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2svARB = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3dARB = procedure(target: TGLenum; s: TGLdouble; t: TGLdouble; r: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3dvARB = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3fARB = procedure(target: TGLenum; s: TGLfloat; t: TGLfloat; r: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3fvARB = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3iARB = procedure(target: TGLenum; s: TGLint; t: TGLint; r: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3ivARB = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3sARB = procedure(target: TGLenum; s: TGLshort; t: TGLshort; r: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3svARB = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4dARB = procedure(target: TGLenum; s: TGLdouble; t: TGLdouble; r: TGLdouble; q: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4dvARB = procedure(target: TGLenum; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4fARB = procedure(target: TGLenum; s: TGLfloat; t: TGLfloat; r: TGLfloat; q: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4fvARB = procedure(target: TGLenum; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4iARB = procedure(target: TGLenum; s: TGLint; t: TGLint; r: TGLint; q: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4ivARB = procedure(target: TGLenum; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4sARB = procedure(target: TGLenum; s: TGLshort; t: TGLshort; r: TGLshort; q: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4svARB = procedure(target: TGLenum; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_point_parameters - TglPointParameterfARB = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameterfvARB = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_texture_compression - TglCompressedTexImage3DARB = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; depth: TGLsizei; border: TGLint; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexImage2DARB = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; border: TGLint; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexImage1DARB = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; border: TGLint; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexSubImage3DARB = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; zoffset: TGLint; width: TGLsizei; height: TGLsizei; depth: TGLsizei; format: TGLenum; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexSubImage2DARB = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; width: TGLsizei; height: TGLsizei; format: TGLenum; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTexSubImage1DARB = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; width: TGLsizei; format: TGLenum; imageSize: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCompressedTexImageARB = procedure(target: TGLenum; level: TGLint; img: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_transpose_matrix - TglLoadTransposeMatrixfARB = procedure(const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadTransposeMatrixdARB = procedure(const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultTransposeMatrixfARB = procedure(const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultTransposeMatrixdARB = procedure(const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_vertex_blend - TglWeightbvARB = procedure(size: TGLint; const weights: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightsvARB = procedure(size: TGLint; const weights: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightivARB = procedure(size: TGLint; const weights: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightfvARB = procedure(size: TGLint; const weights: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightdvARB = procedure(size: TGLint; const weights: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightubvARB = procedure(size: TGLint; const weights: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightusvARB = procedure(size: TGLint; const weights: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightuivARB = procedure(size: TGLint; const weights: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWeightPointerARB = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexBlendARB = procedure(count: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_vertex_buffer_object - TglBindBufferARB = procedure(target: TGLenum; buffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteBuffersARB = procedure(n: TGLsizei; const buffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenBuffersARB = procedure(n: TGLsizei; buffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsBufferARB = function(buffer: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBufferDataARB = procedure(target: TGLenum; size: TGLsizei; const data: PGLvoid; usage: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBufferSubDataARB = procedure(target: TGLenum; offset: TGLsizei; size: TGLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBufferSubDataARB = procedure(target: TGLenum; offset: TGLsizei; size: TGLsizei; data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapBufferARB = function(target: TGLenum; access: TGLenum): PGLvoid; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUnmapBufferARB = function(target: TGLenum): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBufferParameterivARB = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBufferPointervARB = procedure(target: TGLenum; pname: TGLenum; params: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_vertex_program - TglVertexAttrib1dARB = procedure(index: TGLuint; x: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1dvARB = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1fARB = procedure(index: TGLuint; x: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1fvARB = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1sARB = procedure(index: TGLuint; x: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1svARB = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2dARB = procedure(index: TGLuint; x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2dvARB = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2fARB = procedure(index: TGLuint; x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2fvARB = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2sARB = procedure(index: TGLuint; x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2svARB = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3dARB = procedure(index: TGLuint; x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3dvARB = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3fARB = procedure(index: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3fvARB = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3sARB = procedure(index: TGLuint; x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3svARB = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4NbvARB = procedure(index: TGLuint; const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4NivARB = procedure(index: TGLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4NsvARB = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4NubARB = procedure(index: TGLuint; x: TGLubyte; y: TGLubyte; z: TGLubyte; w: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4NubvARB = procedure(index: TGLuint; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4NuivARB = procedure(index: TGLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4NusvARB = procedure(index: TGLuint; const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4bvARB = procedure(index: TGLuint; const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4dARB = procedure(index: TGLuint; x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4dvARB = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4fARB = procedure(index: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4fvARB = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4ivARB = procedure(index: TGLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4sARB = procedure(index: TGLuint; x: TGLshort; y: TGLshort; z: TGLshort; w: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4svARB = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4ubvARB = procedure(index: TGLuint; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4uivARB = procedure(index: TGLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4usvARB = procedure(index: TGLuint; const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribPointerARB = procedure(index: TGLuint; size: TGLint; _type: TGLenum; normalized: TGLboolean; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnableVertexAttribArrayARB = procedure(index: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisableVertexAttribArrayARB = procedure(index: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramStringARB = procedure(target: TGLenum; format: TGLenum; len: TGLsizei; const _string: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindProgramARB = procedure(target: TGLenum; _program: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteProgramsARB = procedure(n: TGLsizei; const programs: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenProgramsARB = procedure(n: TGLsizei; programs: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameter4dARB = procedure(target: TGLenum; index: TGLuint; x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameter4dvARB = procedure(target: TGLenum; index: TGLuint; const params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameter4fARB = procedure(target: TGLenum; index: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameter4fvARB = procedure(target: TGLenum; index: TGLuint; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameter4dARB = procedure(target: TGLenum; index: TGLuint; x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameter4dvARB = procedure(target: TGLenum; index: TGLuint; const params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameter4fARB = procedure(target: TGLenum; index: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameter4fvARB = procedure(target: TGLenum; index: TGLuint; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramEnvParameterdvARB = procedure(target: TGLenum; index: TGLuint; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramEnvParameterfvARB = procedure(target: TGLenum; index: TGLuint; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramLocalParameterdvARB = procedure(target: TGLenum; index: TGLuint; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramLocalParameterfvARB = procedure(target: TGLenum; index: TGLuint; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramivARB = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramStringARB = procedure(target: TGLenum; pname: TGLenum; _string: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribdvARB = procedure(index: TGLuint; pname: TGLenum; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribfvARB = procedure(index: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribivARB = procedure(index: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribPointervARB = procedure(index: TGLuint; pname: TGLenum; _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsProgramARB = function(_program: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_window_pos - TglWindowPos2dARB = procedure(x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2dvARB = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2fARB = procedure(x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2fvARB = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2iARB = procedure(x: TGLint; y: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2ivARB = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2sARB = procedure(x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2svARB = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3dARB = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3dvARB = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3fARB = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3fvARB = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3iARB = procedure(x: TGLint; y: TGLint; z: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3ivARB = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3sARB = procedure(x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3svARB = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_draw_buffers - TglDrawBuffersARB = procedure(n: TGLsizei; bufs: PGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_color_buffer_float - TglClampColorARB = procedure(target: TGLenum; clamp: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_vertex_shader - TglGetActiveAttribARB = procedure(programobj: GLhandleARB; index: GLuint; maxLength: GLsizei; var length: GLsizei; var size: GLint; var _type: GLenum; name: PGLcharARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetAttribLocationARB = function(programObj: GLhandleARB; const char: PGLcharARB): glint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindAttribLocationARB = procedure(programObj: GLhandleARB; index: GLuint; const name: PGLcharARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_shader_objects - TglDeleteObjectARB = procedure(Obj: GLHandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetHandleARB = function(pname: GlEnum): GLHandleARB; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDetachObjectARB = procedure(container, attached: GLHandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCreateShaderObjectARB = function(shaderType: glenum): GLHandleARB; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglShaderSourceARB = procedure(shaderObj: GLHandleARB; count: glsizei; _string: PPGLCharARB; lengths: pglint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompileShaderARB = procedure(shaderObj: GLHandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCreateProgramObjectARB = function: GLHandleARB; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglAttachObjectARB = procedure(programObj, shaderObj: GLhandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLinkProgramARB = procedure(programObj: GLHandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUseProgramObjectARB = procedure(programObj: GLHandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglValidateProgramARB = procedure(programObj: GLhandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1fARB = procedure(location: glint; v0: glfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2fARB = procedure(location: glint; v0, v1: glfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3fARB = procedure(location: glint; v0, v1, v2: glfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4fARB = procedure(location: glint; v0, v1, v2, v3: glfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1iARB = procedure(location: glint; v0: glint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2iARB = procedure(location: glint; v0, v1: glint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3iARB = procedure(location: glint; v0, v1, v2: glint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4iARB = procedure(location: glint; v0, v1, v2, v3: glint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1fvARB = procedure(location: glint; count: GLsizei; value: pglfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2fvARB = procedure(location: glint; count: GLsizei; value: pglfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3fvARB = procedure(location: glint; count: GLsizei; value: pglfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4fvARB = procedure(location: glint; count: GLsizei; value: pglfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1ivARB = procedure(location: glint; count: GLsizei; value: pglint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2ivARB = procedure(location: glint; count: GLsizei; value: pglint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3ivARB = procedure(location: glint; count: GLsizei; value: pglint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4ivARB = procedure(location: glint; count: GLsizei; value: pglint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix2fvARB = procedure(location: glint; count: glsizei; transpose: glboolean; value: pglfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix3fvARB = procedure(location: glint; count: glsizei; transpose: glboolean; value: pglfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformMatrix4fvARB = procedure(location: glint; count: glsizei; transpose: glboolean; value: pglfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetObjectParameterfvARB = procedure(Obj: GLHandleARB; pname: GLEnum; params: PGLFloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetObjectParameterivARB = procedure(Obj: GLHandleARB; pname: GLEnum; params: PGLInt); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetInfoLogARB = procedure(shaderObj: GLHandleARB; maxLength: glsizei; var length: glint; infoLog: PGLcharARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetAttachedObjectsARB = procedure(programobj: GLhandleARB; maxCount: GLsizei; var count: GLsizei; objects: PGLhandleARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformLocationARB = function(programObj: GLhandleARB; const char: PGLcharARB): glint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveUniformARB = procedure(programobj: GLhandleARB; index: GLuint; maxLength: GLsizei; var length: GLsizei; var size: GLint; var _type: GLenum; name: PGLcharARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformfvARB = procedure(programObj: GLhandleARB; location: GLint; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformivARB = procedure(programObj: GLhandleARB; location: GLint; params: PGLInt); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetShaderSourceARB = procedure(shader: GLhandleARB; maxLength: GLsizei; var length: GLsizei; source: PGLcharARB); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_Occlusion_Query - TglGenQueriesARB = procedure(n: GLsizei; ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteQueriesARB = procedure(n: GLsizei; const ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsQueryARB = function(id: GLuint): boolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBeginQueryARB = procedure(target: GLenum; id: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndQueryARB = procedure(target: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetQueryivARB = procedure(target, pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetQueryObjectivARB = procedure(id: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetQueryObjectuivARB = procedure(id: GLuint; pname: GLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_draw_instanced - TglDrawArraysInstancedARB = procedure(mode: GLenum; first: GLint; count: GLsizei; primcount: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawElementsInstancedARB = procedure(mode: GLenum; count: GLsizei; type_: GLenum; const indices: PGLvoid; primcount: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_framebuffer_object - TglIsRenderbuffer = function(renderbuffer: GLuint): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindRenderbuffer = procedure(target: GLenum; renderbuffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteRenderbuffers = procedure(n: GLsizei; const renderbuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenRenderbuffers = procedure(n: GLsizei; renderbuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRenderbufferStorage = procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetRenderbufferParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsFramebuffer = function(framebuffer: GLuint): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindFramebuffer = procedure(target: GLenum; framebuffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteFramebuffers = procedure(n: GLsizei; const framebuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenFramebuffers = procedure(n: GLsizei; framebuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCheckFramebufferStatus = function(target: GLenum): GLenum; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTexture1D = procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTexture2D = procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTexture3D = procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint; zoffset: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferRenderbuffer = procedure(target: GLenum; attachment: GLenum; renderbuffertarget: GLenum; renderbuffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFramebufferAttachmentParameteriv = procedure(target: GLenum; attachment: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenerateMipmap = procedure(target: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBlitFramebuffer = procedure(srcX0: GLint; srcY0: GLint; srcX1: GLint; srcY1: GLint; dstX0: GLint; dstY0: GLint; dstX1: GLint; dstY1: GLint; mask: GLbitfield; filter: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRenderbufferStorageMultisample = procedure(target: GLenum; samples: GLsizei; internalformat: GLenum; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTextureLayer = procedure(target: GLenum; attachment: GLenum; texture: GLuint; level: GLint; layer: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_geometry_shader4 - TglProgramParameteriARB = procedure(program_: GLuint; pname: GLenum; value: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTextureARB = procedure(target: GLenum; attachment: GLenum; texture: GLuint; level: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTextureLayerARB = procedure(target: GLenum; attachment: GLenum; texture: GLuint; level: GLint; layer: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTextureFaceARB = procedure(target: GLenum; attachment: GLenum; texture: GLuint; level: GLint; face: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_instanced_arrays - TglVertexAttribDivisorARB = procedure(index_: GLuint; divisor: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_map_buffer_range - TglMapBufferRange = function(target: GLenum; offset: GLsizei; length: GLsizei; access: GLbitfield): PGLvoid; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFlushMappedBufferRange = procedure(target: GLenum; offset: GLsizei; length: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_texture_buffer_object - TglTexBufferARB = procedure(target: GLenum; internalformat: GLenum; buffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_vertex_array_object - TglBindVertexArray = procedure(array_: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteVertexArrays = procedure(n: GLsizei; const arrays: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenVertexArrays = procedure(n: GLsizei; arrays: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsVertexArray = function(array_: GLuint): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_uniform_buffer_object - TglGetUniformIndices = procedure(program_: GLuint; uniformCount: GLsizei; const uniformNames: PPGLchar; uniformIndices: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveUniformsiv = procedure(program_: GLuint; uniformCount: GLsizei; const uniformIndices: PGLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveUniformName = procedure(program_: GLuint; uniformIndex: GLuint; bufSize: GLsizei; length: PGLsizei; uniformName: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformBlockIndex = function(program_: GLuint; const uniformBlockName: PGLchar): GLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveUniformBlockiv = procedure(program_: GLuint; uniformBlockIndex: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveUniformBlockName = procedure(program_: GLuint; uniformBlockIndex: GLuint; bufSize: GLsizei; length: PGLsizei; uniformBlockName: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniformBlockBinding = procedure(program_: GLuint; uniformBlockIndex: GLuint; uniformBlockBinding: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_copy_buffer - TglCopyBufferSubData = procedure(readTarget: GLenum; writeTarget: GLenum; readOffset: GLint; writeOffset: GLint; size: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_draw_elements_base_vertex - TglDrawElementsBaseVertex = procedure(mode: GLenum; count: GLsizei; type_: GLenum; const indices: PGLvoid; basevertex: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawRangeElementsBaseVertex = procedure(mode: GLenum; start: GLuint; end_: GLuint; count: GLsizei; type_: GLenum; const indices: PGLvoid; basevertex: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawElementsInstancedBaseVertex = procedure(mode: GLenum; count: GLsizei; type_: GLenum; const indices: PGLvoid; primcount: GLsizei; basevertex: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiDrawElementsBaseVertex = procedure(mode: GLenum; const count: PGLsizei; type_: GLenum; const indices: PPGLvoid; primcount: GLsizei; const basevertex: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_provoking_vertex - TglProvokingVertex = procedure(mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_sync - TglFenceSync = function(condition: GLenum; flags: GLbitfield): GLsync; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsSync = function(sync: GLsync): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteSync = procedure(sync: GLsync); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClientWaitSync = function(sync: GLsync; flags: GLbitfield; timeout: GLuint64): GLenum; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWaitSync = procedure(sync: GLsync; flags: GLbitfield; timeout: GLuint64); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetInteger64v = procedure(pname: GLenum; params: PGLint64); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetSynciv = procedure(sync: GLsync; pname: GLenum; butSize: GLsizei; length: PGLsizei; values: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_texture_multisample - TglTexImage2DMultisample = procedure(target: GLenum; samples: GLsizei; internalformat: GLint; width: GLsizei; height: GLsizei; fixedsamplelocations: GLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexImage3DMultisample = procedure(target: GLenum; samples: GLsizei; internalformat: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; fixedsamplelocations: GLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultisamplefv = procedure(pname: GLenum; index_: GLuint; val: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSampleMaski = procedure(index_: GLuint; mask: GLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_draw_buffers_blend - TglBlendEquationi = procedure(buf: GLuint; mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBlendEquationSeparatei = procedure(buf: GLuint; modeRGB: GLenum; modeAlpha: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBlendFunci = procedure(buf: GLuint; src: GLenum; dst: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBlendFuncSeparatei = procedure(buf: GLuint; srcRGB: GLenum; dstRGB: GLenum; srcAlpha: GLenum; dstAlpha: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ARB_sample_shading - TglMinSampleShading = procedure(value: GLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_draw_buffers - TglDrawBuffersATI = procedure(n: TGLsizei; const bufs: PGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_element_array - TglElementPointerATI = procedure(_type: TGLenum; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawElementArrayATI = procedure(mode: TGLenum; count: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawRangeElementArrayATI = procedure(mode: TGLenum; start: TGLuint; _end: TGLuint; count: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_envmap_bumpmap - TglTexBumpParameterivATI = procedure(pname: TGLenum; const param: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexBumpParameterfvATI = procedure(pname: TGLenum; const param: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexBumpParameterivATI = procedure(pname: TGLenum; param: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexBumpParameterfvATI = procedure(pname: TGLenum; param: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_fragment_shader - TglGenFragmentShadersATI = function(range: TGLuint): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindFragmentShaderATI = procedure(id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteFragmentShaderATI = procedure(id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBeginFragmentShaderATI = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndFragmentShaderATI = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPassTexCoordATI = procedure(dst: TGLuint; coord: TGLuint; swizzle: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSampleMapATI = procedure(dst: TGLuint; interp: TGLuint; swizzle: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorFragmentOp1ATI = procedure(op: TGLenum; dst: TGLuint; dstMask: TGLuint; dstMod: TGLuint; arg1: TGLuint; arg1Rep: TGLuint; arg1Mod: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorFragmentOp2ATI = procedure(op: TGLenum; dst: TGLuint; dstMask: TGLuint; dstMod: TGLuint; arg1: TGLuint; arg1Rep: TGLuint; arg1Mod: TGLuint; arg2: TGLuint; arg2Rep: TGLuint; arg2Mod: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorFragmentOp3ATI = procedure(op: TGLenum; dst: TGLuint; dstMask: TGLuint; dstMod: TGLuint; arg1: TGLuint; arg1Rep: TGLuint; arg1Mod: TGLuint; arg2: TGLuint; arg2Rep: TGLuint; arg2Mod: TGLuint; arg3: TGLuint; arg3Rep: TGLuint; arg3Mod: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglAlphaFragmentOp1ATI = procedure(op: TGLenum; dst: TGLuint; dstMod: TGLuint; arg1: TGLuint; arg1Rep: TGLuint; arg1Mod: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglAlphaFragmentOp2ATI = procedure(op: TGLenum; dst: TGLuint; dstMod: TGLuint; arg1: TGLuint; arg1Rep: TGLuint; arg1Mod: TGLuint; arg2: TGLuint; arg2Rep: TGLuint; arg2Mod: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglAlphaFragmentOp3ATI = procedure(op: TGLenum; dst: TGLuint; dstMod: TGLuint; arg1: TGLuint; arg1Rep: TGLuint; arg1Mod: TGLuint; arg2: TGLuint; arg2Rep: TGLuint; arg2Mod: TGLuint; arg3: TGLuint; arg3Rep: TGLuint; arg3Mod: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSetFragmentShaderConstantATI = procedure(dst: TGLuint; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_map_object_buffer - TglMapObjectBufferATI = function(buffer: TGLuint): PGLvoid; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUnmapObjectBufferATI = procedure(buffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_pn_triangles - TglPNTrianglesiATI = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPNTrianglesfATI = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_separate_stencil - TglStencilOpSeparateATI = procedure(face: TGLenum; sfail: TGLenum; dpfail: TGLenum; dppass: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStencilFuncSeparateATI = procedure(frontfunc: TGLenum; backfunc: TGLenum; ref: TGLint; mask: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_vertex_array_object - TglNewObjectBufferATI = function(size: TGLsizei; const _pointer: PGLvoid; usage: TGLenum): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsObjectBufferATI = function(buffer: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUpdateObjectBufferATI = procedure(buffer: TGLuint; offset: TGLuint; size: TGLsizei; const _pointer: PGLvoid; preserve: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetObjectBufferfvATI = procedure(buffer: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetObjectBufferivATI = procedure(buffer: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFreeObjectBufferATI = procedure(buffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglArrayObjectATI = procedure(_array: TGLenum; size: TGLint; _type: TGLenum; stride: TGLsizei; buffer: TGLuint; offset: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetArrayObjectfvATI = procedure(_array: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetArrayObjectivATI = procedure(_array: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantArrayObjectATI = procedure(id: TGLuint; _type: TGLenum; stride: TGLsizei; buffer: TGLuint; offset: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVariantArrayObjectfvATI = procedure(id: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVariantArrayObjectivATI = procedure(id: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_vertex_attrib_array_object - TglVertexAttribArrayObjectATI = procedure(index: TGLuint; size: TGLint; _type: TGLenum; normalized: TGLboolean; stride: TGLsizei; buffer: TGLuint; offset: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribArrayObjectfvATI = procedure(index: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribArrayObjectivATI = procedure(index: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_ATI_vertex_streams - TglVertexStream1sATI = procedure(stream: TGLenum; x: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream1svATI = procedure(stream: TGLenum; const coords: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream1iATI = procedure(stream: TGLenum; x: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream1ivATI = procedure(stream: TGLenum; const coords: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream1fATI = procedure(stream: TGLenum; x: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream1fvATI = procedure(stream: TGLenum; const coords: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream1dATI = procedure(stream: TGLenum; x: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream1dvATI = procedure(stream: TGLenum; const coords: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2sATI = procedure(stream: TGLenum; x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2svATI = procedure(stream: TGLenum; const coords: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2iATI = procedure(stream: TGLenum; x: TGLint; y: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2ivATI = procedure(stream: TGLenum; const coords: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2fATI = procedure(stream: TGLenum; x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2fvATI = procedure(stream: TGLenum; const coords: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2dATI = procedure(stream: TGLenum; x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream2dvATI = procedure(stream: TGLenum; const coords: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3sATI = procedure(stream: TGLenum; x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3svATI = procedure(stream: TGLenum; const coords: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3iATI = procedure(stream: TGLenum; x: TGLint; y: TGLint; z: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3ivATI = procedure(stream: TGLenum; const coords: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3fATI = procedure(stream: TGLenum; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3fvATI = procedure(stream: TGLenum; const coords: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3dATI = procedure(stream: TGLenum; x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream3dvATI = procedure(stream: TGLenum; const coords: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4sATI = procedure(stream: TGLenum; x: TGLshort; y: TGLshort; z: TGLshort; w: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4svATI = procedure(stream: TGLenum; const coords: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4iATI = procedure(stream: TGLenum; x: TGLint; y: TGLint; z: TGLint; w: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4ivATI = procedure(stream: TGLenum; const coords: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4fATI = procedure(stream: TGLenum; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4fvATI = procedure(stream: TGLenum; const coords: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4dATI = procedure(stream: TGLenum; x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexStream4dvATI = procedure(stream: TGLenum; const coords: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3bATI = procedure(stream: TGLenum; nx: TGLbyte; ny: TGLbyte; nz: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3bvATI = procedure(stream: TGLenum; const coords: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3sATI = procedure(stream: TGLenum; nx: TGLshort; ny: TGLshort; nz: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3svATI = procedure(stream: TGLenum; const coords: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3iATI = procedure(stream: TGLenum; nx: TGLint; ny: TGLint; nz: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3ivATI = procedure(stream: TGLenum; const coords: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3fATI = procedure(stream: TGLenum; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3fvATI = procedure(stream: TGLenum; const coords: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3dATI = procedure(stream: TGLenum; nx: TGLdouble; ny: TGLdouble; nz: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalStream3dvATI = procedure(stream: TGLenum; const coords: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClientActiveVertexStreamATI = procedure(stream: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexBlendEnviATI = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexBlendEnvfATI = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_AMD_performance_monitor - TglGetPerfMonitorGroupsAMD = procedure(numGroups: PGLint; groupsSize: GLsizei; groups: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPerfMonitorCountersAMD = procedure(group: GLuint; numCounters: PGLint; maxActiveCouters: PGLint; counterSize: GLsizei; counters: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPerfMonitorGroupStringAMD = procedure(group: GLuint; bufSize: GLsizei; length: PGLsizei; groupString: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPerfMonitorCounterStringAMD = procedure(group: GLuint; counter: GLuint; bufSize: GLsizei; length: PGLsizei; counterString: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPerfMonitorCounterInfoAMD = procedure(group: GLuint; counter: GLuint; pname: GLenum; data: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenPerfMonitorsAMD = procedure(n: GLsizei; monitors: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeletePerfMonitorsAMD = procedure(n: GLsizei; monitors: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSelectPerfMonitorCountersAMD = procedure(monitor: GLuint; enable: GLboolean; group: GLuint; numCounters: GLint; counterList: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBeginPerfMonitorAMD = procedure(monitor: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndPerfMonitorAMD = procedure(monitor: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPerfMonitorCounterDataAMD = procedure(monitor: GLuint; pname: GLenum; dataSize: GLsizei; data: PGLuint; bytesWritten: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_AMD_vertex_shader_tesselator - TglTessellationFactorAMD = procedure(factor: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTessellationModeAMD = procedure(mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - - // GL_EXT_blend_color - TglBlendColorEXT = procedure(red: TGLclampf; green: TGLclampf; blue: TGLclampf; alpha: TGLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_blend_func_separate - TglBlendFuncSeparateEXT = procedure(sfactorRGB: TGLenum; dfactorRGB: TGLenum; sfactorAlpha: TGLenum; dfactorAlpha: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_blend_minmax - TglBlendEquationEXT = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_color_subtable - TglColorSubTableEXT = procedure(target: TGLenum; start: TGLsizei; count: TGLsizei; format: TGLenum; _type: TGLenum; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyColorSubTableEXT = procedure(target: TGLenum; start: TGLsizei; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_compiled_vertex_array - TglLockArraysEXT = procedure(first: TGLint; count: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUnlockArraysEXT = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_convolution - TglConvolutionFilter1DEXT = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; format: TGLenum; _type: TGLenum; const image: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionFilter2DEXT = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; const image: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameterfEXT = procedure(target: TGLenum; pname: TGLenum; params: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameterfvEXT = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameteriEXT = procedure(target: TGLenum; pname: TGLenum; params: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglConvolutionParameterivEXT = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyConvolutionFilter1DEXT = procedure(target: TGLenum; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyConvolutionFilter2DEXT = procedure(target: TGLenum; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetConvolutionFilterEXT = procedure(target: TGLenum; format: TGLenum; _type: TGLenum; image: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetConvolutionParameterfvEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetConvolutionParameterivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetSeparableFilterEXT = procedure(target: TGLenum; format: TGLenum; _type: TGLenum; row: PGLvoid; column: PGLvoid; span: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSeparableFilter2DEXT = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; const row: PGLvoid; const column: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_coordinate_frame - TglTangent3bEXT = procedure(tx: TGLbyte; ty: TGLbyte; tz: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3bvEXT = procedure(const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3dEXT = procedure(tx: TGLdouble; ty: TGLdouble; tz: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3dvEXT = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3fEXT = procedure(tx: TGLfloat; ty: TGLfloat; tz: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3fvEXT = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3iEXT = procedure(tx: TGLint; ty: TGLint; tz: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3ivEXT = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3sEXT = procedure(tx: TGLshort; ty: TGLshort; tz: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangent3svEXT = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3bEXT = procedure(bx: TGLbyte; by: TGLbyte; bz: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3bvEXT = procedure(const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3dEXT = procedure(bx: TGLdouble; by: TGLdouble; bz: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3dvEXT = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3fEXT = procedure(bx: TGLfloat; by: TGLfloat; bz: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3fvEXT = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3iEXT = procedure(bx: TGLint; by: TGLint; bz: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3ivEXT = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3sEXT = procedure(bx: TGLshort; by: TGLshort; bz: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormal3svEXT = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTangentPointerEXT = procedure(_type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBinormalPointerEXT = procedure(_type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_copy_texture - TglCopyTexImage1DEXT = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei; border: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexImage2DEXT = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei; border: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexSubImage1DEXT = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexSubImage2DEXT = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTexSubImage3DEXT = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; zoffset: TGLint; x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_cull_vertex - TglCullParameterdvEXT = procedure(pname: TGLenum; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCullParameterfvEXT = procedure(pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_draw_range_elements - TglDrawRangeElementsEXT = procedure(mode: TGLenum; start: TGLuint; _end: TGLuint; count: TGLsizei; _type: TGLenum; const indices: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_fog_coord - TglFogCoordfEXT = procedure(coord: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordfvEXT = procedure(const coord: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoorddEXT = procedure(coord: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoorddvEXT = procedure(const coord: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordPointerEXT = procedure(_type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_framebuffer_object - TglIsRenderbufferEXT = function(renderbuffer: TGLuint): Boolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindRenderbufferEXT = procedure(target: TGLenum; renderbuffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteRenderbuffersEXT = procedure(n: TGLsizei; const renderbuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenRenderbuffersEXT = procedure(n: TGLsizei; renderbuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRenderbufferStorageEXT = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetRenderbufferParameterivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsFramebufferEXT = function(framebuffer: TGLuint): Boolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindFramebufferEXT = procedure(target: TGLenum; framebuffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteFramebuffersEXT = procedure(n: TGLsizei; const framebuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenFramebuffersEXT = procedure(n: TGLsizei; framebuffers: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCheckFramebufferStatusEXT = function(target: TGLenum): TGLenum; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTexture1DEXT = procedure(target: TGLenum; attachment: TGLenum; textarget: TGLenum; texture: TGLuint; level: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTexture2DEXT = procedure(target: TGLenum; attachment: TGLenum; textarget: TGLenum; texture: TGLuint; level: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTexture3DEXT = procedure(target: TGLenum; attachment: TGLenum; textarget: TGLenum; texture: TGLuint; level: TGLint; zoffset: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferRenderbufferEXT = procedure(target: TGLenum; attachment: TGLenum; renderbuffertarget: TGLenum; renderbuffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFramebufferAttachmentParameterivEXT = procedure(target: TGLenum; attachment: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenerateMipmapEXT = procedure(target: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_histogram - TglGetHistogramEXT = procedure(target: TGLenum; reset: TGLboolean; format: TGLenum; _type: TGLenum; values: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetHistogramParameterfvEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetHistogramParameterivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMinmaxEXT = procedure(target: TGLenum; reset: TGLboolean; format: TGLenum; _type: TGLenum; values: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMinmaxParameterfvEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMinmaxParameterivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglHistogramEXT = procedure(target: TGLenum; width: TGLsizei; internalformat: TGLenum; sink: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMinmaxEXT = procedure(target: TGLenum; internalformat: TGLenum; sink: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglResetHistogramEXT = procedure(target: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglResetMinmaxEXT = procedure(target: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_index_func - TglIndexFuncEXT = procedure(func: TGLenum; ref: TGLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_index_material - TglIndexMaterialEXT = procedure(face: TGLenum; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_light_texture - TglApplyTextureEXT = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureLightEXT = procedure(pname: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureMaterialEXT = procedure(face: TGLenum; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_multi_draw_arrays - TglMultiDrawArraysEXT = procedure(mode: TGLenum; first: PGLint; count: PGLsizei; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiDrawElementsEXT = procedure(mode: TGLenum; const count: PGLsizei; _type: TGLenum; const indices: PGLvoid; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_multisample - TglSampleMaskEXT = procedure(value: TGLclampf; invert: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSamplePatternEXT = procedure(pattern: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_paletted_texture - TglColorTableEXT = procedure(target: TGLenum; internalFormat: TGLenum; width: TGLsizei; format: TGLenum; _type: TGLenum; const table: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableEXT = procedure(target: TGLenum; format: TGLenum; _type: TGLenum; data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableParameterivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableParameterfvEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_pixel_transform - TglPixelTransformParameteriEXT = procedure(target: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTransformParameterfEXT = procedure(target: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTransformParameterivEXT = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTransformParameterfvEXT = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_point_parameters - TglPointParameterfEXT = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameterfvEXT = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_polygon_offset - TglPolygonOffsetEXT = procedure(factor: TGLfloat; bias: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_secondary_color - TglSecondaryColor3bEXT = procedure(red: TGLbyte; green: TGLbyte; blue: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3bvEXT = procedure(const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3dEXT = procedure(red: TGLdouble; green: TGLdouble; blue: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3dvEXT = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3fEXT = procedure(red: TGLfloat; green: TGLfloat; blue: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3fvEXT = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3iEXT = procedure(red: TGLint; green: TGLint; blue: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3ivEXT = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3sEXT = procedure(red: TGLshort; green: TGLshort; blue: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3svEXT = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3ubEXT = procedure(red: TGLubyte; green: TGLubyte; blue: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3ubvEXT = procedure(const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3uiEXT = procedure(red: TGLuint; green: TGLuint; blue: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3uivEXT = procedure(const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3usEXT = procedure(red: TGLushort; green: TGLushort; blue: TGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3usvEXT = procedure(const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColorPointerEXT = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_stencil_two_side - TglActiveStencilFaceEXT = procedure(face: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_subtexture - TglTexSubImage1DEXT = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; width: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexSubImage2DEXT = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; width: TGLsizei; height: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_texture3D - TglTexImage3DEXT = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; depth: TGLsizei; border: TGLint; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexSubImage3DEXT = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; zoffset: TGLint; width: TGLsizei; height: TGLsizei; depth: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_texture_object - TglAreTexturesResidentEXT = function(n: TGLsizei; const textures: PGLuint; residences: PGLboolean): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindTextureEXT = procedure(target: TGLenum; texture: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteTexturesEXT = procedure(n: TGLsizei; const textures: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenTexturesEXT = procedure(n: TGLsizei; textures: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsTextureEXT = function(texture: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPrioritizeTexturesEXT = procedure(n: TGLsizei; const textures: PGLuint; const priorities: PGLclampf); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_texture_perturb_normal - TglTextureNormalEXT = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_vertex_array - TglArrayElementEXT = procedure(i: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorPointerEXT = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; count: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawArraysEXT = procedure(mode: TGLenum; first: TGLint; count: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEdgeFlagPointerEXT = procedure(stride: TGLsizei; count: TGLsizei; const _pointer: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPointervEXT = procedure(pname: TGLenum; params: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexPointerEXT = procedure(_type: TGLenum; stride: TGLsizei; count: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalPointerEXT = procedure(_type: TGLenum; stride: TGLsizei; count: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoordPointerEXT = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; count: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexPointerEXT = procedure(size: TGLint; _type: TGLenum; stride: TGLsizei; count: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_vertex_shader - TglBeginVertexShaderEXT = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndVertexShaderEXT = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindVertexShaderEXT = procedure(id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenVertexShadersEXT = function(range: TGLuint): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteVertexShaderEXT = procedure(id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglShaderOp1EXT = procedure(op: TGLenum; res: TGLuint; arg1: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglShaderOp2EXT = procedure(op: TGLenum; res: TGLuint; arg1: TGLuint; arg2: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglShaderOp3EXT = procedure(op: TGLenum; res: TGLuint; arg1: TGLuint; arg2: TGLuint; arg3: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSwizzleEXT = procedure(res: TGLuint; _in: TGLuint; outX: TGLenum; outY: TGLenum; outZ: TGLenum; outW: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWriteMaskEXT = procedure(res: TGLuint; _in: TGLuint; outX: TGLenum; outY: TGLenum; outZ: TGLenum; outW: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglInsertComponentEXT = procedure(res: TGLuint; src: TGLuint; num: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglExtractComponentEXT = procedure(res: TGLuint; src: TGLuint; num: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenSymbolsEXT = function(datatype: TGLenum; storagetype: TGLenum; range: TGLenum; components: TGLuint): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSetInvariantEXT = procedure(id: TGLuint; _type: TGLenum; const addr: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSetLocalConstantEXT = procedure(id: TGLuint; _type: TGLenum; const addr: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantbvEXT = procedure(id: TGLuint; const addr: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantsvEXT = procedure(id: TGLuint; const addr: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantivEXT = procedure(id: TGLuint; const addr: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantfvEXT = procedure(id: TGLuint; const addr: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantdvEXT = procedure(id: TGLuint; const addr: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantubvEXT = procedure(id: TGLuint; const addr: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantusvEXT = procedure(id: TGLuint; const addr: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantuivEXT = procedure(id: TGLuint; const addr: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVariantPointerEXT = procedure(id: TGLuint; _type: TGLenum; stride: TGLuint; const addr: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnableVariantClientStateEXT = procedure(id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisableVariantClientStateEXT = procedure(id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindLightParameterEXT = function(light: TGLenum; value: TGLenum): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindMaterialParameterEXT = function(face: TGLenum; value: TGLenum): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindTexGenParameterEXT = function(_unit: TGLenum; coord: TGLenum; value: TGLenum): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindTextureUnitParameterEXT = function(_unit: TGLenum; value: TGLenum): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindParameterEXT = function(value: TGLenum): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsVariantEnabledEXT = function(id: TGLuint; cap: TGLenum): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVariantBooleanvEXT = procedure(id: TGLuint; value: TGLenum; data: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVariantIntegervEXT = procedure(id: TGLuint; value: TGLenum; data: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVariantFloatvEXT = procedure(id: TGLuint; value: TGLenum; data: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVariantPointervEXT = procedure(id: TGLuint; value: TGLenum; data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetInvariantBooleanvEXT = procedure(id: TGLuint; value: TGLenum; data: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetInvariantIntegervEXT = procedure(id: TGLuint; value: TGLenum; data: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetInvariantFloatvEXT = procedure(id: TGLuint; value: TGLenum; data: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetLocalConstantBooleanvEXT = procedure(id: TGLuint; value: TGLenum; data: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetLocalConstantIntegervEXT = procedure(id: TGLuint; value: TGLenum; data: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetLocalConstantFloatvEXT = procedure(id: TGLuint; value: TGLenum; data: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_vertex_weighting - TglVertexWeightfEXT = procedure(weight: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexWeightfvEXT = procedure(const weight: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexWeightPointerEXT = procedure(size: TGLsizei; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_stencil_clear_tag - TglStencilClearTagEXT = procedure(stencilTagBits: TGLsizei; stencilClearTag: Tgluint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_framebuffer_blit - TglBlitFramebufferEXT = procedure(srcX0: TGLint; srcY0: TGLint; srcX1: TGLint; srcY1: TGLint; dstX0: TGLint; dstY0: TGLint; dstX1: TGLint; dstY1: TGLint; mask: TGLbitfield; filter: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_framebuffer_multisample - TglRenderbufferStorageMultisampleEXT = procedure(target: TGLenum; samples: TGLsizei; internalformat: TGLenum; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_timer_query - TglGetQueryObjecti64vEXT = procedure(id: TGLuint; pname: TGLenum; params: PGLint64EXT); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetQueryObjectui64vEXT = procedure(id: TGLuint; pname: TGLenum; params: PGLuint64EXT); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_gpu_program_parameters - TglProgramEnvParameters4fvEXT = procedure(target: TGLenum; index: TGLuint; count: TGLsizei; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameters4fvEXT = procedure(target: TGLenum; index: TGLuint; count: TGLsizei; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_bindable_uniform - TglUniformBufferEXT = procedure(_program: TGLuint; location: TGLint; buffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformBufferSizeEXT = function(_program: TGLuint; location: TGLint): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformOffsetEXT = function(_program: TGLuint; location: TGLint): PGLInt; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_draw_buffers2 - TglColorMaskIndexedEXT = procedure(buf: TGLuint; r: TGLboolean; g: TGLboolean; b: TGLboolean; a: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetBooleanIndexedvEXT = procedure(value: TGLenum; index: TGLuint; data: PGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetIntegerIndexedvEXT = procedure(value: TGLenum; index: TGLuint; data: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnableIndexedEXT = procedure(target: TGLenum; index: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisableIndexedEXT = procedure(target: TGLenum; index: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsEnabledIndexedEXT = function(target: TGLenum; index: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_draw_instanced - TglDrawArraysInstancedEXT = procedure(mode: TGLenum; first: TGLint; count: TGLsizei; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawElementsInstancedEXT = procedure(mode: TGLenum; count: TGLsizei; _type: TGLenum; const indices: Pointer; primcount: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_geometry_shader4 - TglProgramParameteriEXT = procedure (_program: TGLuint; pname: TGLenum; value: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTextureEXT = procedure(target: TGLenum; attachment: TGLenum; texture: TGLuint; level: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -// TglFramebufferTextureLayerEXT = procedure(target: TGLenum; attachment: TGLenum; texture: TGLuint; level: TGLint; layer: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferTextureFaceEXT = procedure(target: TGLenum; attachment: TGLenum; texture: TGLuint; level: TGLint; face: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_gpu_shader4 - TglVertexAttribI1iEXT = procedure(index: TGLuint; x: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2iEXT = procedure(index: TGLuint; x: TGLint; y: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3iEXT = procedure(index: TGLuint; x: TGLint; y: TGLint; z: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4iEXT = procedure(index: TGLuint; x: TGLint; y: TGLint; z: TGLint; w: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI1uiEXT = procedure(index: TGLuint; x: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2uiEXT = procedure(index: TGLuint; x: TGLuint; y: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3uiEXT = procedure(index: TGLuint; x: TGLuint; y: TGLuint; z: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4uiEXT = procedure(index: TGLuint; x: TGLuint; y: TGLuint; z: TGLuint; w: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI1ivEXT = procedure(index: TGLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2ivEXT = procedure(index: TGLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3ivEXT = procedure(index: TGLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4ivEXT = procedure(index: TGLuint; const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI1uivEXT = procedure(index: TGLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI2uivEXT = procedure(index: TGLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI3uivEXT = procedure(index: TGLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4uivEXT = procedure(index: TGLuint; const v: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4bvEXT = procedure(index: TGLuint; const v: PGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4svEXT = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4ubvEXT = procedure(index: TGLuint; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribI4usvEXT = procedure(index: TGLuint; const v: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribIPointerEXT = procedure(index: TGLuint; size: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribIivEXT = procedure(index: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribIuivEXT = procedure(index: TGLuint; pname: TGLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1uiEXT = procedure(location: TGLint; v0: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2uiEXT = procedure(location: TGLint; v0: TGLuint; v1: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3uiEXT = procedure(location: TGLint; v0: TGLuint; v1: TGLuint; v2: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4uiEXT = procedure(location: TGLint; v0: TGLuint; v1: TGLuint; v2: TGLuint; v3: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform1uivEXT = procedure(location: TGLint; count: TGLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform2uivEXT = procedure(location: TGLint; count: TGLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform3uivEXT = procedure(location: TGLint; count: TGLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUniform4uivEXT = procedure(location: TGLint; count: TGLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetUniformuivEXT = procedure(_program: TGLuint; location: TGLint; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindFragDataLocationEXT = procedure(_program: TGLuint; colorNumber: TGLuint; const name: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFragDataLocationEXT = function(_program: TGLuint; const name: PGLchar): TGLint; - - // GL_EXT_texture_array - TglFramebufferTextureLayerEXT = procedure(target: TGLenum; attachment: TGLenum; texture: TGLuint; level: TGLint; layer: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_texture_buffer_object - TglTexBufferEXT = procedure(target: TGLenum; internalformat: TGLenum; buffer: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_texture_integer - TglClearColorIiEXT = procedure(r: TGLint; g: TGLint; b: TGLint; a: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearColorIuiEXT = procedure(r: TGLuint; g: TGLuint; b: TGLuint; a: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameterIivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexParameterIuivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexParameterIivEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTexParameterIiuvEXT = procedure(target: TGLenum; pname: TGLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_HP_image_transform - TglImageTransformParameteriHP = procedure(target: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglImageTransformParameterfHP = procedure(target: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglImageTransformParameterivHP = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglImageTransformParameterfvHP = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetImageTransformParameterivHP = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetImageTransformParameterfvHP = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_depth_bounds_test - TglDepthBoundsEXT = procedure(zmin: TGLclampd; zmax: TGLclampd); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_blend_equation_separate - TglBlendEquationSeparateEXT = procedure(modeRGB: TGLenum; modeAlpha: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_transform_feedback - TglBeginTransformFeedbackEXT = procedure(primitiveMode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndTransformFeedbackEXT = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferRangeEXT = procedure(target: GLenum; index_: GLuint; buffer: GLuint; offset: GLsizei; size: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferOffsetEXT = procedure(target: GLenum; index_: GLuint; buffer: GLuint; offset: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferBaseEXT = procedure(target: GLenum; index_: GLuint; buffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTransformFeedbackVaryingsEXT = procedure(program_: GLuint; count: GLsizei; const locations: PGLint; bufferMode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTransformFeedbackVaryingEXT = procedure(program_: GLuint; index_: GLuint; location: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_EXT_direct_state_access - TglClientAttribDefaultEXT = procedure(mask: GLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPushClientAttribDefaultEXT = procedure(mask: GLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixLoadfEXT = procedure(mode: GLenum; const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixLoaddEXT = procedure(mode: GLenum; const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixMultfEXT = procedure(mode: GLenum; const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixMultdEXT = procedure(mode: GLenum; const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixLoadIdentityEXT = procedure(mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixRotatefEXT = procedure(mode: GLenum; angle: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixRotatedEXT = procedure(mode: GLenum; angle: GLdouble; x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixScalefEXT = procedure(mode: GLenum; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixScaledEXT = procedure(mode: GLenum; x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixTranslatefEXT = procedure(mode: GLenum; x: GLfloat; y: GLfloat; z: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixTranslatedEXT = procedure(mode: GLenum; x: GLdouble; y: GLdouble; z: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixFrustumEXT = procedure(mode: GLenum; left: GLdouble; right: GLdouble; bottom: GLdouble; top: GLdouble; zNear: GLdouble; zFar: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixOrthoEXT = procedure(mode: GLenum; left: GLdouble; right: GLdouble; bottom: GLdouble; top: GLdouble; zNear: GLdouble; zFar: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixPopEXT = procedure(mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixPushEXT = procedure(mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixLoadTransposefEXT = procedure(mode: GLenum; const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixLoadTransposedEXT = procedure(mode: GLenum; const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixMultTransposefEXT = procedure(mode: GLenum; const m: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMatrixMultTransposedEXT = procedure(mode: GLenum; const m: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureParameterfEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureParameterfvEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureParameteriEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; param: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureParameterivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureImage1DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureImage2DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureSubImage1DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureSubImage2DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTextureImage1DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; border: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTextureImage2DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; height: GLsizei; border: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTextureSubImage1DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; x: GLint; y: GLint; width: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTextureSubImage2DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; x: GLint; y: GLint; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTextureImageEXT = procedure(texture: GLuint; target: GLenum; level: GLint; format: GLenum; type_: GLenum; pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTextureParameterfvEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTextureParameterivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTextureLevelParameterfvEXT = procedure(texture: GLuint; target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTextureLevelParameterivEXT = procedure(texture: GLuint; target: GLenum; level: GLint; pname: GLenum; params: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureImage3DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureSubImage3DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyTextureSubImage3DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; x: GLint; y: GLint; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexParameterfEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexParameterfvEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexParameteriEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; param: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexParameterivEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexImage1DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexImage2DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexSubImage1DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexSubImage2DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyMultiTexImage1DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; border: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyMultiTexImage2DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; height: GLsizei; border: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyMultiTexSubImage1DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; x: GLint; y: GLint; width: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyMultiTexSubImage2DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; x: GLint; y: GLint; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexImageEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; format: GLenum; type_: GLenum; pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexParameterfvEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexParameterivEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexLevelParameterfvEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexLevelParameterivEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexImage3DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; format: GLenum; type_: GLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexSubImage3DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; type_: GLenum; const pixels:PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyMultiTexSubImage3DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; x: GLint; y: GLint; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindMultiTextureEXT = procedure(texunit: GLenum; target: GLenum; texture: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEnableClientStateIndexedEXT = procedure(array_: GLenum; index_: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDisableClientStateIndexedEXT = procedure(array_: GLenum; index_: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoordPointerEXT = procedure(texunit: GLenum; size: GLint; type_: GLenum; stride: GLsizei; const pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexEnvfEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexEnvfvEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexEnviEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; param: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexEnvivEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexGendEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; param: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexGendvEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; const params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexGenfEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexGenfvEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexGeniEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; param: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexGenivEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexEnvfvEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexEnvivEXT = procedure(texunit: GLenum; target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexGendvEXT = procedure(texunit: GLenum; coord: GLenum; pname: GLenum; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexGenfvEXT = procedure(texunit: GLenum; coord: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexGenivEXT = procedure(texunit: GLenum; coord: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFloatIndexedvEXT = procedure(target: GLenum; index_: GLuint; data: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetDoubleIndexedvEXT = procedure(target: GLenum; index_: GLuint; data: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPointerIndexedvEXT = procedure(target: GLenum; index_: GLuint; data: PPGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTextureImage3DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTextureImage2DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTextureImage1DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTextureSubImage3DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTextureSubImage2DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedTextureSubImage1DEXT = procedure(texture: GLuint; target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCompressedTextureImageEXT = procedure(texture: GLuint; target: GLenum; lod: GLint; img: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedMultiTexImage3DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedMultiTexImage2DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedMultiTexImage1DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedMultiTexSubImage3DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedMultiTexSubImage2DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCompressedMultiTexSubImage1DEXT = procedure(texunit: GLenum; target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; imageSize: GLsizei; const bits: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCompressedMultiTexImageEXT = procedure(texunit: GLenum; target: GLenum; lod: GLint; img: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramStringEXT = procedure(program_: GLuint; target: GLenum; format: GLenum; len: GLsizei; const string_: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameter4dEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameter4dvEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; const params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameter4fEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameter4fvEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedProgramLocalParameterdvEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedProgramLocalParameterfvEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedProgramivEXT = procedure(program_: GLuint; target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedProgramStringEXT = procedure(program_: GLuint; target: GLenum; pname: GLenum; string_: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameters4fvEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; count: GLsizei; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameterI4iEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; x: GLint; y: GLint; z: GLint; w: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameterI4ivEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParametersI4ivEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; count: GLsizei; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameterI4uiEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; x: GLuint; y: GLuint; z: GLuint; w: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParameterI4uivEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedProgramLocalParametersI4uivEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; count: GLsizei; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedProgramLocalParameterIivEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedProgramLocalParameterIuivEXT = procedure(program_: GLuint; target: GLenum; index_: GLuint; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureParameterIivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureParameterIuivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTextureParameterIivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTextureParameterIuivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexParameterIivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexParameterIuivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexParameterIivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMultiTexParameterIuivEXT = procedure(texture: GLuint; target: GLenum; pname: GLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform1fEXT = procedure(program_: GLuint; location: GLint; v0: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform2fEXT = procedure(program_: GLuint; location: GLint; v0: GLfloat; v1: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform3fEXT = procedure(program_: GLuint; location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform4fEXT = procedure(program_: GLuint; location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat; v3: GLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform1iEXT = procedure(program_: GLuint; location: GLint; v0: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform2iEXT = procedure(program_: GLuint; location: GLint; v0: GLint; v1: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform3iEXT = procedure(program_: GLuint; location: GLint; v0: GLint; v1: GLint; v2: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform4iEXT = procedure(program_: GLuint; location: GLint; v0: GLint; v1: GLint; v2: GLint; v3: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform1fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform2fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform3fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform4fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform1ivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform2ivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform3ivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform4ivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix2fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix3fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix4fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix2x3fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix3x2fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix2x4fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix4x2fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix3x4fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniformMatrix4x3fvEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform1uiEXT = procedure(program_: GLuint; location: GLint; v0: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform2uiEXT = procedure(program_: GLuint; location: GLint; v0: GLuint; v1: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform3uiEXT = procedure(program_: GLuint; location: GLint; v0: GLuint; v1: GLuint; v2: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform4uiEXT = procedure(program_: GLuint; location: GLint; v0: GLuint; v1: GLuint; v2: GLuint; v3: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform1uivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform2uivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform3uivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramUniform4uivEXT = procedure(program_: GLuint; location: GLint; count: GLsizei; const value: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedBufferDataEXT = procedure(buffer: GLuint; size: GLsizei; const data: PGLvoid; usage: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedBufferSubDataEXT = procedure(buffer: GLuint; offset: GLsizei; size: GLsizei; const data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapNamedBufferEXT = function(buffer: GLuint; access: GLenum): PGLvoid; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglUnmapNamedBufferEXT = function(buffer: GLuint): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedBufferParameterivEXT = procedure(buffer: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedBufferPointervEXT = procedure(buffer: GLuint; pname: GLenum; params: PPGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedBufferSubDataEXT = procedure(buffer: GLuint; offset: GLsizei; size: GLsizei; data: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureBufferEXT = procedure(texture: GLuint; target: GLenum; internalformat: GLenum; buffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexBufferEXT = procedure(texunit: GLenum; target: GLenum; interformat: GLenum; buffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedRenderbufferStorageEXT = procedure(renderbuffer: GLuint; interformat: GLenum; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedRenderbufferParameterivEXT = procedure(renderbuffer: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCheckNamedFramebufferStatusEXT = function(framebuffer: GLuint; target: GLenum): GLenum; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedFramebufferTexture1DEXT = procedure(framebuffer: GLuint; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedFramebufferTexture2DEXT = procedure(framebuffer: GLuint; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedFramebufferTexture3DEXT = procedure(framebuffer: GLuint; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint; zoffset: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedFramebufferRenderbufferEXT = procedure(framebuffer: GLuint; attachment: GLenum; renderbuffertarget: GLenum; renderbuffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetNamedFramebufferAttachmentParameterivEXT = procedure(framebuffer: GLuint; attachment: GLenum; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenerateTextureMipmapEXT = procedure(texture: GLuint; target: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenerateMultiTexMipmapEXT = procedure(texunit: GLenum; target: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferDrawBufferEXT = procedure(framebuffer: GLuint; mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferDrawBuffersEXT = procedure(framebuffer: GLuint; n: GLsizei; const bufs: PGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFramebufferReadBufferEXT = procedure(framebuffer: GLuint; mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFramebufferParameterivEXT = procedure(framebuffer: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedRenderbufferStorageMultisampleEXT = procedure(renderbuffer: GLuint; samples: GLsizei; internalformat: GLenum; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedRenderbufferStorageMultisampleCoverageEXT = procedure(renderbuffer: GLuint; coverageSamples: GLsizei; colorSamples: GLsizei; internalformat: GLenum; width: GLsizei; height: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedFramebufferTextureEXT = procedure(framebuffer: GLuint; attachment: GLenum; texture: GLuint; level: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedFramebufferTextureLayerEXT = procedure(framebuffer: GLuint; attachment: GLenum; texture: GLuint; level: GLint; layer: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNamedFramebufferTextureFaceEXT = procedure(framebuffer: GLuint; attachment: GLenum; texture: GLuint; level: GLint; face: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTextureRenderbufferEXT = procedure(texture: GLuint; target: GLenum; renderbuffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexRenderbufferEXT = procedure(texunit: GLenum; target: GLenum; renderbuffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_IBM_multimode_draw_arrays - TglMultiModeDrawArraysIBM = procedure(mode: TGLenum; const first: PGLint; const count: PGLsizei; primcount: TGLsizei; modestride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiModeDrawElementsIBM = procedure(const mode: PGLenum; const count: PGLsizei; _type: TGLenum; const indices: PGLvoid; primcount: TGLsizei; modestride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_IBM_vertex_array_lists - TglColorPointerListIBM = procedure(size: TGLint; _type: TGLenum; stride: TGLint; const _pointer: PGLvoid; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColorPointerListIBM = procedure(size: TGLint; _type: TGLenum; stride: TGLint; const _pointer: PGLvoid; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEdgeFlagPointerListIBM = procedure(stride: TGLint; const _pointer: PGLboolean; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordPointerListIBM = procedure(_type: TGLenum; stride: TGLint; const _pointer: PGLvoid; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIndexPointerListIBM = procedure(_type: TGLenum; stride: TGLint; const _pointer: PGLvoid; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalPointerListIBM = procedure(_type: TGLenum; stride: TGLint; const _pointer: PGLvoid; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoordPointerListIBM = procedure(size: TGLint; _type: TGLenum; stride: TGLint; const _pointer: PGLvoid; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexPointerListIBM = procedure(size: TGLint; _type: TGLenum; stride: TGLint; const _pointer: PGLvoid; ptrstride: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_INGR_blend_func_separate - TglBlendFuncSeparateINGR = procedure(sfactorRGB: TGLenum; dfactorRGB: TGLenum; sfactorAlpha: TGLenum; dfactorAlpha: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_INTEL_parallel_arrays - TglVertexPointervINTEL = procedure(size: TGLint; _type: TGLenum; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormalPointervINTEL = procedure(_type: TGLenum; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorPointervINTEL = procedure(size: TGLint; _type: TGLenum; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoordPointervINTEL = procedure(size: TGLint; _type: TGLenum; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_MESA_resize_buffers - TglResizeBuffersMESA = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_MESA_window_pos - TglWindowPos2dMESA = procedure(x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2dvMESA = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2fMESA = procedure(x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2fvMESA = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2iMESA = procedure(x: TGLint; y: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2ivMESA = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2sMESA = procedure(x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos2svMESA = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3dMESA = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3dvMESA = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3fMESA = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3fvMESA = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3iMESA = procedure(x: TGLint; y: TGLint; z: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3ivMESA = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3sMESA = procedure(x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos3svMESA = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4dMESA = procedure(x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4dvMESA = procedure(const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4fMESA = procedure(x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4fvMESA = procedure(const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4iMESA = procedure(x: TGLint; y: TGLint; z: TGLint; w: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4ivMESA = procedure(const v: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4sMESA = procedure(x: TGLshort; y: TGLshort; z: TGLshort; w: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglWindowPos4svMESA = procedure(const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_evaluators - TglMapControlPointsNV = procedure(target: TGLenum; index: TGLuint; _type: TGLenum; ustride: TGLsizei; vstride: TGLsizei; uorder: TGLint; vorder: TGLint; _packed: TGLboolean; const points: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapParameterivNV = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMapParameterfvNV = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapControlPointsNV = procedure(target: TGLenum; index: TGLuint; _type: TGLenum; ustride: TGLsizei; vstride: TGLsizei; _packed: TGLboolean; points: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapParameterivNV = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapParameterfvNV = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapAttribParameterivNV = procedure(target: TGLenum; index: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetMapAttribParameterfvNV = procedure(target: TGLenum; index: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEvalMapsNV = procedure(target: TGLenum; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_fence - TglDeleteFencesNV = procedure(n: TGLsizei; const fences: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenFencesNV = procedure(n: TGLsizei; fences: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsFenceNV = function(fence: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTestFenceNV = function(fence: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFenceivNV = procedure(fence: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFinishFenceNV = procedure(fence: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSetFenceNV = procedure(fence: TGLuint; condition: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_fragment_program - TglProgramNamedParameter4fNV = procedure(id: TGLuint; len: TGLsizei; const name: PGLubyte; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramNamedParameter4dNV = procedure(id: TGLuint; len: TGLsizei; const name: PGLubyte; x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramNamedParameter4fvNV = procedure(id: TGLuint; len: TGLsizei; const name: PGLubyte; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramNamedParameter4dvNV = procedure(id: TGLuint; len: TGLsizei; const name: PGLubyte; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramNamedParameterfvNV = procedure(id: TGLuint; len: TGLsizei; const name: PGLubyte; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramNamedParameterdvNV = procedure(id: TGLuint; len: TGLsizei; const name: PGLubyte; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_half_float - TglVertex2hNV = procedure(x: TGLhalfNV; y: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex2hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3hNV = procedure(x: TGLhalfNV; y: TGLhalfNV; z: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex3hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4hNV = procedure(x: TGLhalfNV; y: TGLhalfNV; z: TGLhalfNV; w: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertex4hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3hNV = procedure(nx: TGLhalfNV; ny: TGLhalfNV; nz: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3hNV = procedure(red: TGLhalfNV; green: TGLhalfNV; blue: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4hNV = procedure(red: TGLhalfNV; green: TGLhalfNV; blue: TGLhalfNV; alpha: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1hNV = procedure(s: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord1hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2hNV = procedure(s: TGLhalfNV; t: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3hNV = procedure(s: TGLhalfNV; t: TGLhalfNV; r: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord3hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4hNV = procedure(s: TGLhalfNV; t: TGLhalfNV; r: TGLhalfNV; q: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1hNV = procedure(target: TGLenum; s: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord1hvNV = procedure(target: TGLenum; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2hNV = procedure(target: TGLenum; s: TGLhalfNV; t: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord2hvNV = procedure(target: TGLenum; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3hNV = procedure(target: TGLenum; s: TGLhalfNV; t: TGLhalfNV; r: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord3hvNV = procedure(target: TGLenum; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4hNV = procedure(target: TGLenum; s: TGLhalfNV; t: TGLhalfNV; r: TGLhalfNV; q: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglMultiTexCoord4hvNV = procedure(target: TGLenum; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordhNV = procedure(fog: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFogCoordhvNV = procedure(const fog: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3hNV = procedure(red: TGLhalfNV; green: TGLhalfNV; blue: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSecondaryColor3hvNV = procedure(const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexWeighthNV = procedure(weight: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexWeighthvNV = procedure(const weight: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1hNV = procedure(index: TGLuint; x: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1hvNV = procedure(index: TGLuint; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2hNV = procedure(index: TGLuint; x: TGLhalfNV; y: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2hvNV = procedure(index: TGLuint; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3hNV = procedure(index: TGLuint; x: TGLhalfNV; y: TGLhalfNV; z: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3hvNV = procedure(index: TGLuint; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4hNV = procedure(index: TGLuint; x: TGLhalfNV; y: TGLhalfNV; z: TGLhalfNV; w: TGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4hvNV = procedure(index: TGLuint; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs1hvNV = procedure(index: TGLuint; n: TGLsizei; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs2hvNV = procedure(index: TGLuint; n: TGLsizei; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs3hvNV = procedure(index: TGLuint; n: TGLsizei; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs4hvNV = procedure(index: TGLuint; n: TGLsizei; const v: PGLhalfNV); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_occlusion_query - TglGenOcclusionQueriesNV = procedure(n: TGLsizei; ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteOcclusionQueriesNV = procedure(n: TGLsizei; const ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsOcclusionQueryNV = function(id: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBeginOcclusionQueryNV = procedure(id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndOcclusionQueryNV = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetOcclusionQueryivNV = procedure(id: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetOcclusionQueryuivNV = procedure(id: TGLuint; pname: TGLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_pixel_data_range - TglPixelDataRangeNV = procedure(target: TGLenum; length: TGLsizei; _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFlushPixelDataRangeNV = procedure(target: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_point_sprite - TglPointParameteriNV = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameterivNV = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_primitive_restart - TglPrimitiveRestartNV = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPrimitiveRestartIndexNV = procedure(index: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_register_combiners - TglCombinerParameterfvNV = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCombinerParameterfNV = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCombinerParameterivNV = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCombinerParameteriNV = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCombinerInputNV = procedure(stage: TGLenum; portion: TGLenum; variable: TGLenum; input: TGLenum; mapping: TGLenum; componentUsage: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCombinerOutputNV = procedure(stage: TGLenum; portion: TGLenum; abOutput: TGLenum; cdOutput: TGLenum; sumOutput: TGLenum; scale: TGLenum; bias: TGLenum; abDotProduct: TGLboolean; cdDotProduct: TGLboolean; muxSum: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFinalCombinerInputNV = procedure(variable: TGLenum; input: TGLenum; mapping: TGLenum; componentUsage: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCombinerInputParameterfvNV = procedure(stage: TGLenum; portion: TGLenum; variable: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCombinerInputParameterivNV = procedure(stage: TGLenum; portion: TGLenum; variable: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCombinerOutputParameterfvNV = procedure(stage: TGLenum; portion: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCombinerOutputParameterivNV = procedure(stage: TGLenum; portion: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFinalCombinerInputParameterfvNV = procedure(variable: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFinalCombinerInputParameterivNV = procedure(variable: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_register_combiners2 - TglCombinerStageParameterfvNV = procedure(stage: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetCombinerStageParameterfvNV = procedure(stage: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_vertex_array_range - TglFlushVertexArrayRangeNV = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexArrayRangeNV = procedure(length: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_vertex_program - TglAreProgramsResidentNV = function(n: TGLsizei; const programs: PGLuint; residences: PGLboolean): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindProgramNV = procedure(target: TGLenum; id: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteProgramsNV = procedure(n: TGLsizei; const programs: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglExecuteProgramNV = procedure(target: TGLenum; id: TGLuint; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenProgramsNV = procedure(n: TGLsizei; programs: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramParameterdvNV = procedure(target: TGLenum; index: TGLuint; pname: TGLenum; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramParameterfvNV = procedure(target: TGLenum; index: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramivNV = procedure(id: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramStringNV = procedure(id: TGLuint; pname: TGLenum; _program: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTrackMatrixivNV = procedure(target: TGLenum; address: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribdvNV = procedure(index: TGLuint; pname: TGLenum; params: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribfvNV = procedure(index: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribivNV = procedure(index: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVertexAttribPointervNV = procedure(index: TGLuint; pname: TGLenum; _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsProgramNV = function(id: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadProgramNV = procedure(target: TGLenum; id: TGLuint; len: TGLsizei; const _program: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramParameter4dNV = procedure(target: TGLenum; index: TGLuint; x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramParameter4dvNV = procedure(target: TGLenum; index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramParameter4fNV = procedure(target: TGLenum; index: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramParameter4fvNV = procedure(target: TGLenum; index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramParameters4dvNV = procedure(target: TGLenum; index: TGLuint; count: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramParameters4fvNV = procedure(target: TGLenum; index: TGLuint; count: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglRequestResidentProgramsNV = procedure(n: TGLsizei; const programs: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTrackMatrixNV = procedure(target: TGLenum; address: TGLuint; matrix: TGLenum; transform: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribPointerNV = procedure(index: TGLuint; fsize: TGLint; _type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1dNV = procedure(index: TGLuint; x: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1dvNV = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1fNV = procedure(index: TGLuint; x: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1fvNV = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1sNV = procedure(index: TGLuint; x: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib1svNV = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2dNV = procedure(index: TGLuint; x: TGLdouble; y: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2dvNV = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2fNV = procedure(index: TGLuint; x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2fvNV = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2sNV = procedure(index: TGLuint; x: TGLshort; y: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib2svNV = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3dNV = procedure(index: TGLuint; x: TGLdouble; y: TGLdouble; z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3dvNV = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3fNV = procedure(index: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3fvNV = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3sNV = procedure(index: TGLuint; x: TGLshort; y: TGLshort; z: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib3svNV = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4dNV = procedure(index: TGLuint; x: TGLdouble; y: TGLdouble; z: TGLdouble; w: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4dvNV = procedure(index: TGLuint; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4fNV = procedure(index: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4fvNV = procedure(index: TGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4sNV = procedure(index: TGLuint; x: TGLshort; y: TGLshort; z: TGLshort; w: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4svNV = procedure(index: TGLuint; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4ubNV = procedure(index: TGLuint; x: TGLubyte; y: TGLubyte; z: TGLubyte; w: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttrib4ubvNV = procedure(index: TGLuint; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs1dvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs1fvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs1svNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs2dvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs2fvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs2svNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs3dvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs3fvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs3svNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs4dvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs4fvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs4svNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglVertexAttribs4ubvNV = procedure(index: TGLuint; count: TGLsizei; const v: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_depth_buffer_float - TglDepthRangedNV = procedure(n: TGLdouble; f: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglClearDepthdNV = procedure(d: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDepthBoundsdNV = procedure(zmin: TGLdouble; zmax: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_framebuffer_multisample_coverage - TglRenderbufferStorageMultsampleCoverageNV = procedure(target: TGLenum; coverageSamples: TGLsizei; colorSamples: TGLsizei; internalformat: TGLenum; width: TGLsizei; height: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_geometry_program4 - TglProgramVertexLimitNV = procedure(target: TGLenum; limit: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_gpu_program4 - TglProgramLocalParameterI4iNV = procedure(target: TGLenum; index: TGLuint; x: TGLint; y: TGLint; z: TGLint; w: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameterI4ivNV = procedure(target: TGLenum; index: TGLuint; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParametersI4ivNV = procedure(target: TGLenum; index: TGLuint; count: TGLsizei; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameterI4uiNV = procedure(target: TGLenum; index: TGLuint; x: TGLuint; y: TGLuint; z: TGLuint; w: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParameterI4uivNV = procedure(target: TGLenum; index: TGLuint; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramLocalParametersI4uivNV = procedure(target: TGLenum; index: TGLuint; count: TGLsizei; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameterI4iNV = procedure(target: TGLenum; index: TGLuint; x: TGLint; y: TGLint; z: TGLint; w: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameterI4ivNV = procedure(target: TGLenum; index: TGLuint; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParametersI4ivNV = procedure(target: TGLenum; index: TGLuint; count: TGLsizei; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameterI4uiNV = procedure(target: TGLenum; index: TGLuint; x: TGLuint; y: TGLuint; z: TGLuint; w: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParameterI4uivNV = procedure(target: TGLenum; index: TGLuint; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramEnvParametersI4uivNV = procedure(target: TGLenum; index: TGLuint; count: TGLsizei; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramLocalParameterIivNV = procedure(target: TGLenum; index: TGLuint; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramLocalParameterIuivNV = procedure(target: TGLenum; index: TGLuint; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramEnvParameterIivNV = procedure(target: TGLenum; index: TGLuint; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetProgramEnvParameterIuivNV = procedure(target: TGLenum; index: TGLuint; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_parameter_buffer_object - TglProgramBufferParametersfvNV = procedure(target: TGLenum; buffer: TGLuint; index: TGLuint; count: TGLsizei; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramBufferParametersIivNV = procedure(target: TGLenum; buffer: TGLuint; index: TGLuint; count: TGLsizei; const params: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglProgramBufferParametersIuivNV = procedure(target: TGLenum; buffer: TGLuint; index: TGLuint; count: TGLuint; const params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_transform_feedback - TglBeginTransformFeedbackNV = procedure(primitiveMode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndTransformFeedbackNV = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTransformFeedbackAttribsNV = procedure(count: TGLsizei; const attribs: TGLint; bufferMode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferRangeNV = procedure(target: GLenum; index: GLuint; buffer: GLuint; offset: GLint; size: GLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferOffsetNV = procedure(target: GLenum; index: GLuint; buffer: GLuint; offset: GLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglBindBufferBaseNV = procedure(target: GLenum; index: GLuint; buffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTransformFeedbackVaryingsNV = procedure(program_: TGLuint; count: TGLsizei; const varyings: PPGLchar; bufferMode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglActiveVaryingNV = procedure(program_: TGLuint; const name: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVaryingLocationNV = function(program_: TGLuint; const name: PGLchar): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetActiveVaryingNV = procedure(program_: TGLuint; index: TGLuint; bufSize: TGLsizei; length: PGLsizei; size: PGLsizei; _type: PGLenum; name: PGLchar); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetTransformFeedbackVaryingNV = procedure(program_: TGLuint; index: TGLuint; location: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_conditional_render - TglBeginConditionalRenderNV = procedure(id: GLuint; mode: GLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglEndConditionalRenderNV = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_present_video - TglPresentFrameKeyedNV = procedure(video_slot: GLuint; minPresentTime: GLuint64EXT; beginPresentTimeId: GLuint; presentDuratioId: GLuint; type_: GLenum; target0: GLenum; fill0: GLuint; key0: GLuint; target1: GLenum; fill1: GLuint; key1: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPresentFrameDualFillNV = procedure(video_slot: GLuint; minPresentTime: GLuint64EXT; beginPresentTimeId: GLuint; presentDurationId: GLuint; type_: GLenum; target0: GLenum; fill0: GLuint; target1: GLenum; fill1: GLuint; target2: GLenum; fill2: GLuint; target3: GLenum; fill3: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVideoivNV = procedure(video_slot: GLuint; pname: GLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVideouivNV = procedure(video_slot: GLuint; pname: GLenum; params: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVideoi64vNV = procedure(video_slot: GLuint; pname: GLenum; params: PGLint64EXT); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetVideoui64vNV = procedure(video_slot: GLuint; pname: GLenum; params: PGLuint64EXT); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} -// TglVideoParameterivNV = procedure(video_slot: GLuint; pname: GLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_explicit_multisample - TglGetMultisamplefvNV = procedure (pname: GLenum; index: GLuint; val: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSampleMaskIndexedNV = procedure (index: GLuint; mask: GLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexRenderbufferNV = procedure (target: GLenum; renderbuffer: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_NV_transform_feedback2 - TglBindTransformFeedbackNV = procedure(target: GLenum; id: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteTransformFeedbacksNV = procedure(n: GLsizei; ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenTransformFeedbacksNV = procedure(n: GLsizei; ids: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsTransformFeedbackNV = function (id: GLuint): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPauseTransformFeedbackNV = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglResumeTransformFeedbackNV = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDrawTransformFeedbackNV = procedure(mode: GLenum; id: GLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_PGI_misc_hints - TglHintPGI = procedure(target: TGLenum; mode: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_detail_texture - TglDetailTexFuncSGIS = procedure(target: TGLenum; n: TGLsizei; const points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetDetailTexFuncSGIS = procedure(target: TGLenum; points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_fog_function - TglFogFuncSGIS = procedure(n: TGLsizei; const points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFogFuncSGIS = procedure(points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_multisample - TglSampleMaskSGIS = procedure(value: TGLclampf; invert: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSamplePatternSGIS = procedure(pattern: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_pixel_texture - TglPixelTexGenParameteriSGIS = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTexGenParameterivSGIS = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTexGenParameterfSGIS = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPixelTexGenParameterfvSGIS = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPixelTexGenParameterivSGIS = procedure(pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetPixelTexGenParameterfvSGIS = procedure(pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_point_parameters - TglPointParameterfSGIS = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPointParameterfvSGIS = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_sharpen_texture - TglSharpenTexFuncSGIS = procedure(target: TGLenum; n: TGLsizei; const points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetSharpenTexFuncSGIS = procedure(target: TGLenum; points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_texture4D - TglTexImage4DSGIS = procedure(target: TGLenum; level: TGLint; internalformat: TGLenum; width: TGLsizei; height: TGLsizei; depth: TGLsizei; size4d: TGLsizei; border: TGLint; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexSubImage4DSGIS = procedure(target: TGLenum; level: TGLint; xoffset: TGLint; yoffset: TGLint; zoffset: TGLint; woffset: TGLint; width: TGLsizei; height: TGLsizei; depth: TGLsizei; size4d: TGLsizei; format: TGLenum; _type: TGLenum; const pixels: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_texture_color_mask - TglTextureColorMaskSGIS = procedure(red: TGLboolean; green: TGLboolean; blue: TGLboolean; alpha: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIS_texture_filter4 - TglGetTexFilterFuncSGIS = procedure(target: TGLenum; filter: TGLenum; weights: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexFilterFuncSGIS = procedure(target: TGLenum; filter: TGLenum; n: TGLsizei; const weights: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_async - TglAsyncMarkerSGIX = procedure(marker: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFinishAsyncSGIX = function(markerp: PGLuint): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPollAsyncSGIX = function(markerp: PGLuint): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGenAsyncMarkersSGIX = function(range: TGLsizei): TGLuint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeleteAsyncMarkersSGIX = procedure(marker: TGLuint; range: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglIsAsyncMarkerSGIX = function(marker: TGLuint): TGLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_flush_raster - TglFlushRasterSGIX = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_fragment_lighting - TglFragmentColorMaterialSGIX = procedure(face: TGLenum; mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightfSGIX = procedure(light: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightfvSGIX = procedure(light: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightiSGIX = procedure(light: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightivSGIX = procedure(light: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightModelfSGIX = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightModelfvSGIX = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightModeliSGIX = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentLightModelivSGIX = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentMaterialfSGIX = procedure(face: TGLenum; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentMaterialfvSGIX = procedure(face: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentMaterialiSGIX = procedure(face: TGLenum; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglFragmentMaterialivSGIX = procedure(face: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFragmentLightfvSGIX = procedure(light: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFragmentLightivSGIX = procedure(light: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFragmentMaterialfvSGIX = procedure(face: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetFragmentMaterialivSGIX = procedure(face: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLightEnviSGIX = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_framezoom - TglFrameZoomSGIX = procedure(factor: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_igloo_interface - TglIglooInterfaceSGIX = procedure(pname: TGLenum; const params: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_instruments - TglGetInstrumentsSGIX = function(): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglInstrumentsBufferSGIX = procedure(size: TGLsizei; buffer: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglPollInstrumentsSGIX = function(marker_p: PGLint): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReadInstrumentsSGIX = procedure(marker: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStartInstrumentsSGIX = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglStopInstrumentsSGIX = procedure(marker: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_list_priority - TglGetListParameterfvSGIX = procedure(list: TGLuint; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetListParameterivSGIX = procedure(list: TGLuint; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglListParameterfSGIX = procedure(list: TGLuint; pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglListParameterfvSGIX = procedure(list: TGLuint; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglListParameteriSGIX = procedure(list: TGLuint; pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglListParameterivSGIX = procedure(list: TGLuint; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_pixel_texture - TglPixelTexGenSGIX = procedure(mode: TGLenum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_polynomial_ffd - TglDeformationMap3dSGIX = procedure(target: TGLenum; u1: TGLdouble; u2: TGLdouble; ustride: TGLint; uorder: TGLint; v1: TGLdouble; v2: TGLdouble; vstride: TGLint; vorder: TGLint; w1: TGLdouble; w2: TGLdouble; wstride: TGLint; worder: TGLint; const points: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeformationMap3fSGIX = procedure(target: TGLenum; u1: TGLfloat; u2: TGLfloat; ustride: TGLint; uorder: TGLint; v1: TGLfloat; v2: TGLfloat; vstride: TGLint; vorder: TGLint; w1: TGLfloat; w2: TGLfloat; wstride: TGLint; worder: TGLint; const points: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglDeformSGIX = procedure(mask: TGLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglLoadIdentityDeformationMapSGIX = procedure(mask: TGLbitfield); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_reference_plane - TglReferencePlaneSGIX = procedure(const equation: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_sprite - TglSpriteParameterfSGIX = procedure(pname: TGLenum; param: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSpriteParameterfvSGIX = procedure(pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSpriteParameteriSGIX = procedure(pname: TGLenum; param: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglSpriteParameterivSGIX = procedure(pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGIX_tag_sample_buffer - TglTagSampleBufferSGIX = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SGI_color_table - TglColorTableSGI = procedure(target: TGLenum; internalformat: TGLenum; width: TGLsizei; format: TGLenum; _type: TGLenum; const table: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorTableParameterfvSGI = procedure(target: TGLenum; pname: TGLenum; const params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColorTableParameterivSGI = procedure(target: TGLenum; pname: TGLenum; const params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglCopyColorTableSGI = procedure(target: TGLenum; internalformat: TGLenum; x: TGLint; y: TGLint; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableSGI = procedure(target: TGLenum; format: TGLenum; _type: TGLenum; table: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableParameterfvSGI = procedure(target: TGLenum; pname: TGLenum; params: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGetColorTableParameterivSGI = procedure(target: TGLenum; pname: TGLenum; params: PGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SUNX_constant_data - TglFinishTextureSUNX = procedure(); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SUN_global_alpha - TglGlobalAlphaFactorbSUN = procedure(factor: TGLbyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGlobalAlphaFactorsSUN = procedure(factor: TGLshort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGlobalAlphaFactoriSUN = procedure(factor: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGlobalAlphaFactorfSUN = procedure(factor: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGlobalAlphaFactordSUN = procedure(factor: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGlobalAlphaFactorubSUN = procedure(factor: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGlobalAlphaFactorusSUN = procedure(factor: TGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglGlobalAlphaFactoruiSUN = procedure(factor: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SUN_mesh_array - TglDrawMeshArraysSUN = procedure(mode: TGLenum; first: TGLint; count: TGLsizei; width: TGLsizei); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SUN_triangle_list - TglReplacementCodeuiSUN = procedure(code: TGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeusSUN = procedure(code: TGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeubSUN = procedure(code: TGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuivSUN = procedure(const code: PGLuint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeusvSUN = procedure(const code: PGLushort); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeubvSUN = procedure(const code: PGLubyte); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodePointerSUN = procedure(_type: TGLenum; stride: TGLsizei; const _pointer: PGLvoid); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // GL_SUN_vertex - TglColor4ubVertex2fSUN = procedure(r: TGLubyte; g: TGLubyte; b: TGLubyte; a: TGLubyte; x: TGLfloat; y: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4ubVertex2fvSUN = procedure(const c: PGLubyte; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4ubVertex3fSUN = procedure(r: TGLubyte; g: TGLubyte; b: TGLubyte; a: TGLubyte; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4ubVertex3fvSUN = procedure(const c: PGLubyte; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3fVertex3fSUN = procedure(r: TGLfloat; g: TGLfloat; b: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor3fVertex3fvSUN = procedure(const c: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3fVertex3fSUN = procedure(nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglNormal3fVertex3fvSUN = procedure(const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4fNormal3fVertex3fSUN = procedure(r: TGLfloat; g: TGLfloat; b: TGLfloat; a: TGLfloat; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglColor4fNormal3fVertex3fvSUN = procedure(const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fVertex3fSUN = procedure(s: TGLfloat; t: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fVertex3fvSUN = procedure(const tc: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4fVertex4fSUN = procedure(s: TGLfloat; t: TGLfloat; p: TGLfloat; q: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4fVertex4fvSUN = procedure(const tc: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fColor4ubVertex3fSUN = procedure(s: TGLfloat; t: TGLfloat; r: TGLubyte; g: TGLubyte; b: TGLubyte; a: TGLubyte; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fColor4ubVertex3fvSUN = procedure(const tc: PGLfloat; const c: PGLubyte; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fColor3fVertex3fSUN = procedure(s: TGLfloat; t: TGLfloat; r: TGLfloat; g: TGLfloat; b: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fColor3fVertex3fvSUN = procedure(const tc: PGLfloat; const c: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fNormal3fVertex3fSUN = procedure(s: TGLfloat; t: TGLfloat; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fNormal3fVertex3fvSUN = procedure(const tc: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fColor4fNormal3fVertex3fSUN = procedure(s: TGLfloat; t: TGLfloat; r: TGLfloat; g: TGLfloat; b: TGLfloat; a: TGLfloat; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord2fColor4fNormal3fVertex3fvSUN = procedure(const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4fColor4fNormal3fVertex4fSUN = procedure(s: TGLfloat; t: TGLfloat; p: TGLfloat; q: TGLfloat; r: TGLfloat; g: TGLfloat; b: TGLfloat; a: TGLfloat; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat; w: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglTexCoord4fColor4fNormal3fVertex4fvSUN = procedure(const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiVertex3fSUN = procedure(rc: TGLuint; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiVertex3fvSUN = procedure(const rc: PGLuint; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiColor4ubVertex3fSUN = procedure(rc: TGLuint; r: TGLubyte; g: TGLubyte; b: TGLubyte; a: TGLubyte; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiColor4ubVertex3fvSUN = procedure(const rc: PGLuint; const c: PGLubyte; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiColor3fVertex3fSUN = procedure(rc: TGLuint; r: TGLfloat; g: TGLfloat; b: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiColor3fVertex3fvSUN = procedure(const rc: PGLuint; const c: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiNormal3fVertex3fSUN = procedure(rc: TGLuint; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiNormal3fVertex3fvSUN = procedure(const rc: PGLuint; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiColor4fNormal3fVertex3fSUN = procedure(rc: TGLuint; r: TGLfloat; g: TGLfloat; b: TGLfloat; a: TGLfloat; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiColor4fNormal3fVertex3fvSUN = procedure(const rc: PGLuint; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiTexCoord2fVertex3fSUN = procedure(rc: TGLuint; s: TGLfloat; t: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiTexCoord2fVertex3fvSUN = procedure(const rc: PGLuint; const tc: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiTexCoord2fNormal3fVertex3fSUN = procedure(rc: TGLuint; s: TGLfloat; t: TGLfloat; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN = procedure(const rc: PGLuint; const tc: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN = procedure(rc: TGLuint; s: TGLfloat; t: TGLfloat; r: TGLfloat; g: TGLfloat; b: TGLfloat; a: TGLfloat; nx: TGLfloat; ny: TGLfloat; nz: TGLfloat; x: TGLfloat; y: TGLfloat; z: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TglReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN = procedure(const rc: PGLuint; const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - - // window support functions -{$IFDEF DGL_WIN} - TwglGetProcAddress = function(ProcName: PAnsiChar): Pointer; stdcall; - TwglCopyContext = function(p1: HGLRC; p2: HGLRC; p3: Cardinal): BOOL; stdcall; - TwglCreateContext = function(DC: HDC): HGLRC; stdcall; - TwglCreateLayerContext = function(p1: HDC; p2: Integer): HGLRC; stdcall; - TwglDeleteContext = function(p1: HGLRC): BOOL; stdcall; - TwglDescribeLayerPlane = function(p1: HDC; p2, p3: Integer; p4: Cardinal; p5: PLayerPlaneDescriptor): BOOL; stdcall; - TwglGetCurrentContext = function: HGLRC; stdcall; - TwglGetCurrentDC = function: HDC; stdcall; - TwglGetLayerPaletteEntries = function(p1: HDC; p2, p3, p4: Integer; var pcr): Integer; stdcall; - TwglMakeCurrent = function(DC: HDC; p2: HGLRC): BOOL; stdcall; - TwglRealizeLayerPalette = function(p1: HDC; p2: Integer; p3: BOOL): BOOL; stdcall; - TwglSetLayerPaletteEntries = function(p1: HDC; p2, p3, p4: Integer; var pcr): Integer; stdcall; - TwglShareLists = function(p1, p2: HGLRC): BOOL; stdcall; - TwglSwapLayerBuffers = function(p1: HDC; p2: Cardinal): BOOL; stdcall; - TwglSwapMultipleBuffers = function(p1: UINT; const p2: PWGLSWAP): DWORD; stdcall; - TwglUseFontBitmapsA = function(DC: HDC; p2, p3, p4: DWORD): BOOL; stdcall; - TwglUseFontBitmapsW = function(DC: HDC; p2, p3, p4: DWORD): BOOL; stdcall; - TwglUseFontBitmaps = function(DC: HDC; p2, p3, p4: DWORD): BOOL; stdcall; - - TwglUseFontOutlinesA = function(p1: HDC; p2, p3, p4: DWORD; p5, p6: Single; p7: Integer; p8: PGlyphMetricsFloat): BOOL; stdcall; - TwglUseFontOutlinesW = function(p1: HDC; p2, p3, p4: DWORD; p5, p6: Single; p7: Integer; p8: PGlyphMetricsFloat): BOOL; stdcall; - TwglUseFontOutlines = function(p1: HDC; p2, p3, p4: DWORD; p5, p6: Single; p7: Integer; p8: PGlyphMetricsFloat): BOOL; stdcall; - - - // WGL_ARB_buffer_region - TwglCreateBufferRegionARB = function(hDC: HDC; iLayerPlane: TGLint; uType: TGLuint): THandle; stdcall; - TwglDeleteBufferRegionARB = procedure(hRegion: THandle); stdcall; - TwglSaveBufferRegionARB = function(hRegion: THandle; x: TGLint; y: TGLint; width: TGLint; height: TGLint): Boolean; stdcall; - TwglRestoreBufferRegionARB = function(hRegion: THandle; x: TGLint; y: TGLint; width: TGLint; height: TGLint; xSrc: TGLint; ySrc: TGLint): Boolean; stdcall; - - // WGL_ARB_extensions_string - TwglGetExtensionsStringARB = function(hdc: HDC): PAnsiChar; stdcall; - - // WGL_ARB_make_current_read - TwglMakeContextCurrentARB = function(hDrawDC: HDC; hReadDC: HDC; hglrc: HGLRC): Boolean; stdcall; - TwglGetCurrentReadDCARB = function(): HDC; stdcall; - - // WGL_ARB_pbuffer - TwglCreatePbufferARB = function(hDC: HDC; iPixelFormat: TGLint; iWidth: TGLint; iHeight: TGLint; const piAttribList: PGLint): HPBUFFERARB; stdcall; - TwglGetPbufferDCARB = function(hPbuffer: HPBUFFERARB): HDC; stdcall; - TwglReleasePbufferDCARB = function(hPbuffer: HPBUFFERARB; hDC: HDC): TGLint; stdcall; - TwglDestroyPbufferARB = function(hPbuffer: HPBUFFERARB): Boolean; stdcall; - TwglQueryPbufferARB = function(hPbuffer: HPBUFFERARB; iAttribute: TGLint; piValue: PGLint): Boolean; stdcall; - - // WGL_ARB_pixel_format - TwglGetPixelFormatAttribivARB = function(hdc: HDC; iPixelFormat: TGLint; iLayerPlane: TGLint; nAttributes: TGLuint; const piAttributes: PGLint; piValues: PGLint): Boolean; stdcall; - TwglGetPixelFormatAttribfvARB = function(hdc: HDC; iPixelFormat: TGLint; iLayerPlane: TGLint; nAttributes: TGLuint; const piAttributes: PGLint; pfValues: PGLfloat): Boolean; stdcall; - TwglChoosePixelFormatARB = function(hdc: HDC; const piAttribIList: PGLint; const pfAttribFList: PGLfloat; nMaxFormats: TGLuint; piFormats: PGLint; nNumFormats: PGLuint): BOOL; stdcall; - - // WGL_ARB_color_buffer_float - TwglClampColorARB = procedure(target: TGLenum; clamp: TGLenum); stdcall; - - // WGL_ARB_render_texture - TwglBindTexImageARB = function(hPbuffer: HPBUFFERARB; iBuffer: TGLint): Boolean; stdcall; - TwglReleaseTexImageARB = function(hPbuffer: HPBUFFERARB; iBuffer: TGLint): Boolean; stdcall; - TwglSetPbufferAttribARB = function(hPbuffer: HPBUFFERARB; const piAttribList: PGLint): Boolean; stdcall; - - // WGL_ARB_create_context - TwglCreateContextAttribsARB = function(hDC: HDC; hShareContext: HGLRC; const attribList: PGLint): HGLRC; stdcall; - - // WGL_AMD_gpu_association - TwglGetGPUIDsAMD = function(maxCount: Cardinal; ids: PCardinal): Cardinal; stdcall; - TwglGetGPUInfoAMD = function(id: Cardinal; property_: Integer; dataType: GLenum; size: Cardinal; data: Pointer): Integer; stdcall; - TwglGetContextGPUIDAMD = function(hglrc: HGLRC): Cardinal; stdcall; - TwglCreateAssociatedContextAMD = function(id: Cardinal): HGLRC; stdcall; - TwglCreateAssociatedContextAttribsAMD = function(id: Cardinal; hShareContext: HGLRC; const attribList: PInteger): HGLRC; stdcall; - TwglDeleteAssociatedContextAMD = function(hglrc: HGLRC): Boolean; stdcall; - TwglMakeAssociatedContextCurrentAMD = function(hglrc: HGLRC): Boolean; stdcall; - TwglGetCurrentAssociatedContextAMD = function(): HGLRC; stdcall; - TwglBlitContextFramebufferAMD = procedure(dstCtx: HGLRC; srcX0: GLint; srcY0: GLint; srcX1: GLint; srcY1: GLint; dstX0: GLint; dstY0: GLint; dstX1: GLint; dstY1: GLint; mask: GLbitfield; filter: GLenum); stdcall; - - // WGL_EXT_display_color_table - TwglCreateDisplayColorTableEXT = function(id: TGLushort): TGLboolean; stdcall; - TwglLoadDisplayColorTableEXT = function(const table: PGLushort; length: TGLuint): TGLboolean; stdcall; - TwglBindDisplayColorTableEXT = function(id: TGLushort): TGLboolean; stdcall; - TwglDestroyDisplayColorTableEXT = procedure(id: TGLushort); stdcall; - - // WGL_EXT_extensions_string - TwglGetExtensionsStringEXT = function(): PAnsiChar; stdcall; - - // WGL_EXT_make_current_read - TwglMakeContextCurrentEXT = function(hDrawDC: HDC; hReadDC: HDC; hglrc: HGLRC): Boolean; stdcall; - TwglGetCurrentReadDCEXT = function(): HDC; stdcall; - - // WGL_EXT_pbuffer - TwglCreatePbufferEXT = function(hDC: HDC; iPixelFormat: TGLint; iWidth: TGLint; iHeight: TGLint; const piAttribList: PGLint): HPBUFFEREXT; stdcall; - TwglGetPbufferDCEXT = function(hPbuffer: HPBUFFEREXT): HDC; stdcall; - TwglReleasePbufferDCEXT = function(hPbuffer: HPBUFFEREXT; hDC: HDC): TGLint; stdcall; - TwglDestroyPbufferEXT = function(hPbuffer: HPBUFFEREXT): Boolean; stdcall; - TwglQueryPbufferEXT = function(hPbuffer: HPBUFFEREXT; iAttribute: TGLint; piValue: PGLint): Boolean; stdcall; - - // WGL_EXT_pixel_format - TwglGetPixelFormatAttribivEXT = function(hdc: HDC; iPixelFormat: TGLint; iLayerPlane: TGLint; nAttributes: TGLuint; piAttributes: PGLint; piValues: PGLint): Boolean; stdcall; - TwglGetPixelFormatAttribfvEXT = function(hdc: HDC; iPixelFormat: TGLint; iLayerPlane: TGLint; nAttributes: TGLuint; piAttributes: PGLint; pfValues: PGLfloat): Boolean; stdcall; - TwglChoosePixelFormatEXT = function(hdc: HDC; const piAttribIList: PGLint; const pfAttribFList: PGLfloat; nMaxFormats: TGLuint; piFormats: PGLint; nNumFormats: PGLuint): Boolean; stdcall; - - // WGL_EXT_swap_control - TwglSwapIntervalEXT = function(interval: TGLint): Boolean; stdcall; - TwglGetSwapIntervalEXT = function(): TGLint; stdcall; - - // WGL_I3D_digital_video_control - TwglGetDigitalVideoParametersI3D = function(hDC: HDC; iAttribute: TGLint; piValue: PGLint): Boolean; stdcall; - TwglSetDigitalVideoParametersI3D = function(hDC: HDC; iAttribute: TGLint; const piValue: PGLint): Boolean; stdcall; - - // WGL_I3D_gamma - TwglGetGammaTableParametersI3D = function(hDC: HDC; iAttribute: TGLint; piValue: PGLint): Boolean; stdcall; - TwglSetGammaTableParametersI3D = function(hDC: HDC; iAttribute: TGLint; const piValue: PGLint): Boolean; stdcall; - TwglGetGammaTableI3D = function(hDC: HDC; iEntries: TGLint; puRed: PGLushort; puGreen: PGLushort; puBlue: PGLushort): Boolean; stdcall; - TwglSetGammaTableI3D = function(hDC: HDC; iEntries: TGLint; const puRed: PGLushort; const puGreen: PGLushort; const puBlue: PGLushort): Boolean; stdcall; - - // WGL_I3D_genlock - TwglEnableGenlockI3D = function(hDC: HDC): Boolean; stdcall; - TwglDisableGenlockI3D = function(hDC: HDC): Boolean; stdcall; - TwglIsEnabledGenlockI3D = function(hDC: HDC; pFlag: Boolean): Boolean; stdcall; - TwglGenlockSourceI3D = function(hDC: HDC; uSource: TGLuint): Boolean; stdcall; - TwglGetGenlockSourceI3D = function(hDC: HDC; uSource: PGLuint): Boolean; stdcall; - TwglGenlockSourceEdgeI3D = function(hDC: HDC; uEdge: TGLuint): Boolean; stdcall; - TwglGetGenlockSourceEdgeI3D = function(hDC: HDC; uEdge: PGLuint): Boolean; stdcall; - TwglGenlockSampleRateI3D = function(hDC: HDC; uRate: TGLuint): Boolean; stdcall; - TwglGetGenlockSampleRateI3D = function(hDC: HDC; uRate: PGLuint): Boolean; stdcall; - TwglGenlockSourceDelayI3D = function(hDC: HDC; uDelay: TGLuint): Boolean; stdcall; - TwglGetGenlockSourceDelayI3D = function(hDC: HDC; uDelay: PGLuint): Boolean; stdcall; - TwglQueryGenlockMaxSourceDelayI3D = function(hDC: HDC; uMaxLineDelay: PGLuint; uMaxPixelDelay: PGLuint): Boolean; stdcall; - - // WGL_I3D_image_buffer - TwglCreateImageBufferI3D = function(hDC: HDC; dwSize: TGLuint; uFlags: TGLuint): TGLvoid; stdcall; - TwglDestroyImageBufferI3D = function(hDC: HDC; pAddress: TGLvoid): Boolean; stdcall; - TwglAssociateImageBufferEventsI3D = function(hDC: HDC; const pEvent: THandle; const pAddress: PGLvoid; const pSize: PGLuint; count: TGLuint): Boolean; stdcall; - TwglReleaseImageBufferEventsI3D = function(hDC: HDC; const pAddress: PGLvoid; count: TGLuint): Boolean; stdcall; - - // WGL_I3D_swap_frame_lock - TwglEnableFrameLockI3D = function(): Boolean; stdcall; - TwglDisableFrameLockI3D = function(): Boolean; stdcall; - TwglIsEnabledFrameLockI3D = function(pFlag: Boolean): Boolean; stdcall; - TwglQueryFrameLockMasterI3D = function(pFlag: Boolean): Boolean; stdcall; - - // WGL_I3D_swap_frame_usage - TwglGetFrameUsageI3D = function(pUsage: PGLfloat): Boolean; stdcall; - TwglBeginFrameTrackingI3D = function(): Boolean; stdcall; - TwglEndFrameTrackingI3D = function(): Boolean; stdcall; - TwglQueryFrameTrackingI3D = function(pFrameCount: PGLuint; pMissedFrames: PGLuint; pLastMissedUsage: PGLfloat): Boolean; stdcall; - - // WGL_NV_vertex_array_range - TwglAllocateMemoryNV = procedure(size: TGLsizei; readfreq: TGLfloat; writefreq: TGLfloat; priority: TGLfloat); stdcall; - TwglFreeMemoryNV = procedure(_pointer: Pointer); stdcall; - - // WGL_NV_present_video - TwglEnumerateVideoDevicesNV = function(hdc: HDC; phDeviceList: PHVIDEOOUTPUTDEVICENV): Integer; stdcall; - TwglBindVideoDeviceNV = function(hd: HDC; uVideoSlot: Cardinal; hVideoDevice: HVIDEOOUTPUTDEVICENV; piAttribList: PInteger): Boolean; stdcall; - TwglQueryCurrentContextNV = function(iAttribute: Integer; piValue: PInteger): Boolean; stdcall; - - // WGL_NV_video_out - TwglGetVideoDeviceNV = function(hDC: HDC; numDevices: Integer; hVideoDevice: PHPVIDEODEV): Boolean; stdcall; - TwglReleaseVideoDeviceNV = function(hVideoDevice: HPVIDEODEV): Boolean; stdcall; - TwglBindVideoImageNV = function(hVideoDevice: HPVIDEODEV; hPbuffer: HPBUFFERARB; iVideoBuffer: Integer): Boolean; stdcall; - TwglReleaseVideoImageNV = function(hPbuffer: HPBUFFERARB; iVideoBuffer: Integer): Boolean; stdcall; - TwglSendPbufferToVideoNV = function(hPbuffer: HPBUFFERARB; iBufferType: Integer; pulCounterPbuffer: PCardinal; bBlock: Boolean): Boolean; stdcall; - TwglGetVideoInfoNV = function(hpVideoDevice: HPVIDEODEV; pulCounterOutputPbuffer: PCardinal; pulCounterOutputVideo: PCardinal): Boolean; stdcall; - - // WGL_NV_swap_group - TwglJoinSwapGroupNV = function(hDC: HDC; group: GLuint): Boolean; stdcall; - TwglBindSwapBarrierNV = function(group: GLuint; barrier: GLuint): Boolean; stdcall; - TwglQuerySwapGroupNV = function(hDC: HDC; group: PGLuint; barrier: PGLuint): Boolean; stdcall; - TwglQueryMaxSwapGroupsNV = function(hDC: HDC; mxGroups: PGLuint; maxBarriers: PGLuint): Boolean; stdcall; - TwglQueryFrameCountNV = function(hDC: HDC; count: PGLuint): Boolean; stdcall; - TwglResetFrameCountNV = function(hDC: HDC): Boolean; stdcall; - - // WGL_NV_gpu_affinity - TwglEnumGpusNV = function(iGpuIndex: Cardinal; phGpu: PHGPUNV): Boolean; stdcall; - TwglEnumGpuDevicesNV = function(hGpu: HGPUNV; iDeviceIndex: Cardinal; lpGpuDevice: PGPU_DEVICE): Boolean; stdcall; - TwglCreateAffinityDCNV = function(const phGpuList: PHGPUNV): HDC; stdcall; - TwglEnumGpusFromAffinityDCNV = function(hAffinityDC: HDC; iGpuIndex: Cardinal; hGpu: PHGPUNV): Boolean; stdcall; - TwglDeleteDCNV = function(hDC: HDC): Boolean; stdcall; - - // WGL_OML_sync_control - TwglGetSyncValuesOML = function(hdc: HDC; ust: PGLint64; msc: PGLint64; sbc: PGLint64): Boolean; stdcall; - TwglGetMscRateOML = function(hdc: HDC; numerator: PGLint; denominator: PGLint): Boolean; stdcall; - TwglSwapBuffersMscOML = function(hdc: HDC; target_msc: TGLint64; divisor: TGLint64; remainder: TGLint64): TGLint64; stdcall; - TwglSwapLayerBuffersMscOML = function(hdc: HDC; fuPlanes: TGLint; target_msc: TGLint64; divisor: TGLint64; remainder: TGLint64): TGLint64; stdcall; - TwglWaitForMscOML = function(hdc: HDC; target_msc: TGLint64; divisor: TGLint64; remainder: TGLint64; ust: PGLint64; msc: PGLint64; sbc: PGLint64): Boolean; stdcall; - TwglWaitForSbcOML = function(hdc: HDC; target_sbc: TGLint64; ust: PGLint64; msc: PGLint64; sbc: PGLint64): Boolean; stdcall; - - // WGL_3DL_stereo_control - TwglSetStereoEmitterState3DL = function(hDC: HDC; uState: UINT): Boolean; stdcall; - - // WIN_draw_range_elements - TglDrawRangeElementsWIN = procedure(mode: TGLenum; start: TGLuint; _end: TGLuint; count: TGLsizei; _type: TGLenum; const indices: PGLvoid); stdcall; - - // WIN_swap_hint - TglAddSwapHintRectWIN = procedure(x: TGLint; y: TGLint; width: TGLsizei; height: TGLsizei); stdcall; -{$ENDIF} - -{$IFDEF DGL_LINUX} - TglXChooseVisual = function(dpy: PDisplay; screen: GLint; attribList: PGLint): PXVisualInfo; cdecl; - TglXCopyContext = procedure(dpy: PDisplay; src: GLXContext; dst: GLXContext; mask: GLuint); cdecl; - TglXCreateContext = function(dpy: PDisplay; vis: PXVisualInfo; shareList: GLXContext; direct: GLboolean): GLXContext; cdecl; - TglXCreateGLXPixmap = function(dpy: PDisplay; vis: PXVisualInfo; pixmap: Pixmap): GLXPixmap cdecl; - TglXDestroyContext = procedure(dpy: PDisplay; ctx: GLXContext); cdecl; - TglXDestroyGLXPixmap = procedure(dpy : PDisplay; pix: GLXPixmap); cdecl; - TglXGetConfig = function(dpy : PDisplay; vis: PXVisualInfo; attrib: GLint; value: PGLint): GLint; cdecl; - TglXGetCurrentContext = function: GLXContext cdecl; - TglXGetCurrentDrawable = function: GLXDrawable cdecl; - TglXIsDirect = function(dpy: PDisplay; ctx: GLXContext): glboolean; cdecl; - TglXMakeCurrent = function(dpy: PDisplay; drawable: GLXDrawable; ctx: GLXContext): GLboolean cdecl; - TglXQueryExtension = function(dpy: PDisplay; errorBase: PGLint; eventBase: PGLint): GLboolean; cdecl; - TglXQueryVersion = function(dpy: PDisplay; major: PGLint; minor: PGLint): GLboolean cdecl; - TglXSwapBuffers = procedure(dpy: PDisplay; drawable: GLXDrawable); cdecl; - TglXUseXFont = procedure(font: Font; first: GLint; count: GLint; listBase: GLint); cdecl; - TglXWaitGL = procedure; cdecl; - TglXWaitX = procedure; cdecl; - - TglXGetClientString = function(dpy: PDisplay; name: GLint): PGLchar; cdecl; - TglXQueryServerString = function(dpy: PDisplay; screen: GLint; name: GLint): PGLchar; cdecl; - TglXQueryExtensionsString = function(dpy: PDisplay; screen: GLint): PGLchar; cdecl; - - // GLX_VERSION_1_3 - TglXGetFBConfigs = function(dpy: PDisplay; screen: GLint; nelements: PGLint): GLXFBConfig; cdecl; - TglXChooseFBConfig = function(dpy: PDisplay; screen: GLint; attrib_list: PGLint; nelements: PGLint): GLXFBConfig; cdecl; - TglXGetFBConfigAttrib = function(dpy: PDisplay; config: GLXFBConfig; attribute: GLint; value: PGLint): glint; cdecl; - TglXGetVisualFromFBConfig = function(dpy: PDisplay; config: GLXFBConfig) : PXVisualInfo; - TglXCreateWindow = function(dpy: PDisplay; config: GLXFBConfig; win: Window; attrib_list: PGLint): GLXWindow; cdecl; - TglXDestroyWindow = procedure(dpy: PDisplay; win: GLXWindow); cdecl; - TglXCreatePixmap = function(dpy: PDisplay; config: GLXFBConfig; pixmap: Pixmap; attrib_list: PGLint): GLXPixmap; cdecl; - - TglXDestroyPixmap = procedure(dpy: PDisplay; pixmap: GLXPixmap); cdecl; - TglXCreatePbuffer = function(dpy: PDisplay; config: GLXFBConfig; attrib_list: PGLint): GLXPbuffer; cdecl; - TglXDestroyPbuffer = procedure(dpy: PDisplay; pbuf: GLXPbuffer); cdecl; - TglXQueryDrawable = procedure(dpy: PDisplay; draw: GLXDrawable; attribute: GLint; value: PGLuint); cdecl; - TglXCreateNewContext = function(dpy: PDisplay; config: GLXFBConfig; render_type: GLint; share_list: GLXContext; direct: GLboolean): GLXContext cdecl; - TglXMakeContextCurrent = function(display: PDisplay; draw: GLXDrawable; read_: GLXDrawable; ctx: GLXContext): GLboolean; cdecl; - TglXGetCurrentReadDrawable = function: GLXDrawable; cdecl; - TglXGetCurreentDisplay = function: PDisplay; - - TglXQueryContext = function(dpy: PDisplay; ctx: GLXContext; attribute: GLint; value: PGLint): GLint; cdecl; - TglXSelectEvent = procedure(dpy: PDisplay; draw: GLXDrawable; event_mask: GLuint); cdecl; - TglXGetSelectedEvent = procedure(dpy: PDisplay; draw: GLXDrawable; event_mask: PGLuint); cdecl; - - // GLX_VERSION_1_4 - TglXGetProcAddress = function(const name: PAnsiChar): pointer; cdecl; - - // GLX_ARB_get_proc_address - TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl; - - // GLX_ARB_create_context - TglXCreateContextAttribsARB = function(dpy: PDisplay; config: GLXFBConfig; share_context: GLXContext; direct: GLboolean; const attrib_list: PGLint): GLXContext; cdecl; - - // GLX_EXT_import_context - TglXGetCurrentDisplayEXT = function: PDisplay; cdecl; - TglXQueryContextInfoEXT = function(dpy: PDisplay; context: GLXContext; attribute: GLint; value: PGLint): GLint; cdecl; - TglXGetContextIDEXT = function(const context: GLXContext): GLXContextID; cdecl; - TglXImportContextEXT = function(dpy: PDisplay; contextID: GLXContextID): GLXContext; cdecl; - TglXFreeContextEXT = procedure(dpy: PDisplay; context: GLXContext); cdecl; - - // GLX_EXT_texture_from_pixmap - TglXBindTexImageEXT = procedure(dpy: PDisplay; drawable: GLXDrawable; buffer: GLint; const attrib_list: PGLint); cdecl; - TglXReleaseTexImageEXT = procedure(dpy: PDisplay; drawable: GLXDrawable; buffer: GLint); cdecl; -{$ENDIF} - - // GL utility functions and procedures - TgluErrorString = function(errCode: TGLEnum): PAnsiChar; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluGetString = function(name: TGLEnum): PAnsiChar; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluOrtho2D = procedure(left, right, bottom, top: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluPerspective = procedure(fovy, aspect, zNear, zFar: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluPickMatrix = procedure(x, y, width, height: TGLdouble; const viewport: TVector4i); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluLookAt = procedure(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluProject = function(objx, objy, obyz: GLdouble; modelMatrix: PGLdouble; projMatrix: PGLdouble; viewport: PGLint; var winx, winy, winz: GLDouble): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluUnProject = function(winx, winy, winz: GLdouble; modelMatrix: PGLdouble; projMatrix: PGLdouble; viewport: PGLint; var objx, objy, objz: GLdouble): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluScaleImage = function(format: TGLEnum; widthin, heightin: TGLint; typein: TGLEnum; datain: Pointer; widthout, heightout: TGLint; typeout: TGLEnum; const dataout: Pointer): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluBuild1DMipmaps = function(target: TGLEnum; components, width: TGLint; format, atype: TGLEnum; const data: Pointer): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluBuild2DMipmaps = function(target: TGLEnum; components, width, height: TGLint; format, atype: TGLEnum; const Data: Pointer): TGLint; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNewQuadric = function: PGLUquadric; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluDeleteQuadric = procedure(state: PGLUquadric); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluQuadricNormals = procedure(quadObject: PGLUquadric; normals: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluQuadricTexture = procedure(quadObject: PGLUquadric; textureCoords: TGLboolean); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluQuadricOrientation = procedure(quadObject: PGLUquadric; orientation: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluQuadricDrawStyle = procedure(quadObject: PGLUquadric; drawStyle: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluCylinder = procedure(quadObject: PGLUquadric; baseRadius, topRadius, height: TGLdouble; slices, stacks: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluDisk = procedure(quadObject: PGLUquadric; innerRadius, outerRadius: TGLdouble; slices, loops: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluPartialDisk = procedure(quadObject: PGLUquadric; innerRadius, outerRadius: TGLdouble; slices, loops: TGLint; startAngle, sweepAngle: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluSphere = procedure(quadObject: PGLUquadric; radius: TGLdouble; slices, stacks: TGLint); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluQuadricCallback = procedure(quadObject: PGLUquadric; which: TGLEnum; fn: TGLUQuadricErrorProc); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNewTess = function: PGLUtesselator; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluDeleteTess = procedure(tess: PGLUtesselator); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessBeginPolygon = procedure(tess: PGLUtesselator; polygon_data: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessBeginContour = procedure(tess: PGLUtesselator); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessVertex = procedure(tess: PGLUtesselator; const coords: TGLArrayd3; data: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessEndContour = procedure(tess: PGLUtesselator); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessEndPolygon = procedure(tess: PGLUtesselator); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessProperty = procedure(tess: PGLUtesselator; which: TGLEnum; value: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessNormal = procedure(tess: PGLUtesselator; x, y, z: TGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluTessCallback = procedure(tess: PGLUtesselator; which: TGLEnum; fn: Pointer); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluGetTessProperty = procedure(tess: PGLUtesselator; which: TGLEnum; value: PGLdouble); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNewNurbsRenderer = function: PGLUnurbs; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluDeleteNurbsRenderer = procedure(nobj: PGLUnurbs); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluBeginSurface = procedure(nobj: PGLUnurbs); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluBeginCurve = procedure(nobj: PGLUnurbs); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluEndCurve = procedure(nobj: PGLUnurbs); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluEndSurface = procedure(nobj: PGLUnurbs); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluBeginTrim = procedure(nobj: PGLUnurbs); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluEndTrim = procedure(nobj: PGLUnurbs); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluPwlCurve = procedure(nobj: PGLUnurbs; count: TGLint; points: PGLfloat; stride: TGLint; atype: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNurbsCurve = procedure(nobj: PGLUnurbs; nknots: TGLint; knot: PGLfloat; stride: TGLint; ctlarray: PGLfloat; order: TGLint; atype: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNurbsSurface = procedure(nobj: PGLUnurbs; sknot_count: TGLint; sknot: PGLfloat; tknot_count: TGLint; tknot: PGLfloat; s_stride, t_stride: TGLint; ctlarray: PGLfloat; sorder, torder: TGLint; atype: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluLoadSamplingMatrices = procedure(nobj: PGLUnurbs; const modelMatrix, projMatrix: TGLMatrixf4; const viewport: TVector4i); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNurbsProperty = procedure(nobj: PGLUnurbs; aproperty: TGLEnum; value: TGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluGetNurbsProperty = procedure(nobj: PGLUnurbs; aproperty: TGLEnum; value: PGLfloat); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNurbsCallback = procedure(nobj: PGLUnurbs; which: TGLEnum; fn: TGLUNurbsErrorProc); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluBeginPolygon = procedure(tess: PGLUtesselator); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluNextContour = procedure(tess: PGLUtesselator; atype: TGLEnum); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - TgluEndPolygon = procedure(tess: PGLUtesselator); {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - -var - // GL_VERSION_1_0 - glCullFace: TglCullFace; - glFrontFace: TglFrontFace; - glHint: TglHint; - glLineWidth: TglLineWidth; - glPointSize: TglPointSize; - glPolygonMode: TglPolygonMode; - glScissor: TglScissor; - glTexParameterf: TglTexParameterf; - glTexParameterfv: TglTexParameterfv; - glTexParameteri: TglTexParameteri; - glTexParameteriv: TglTexParameteriv; - glTexImage1D: TglTexImage1D; - glTexImage2D: TglTexImage2D; - glDrawBuffer: TglDrawBuffer; - glClear: TglClear; - glClearColor: TglClearColor; - glClearStencil: TglClearStencil; - glClearDepth: TglClearDepth; - glStencilMask: TglStencilMask; - glColorMask: TglColorMask; - glDepthMask: TglDepthMask; - glDisable: TglDisable; - glEnable: TglEnable; - glFinish: TglFinish; - glFlush: TglFlush; - glBlendFunc: TglBlendFunc; - glLogicOp: TglLogicOp; - glStencilFunc: TglStencilFunc; - glStencilOp: TglStencilOp; - glDepthFunc: TglDepthFunc; - glPixelStoref: TglPixelStoref; - glPixelStorei: TglPixelStorei; - glReadBuffer: TglReadBuffer; - glReadPixels: TglReadPixels; - glGetBooleanv: TglGetBooleanv; - glGetDoublev: TglGetDoublev; - glGetError: TglGetError; - glGetFloatv: TglGetFloatv; - glGetIntegerv: TglGetIntegerv; - glGetString: TglGetString; - glGetTexImage: TglGetTexImage; - glGetTexParameteriv: TglGetTexParameteriv; - glGetTexParameterfv: TglGetTexParameterfv; - glGetTexLevelParameterfv: TglGetTexLevelParameterfv; - glGetTexLevelParameteriv: TglGetTexLevelParameteriv; - glIsEnabled: TglIsEnabled; - glDepthRange: TglDepthRange; - glViewport: TglViewport; - - // GL_VERSION_1_1 - glDrawArrays: TglDrawArrays; - glDrawElements: TglDrawElements; - glGetPointerv: TglGetPointerv; - glPolygonOffset: TglPolygonOffset; - glCopyTexImage1D: TglCopyTexImage1D; - glCopyTexImage2D: TglCopyTexImage2D; - glCopyTexSubImage1D: TglCopyTexSubImage1D; - glCopyTexSubImage2D: TglCopyTexSubImage2D; - glTexSubImage1D: TglTexSubImage1D; - glTexSubImage2D: TglTexSubImage2D; - glBindTexture: TglBindTexture; - glDeleteTextures: TglDeleteTextures; - glGenTextures: TglGenTextures; -{$ifdef DGL_DEPRECATED} - glAccum: TglAccum; - glAlphaFunc: TglAlphaFunc; - glAreTexturesResident: TglAreTexturesResident; - glArrayElement: TglArrayElement; - glBegin: TglBegin; - glBitmap: TglBitmap; - glCallList: TglCallList; - glCallLists: TglCallLists; - glClearAccum: TglClearAccum; - glClearIndex: TglClearIndex; - glClipPlane: TglClipPlane; - glColor3b: TglColor3b; - glColor3bv: TglColor3bv; - glColor3d: TglColor3d; - glColor3dv: TglColor3dv; - glColor3f: TglColor3f; - glColor3fv: TglColor3fv; - glColor3i: TglColor3i; - glColor3iv: TglColor3iv; - glColor3s: TglColor3s; - glColor3sv: TglColor3sv; - glColor3ub: TglColor3ub; - glColor3ubv: TglColor3ubv; - glColor3ui: TglColor3ui; - glColor3uiv: TglColor3uiv; - glColor3us: TglColor3us; - glColor3usv: TglColor3usv; - glColor4b: TglColor4b; - glColor4bv: TglColor4bv; - glColor4d: TglColor4d; - glColor4dv: TglColor4dv; - glColor4f: TglColor4f; - glColor4fv: TglColor4fv; - glColor4i: TglColor4i; - glColor4iv: TglColor4iv; - glColor4s: TglColor4s; - glColor4sv: TglColor4sv; - glColor4ub: TglColor4ub; - glColor4ubv: TglColor4ubv; - glColor4ui: TglColor4ui; - glColor4uiv: TglColor4uiv; - glColor4us: TglColor4us; - glColor4usv: TglColor4usv; - glColorMaterial: TglColorMaterial; - glColorPointer: TglColorPointer; - glCopyPixels: TglCopyPixels; - glDeleteLists: TglDeleteLists; - glDisableClientState: TglDisableClientState; - glDrawPixels: TglDrawPixels; - glEdgeFlag: TglEdgeFlag; - glEdgeFlagPointer: TglEdgeFlagPointer; - glEdgeFlagv: TglEdgeFlagv; - glEnableClientState: TglEnableClientState; - glEnd: TglEnd; - glEndList: TglEndList; - glEvalCoord1d: TglEvalCoord1d; - glEvalCoord1dv: TglEvalCoord1dv; - glEvalCoord1f: TglEvalCoord1f; - glEvalCoord1fv: TglEvalCoord1fv; - glEvalCoord2d: TglEvalCoord2d; - glEvalCoord2dv: TglEvalCoord2dv; - glEvalCoord2f: TglEvalCoord2f; - glEvalCoord2fv: TglEvalCoord2fv; - glEvalMesh1: TglEvalMesh1; - glEvalMesh2: TglEvalMesh2; - glEvalPoint1: TglEvalPoint1; - glEvalPoint2: TglEvalPoint2; - glFeedbackBuffer: TglFeedbackBuffer; - glFogf: TglFogf; - glFogfv: TglFogfv; - glFogi: TglFogi; - glFogiv: TglFogiv; - glFrustum: TglFrustum; - glGenLists: TglGenLists; - glGetClipPlane: TglGetClipPlane; - glGetLightfv: TglGetLightfv; - glGetLightiv: TglGetLightiv; - glGetMapdv: TglGetMapdv; - glGetMapfv: TglGetMapfv; - glGetMapiv: TglGetMapiv; - glGetMaterialfv: TglGetMaterialfv; - glGetMaterialiv: TglGetMaterialiv; - glGetPixelMapfv: TglGetPixelMapfv; - glGetPixelMapuiv: TglGetPixelMapuiv; - glGetPixelMapusv: TglGetPixelMapusv; - glGetPolygonStipple: TglGetPolygonStipple; - glGetTexEnvfv: TglGetTexEnvfv; - glGetTexEnviv: TglGetTexEnviv; - glGetTexGendv: TglGetTexGendv; - glGetTexGenfv: TglGetTexGenfv; - glGetTexGeniv: TglGetTexGeniv; - glIndexMask: TglIndexMask; - glIndexPointer: TglIndexPointer; - glIndexd: TglIndexd; - glIndexdv: TglIndexdv; - glIndexf: TglIndexf; - glIndexfv: TglIndexfv; - glIndexi: TglIndexi; - glIndexiv: TglIndexiv; - glIndexs: TglIndexs; - glIndexsv: TglIndexsv; - glIndexub: TglIndexub; - glIndexubv: TglIndexubv; - glInitNames: TglInitNames; - glInterleavedArrays: TglInterleavedArrays; - glIsList: TglIsList; - glIsTexture: TglIsTexture; - glLightModelf: TglLightModelf; - glLightModelfv: TglLightModelfv; - glLightModeli: TglLightModeli; - glLightModeliv: TglLightModeliv; - glLightf: TglLightf; - glLightfv: TglLightfv; - glLighti: TglLighti; - glLightiv: TglLightiv; - glLineStipple: TglLineStipple; - glListBase: TglListBase; - glLoadIdentity: TglLoadIdentity; - glLoadMatrixd: TglLoadMatrixd; - glLoadMatrixf: TglLoadMatrixf; - glLoadName: TglLoadName; - glMap1d: TglMap1d; - glMap1f: TglMap1f; - glMap2d: TglMap2d; - glMap2f: TglMap2f; - glMapGrid1d: TglMapGrid1d; - glMapGrid1f: TglMapGrid1f; - glMapGrid2d: TglMapGrid2d; - glMapGrid2f: TglMapGrid2f; - glMaterialf: TglMaterialf; - glMaterialfv: TglMaterialfv; - glMateriali: TglMateriali; - glMaterialiv: TglMaterialiv; - glMatrixMode: TglMatrixMode; - glMultMatrixd: TglMultMatrixd; - glMultMatrixf: TglMultMatrixf; - glNewList: TglNewList; - glNormal3b: TglNormal3b; - glNormal3bv: TglNormal3bv; - glNormal3d: TglNormal3d; - glNormal3dv: TglNormal3dv; - glNormal3f: TglNormal3f; - glNormal3fv: TglNormal3fv; - glNormal3i: TglNormal3i; - glNormal3iv: TglNormal3iv; - glNormal3s: TglNormal3s; - glNormal3sv: TglNormal3sv; - glNormalPointer: TglNormalPointer; - glOrtho: TglOrtho; - glPassThrough: TglPassThrough; - glPixelMapfv: TglPixelMapfv; - glPixelMapuiv: TglPixelMapuiv; - glPixelMapusv: TglPixelMapusv; - glPixelTransferf: TglPixelTransferf; - glPixelTransferi: TglPixelTransferi; - glPixelZoom: TglPixelZoom; - glPolygonStipple: TglPolygonStipple; - glPopAttrib: TglPopAttrib; - glPopClientAttrib: TglPopClientAttrib; - glPopMatrix: TglPopMatrix; - glPopName: TglPopName; - glPrioritizeTextures: TglPrioritizeTextures; - glPushAttrib: TglPushAttrib; - glPushClientAttrib: TglPushClientAttrib; - glPushMatrix: TglPushMatrix; - glPushName: TglPushName; - glRasterPos2d: TglRasterPos2d; - glRasterPos2dv: TglRasterPos2dv; - glRasterPos2f: TglRasterPos2f; - glRasterPos2fv: TglRasterPos2fv; - glRasterPos2i: TglRasterPos2i; - glRasterPos2iv: TglRasterPos2iv; - glRasterPos2s: TglRasterPos2s; - glRasterPos2sv: TglRasterPos2sv; - glRasterPos3d: TglRasterPos3d; - glRasterPos3dv: TglRasterPos3dv; - glRasterPos3f: TglRasterPos3f; - glRasterPos3fv: TglRasterPos3fv; - glRasterPos3i: TglRasterPos3i; - glRasterPos3iv: TglRasterPos3iv; - glRasterPos3s: TglRasterPos3s; - glRasterPos3sv: TglRasterPos3sv; - glRasterPos4d: TglRasterPos4d; - glRasterPos4dv: TglRasterPos4dv; - glRasterPos4f: TglRasterPos4f; - glRasterPos4fv: TglRasterPos4fv; - glRasterPos4i: TglRasterPos4i; - glRasterPos4iv: TglRasterPos4iv; - glRasterPos4s: TglRasterPos4s; - glRasterPos4sv: TglRasterPos4sv; - glRectd: TglRectd; - glRectdv: TglRectdv; - glRectf: TglRectf; - glRectfv: TglRectfv; - glRecti: TglRecti; - glRectiv: TglRectiv; - glRects: TglRects; - glRectsv: TglRectsv; - glRenderMode: TglRenderMode; - glRotated: TglRotated; - glRotatef: TglRotatef; - glScaled: TglScaled; - glScalef: TglScalef; - glSelectBuffer: TglSelectBuffer; - glShadeModel: TglShadeModel; - glTexCoord1d: TglTexCoord1d; - glTexCoord1dv: TglTexCoord1dv; - glTexCoord1f: TglTexCoord1f; - glTexCoord1fv: TglTexCoord1fv; - glTexCoord1i: TglTexCoord1i; - glTexCoord1iv: TglTexCoord1iv; - glTexCoord1s: TglTexCoord1s; - glTexCoord1sv: TglTexCoord1sv; - glTexCoord2d: TglTexCoord2d; - glTexCoord2dv: TglTexCoord2dv; - glTexCoord2f: TglTexCoord2f; - glTexCoord2fv: TglTexCoord2fv; - glTexCoord2i: TglTexCoord2i; - glTexCoord2iv: TglTexCoord2iv; - glTexCoord2s: TglTexCoord2s; - glTexCoord2sv: TglTexCoord2sv; - glTexCoord3d: TglTexCoord3d; - glTexCoord3dv: TglTexCoord3dv; - glTexCoord3f: TglTexCoord3f; - glTexCoord3fv: TglTexCoord3fv; - glTexCoord3i: TglTexCoord3i; - glTexCoord3iv: TglTexCoord3iv; - glTexCoord3s: TglTexCoord3s; - glTexCoord3sv: TglTexCoord3sv; - glTexCoord4d: TglTexCoord4d; - glTexCoord4dv: TglTexCoord4dv; - glTexCoord4f: TglTexCoord4f; - glTexCoord4fv: TglTexCoord4fv; - glTexCoord4i: TglTexCoord4i; - glTexCoord4iv: TglTexCoord4iv; - glTexCoord4s: TglTexCoord4s; - glTexCoord4sv: TglTexCoord4sv; - glTexCoordPointer: TglTexCoordPointer; - glTexEnvf: TglTexEnvf; - glTexEnvfv: TglTexEnvfv; - glTexEnvi: TglTexEnvi; - glTexEnviv: TglTexEnviv; - glTexGend: TglTexGend; - glTexGendv: TglTexGendv; - glTexGenf: TglTexGenf; - glTexGenfv: TglTexGenfv; - glTexGeni: TglTexGeni; - glTexGeniv: TglTexGeniv; - glTranslated: TglTranslated; - glTranslatef: TglTranslatef; - glVertex2d: TglVertex2d; - glVertex2dv: TglVertex2dv; - glVertex2f: TglVertex2f; - glVertex2fv: TglVertex2fv; - glVertex2i: TglVertex2i; - glVertex2iv: TglVertex2iv; - glVertex2s: TglVertex2s; - glVertex2sv: TglVertex2sv; - glVertex3d: TglVertex3d; - glVertex3dv: TglVertex3dv; - glVertex3f: TglVertex3f; - glVertex3fv: TglVertex3fv; - glVertex3i: TglVertex3i; - glVertex3iv: TglVertex3iv; - glVertex3s: TglVertex3s; - glVertex3sv: TglVertex3sv; - glVertex4d: TglVertex4d; - glVertex4dv: TglVertex4dv; - glVertex4f: TglVertex4f; - glVertex4fv: TglVertex4fv; - glVertex4i: TglVertex4i; - glVertex4iv: TglVertex4iv; - glVertex4s: TglVertex4s; - glVertex4sv: TglVertex4sv; - glVertexPointer: TglVertexPointer; -{$endif} - - // GL_VERSION_1_2 - glBlendColor: TglBlendColor; - glBlendEquation: TglBlendEquation; - glDrawRangeElements: TglDrawRangeElements; - glTexImage3D: TglTexImage3D; - glTexSubImage3D: TglTexSubImage3D; - glCopyTexSubImage3D: TglCopyTexSubImage3D; -{$ifdef DGL_DEPRECATED} - glColorTable: TglColorTable; - glColorTableParameterfv: TglColorTableParameterfv; - glColorTableParameteriv: TglColorTableParameteriv; - glCopyColorTable: TglCopyColorTable; - glGetColorTable: TglGetColorTable; - glGetColorTableParameterfv: TglGetColorTableParameterfv; - glGetColorTableParameteriv: TglGetColorTableParameteriv; - glColorSubTable: TglColorSubTable; - glCopyColorSubTable: TglCopyColorSubTable; - glConvolutionFilter1D: TglConvolutionFilter1D; - glConvolutionFilter2D: TglConvolutionFilter2D; - glConvolutionParameterf: TglConvolutionParameterf; - glConvolutionParameterfv: TglConvolutionParameterfv; - glConvolutionParameteri: TglConvolutionParameteri; - glConvolutionParameteriv: TglConvolutionParameteriv; - glCopyConvolutionFilter1D: TglCopyConvolutionFilter1D; - glCopyConvolutionFilter2D: TglCopyConvolutionFilter2D; - glGetConvolutionFilter: TglGetConvolutionFilter; - glGetConvolutionParameterfv: TglGetConvolutionParameterfv; - glGetConvolutionParameteriv: TglGetConvolutionParameteriv; - glGetSeparableFilter: TglGetSeparableFilter; - glSeparableFilter2D: TglSeparableFilter2D; - glGetHistogram: TglGetHistogram; - glGetHistogramParameterfv: TglGetHistogramParameterfv; - glGetHistogramParameteriv: TglGetHistogramParameteriv; - glGetMinmax: TglGetMinmax; - glGetMinmaxParameterfv: TglGetMinmaxParameterfv; - glGetMinmaxParameteriv: TglGetMinmaxParameteriv; - glHistogram: TglHistogram; - glMinmax: TglMinmax; - glResetHistogram: TglResetHistogram; - glResetMinmax: TglResetMinmax; -{$endif} - - // GL_VERSION_1_3 - glActiveTexture: TglActiveTexture; - glSampleCoverage: TglSampleCoverage; - glCompressedTexImage3D: TglCompressedTexImage3D; - glCompressedTexImage2D: TglCompressedTexImage2D; - glCompressedTexImage1D: TglCompressedTexImage1D; - glCompressedTexSubImage3D: TglCompressedTexSubImage3D; - glCompressedTexSubImage2D: TglCompressedTexSubImage2D; - glCompressedTexSubImage1D: TglCompressedTexSubImage1D; - glGetCompressedTexImage: TglGetCompressedTexImage; -{$ifdef DGL_DEPRECATED} - glClientActiveTexture: TglClientActiveTexture; - glMultiTexCoord1d: TglMultiTexCoord1d; - glMultiTexCoord1dv: TglMultiTexCoord1dv; - glMultiTexCoord1f: TglMultiTexCoord1f; - glMultiTexCoord1fv: TglMultiTexCoord1fv; - glMultiTexCoord1i: TglMultiTexCoord1i; - glMultiTexCoord1iv: TglMultiTexCoord1iv; - glMultiTexCoord1s: TglMultiTexCoord1s; - glMultiTexCoord1sv: TglMultiTexCoord1sv; - glMultiTexCoord2d: TglMultiTexCoord2d; - glMultiTexCoord2dv: TglMultiTexCoord2dv; - glMultiTexCoord2f: TglMultiTexCoord2f; - glMultiTexCoord2fv: TglMultiTexCoord2fv; - glMultiTexCoord2i: TglMultiTexCoord2i; - glMultiTexCoord2iv: TglMultiTexCoord2iv; - glMultiTexCoord2s: TglMultiTexCoord2s; - glMultiTexCoord2sv: TglMultiTexCoord2sv; - glMultiTexCoord3d: TglMultiTexCoord3d; - glMultiTexCoord3dv: TglMultiTexCoord3dv; - glMultiTexCoord3f: TglMultiTexCoord3f; - glMultiTexCoord3fv: TglMultiTexCoord3fv; - glMultiTexCoord3i: TglMultiTexCoord3i; - glMultiTexCoord3iv: TglMultiTexCoord3iv; - glMultiTexCoord3s: TglMultiTexCoord3s; - glMultiTexCoord3sv: TglMultiTexCoord3sv; - glMultiTexCoord4d: TglMultiTexCoord4d; - glMultiTexCoord4dv: TglMultiTexCoord4dv; - glMultiTexCoord4f: TglMultiTexCoord4f; - glMultiTexCoord4fv: TglMultiTexCoord4fv; - glMultiTexCoord4i: TglMultiTexCoord4i; - glMultiTexCoord4iv: TglMultiTexCoord4iv; - glMultiTexCoord4s: TglMultiTexCoord4s; - glMultiTexCoord4sv: TglMultiTexCoord4sv; - glLoadTransposeMatrixf: TglLoadTransposeMatrixf; - glLoadTransposeMatrixd: TglLoadTransposeMatrixd; - glMultTransposeMatrixf: TglMultTransposeMatrixf; - glMultTransposeMatrixd: TglMultTransposeMatrixd; -{$endif} - - // GL_VERSION_1_4 - glBlendFuncSeparate: TglBlendFuncSeparate; - glMultiDrawArrays: TglMultiDrawArrays; - glMultiDrawElements: TglMultiDrawElements; - glPointParameterf: TglPointParameterf; - glPointParameterfv: TglPointParameterfv; - glPointParameteri: TglPointParameteri; - glPointParameteriv: TglPointParameteriv; -{$ifdef DGL_DEPRECATED} - glFogCoordf: TglFogCoordf; - glFogCoordfv: TglFogCoordfv; - glFogCoordd: TglFogCoordd; - glFogCoorddv: TglFogCoorddv; - glFogCoordPointer: TglFogCoordPointer; - glSecondaryColor3b: TglSecondaryColor3b; - glSecondaryColor3bv: TglSecondaryColor3bv; - glSecondaryColor3d: TglSecondaryColor3d; - glSecondaryColor3dv: TglSecondaryColor3dv; - glSecondaryColor3f: TglSecondaryColor3f; - glSecondaryColor3fv: TglSecondaryColor3fv; - glSecondaryColor3i: TglSecondaryColor3i; - glSecondaryColor3iv: TglSecondaryColor3iv; - glSecondaryColor3s: TglSecondaryColor3s; - glSecondaryColor3sv: TglSecondaryColor3sv; - glSecondaryColor3ub: TglSecondaryColor3ub; - glSecondaryColor3ubv: TglSecondaryColor3ubv; - glSecondaryColor3ui: TglSecondaryColor3ui; - glSecondaryColor3uiv: TglSecondaryColor3uiv; - glSecondaryColor3us: TglSecondaryColor3us; - glSecondaryColor3usv: TglSecondaryColor3usv; - glSecondaryColorPointer: TglSecondaryColorPointer; - glWindowPos2d: TglWindowPos2d; - glWindowPos2dv: TglWindowPos2dv; - glWindowPos2f: TglWindowPos2f; - glWindowPos2fv: TglWindowPos2fv; - glWindowPos2i: TglWindowPos2i; - glWindowPos2iv: TglWindowPos2iv; - glWindowPos2s: TglWindowPos2s; - glWindowPos2sv: TglWindowPos2sv; - glWindowPos3d: TglWindowPos3d; - glWindowPos3dv: TglWindowPos3dv; - glWindowPos3f: TglWindowPos3f; - glWindowPos3fv: TglWindowPos3fv; - glWindowPos3i: TglWindowPos3i; - glWindowPos3iv: TglWindowPos3iv; - glWindowPos3s: TglWindowPos3s; - glWindowPos3sv: TglWindowPos3sv; -{$endif} - - // GL_VERSION_1_5 - glGenQueries: TglGenQueries; - glDeleteQueries: TglDeleteQueries; - glIsQuery: TglIsQuery; - glBeginQuery: TglBeginQuery; - glEndQuery: TglEndQuery; - glGetQueryiv: TglGetQueryiv; - glGetQueryObjectiv: TglGetQueryObjectiv; - glGetQueryObjectuiv: TglGetQueryObjectuiv; - glBindBuffer: TglBindBuffer; - glDeleteBuffers: TglDeleteBuffers; - glGenBuffers: TglGenBuffers; - glIsBuffer: TglIsBuffer; - glBufferData: TglBufferData; - glBufferSubData: TglBufferSubData; - glGetBufferSubData: TglGetBufferSubData; - glMapBuffer: TglMapBuffer; - glUnmapBuffer: TglUnmapBuffer; - glGetBufferParameteriv: TglGetBufferParameteriv; - glGetBufferPointerv: TglGetBufferPointerv; - - // GL_VERSION_2_0 - glBlendEquationSeparate: TglBlendEquationSeparate; - glDrawBuffers: TglDrawBuffers; - glStencilOpSeparate: TglStencilOpSeparate; - glStencilFuncSeparate: TglStencilFuncSeparate; - glStencilMaskSeparate: TglStencilMaskSeparate; - glAttachShader: TglAttachShader; - glBindAttribLocation: TglBindAttribLocation; - glCompileShader: TglCompileShader; - glCreateProgram: TglCreateProgram; - glCreateShader: TglCreateShader; - glDeleteProgram: TglDeleteProgram; - glDeleteShader: TglDeleteShader; - glDetachShader: TglDetachShader; - glDisableVertexAttribArray: TglDisableVertexAttribArray; - glEnableVertexAttribArray: TglEnableVertexAttribArray; - glGetActiveAttrib: TglGetActiveAttrib; - glGetActiveUniform: TglGetActiveUniform; - glGetAttachedShaders: TglGetAttachedShaders; - glGetAttribLocation: TglGetAttribLocation; - glGetProgramiv: TglGetProgramiv; - glGetProgramInfoLog: TglGetProgramInfoLog; - glGetShaderiv: TglGetShaderiv; - glGetShaderInfoLog: TglGetShaderInfoLog; - glGetShaderSource: TglGetShaderSource; - glGetUniformLocation: TglGetUniformLocation; - glGetUniformfv: TglGetUniformfv; - glGetUniformiv: TglGetUniformiv; - glGetVertexAttribfv: TglGetVertexAttribfv; - glGetVertexAttribiv: TglGetVertexAttribiv; - glGetVertexAttribPointerv: TglGetVertexAttribPointerv; - glIsProgram: TglIsProgram; - glIsShader: TglIsShader; - glLinkProgram: TglLinkProgram; - glShaderSource: TglShaderSource; - glUseProgram: TglUseProgram; - glUniform1f: TglUniform1f; - glUniform2f: TglUniform2f; - glUniform3f: TglUniform3f; - glUniform4f: TglUniform4f; - glUniform1i: TglUniform1i; - glUniform2i: TglUniform2i; - glUniform3i: TglUniform3i; - glUniform4i: TglUniform4i; - glUniform1fv: TglUniform1fv; - glUniform2fv: TglUniform2fv; - glUniform3fv: TglUniform3fv; - glUniform4fv: TglUniform4fv; - glUniform1iv: TglUniform1iv; - glUniform2iv: TglUniform2iv; - glUniform3iv: TglUniform3iv; - glUniform4iv: TglUniform4iv; - glUniformMatrix2fv: TglUniformMatrix2fv; - glUniformMatrix3fv: TglUniformMatrix3fv; - glUniformMatrix4fv: TglUniformMatrix4fv; - glValidateProgram: TglValidateProgram; - glVertexAttrib1d: TglVertexAttrib1d; - glVertexAttrib1dv: TglVertexAttrib1dv; - glVertexAttrib1f: TglVertexAttrib1f; - glVertexAttrib1fv: TglVertexAttrib1fv; - glVertexAttrib1s: TglVertexAttrib1s; - glVertexAttrib1sv: TglVertexAttrib1sv; - glVertexAttrib2d: TglVertexAttrib2d; - glVertexAttrib2dv: TglVertexAttrib2dv; - glVertexAttrib2f: TglVertexAttrib2f; - glVertexAttrib2fv: TglVertexAttrib2fv; - glVertexAttrib2s: TglVertexAttrib2s; - glVertexAttrib2sv: TglVertexAttrib2sv; - glVertexAttrib3d: TglVertexAttrib3d; - glVertexAttrib3dv: TglVertexAttrib3dv; - glVertexAttrib3f: TglVertexAttrib3f; - glVertexAttrib3fv: TglVertexAttrib3fv; - glVertexAttrib3s: TglVertexAttrib3s; - glVertexAttrib3sv: TglVertexAttrib3sv; - glVertexAttrib4Nbv: TglVertexAttrib4Nbv; - glVertexAttrib4Niv: TglVertexAttrib4Niv; - glVertexAttrib4Nsv: TglVertexAttrib4Nsv; - glVertexAttrib4Nub: TglVertexAttrib4Nub; - glVertexAttrib4Nubv: TglVertexAttrib4Nubv; - glVertexAttrib4Nuiv: TglVertexAttrib4Nuiv; - glVertexAttrib4Nusv: TglVertexAttrib4Nusv; - glVertexAttrib4bv: TglVertexAttrib4bv; - glVertexAttrib4d: TglVertexAttrib4d; - glVertexAttrib4dv: TglVertexAttrib4dv; - glVertexAttrib4f: TglVertexAttrib4f; - glVertexAttrib4fv: TglVertexAttrib4fv; - glVertexAttrib4iv: TglVertexAttrib4iv; - glVertexAttrib4s: TglVertexAttrib4s; - glVertexAttrib4sv: TglVertexAttrib4sv; - glVertexAttrib4ubv: TglVertexAttrib4ubv; - glVertexAttrib4uiv: TglVertexAttrib4uiv; - glVertexAttrib4usv: TglVertexAttrib4usv; - glVertexAttribPointer: TglVertexAttribPointer; - - // GL_VERSION_2_1 - glUniformMatrix2x3fv: TglUniformMatrix2x3fv; - glUniformMatrix3x2fv: TglUniformMatrix3x2fv; - glUniformMatrix2x4fv: TglUniformMatrix2x4fv; - glUniformMatrix4x2fv: TglUniformMatrix4x2fv; - glUniformMatrix3x4fv: TglUniformMatrix3x4fv; - glUniformMatrix4x3fv: TglUniformMatrix4x3fv; - - // GL_VERSION_3_0 - glColorMaski: TglColorMaski; - glGetBooleani_v: TglGetBooleani_v; - glGetIntegeri_v: TglGetIntegeri_v; - glEnablei: TglEnablei; - glDisablei: TglDisablei; - glIsEnabledi: TglIsEnabledi; - glBeginTransformFeedback: TglBeginTransformFeedback; - glEndTransformFeedback: TglEndTransformFeedback; - glBindBufferRange: TglBindBufferRange; - glBindBufferBase: TglBindBufferBase; - glTransformFeedbackVaryings: TglTransformFeedbackVaryings; - glGetTransformFeedbackVarying: TglGetTransformFeedbackVarying; - glClampColor: TglClampColor; - glBeginConditionalRender: TglBeginConditionalRender; - glEndConditionalRender: TglEndConditionalRender; - glVertexAttribI1i: TglVertexAttribI1i; - glVertexAttribI2i: TglVertexAttribI2i; - glVertexAttribI3i: TglVertexAttribI3i; - glVertexAttribI4i: TglVertexAttribI4i; - glVertexAttribI1ui: TglVertexAttribI1ui; - glVertexAttribI2ui: TglVertexAttribI2ui; - glVertexAttribI3ui: TglVertexAttribI3ui; - glVertexAttribI4ui: TglVertexAttribI4ui; - glVertexAttribI1iv: TglVertexAttribI1iv; - glVertexAttribI2iv: TglVertexAttribI2iv; - glVertexAttribI3iv: TglVertexAttribI3iv; - glVertexAttribI4iv: TglVertexAttribI4iv; - glVertexAttribI1uiv: TglVertexAttribI1uiv; - glVertexAttribI2uiv: TglVertexAttribI2uiv; - glVertexAttribI3uiv: TglVertexAttribI3uiv; - glVertexAttribI4uiv: TglVertexAttribI4uiv; - glVertexAttribI4bv: TglVertexAttribI4bv; - glVertexAttribI4sv: TglVertexAttribI4sv; - glVertexAttribI4ubv: TglVertexAttribI4ubv; - glVertexAttribI4usv: TglVertexAttribI4usv; - glVertexAttribIPointer: TglVertexAttribIPointer; - glGetVertexAttribIiv: TglGetVertexAttribIiv; - glGetVertexAttribIuiv: TglGetVertexAttribIuiv; - glGetUniformuiv: TglGetUniformuiv; - glBindFragDataLocation: TglBindFragDataLocation; - glGetFragDataLocation: TglGetFragDataLocation; - glUniform1ui: TglUniform1ui; - glUniform2ui: TglUniform2ui; - glUniform3ui: TglUniform3ui; - glUniform4ui: TglUniform4ui; - glUniform1uiv: TglUniform1uiv; - glUniform2uiv: TglUniform2uiv; - glUniform3uiv: TglUniform3uiv; - glUniform4uiv: TglUniform4uiv; - glTexParameterIiv: TglTexParameterIiv; - glTexParameterIuiv: TglTexParameterIuiv; - glGetTexParameterIiv: TglGetTexParameterIiv; - glGetTexParameterIuiv: TglGetTexParameterIuiv; - glClearBufferiv: TglClearBufferiv; - glClearBufferuiv: TglClearBufferuiv; - glClearBufferfv: TglClearBufferfv; - glClearBufferfi: TglClearBufferfi; - glGetStringi: TglGetStringi; - - // GL_VERSION_3_1 - glDrawArraysInstanced: TglDrawArraysInstanced; - glDrawElementsInstanced: TglDrawElementsInstanced; - glTexBuffer: TglTexBuffer; - glPrimitiveRestartIndex: TglPrimitiveRestartIndex; - - // GL_VERSION_3_2 - { OpenGL 3.2 also reuses entry points from these extensions: } - { ARB_draw_elements_base_vertex } - { ARB_provoking_vertex } - { ARB_sync } - { ARB_texture_multisample } - glGetInteger64i_v: TglGetInteger64i_v; - glGetBufferParameteri64v: TglGetBufferParameteri64v; - glProgramParameteri: TglProgramParameteri; - glFramebufferTexture: TglFramebufferTexture; - glFramebufferTextureFace: TglFramebufferTextureFace; - - // GL_3DFX_tbuffer - glTbufferMask3DFX: TglTbufferMask3DFX; - - // GL_APPLE_element_array - glElementPointerAPPLE: TglElementPointerAPPLE; - glDrawElementArrayAPPLE: TglDrawElementArrayAPPLE; - glDrawRangeElementArrayAPPLE: TglDrawRangeElementArrayAPPLE; - glMultiDrawElementArrayAPPLE: TglMultiDrawElementArrayAPPLE; - glMultiDrawRangeElementArrayAPPLE: TglMultiDrawRangeElementArrayAPPLE; - - // GL_APPLE_fence - glGenFencesAPPLE: TglGenFencesAPPLE; - glDeleteFencesAPPLE: TglDeleteFencesAPPLE; - glSetFenceAPPLE: TglSetFenceAPPLE; - glIsFenceAPPLE: TglIsFenceAPPLE; - glTestFenceAPPLE: TglTestFenceAPPLE; - glFinishFenceAPPLE: TglFinishFenceAPPLE; - glTestObjectAPPLE: TglTestObjectAPPLE; - glFinishObjectAPPLE: TglFinishObjectAPPLE; - - // GL_APPLE_vertex_array_object - glBindVertexArrayAPPLE: TglBindVertexArrayAPPLE; - glDeleteVertexArraysAPPLE: TglDeleteVertexArraysAPPLE; - glGenVertexArraysAPPLE: TglGenVertexArraysAPPLE; - glIsVertexArrayAPPLE: TglIsVertexArrayAPPLE; - - // GL_APPLE_vertex_array_range - glVertexArrayRangeAPPLE: TglVertexArrayRangeAPPLE; - glFlushVertexArrayRangeAPPLE: TglFlushVertexArrayRangeAPPLE; - glVertexArrayParameteriAPPLE: TglVertexArrayParameteriAPPLE; - - // GL_APPLE_texture_range - glTextureRangeAPPLE: TglTextureRangeAPPLE; - glGetTexParameterPointervAPPLE: TglGetTexParameterPointervAPPLE; - - // GL_APPLE_vertex_program_evaluators - glEnableVertexAttribAPPLE: TglEnableVertexAttribAPPLE; - glDisableVertexAttribAPPLE: TglDisableVertexAttribAPPLE; - glIsVertexAttribEnabledAPPLE: TglIsVertexAttribEnabledAPPLE; - glMapVertexAttrib1dAPPLE: TglMapVertexAttrib1dAPPLE; - glMapVertexAttrib1fAPPLE: TglMapVertexAttrib1fAPPLE; - glMapVertexAttrib2dAPPLE: TglMapVertexAttrib2dAPPLE; - glMapVertexAttrib2fAPPLE: TglMapVertexAttrib2fAPPLE; - - // GL_APPLE_object_purgeable - glObjectPurgeableAPPLE: TglObjectPurgeableAPPLE; - glObjectUnpurgeableAPPLE: TglObjectUnpurgeableAPPLE; - glGetObjectParameterivAPPLE: TglGetObjectParameterivAPPLE; - - // GL_ARB_matrix_palette - glCurrentPaletteMatrixARB: TglCurrentPaletteMatrixARB; - glMatrixIndexubvARB: TglMatrixIndexubvARB; - glMatrixIndexusvARB: TglMatrixIndexusvARB; - glMatrixIndexuivARB: TglMatrixIndexuivARB; - glMatrixIndexPointerARB: TglMatrixIndexPointerARB; - - // GL_ARB_multisample - glSampleCoverageARB: TglSampleCoverageARB; - - // GL_ARB_multitexture - glActiveTextureARB: TglActiveTextureARB; - glClientActiveTextureARB: TglClientActiveTextureARB; - glMultiTexCoord1dARB: TglMultiTexCoord1dARB; - glMultiTexCoord1dvARB: TglMultiTexCoord1dvARB; - glMultiTexCoord1fARB: TglMultiTexCoord1fARB; - glMultiTexCoord1fvARB: TglMultiTexCoord1fvARB; - glMultiTexCoord1iARB: TglMultiTexCoord1iARB; - glMultiTexCoord1ivARB: TglMultiTexCoord1ivARB; - glMultiTexCoord1sARB: TglMultiTexCoord1sARB; - glMultiTexCoord1svARB: TglMultiTexCoord1svARB; - glMultiTexCoord2dARB: TglMultiTexCoord2dARB; - glMultiTexCoord2dvARB: TglMultiTexCoord2dvARB; - glMultiTexCoord2fARB: TglMultiTexCoord2fARB; - glMultiTexCoord2fvARB: TglMultiTexCoord2fvARB; - glMultiTexCoord2iARB: TglMultiTexCoord2iARB; - glMultiTexCoord2ivARB: TglMultiTexCoord2ivARB; - glMultiTexCoord2sARB: TglMultiTexCoord2sARB; - glMultiTexCoord2svARB: TglMultiTexCoord2svARB; - glMultiTexCoord3dARB: TglMultiTexCoord3dARB; - glMultiTexCoord3dvARB: TglMultiTexCoord3dvARB; - glMultiTexCoord3fARB: TglMultiTexCoord3fARB; - glMultiTexCoord3fvARB: TglMultiTexCoord3fvARB; - glMultiTexCoord3iARB: TglMultiTexCoord3iARB; - glMultiTexCoord3ivARB: TglMultiTexCoord3ivARB; - glMultiTexCoord3sARB: TglMultiTexCoord3sARB; - glMultiTexCoord3svARB: TglMultiTexCoord3svARB; - glMultiTexCoord4dARB: TglMultiTexCoord4dARB; - glMultiTexCoord4dvARB: TglMultiTexCoord4dvARB; - glMultiTexCoord4fARB: TglMultiTexCoord4fARB; - glMultiTexCoord4fvARB: TglMultiTexCoord4fvARB; - glMultiTexCoord4iARB: TglMultiTexCoord4iARB; - glMultiTexCoord4ivARB: TglMultiTexCoord4ivARB; - glMultiTexCoord4sARB: TglMultiTexCoord4sARB; - glMultiTexCoord4svARB: TglMultiTexCoord4svARB; - - // GL_ARB_point_parameters - glPointParameterfARB: TglPointParameterfARB; - glPointParameterfvARB: TglPointParameterfvARB; - - // GL_ARB_texture_compression - glCompressedTexImage3DARB: TglCompressedTexImage3DARB; - glCompressedTexImage2DARB: TglCompressedTexImage2DARB; - glCompressedTexImage1DARB: TglCompressedTexImage1DARB; - glCompressedTexSubImage3DARB: TglCompressedTexSubImage3DARB; - glCompressedTexSubImage2DARB: TglCompressedTexSubImage2DARB; - glCompressedTexSubImage1DARB: TglCompressedTexSubImage1DARB; - glGetCompressedTexImageARB: TglGetCompressedTexImageARB; - - // GL_ARB_transpose_matrix - glLoadTransposeMatrixfARB: TglLoadTransposeMatrixfARB; - glLoadTransposeMatrixdARB: TglLoadTransposeMatrixdARB; - glMultTransposeMatrixfARB: TglMultTransposeMatrixfARB; - glMultTransposeMatrixdARB: TglMultTransposeMatrixdARB; - - // GL_ARB_vertex_blend - glWeightbvARB: TglWeightbvARB; - glWeightsvARB: TglWeightsvARB; - glWeightivARB: TglWeightivARB; - glWeightfvARB: TglWeightfvARB; - glWeightdvARB: TglWeightdvARB; - glWeightubvARB: TglWeightubvARB; - glWeightusvARB: TglWeightusvARB; - glWeightuivARB: TglWeightuivARB; - glWeightPointerARB: TglWeightPointerARB; - glVertexBlendARB: TglVertexBlendARB; - - // GL_ARB_vertex_buffer_object - glBindBufferARB: TglBindBufferARB; - glDeleteBuffersARB: TglDeleteBuffersARB; - glGenBuffersARB: TglGenBuffersARB; - glIsBufferARB: TglIsBufferARB; - glBufferDataARB: TglBufferDataARB; - glBufferSubDataARB: TglBufferSubData; - glGetBufferSubDataARB: TglGetBufferSubDataARB; - glMapBufferARB: TglMapBufferARB; - glUnmapBufferARB: TglUnmapBufferARB; - glGetBufferParameterivARB: TglGetBufferParameterivARB; - glGetBufferPointervARB: TglGetBufferPointervARB; - - // GL_ARB_vertex_program - glVertexAttrib1dARB: TglVertexAttrib1dARB; - glVertexAttrib1dvARB: TglVertexAttrib1dvARB; - glVertexAttrib1fARB: TglVertexAttrib1fARB; - glVertexAttrib1fvARB: TglVertexAttrib1fvARB; - glVertexAttrib1sARB: TglVertexAttrib1sARB; - glVertexAttrib1svARB: TglVertexAttrib1svARB; - glVertexAttrib2dARB: TglVertexAttrib2dARB; - glVertexAttrib2dvARB: TglVertexAttrib2dvARB; - glVertexAttrib2fARB: TglVertexAttrib2fARB; - glVertexAttrib2fvARB: TglVertexAttrib2fvARB; - glVertexAttrib2sARB: TglVertexAttrib2sARB; - glVertexAttrib2svARB: TglVertexAttrib2svARB; - glVertexAttrib3dARB: TglVertexAttrib3dARB; - glVertexAttrib3dvARB: TglVertexAttrib3dvARB; - glVertexAttrib3fARB: TglVertexAttrib3fARB; - glVertexAttrib3fvARB: TglVertexAttrib3fvARB; - glVertexAttrib3sARB: TglVertexAttrib3sARB; - glVertexAttrib3svARB: TglVertexAttrib3svARB; - glVertexAttrib4NbvARB: TglVertexAttrib4NbvARB; - glVertexAttrib4NivARB: TglVertexAttrib4NivARB; - glVertexAttrib4NsvARB: TglVertexAttrib4NsvARB; - glVertexAttrib4NubARB: TglVertexAttrib4NubARB; - glVertexAttrib4NubvARB: TglVertexAttrib4NubvARB; - glVertexAttrib4NuivARB: TglVertexAttrib4NuivARB; - glVertexAttrib4NusvARB: TglVertexAttrib4NusvARB; - glVertexAttrib4bvARB: TglVertexAttrib4bvARB; - glVertexAttrib4dARB: TglVertexAttrib4dARB; - glVertexAttrib4dvARB: TglVertexAttrib4dvARB; - glVertexAttrib4fARB: TglVertexAttrib4fARB; - glVertexAttrib4fvARB: TglVertexAttrib4fvARB; - glVertexAttrib4ivARB: TglVertexAttrib4ivARB; - glVertexAttrib4sARB: TglVertexAttrib4sARB; - glVertexAttrib4svARB: TglVertexAttrib4svARB; - glVertexAttrib4ubvARB: TglVertexAttrib4ubvARB; - glVertexAttrib4uivARB: TglVertexAttrib4uivARB; - glVertexAttrib4usvARB: TglVertexAttrib4usvARB; - glVertexAttribPointerARB: TglVertexAttribPointerARB; - glEnableVertexAttribArrayARB: TglEnableVertexAttribArrayARB; - glDisableVertexAttribArrayARB: TglDisableVertexAttribArrayARB; - glProgramStringARB: TglProgramStringARB; - glBindProgramARB: TglBindProgramARB; - glDeleteProgramsARB: TglDeleteProgramsARB; - glGenProgramsARB: TglGenProgramsARB; - - glProgramEnvParameter4dARB: TglProgramEnvParameter4dARB; - glProgramEnvParameter4dvARB: TglProgramEnvParameter4dvARB; - glProgramEnvParameter4fARB: TglProgramEnvParameter4fARB; - glProgramEnvParameter4fvARB: TglProgramEnvParameter4fvARB; - glProgramLocalParameter4dARB: TglProgramLocalParameter4dARB; - glProgramLocalParameter4dvARB: TglProgramLocalParameter4dvARB; - glProgramLocalParameter4fARB: TglProgramLocalParameter4fARB; - glProgramLocalParameter4fvARB: TglProgramLocalParameter4fvARB; - glGetProgramEnvParameterdvARB: TglGetProgramEnvParameterdvARB; - glGetProgramEnvParameterfvARB: TglGetProgramEnvParameterfvARB; - glGetProgramLocalParameterdvARB: TglGetProgramLocalParameterdvARB; - glGetProgramLocalParameterfvARB: TglGetProgramLocalParameterfvARB; - glGetProgramivARB: TglGetProgramivARB; - glGetProgramStringARB: TglGetProgramStringARB; - glGetVertexAttribdvARB: TglGetVertexAttribdvARB; - glGetVertexAttribfvARB: TglGetVertexAttribfvARB; - glGetVertexAttribivARB: TglGetVertexAttribivARB; - glGetVertexAttribPointervARB: TglGetVertexAttribPointervARB; - glIsProgramARB: TglIsProgramARB; - - // GL_ARB_window_pos - glWindowPos2dARB: TglWindowPos2dARB; - glWindowPos2dvARB: TglWindowPos2dvARB; - glWindowPos2fARB: TglWindowPos2fARB; - glWindowPos2fvARB: TglWindowPos2fvARB; - glWindowPos2iARB: TglWindowPos2iARB; - glWindowPos2ivARB: TglWindowPos2ivARB; - glWindowPos2sARB: TglWindowPos2sARB; - glWindowPos2svARB: TglWindowPos2svARB; - glWindowPos3dARB: TglWindowPos3dARB; - glWindowPos3dvARB: TglWindowPos3dvARB; - glWindowPos3fARB: TglWindowPos3fARB; - glWindowPos3fvARB: TglWindowPos3fvARB; - glWindowPos3iARB: TglWindowPos3iARB; - glWindowPos3ivARB: TglWindowPos3ivARB; - glWindowPos3sARB: TglWindowPos3sARB; - glWindowPos3svARB: TglWindowPos3svARB; - - // GL_ARB_draw_buffers - glDrawBuffersARB: TglDrawBuffersARB; - - // GL_ARB_color_buffer_float - glClampColorARB: TglClampColorARB; - - // GL_ARB_vertex_shader - glGetActiveAttribARB: TglGetActiveAttribARB; - glGetAttribLocationARB: TglGetAttribLocationARB; - glBindAttribLocationARB: TglBindAttribLocationARB; - - // GL_ARB_shader_objects - glDeleteObjectARB: TglDeleteObjectARB; - glGetHandleARB: TglGetHandleARB; - glDetachObjectARB: TglDetachObjectARB; - glCreateShaderObjectARB: TglCreateShaderObjectARB; - glShaderSourceARB: TglShaderSourceARB; - glCompileShaderARB: TglCompileShaderARB; - glCreateProgramObjectARB: TglCreateProgramObjectARB; - glAttachObjectARB: TglAttachObjectARB; - glLinkProgramARB: TglLinkProgramARB; - glUseProgramObjectARB: TglUseProgramObjectARB; - glValidateProgramARB: TglValidateProgramARB; - glUniform1fARB: TglUniform1fARB; - glUniform2fARB: TglUniform2fARB; - glUniform3fARB: TglUniform3fARB; - glUniform4fARB: TglUniform4fARB; - glUniform1iARB: TglUniform1iARB; - glUniform2iARB: TglUniform2iARB; - glUniform3iARB: TglUniform3iARB; - glUniform4iARB: TglUniform4iARB; - glUniform1fvARB: TglUniform1fvARB; - glUniform2fvARB: TglUniform2fvARB; - glUniform3fvARB: TglUniform3fvARB; - glUniform4fvARB: TglUniform4fvARB; - glUniform1ivARB: TglUniform1ivARB; - glUniform2ivARB: TglUniform2ivARB; - glUniform3ivARB: TglUniform3ivARB; - glUniform4ivARB: TglUniform4ivARB; - glUniformMatrix2fvARB: TglUniformMatrix2fvARB; - glUniformMatrix3fvARB: TglUniformMatrix3fvARB; - glUniformMatrix4fvARB: TglUniformMatrix4fvARB; - glGetObjectParameterfvARB: TglGetObjectParameterfvARB; - glGetObjectParameterivARB: TglGetObjectParameterivARB; - glGetInfoLogARB: TglGetInfoLogARB; - glGetAttachedObjectsARB: TglGetAttachedObjectsARB; - glGetUniformLocationARB: TglGetUniformLocationARB; - glGetActiveUniformARB: TglGetActiveUniformARB; - glGetUniformfvARB: TglGetUniformfvARB; - glGetUniformivARB: TglGetUniformivARB; - glGetShaderSourceARB: TglGetShaderSourceARB; - - // GL_ARB_Occlusion_Query - glGenQueriesARB: TglGenQueriesARB; - glDeleteQueriesARB: TglDeleteQueriesARB; - glIsQueryARB: TglIsQueryARB; - glBeginQueryARB: TglBeginQueryARB; - glEndQueryARB: TglEndQueryARB; - glGetQueryivARB: TglGetQueryivARB; - glGetQueryObjectivARB: TglGetQueryObjectivARB; - glGetQueryObjectuivARB: TglGetQueryObjectuivARB; - - // GL_ARB_draw_instanced - glDrawArraysInstancedARB: TglDrawArraysInstancedARB; - glDrawElementsInstancedARB: TglDrawElementsInstancedARB; - - // GL_ARB_framebuffer_object - glIsRenderbuffer: TglIsRenderbuffer; - glBindRenderbuffer: TglBindRenderbuffer; - glDeleteRenderbuffers: TglDeleteRenderbuffers; - glGenRenderbuffers: TglGenRenderbuffers; - glRenderbufferStorage: TglRenderbufferStorage; - glGetRenderbufferParameteriv: TglGetRenderbufferParameteriv; - glIsFramebuffer: TglIsFramebuffer; - glBindFramebuffer: TglBindFramebuffer; - glDeleteFramebuffers: TglDeleteFramebuffers; - glGenFramebuffers: TglGenFramebuffers; - glCheckFramebufferStatus: TglCheckFramebufferStatus; - glFramebufferTexture1D: TglFramebufferTexture1D; - glFramebufferTexture2D: TglFramebufferTexture2D; - glFramebufferTexture3D: TglFramebufferTexture3D; - glFramebufferRenderbuffer: TglFramebufferRenderbuffer; - glGetFramebufferAttachmentParameteriv: TglGetFramebufferAttachmentParameteriv; - glGenerateMipmap: TglGenerateMipmap; - glBlitFramebuffer: TglBlitFramebuffer; - glRenderbufferStorageMultisample: TglRenderbufferStorageMultisample; - glFramebufferTextureLayer: TglFramebufferTextureLayer; - - // GL_ARB_geometry_shader4 - glProgramParameteriARB: TglProgramParameteriARB; - glFramebufferTextureARB: TglFramebufferTextureARB; - glFramebufferTextureLayerARB: TglFramebufferTextureLayerARB; - glFramebufferTextureFaceARB: TglFramebufferTextureFaceARB; - - // GL_ARB_instanced_arrays - glVertexAttribDivisorARB: TglVertexAttribDivisorARB; - - // GL_ARB_map_buffer_range - glMapBufferRange: TglMapBufferRange; - glFlushMappedBufferRange: TglFlushMappedBufferRange; - - // GL_ARB_texture_buffer_object - glTexBufferARB: TglTexBufferARB; - - // GL_ARB_vertex_array_object - glBindVertexArray: TglBindVertexArray; - glDeleteVertexArrays: TglDeleteVertexArrays; - glGenVertexArrays: TglGenVertexArrays; - glIsVertexArray: TglIsVertexArray; - - // GL_ARB_uniform_buffer_object - glGetUniformIndices: TglGetUniformIndices; - glGetActiveUniformsiv: TglGetActiveUniformsiv; - glGetActiveUniformName: TglGetActiveUniformName; - glGetUniformBlockIndex: TglGetUniformBlockIndex; - glGetActiveUniformBlockiv: TglGetActiveUniformBlockiv; - glGetActiveUniformBlockName: TglGetActiveUniformBlockName; - glUniformBlockBinding: TglUniformBlockBinding; - - // GL_ARB_copy_buffer - glCopyBufferSubData: TglCopyBufferSubData; - - // GL_ARB_draw_elements_base_vertex - glDrawElementsBaseVertex: TglDrawElementsBaseVertex; - glDrawRangeElementsBaseVertex: TglDrawRangeElementsBaseVertex; - glDrawElementsInstancedBaseVertex: TglDrawElementsInstancedBaseVertex; - glMultiDrawElementsBaseVertex: TglMultiDrawElementsBaseVertex; - - // GL_ARB_provoking_vertex - glProvokingVertex: TglProvokingVertex; - - // GL_ARB_sync - glFenceSync: TglFenceSync; - glIsSync: TglIsSync; - glDeleteSync: TglDeleteSync; - glClientWaitSync: TglClientWaitSync; - glWaitSync: TglWaitSync; - glGetInteger64v: TglGetInteger64v; - glGetSynciv: TglGetSynciv; - - // GL_ARB_texture_multisample - glTexImage2DMultisample: TglTexImage2DMultisample; - glTexImage3DMultisample: TglTexImage3DMultisample; - glGetMultisamplefv: TglGetMultisamplefv; - glSampleMaski: TglSampleMaski; - - // GL_ARB_draw_buffers_blend - glBlendEquationi: TglBlendEquationi; - glBlendEquationSeparatei: TglBlendEquationSeparatei; - glBlendFunci: TglBlendFunci; - glBlendFuncSeparatei: TglBlendFuncSeparatei; - - // GL_ARB_sample_shading - glMinSampleShading: TglMinSampleShading; - - // GL_ATI_draw_buffers - glDrawBuffersATI: TglDrawBuffersATI; - - // GL_ATI_element_array - glElementPointerATI: TglElementPointerATI; - glDrawElementArrayATI: TglDrawElementArrayATI; - glDrawRangeElementArrayATI: TglDrawRangeElementArrayATI; - - // GL_ATI_envmap_bumpmap - glTexBumpParameterivATI: TglTexBumpParameterivATI; - glTexBumpParameterfvATI: TglTexBumpParameterfvATI; - glGetTexBumpParameterivATI: TglGetTexBumpParameterivATI; - glGetTexBumpParameterfvATI: TglGetTexBumpParameterfvATI; - - // GL_ATI_fragment_shader - glGenFragmentShadersATI: TglGenFragmentShadersATI; - glBindFragmentShaderATI: TglBindFragmentShaderATI; - glDeleteFragmentShaderATI: TglDeleteFragmentShaderATI; - glBeginFragmentShaderATI: TglBeginFragmentShaderATI; - glEndFragmentShaderATI: TglEndFragmentShaderATI; - glPassTexCoordATI: TglPassTexCoordATI; - glSampleMapATI: TglSampleMapATI; - glColorFragmentOp1ATI: TglColorFragmentOp1ATI; - glColorFragmentOp2ATI: TglColorFragmentOp2ATI; - glColorFragmentOp3ATI: TglColorFragmentOp3ATI; - glAlphaFragmentOp1ATI: TglAlphaFragmentOp1ATI; - glAlphaFragmentOp2ATI: TglAlphaFragmentOp2ATI; - glAlphaFragmentOp3ATI: TglAlphaFragmentOp3ATI; - glSetFragmentShaderConstantATI: TglSetFragmentShaderConstantATI; - - // GL_ATI_map_object_buffer - glMapObjectBufferATI: TglMapObjectBufferATI; - glUnmapObjectBufferATI: TglUnmapObjectBufferATI; - - // GL_ATI_pn_triangles - glPNTrianglesiATI: TglPNTrianglesiATI; - glPNTrianglesfATI: TglPNTrianglesfATI; - - // GL_ATI_separate_stencil - glStencilOpSeparateATI: TglStencilOpSeparateATI; - glStencilFuncSeparateATI: TglStencilFuncSeparateATI; - - // GL_ATI_vertex_array_object - glNewObjectBufferATI: TglNewObjectBufferATI; - glIsObjectBufferATI: TglIsObjectBufferATI; - glUpdateObjectBufferATI: TglUpdateObjectBufferATI; - glGetObjectBufferfvATI: TglGetObjectBufferfvATI; - glGetObjectBufferivATI: TglGetObjectBufferivATI; - glFreeObjectBufferATI: TglFreeObjectBufferATI; - glArrayObjectATI: TglArrayObjectATI; - glGetArrayObjectfvATI: TglGetArrayObjectfvATI; - glGetArrayObjectivATI: TglGetArrayObjectivATI; - glVariantArrayObjectATI: TglVariantArrayObjectATI; - glGetVariantArrayObjectfvATI: TglGetVariantArrayObjectfvATI; - glGetVariantArrayObjectivATI: TglGetVariantArrayObjectivATI; - glVertexAttribArrayObjectATI: TglVertexAttribArrayObjectATI; - glGetVertexAttribArrayObjectfvATI: TglGetVertexAttribArrayObjectfvATI; - glGetVertexAttribArrayObjectivATI: TglGetVertexAttribArrayObjectivATI; - - // GL_ATI_vertex_streams - glVertexStream1sATI: TglVertexStream1sATI; - glVertexStream1svATI: TglVertexStream1svATI; - glVertexStream1iATI: TglVertexStream1iATI; - glVertexStream1ivATI: TglVertexStream1ivATI; - glVertexStream1fATI: TglVertexStream1fATI; - glVertexStream1fvATI: TglVertexStream1fvATI; - glVertexStream1dATI: TglVertexStream1dATI; - glVertexStream1dvATI: TglVertexStream1dvATI; - glVertexStream2sATI: TglVertexStream2sATI; - glVertexStream2svATI: TglVertexStream2svATI; - glVertexStream2iATI: TglVertexStream2iATI; - glVertexStream2ivATI: TglVertexStream2ivATI; - glVertexStream2fATI: TglVertexStream2fATI; - glVertexStream2fvATI: TglVertexStream2fvATI; - glVertexStream2dATI: TglVertexStream2dATI; - glVertexStream2dvATI: TglVertexStream2dvATI; - glVertexStream3sATI: TglVertexStream3sATI; - glVertexStream3svATI: TglVertexStream3svATI; - glVertexStream3iATI: TglVertexStream3iATI; - glVertexStream3ivATI: TglVertexStream3ivATI; - glVertexStream3fATI: TglVertexStream3fATI; - glVertexStream3fvATI: TglVertexStream3fvATI; - glVertexStream3dATI: TglVertexStream3dATI; - glVertexStream3dvATI: TglVertexStream3dvATI; - glVertexStream4sATI: TglVertexStream4sATI; - glVertexStream4svATI: TglVertexStream4svATI; - glVertexStream4iATI: TglVertexStream4iATI; - glVertexStream4ivATI: TglVertexStream4ivATI; - glVertexStream4fATI: TglVertexStream4fATI; - glVertexStream4fvATI: TglVertexStream4fvATI; - glVertexStream4dATI: TglVertexStream4dATI; - glVertexStream4dvATI: TglVertexStream4dvATI; - glNormalStream3bATI: TglNormalStream3bATI; - glNormalStream3bvATI: TglNormalStream3bvATI; - glNormalStream3sATI: TglNormalStream3sATI; - glNormalStream3svATI: TglNormalStream3svATI; - glNormalStream3iATI: TglNormalStream3iATI; - glNormalStream3ivATI: TglNormalStream3ivATI; - glNormalStream3fATI: TglNormalStream3fATI; - glNormalStream3fvATI: TglNormalStream3fvATI; - glNormalStream3dATI: TglNormalStream3dATI; - glNormalStream3dvATI: TglNormalStream3dvATI; - glClientActiveVertexStreamATI: TglClientActiveVertexStreamATI; - glVertexBlendEnviATI: TglVertexBlendEnviATI; - glVertexBlendEnvfATI: TglVertexBlendEnvfATI; - - // GL_AMD_performance_monitor - glGetPerfMonitorGroupsAMD: TglGetPerfMonitorGroupsAMD; - glGetPerfMonitorCountersAMD: TglGetPerfMonitorCountersAMD; - glGetPerfMonitorGroupStringAMD: TglGetPerfMonitorGroupStringAMD; - glGetPerfMonitorCounterStringAMD: TglGetPerfMonitorCounterStringAMD; - glGetPerfMonitorCounterInfoAMD: TglGetPerfMonitorCounterInfoAMD; - glGenPerfMonitorsAMD: TglGenPerfMonitorsAMD; - glDeletePerfMonitorsAMD: TglDeletePerfMonitorsAMD; - glSelectPerfMonitorCountersAMD: TglSelectPerfMonitorCountersAMD; - glBeginPerfMonitorAMD: TglBeginPerfMonitorAMD; - glEndPerfMonitorAMD: TglEndPerfMonitorAMD; - glGetPerfMonitorCounterDataAMD: TglGetPerfMonitorCounterDataAMD; - - // GL_EXT_blend_color - glBlendColorEXT: TglBlendColorEXT; - - // GL_EXT_blend_func_separate - glBlendFuncSeparateEXT: TglBlendFuncSeparateEXT; - - // GL_EXT_blend_minmax - glBlendEquationEXT: TglBlendEquationEXT; - - // GL_EXT_color_subtable - glColorSubTableEXT: TglColorSubTableEXT; - glCopyColorSubTableEXT: TglCopyColorSubTableEXT; - - // GL_EXT_compiled_vertex_array - glLockArraysEXT: TglLockArraysEXT; - glUnlockArraysEXT: TglUnlockArraysEXT; - - // GL_EXT_convolution - glConvolutionFilter1DEXT: TglConvolutionFilter1DEXT; - glConvolutionFilter2DEXT: TglConvolutionFilter2DEXT; - glConvolutionParameterfEXT: TglConvolutionParameterfEXT; - glConvolutionParameterfvEXT: TglConvolutionParameterfvEXT; - glConvolutionParameteriEXT: TglConvolutionParameteriEXT; - glConvolutionParameterivEXT: TglConvolutionParameterivEXT; - glCopyConvolutionFilter1DEXT: TglCopyConvolutionFilter1DEXT; - glCopyConvolutionFilter2DEXT: TglCopyConvolutionFilter2DEXT; - glGetConvolutionFilterEXT: TglGetConvolutionFilterEXT; - glGetConvolutionParameterfvEXT: TglGetConvolutionParameterfvEXT; - glGetConvolutionParameterivEXT: TglGetConvolutionParameterivEXT; - glGetSeparableFilterEXT: TglGetSeparableFilterEXT; - glSeparableFilter2DEXT: TglSeparableFilter2DEXT; - - // GL_EXT_coordinate_frame - glTangent3bEXT: TglTangent3bEXT; - glTangent3bvEXT: TglTangent3bvEXT; - glTangent3dEXT: TglTangent3dEXT; - glTangent3dvEXT: TglTangent3dvEXT; - glTangent3fEXT: TglTangent3fEXT; - glTangent3fvEXT: TglTangent3fvEXT; - glTangent3iEXT: TglTangent3iEXT; - glTangent3ivEXT: TglTangent3ivEXT; - glTangent3sEXT: TglTangent3sEXT; - glTangent3svEXT: TglTangent3svEXT; - glBinormal3bEXT: TglBinormal3bEXT; - glBinormal3bvEXT: TglBinormal3bvEXT; - glBinormal3dEXT: TglBinormal3dEXT; - glBinormal3dvEXT: TglBinormal3dvEXT; - glBinormal3fEXT: TglBinormal3fEXT; - glBinormal3fvEXT: TglBinormal3fvEXT; - glBinormal3iEXT: TglBinormal3iEXT; - glBinormal3ivEXT: TglBinormal3ivEXT; - glBinormal3sEXT: TglBinormal3sEXT; - glBinormal3svEXT: TglBinormal3svEXT; - glTangentPointerEXT: TglTangentPointerEXT; - glBinormalPointerEXT: TglBinormalPointerEXT; - - // GL_EXT_copy_texture - glCopyTexImage1DEXT: TglCopyTexImage1DEXT; - glCopyTexImage2DEXT: TglCopyTexImage2DEXT; - glCopyTexSubImage1DEXT: TglCopyTexSubImage1DEXT; - glCopyTexSubImage2DEXT: TglCopyTexSubImage2DEXT; - glCopyTexSubImage3DEXT: TglCopyTexSubImage3DEXT; - - // GL_EXT_cull_vertex - glCullParameterdvEXT: TglCullParameterdvEXT; - glCullParameterfvEXT: TglCullParameterfvEXT; - - // GL_EXT_draw_range_elements - glDrawRangeElementsEXT: TglDrawRangeElementsEXT; - - // GL_EXT_fog_coord - glFogCoordfEXT: TglFogCoordfEXT; - glFogCoordfvEXT: TglFogCoordfvEXT; - glFogCoorddEXT: TglFogCoorddEXT; - glFogCoorddvEXT: TglFogCoorddvEXT; - glFogCoordPointerEXT: TglFogCoordPointerEXT; - - // GL_EXT_framebuffer_object - glIsRenderbufferEXT: TglIsRenderbufferEXT; - glBindRenderbufferEXT: TglBindRenderbufferEXT; - glDeleteRenderbuffersEXT: TglDeleteRenderbuffersEXT; - glGenRenderbuffersEXT: TglGenRenderbuffersEXT; - glRenderbufferStorageEXT: TglRenderbufferStorageEXT; - glGetRenderbufferParameterivEXT: TglGetRenderbufferParameterivEXT; - glIsFramebufferEXT: TglIsFramebufferEXT; - glBindFramebufferEXT: TglBindFramebufferEXT; - glDeleteFramebuffersEXT: TglDeleteFramebuffersEXT; - glGenFramebuffersEXT: TglGenFramebuffersEXT; - glCheckFramebufferStatusEXT: TglCheckFramebufferStatusEXT; - glFramebufferTexture1DEXT: TglFramebufferTexture1DEXT; - glFramebufferTexture2DEXT: TglFramebufferTexture2DEXT; - glFramebufferTexture3DEXT: TglFramebufferTexture3DEXT; - glFramebufferRenderbufferEXT: TglFramebufferRenderbufferEXT; - glGetFramebufferAttachmentParameterivEXT: TglGetFramebufferAttachmentParameterivEXT; - glGenerateMipmapEXT: TglGenerateMipmapEXT; - - // GL_EXT_histogram - glGetHistogramEXT: TglGetHistogramEXT; - glGetHistogramParameterfvEXT: TglGetHistogramParameterfvEXT; - glGetHistogramParameterivEXT: TglGetHistogramParameterivEXT; - glGetMinmaxEXT: TglGetMinmaxEXT; - glGetMinmaxParameterfvEXT: TglGetMinmaxParameterfvEXT; - glGetMinmaxParameterivEXT: TglGetMinmaxParameterivEXT; - glHistogramEXT: TglHistogramEXT; - glMinmaxEXT: TglMinmaxEXT; - glResetHistogramEXT: TglResetHistogramEXT; - glResetMinmaxEXT: TglResetMinmaxEXT; - - // GL_EXT_index_func - glIndexFuncEXT: TglIndexFuncEXT; - - // GL_EXT_index_material - glIndexMaterialEXT: TglIndexMaterialEXT; - - // GL_EXT_light_texture - glApplyTextureEXT: TglApplyTextureEXT; - glTextureLightEXT: TglTextureLightEXT; - glTextureMaterialEXT: TglTextureMaterialEXT; - - // GL_EXT_multi_draw_arrays - glMultiDrawArraysEXT: TglMultiDrawArraysEXT; - glMultiDrawElementsEXT: TglMultiDrawElementsEXT; - - // GL_EXT_multisample - glSampleMaskEXT: TglSampleMaskEXT; - glSamplePatternEXT: TglSamplePatternEXT; - - // GL_EXT_paletted_texture - glColorTableEXT: TglColorTableEXT; - glGetColorTableEXT: TglGetColorTableEXT; - glGetColorTableParameterivEXT: TglGetColorTableParameterivEXT; - glGetColorTableParameterfvEXT: TglGetColorTableParameterfvEXT; - - // GL_EXT_pixel_transform - glPixelTransformParameteriEXT: TglPixelTransformParameteriEXT; - glPixelTransformParameterfEXT: TglPixelTransformParameterfEXT; - glPixelTransformParameterivEXT: TglPixelTransformParameterivEXT; - glPixelTransformParameterfvEXT: TglPixelTransformParameterfvEXT; - - // GL_EXT_point_parameters - glPointParameterfEXT: TglPointParameterfEXT; - glPointParameterfvEXT: TglPointParameterfvEXT; - - // GL_EXT_polygon_offset - glPolygonOffsetEXT: TglPolygonOffsetEXT; - - // GL_EXT_secondary_color - glSecondaryColor3bEXT: TglSecondaryColor3bEXT; - glSecondaryColor3bvEXT: TglSecondaryColor3bvEXT; - glSecondaryColor3dEXT: TglSecondaryColor3dEXT; - glSecondaryColor3dvEXT: TglSecondaryColor3dvEXT; - glSecondaryColor3fEXT: TglSecondaryColor3fEXT; - glSecondaryColor3fvEXT: TglSecondaryColor3fvEXT; - glSecondaryColor3iEXT: TglSecondaryColor3iEXT; - glSecondaryColor3ivEXT: TglSecondaryColor3ivEXT; - glSecondaryColor3sEXT: TglSecondaryColor3sEXT; - glSecondaryColor3svEXT: TglSecondaryColor3svEXT; - glSecondaryColor3ubEXT: TglSecondaryColor3ubEXT; - glSecondaryColor3ubvEXT: TglSecondaryColor3ubvEXT; - glSecondaryColor3uiEXT: TglSecondaryColor3uiEXT; - glSecondaryColor3uivEXT: TglSecondaryColor3uivEXT; - glSecondaryColor3usEXT: TglSecondaryColor3usEXT; - glSecondaryColor3usvEXT: TglSecondaryColor3usvEXT; - glSecondaryColorPointerEXT: TglSecondaryColorPointerEXT; - - // GL_EXT_stencil_two_side - glActiveStencilFaceEXT: TglActiveStencilFaceEXT; - - // GL_EXT_subtexture - glTexSubImage1DEXT: TglTexSubImage1DEXT; - glTexSubImage2DEXT: TglTexSubImage2DEXT; - - // GL_EXT_texture3D - glTexImage3DEXT: TglTexImage3DEXT; - glTexSubImage3DEXT: TglTexSubImage3DEXT; - - // GL_EXT_texture_object - glAreTexturesResidentEXT: TglAreTexturesResidentEXT; - glBindTextureEXT: TglBindTextureEXT; - glDeleteTexturesEXT: TglDeleteTexturesEXT; - glGenTexturesEXT: TglGenTexturesEXT; - glIsTextureEXT: TglIsTextureEXT; - glPrioritizeTexturesEXT: TglPrioritizeTexturesEXT; - - // GL_EXT_texture_perturb_normal - glTextureNormalEXT: TglTextureNormalEXT; - - // GL_EXT_vertex_array - glArrayElementEXT: TglArrayElementEXT; - glColorPointerEXT: TglColorPointerEXT; - glDrawArraysEXT: TglDrawArraysEXT; - glEdgeFlagPointerEXT: TglEdgeFlagPointerEXT; - glGetPointervEXT: TglGetPointervEXT; - glIndexPointerEXT: TglIndexPointerEXT; - glNormalPointerEXT: TglNormalPointerEXT; - glTexCoordPointerEXT: TglTexCoordPointerEXT; - glVertexPointerEXT: TglVertexPointerEXT; - - // GL_EXT_vertex_shader - glBeginVertexShaderEXT: TglBeginVertexShaderEXT; - glEndVertexShaderEXT: TglEndVertexShaderEXT; - glBindVertexShaderEXT: TglBindVertexShaderEXT; - glGenVertexShadersEXT: TglGenVertexShadersEXT; - glDeleteVertexShaderEXT: TglDeleteVertexShaderEXT; - glShaderOp1EXT: TglShaderOp1EXT; - glShaderOp2EXT: TglShaderOp2EXT; - glShaderOp3EXT: TglShaderOp3EXT; - glSwizzleEXT: TglSwizzleEXT; - glWriteMaskEXT: TglWriteMaskEXT; - glInsertComponentEXT: TglInsertComponentEXT; - glExtractComponentEXT: TglExtractComponentEXT; - glGenSymbolsEXT: TglGenSymbolsEXT; - glSetInvariantEXT: TglSetInvariantEXT; - glSetLocalConstantEXT: TglSetLocalConstantEXT; - glVariantbvEXT: TglVariantbvEXT; - glVariantsvEXT: TglVariantsvEXT; - glVariantivEXT: TglVariantivEXT; - glVariantfvEXT: TglVariantfvEXT; - glVariantdvEXT: TglVariantdvEXT; - glVariantubvEXT: TglVariantubvEXT; - glVariantusvEXT: TglVariantusvEXT; - glVariantuivEXT: TglVariantuivEXT; - glVariantPointerEXT: TglVariantPointerEXT; - glEnableVariantClientStateEXT: TglEnableVariantClientStateEXT; - glDisableVariantClientStateEXT: TglDisableVariantClientStateEXT; - glBindLightParameterEXT: TglBindLightParameterEXT; - glBindMaterialParameterEXT: TglBindMaterialParameterEXT; - glBindTexGenParameterEXT: TglBindTexGenParameterEXT; - glBindTextureUnitParameterEXT: TglBindTextureUnitParameterEXT; - glBindParameterEXT: TglBindParameterEXT; - glIsVariantEnabledEXT: TglIsVariantEnabledEXT; - glGetVariantBooleanvEXT: TglGetVariantBooleanvEXT; - glGetVariantIntegervEXT: TglGetVariantIntegervEXT; - glGetVariantFloatvEXT: TglGetVariantFloatvEXT; - glGetVariantPointervEXT: TglGetVariantPointervEXT; - glGetInvariantBooleanvEXT: TglGetInvariantBooleanvEXT; - glGetInvariantIntegervEXT: TglGetInvariantIntegervEXT; - glGetInvariantFloatvEXT: TglGetInvariantFloatvEXT; - glGetLocalConstantBooleanvEXT: TglGetLocalConstantBooleanvEXT; - glGetLocalConstantIntegervEXT: TglGetLocalConstantIntegervEXT; - glGetLocalConstantFloatvEXT: TglGetLocalConstantFloatvEXT; - - // GL_EXT_vertex_weighting - glVertexWeightfEXT: TglVertexWeightfEXT; - glVertexWeightfvEXT: TglVertexWeightfvEXT; - glVertexWeightPointerEXT: TglVertexWeightPointerEXT; - - // GL_EXT_stencil_clear_tag - glStencilClearTagEXT: TglStencilClearTagEXT; - - // GL_EXT_framebuffer_blit - glBlitFramebufferEXT: TglBlitFramebufferEXT; - - // GL_EXT_framebuffer_multisample - glRenderbufferStorageMultisampleEXT: TglRenderbufferStorageMultisampleEXT; - - // GL_EXT_timer_query - glGetQueryObjecti64vEXT: TglGetQueryObjecti64vEXT; - glGetQueryObjectui64vEXT: TglGetQueryObjectui64vEXT; - - // GL_EXT_gpu_program_parameters - glProgramEnvParameters4fvEXT: TglProgramEnvParameters4fvEXT; - glProgramLocalParameters4fvEXT: TglProgramLocalParameters4fvEXT; - - // GL_EXT_bindable_uniform - glUniformBufferEXT: TglUniformBufferEXT; - glGetUniformBufferSizeEXT: TglGetUniformBufferSizeEXT; - glGetUniformOffsetEXT: TglGetUniformOffsetEXT; - - // GL_EXT_draw_buffers2 - glColorMaskIndexedEXT: TglColorMaskIndexedEXT; - glGetBooleanIndexedvEXT: TglGetBooleanIndexedvEXT; - glGetIntegerIndexedvEXT: TglGetIntegerIndexedvEXT; - glEnableIndexedEXT: TglEnableIndexedEXT; - glDisableIndexedEXT: TglDisableIndexedEXT; - glIsEnabledIndexedEXT: TglIsEnabledIndexedEXT; - - // GL_EXT_draw_instanced - glDrawArraysInstancedEXT: TglDrawArraysInstancedEXT; - glDrawElementsInstancedEXT: TglDrawElementsInstancedEXT; - - // GL_EXT_geometry_shader4 - glProgramParameteriEXT: TglProgramParameteriEXT; - glFramebufferTextureEXT: TglFramebufferTextureEXT; -// glFramebufferTextureLayerEXT: TglFramebufferTextureLayerEXT; - glFramebufferTextureFaceEXT: TglFramebufferTextureFaceEXT; - - // GL_EXT_gpu_shader4 - glVertexAttribI1iEXT: TglVertexAttribI1iEXT; - glVertexAttribI2iEXT: TglVertexAttribI2iEXT; - glVertexAttribI3iEXT: TglVertexAttribI3iEXT; - glVertexAttribI4iEXT: TglVertexAttribI4iEXT; - glVertexAttribI1uiEXT: TglVertexAttribI1uiEXT; - glVertexAttribI2uiEXT: TglVertexAttribI2uiEXT; - glVertexAttribI3uiEXT: TglVertexAttribI3uiEXT; - glVertexAttribI4uiEXT: TglVertexAttribI4uiEXT; - glVertexAttribI1ivEXT: TglVertexAttribI1ivEXT; - glVertexAttribI2ivEXT: TglVertexAttribI2ivEXT; - glVertexAttribI3ivEXT: TglVertexAttribI3ivEXT; - glVertexAttribI4ivEXT: TglVertexAttribI4ivEXT; - glVertexAttribI1uivEXT: TglVertexAttribI1uivEXT; - glVertexAttribI2uivEXT: TglVertexAttribI2uivEXT; - glVertexAttribI3uivEXT: TglVertexAttribI3uivEXT; - glVertexAttribI4uivEXT: TglVertexAttribI4uivEXT; - glVertexAttribI4bvEXT:TglVertexAttribI4bvEXT ; - glVertexAttribI4svEXT: TglVertexAttribI4svEXT; - glVertexAttribI4ubvEXT: TglVertexAttribI4ubvEXT; - glVertexAttribI4usvEXT: TglVertexAttribI4usvEXT; - glVertexAttribIPointerEXT: TglVertexAttribIPointerEXT; - glGetVertexAttribIivEXT: TglGetVertexAttribIivEXT; - glGetVertexAttribIuivEXT: TglGetVertexAttribIuivEXT; - glUniform1uiEXT: TglUniform1uiEXT; - glUniform2uiEXT: TglUniform2uiEXT; - glUniform3uiEXT: TglUniform3uiEXT; - glUniform4uiEXT: TglUniform4uiEXT; - glUniform1uivEXT: TglUniform1uivEXT; - glUniform2uivEXT: TglUniform2uivEXT; - glUniform3uivEXT: TglUniform3uivEXT; - glUniform4uivEXT: TglUniform4uivEXT; - glGetUniformuivEXT: TglGetUniformuivEXT; - glBindFragDataLocationEXT: TglBindFragDataLocationEXT; - glGetFragDataLocationEXT: TglGetFragDataLocationEXT; - - // GL_EXT_texture_array - glFramebufferTextureLayerEXT: TglFramebufferTextureLayerEXT; - - // GL_EXT_texture_buffer_object - glTexBufferEXT: TglTexBufferEXT; - - // GL_EXT_texture_integer - glClearColorIiEXT: TglClearColorIiEXT; - glClearColorIuiEXT: TglClearColorIuiEXT; - glTexParameterIivEXT: TglTexParameterIivEXT; - glTexParameterIuivEXT: TglTexParameterIuivEXT; - glGetTexParameterIivEXT: TglGetTexParameterIivEXT; - glGetTexParameterIiuvEXT: TglGetTexParameterIiuvEXT; - - // GL_EXT_transform_feedback - glBeginTransformFeedbackEXT: TglBeginTransformFeedbackEXT; - glEndTransformFeedbackEXT: TglEndTransformFeedbackEXT; - glBindBufferRangeEXT: TglBindBufferRangeEXT; - glBindBufferOffsetEXT: TglBindBufferOffsetEXT; - glBindBufferBaseEXT: TglBindBufferBaseEXT; - glTransformFeedbackVaryingsEXT: TglTransformFeedbackVaryingsEXT; - glGetTransformFeedbackVaryingEXT: TglGetTransformFeedbackVaryingEXT; - - // GL_EXT_direct_state_access - glClientAttribDefaultEXT: TglClientAttribDefaultEXT; - glPushClientAttribDefaultEXT: TglPushClientAttribDefaultEXT; - glMatrixLoadfEXT: TglMatrixLoadfEXT; - glMatrixLoaddEXT: TglMatrixLoaddEXT; - glMatrixMultfEXT: TglMatrixMultfEXT; - glMatrixMultdEXT: TglMatrixMultdEXT; - glMatrixLoadIdentityEXT: TglMatrixLoadIdentityEXT; - glMatrixRotatefEXT: TglMatrixRotatefEXT; - glMatrixRotatedEXT: TglMatrixRotatedEXT; - glMatrixScalefEXT: TglMatrixScalefEXT; - glMatrixScaledEXT: TglMatrixScaledEXT; - glMatrixTranslatefEXT: TglMatrixTranslatefEXT; - glMatrixTranslatedEXT: TglMatrixTranslatedEXT; - glMatrixFrustumEXT: TglMatrixFrustumEXT; - glMatrixOrthoEXT: TglMatrixOrthoEXT; - glMatrixPopEXT: TglMatrixPopEXT; - glMatrixPushEXT: TglMatrixPushEXT; - glMatrixLoadTransposefEXT: TglMatrixLoadTransposefEXT; - glMatrixLoadTransposedEXT: TglMatrixLoadTransposedEXT; - glMatrixMultTransposefEXT: TglMatrixMultTransposefEXT; - glMatrixMultTransposedEXT: TglMatrixMultTransposedEXT; - glTextureParameterfEXT: TglTextureParameterfEXT; - glTextureParameterfvEXT: TglTextureParameterfvEXT; - glTextureParameteriEXT: TglTextureParameteriEXT; - glTextureParameterivEXT: TglTextureParameterivEXT; - glTextureImage1DEXT: TglTextureImage1DEXT; - glTextureImage2DEXT: TglTextureImage2DEXT; - glTextureSubImage1DEXT: TglTextureSubImage1DEXT; - glTextureSubImage2DEXT: TglTextureSubImage2DEXT; - glCopyTextureImage1DEXT: TglCopyTextureImage1DEXT; - glCopyTextureImage2DEXT: TglCopyTextureImage2DEXT; - glCopyTextureSubImage1DEXT: TglCopyTextureSubImage1DEXT; - glCopyTextureSubImage2DEXT: TglCopyTextureSubImage2DEXT; - glGetTextureImageEXT: TglGetTextureImageEXT; - glGetTextureParameterfvEXT: TglGetTextureParameterfvEXT; - glGetTextureParameterivEXT: TglGetTextureParameterivEXT; - glGetTextureLevelParameterfvEXT: TglGetTextureLevelParameterfvEXT; - glGetTextureLevelParameterivEXT: TglGetTextureLevelParameterivEXT; - glTextureImage3DEXT: TglTextureImage3DEXT; - glTextureSubImage3DEXT: TglTextureSubImage3DEXT; - glCopyTextureSubImage3DEXT: TglCopyTextureSubImage3DEXT; - glMultiTexParameterfEXT: TglMultiTexParameterfEXT; - glMultiTexParameterfvEXT: TglMultiTexParameterfvEXT; - glMultiTexParameteriEXT: TglMultiTexParameteriEXT; - glMultiTexParameterivEXT: TglMultiTexParameterivEXT; - glMultiTexImage1DEXT: TglMultiTexImage1DEXT; - glMultiTexImage2DEXT: TglMultiTexImage2DEXT; - glMultiTexSubImage1DEXT: TglMultiTexSubImage1DEXT; - glMultiTexSubImage2DEXT: TglMultiTexSubImage2DEXT; - glCopyMultiTexImage1DEXT: TglCopyMultiTexImage1DEXT; - glCopyMultiTexImage2DEXT: TglCopyMultiTexImage2DEXT; - glCopyMultiTexSubImage1DEXT: TglCopyMultiTexSubImage1DEXT; - glCopyMultiTexSubImage2DEXT: TglCopyMultiTexSubImage2DEXT; - glGetMultiTexImageEXT: TglGetMultiTexImageEXT; - glGetMultiTexParameterfvEXT: TglGetMultiTexParameterfvEXT; - glGetMultiTexParameterivEXT: TglGetMultiTexParameterivEXT; - glGetMultiTexLevelParameterfvEXT: TglGetMultiTexLevelParameterfvEXT; - glGetMultiTexLevelParameterivEXT: TglGetMultiTexLevelParameterivEXT; - glMultiTexImage3DEXT: TglMultiTexImage3DEXT; - glMultiTexSubImage3DEXT: TglMultiTexSubImage3DEXT; - glCopyMultiTexSubImage3DEXT: TglCopyMultiTexSubImage3DEXT; - glBindMultiTextureEXT: TglBindMultiTextureEXT; - glEnableClientStateIndexedEXT: TglEnableClientStateIndexedEXT; - glDisableClientStateIndexedEXT: TglDisableClientStateIndexedEXT; - glMultiTexCoordPointerEXT: TglMultiTexCoordPointerEXT; - glMultiTexEnvfEXT: TglMultiTexEnvfEXT; - glMultiTexEnvfvEXT: TglMultiTexEnvfvEXT; - glMultiTexEnviEXT: TglMultiTexEnviEXT; - glMultiTexEnvivEXT: TglMultiTexEnvivEXT; - glMultiTexGendEXT: TglMultiTexGendEXT; - glMultiTexGendvEXT: TglMultiTexGendvEXT; - glMultiTexGenfEXT: TglMultiTexGenfEXT; - glMultiTexGenfvEXT: TglMultiTexGenfvEXT; - glMultiTexGeniEXT: TglMultiTexGeniEXT; - glMultiTexGenivEXT: TglMultiTexGenivEXT; - glGetMultiTexEnvfvEXT: TglGetMultiTexEnvfvEXT; - glGetMultiTexEnvivEXT: TglGetMultiTexEnvivEXT; - glGetMultiTexGendvEXT: TglGetMultiTexGendvEXT; - glGetMultiTexGenfvEXT: TglGetMultiTexGenfvEXT; - glGetMultiTexGenivEXT: TglGetMultiTexGenivEXT; - glGetFloatIndexedvEXT: TglGetFloatIndexedvEXT; - glGetDoubleIndexedvEXT: TglGetDoubleIndexedvEXT; - glGetPointerIndexedvEXT: TglGetPointerIndexedvEXT; - glCompressedTextureImage3DEXT: TglCompressedTextureImage3DEXT; - glCompressedTextureImage2DEXT: TglCompressedTextureImage2DEXT; - glCompressedTextureImage1DEXT: TglCompressedTextureImage1DEXT; - glCompressedTextureSubImage3DEXT: TglCompressedTextureSubImage3DEXT; - glCompressedTextureSubImage2DEXT: TglCompressedTextureSubImage2DEXT; - glCompressedTextureSubImage1DEXT: TglCompressedTextureSubImage1DEXT; - glGetCompressedTextureImageEXT: TglGetCompressedTextureImageEXT; - glCompressedMultiTexImage3DEXT: TglCompressedMultiTexImage3DEXT; - glCompressedMultiTexImage2DEXT: TglCompressedMultiTexImage2DEXT; - glCompressedMultiTexImage1DEXT: TglCompressedMultiTexImage1DEXT; - glCompressedMultiTexSubImage3DEXT: TglCompressedMultiTexSubImage3DEXT; - glCompressedMultiTexSubImage2DEXT: TglCompressedMultiTexSubImage2DEXT; - glCompressedMultiTexSubImage1DEXT: TglCompressedMultiTexSubImage1DEXT; - glGetCompressedMultiTexImageEXT: TglGetCompressedMultiTexImageEXT; - glNamedProgramStringEXT: TglNamedProgramStringEXT; - glNamedProgramLocalParameter4dEXT: TglNamedProgramLocalParameter4dEXT; - glNamedProgramLocalParameter4dvEXT: TglNamedProgramLocalParameter4dvEXT; - glNamedProgramLocalParameter4fEXT: TglNamedProgramLocalParameter4fEXT; - glNamedProgramLocalParameter4fvEXT: TglNamedProgramLocalParameter4fvEXT; - glGetNamedProgramLocalParameterdvEXT: TglGetNamedProgramLocalParameterdvEXT; - glGetNamedProgramLocalParameterfvEXT: TglGetNamedProgramLocalParameterfvEXT; - glGetNamedProgramivEXT: TglGetNamedProgramivEXT; - glGetNamedProgramStringEXT: TglGetNamedProgramStringEXT; - glNamedProgramLocalParameters4fvEXT: TglNamedProgramLocalParameters4fvEXT; - glNamedProgramLocalParameterI4iEXT: TglNamedProgramLocalParameterI4iEXT; - glNamedProgramLocalParameterI4ivEXT: TglNamedProgramLocalParameterI4ivEXT; - glNamedProgramLocalParametersI4ivEXT: TglNamedProgramLocalParametersI4ivEXT; - glNamedProgramLocalParameterI4uiEXT: TglNamedProgramLocalParameterI4uiEXT; - glNamedProgramLocalParameterI4uivEXT: TglNamedProgramLocalParameterI4uivEXT; - glNamedProgramLocalParametersI4uivEXT: TglNamedProgramLocalParametersI4uivEXT; - glGetNamedProgramLocalParameterIivEXT: TglGetNamedProgramLocalParameterIivEXT; - glGetNamedProgramLocalParameterIuivEXT: TglGetNamedProgramLocalParameterIuivEXT; - glTextureParameterIivEXT: TglTextureParameterIivEXT; - glTextureParameterIuivEXT: TglTextureParameterIuivEXT; - glGetTextureParameterIivEXT: TglGetTextureParameterIivEXT; - glGetTextureParameterIuivEXT: TglGetTextureParameterIuivEXT; - glMultiTexParameterIivEXT: TglMultiTexParameterIivEXT; - glMultiTexParameterIuivEXT: TglMultiTexParameterIuivEXT; - glGetMultiTexParameterIivEXT: TglGetMultiTexParameterIivEXT; - glGetMultiTexParameterIuivEXT: TglGetMultiTexParameterIuivEXT; - glProgramUniform1fEXT: TglProgramUniform1fEXT; - glProgramUniform2fEXT: TglProgramUniform2fEXT; - glProgramUniform3fEXT: TglProgramUniform3fEXT; - glProgramUniform4fEXT: TglProgramUniform4fEXT; - glProgramUniform1iEXT: TglProgramUniform1iEXT; - glProgramUniform2iEXT: TglProgramUniform2iEXT; - glProgramUniform3iEXT: TglProgramUniform3iEXT; - glProgramUniform4iEXT: TglProgramUniform4iEXT; - glProgramUniform1fvEXT: TglProgramUniform1fvEXT; - glProgramUniform2fvEXT: TglProgramUniform2fvEXT; - glProgramUniform3fvEXT: TglProgramUniform3fvEXT; - glProgramUniform4fvEXT: TglProgramUniform4fvEXT; - glProgramUniform1ivEXT: TglProgramUniform1ivEXT; - glProgramUniform2ivEXT: TglProgramUniform2ivEXT; - glProgramUniform3ivEXT: TglProgramUniform3ivEXT; - glProgramUniform4ivEXT: TglProgramUniform4ivEXT; - glProgramUniformMatrix2fvEXT: TglProgramUniformMatrix2fvEXT; - glProgramUniformMatrix3fvEXT: TglProgramUniformMatrix3fvEXT; - glProgramUniformMatrix4fvEXT: TglProgramUniformMatrix4fvEXT; - glProgramUniformMatrix2x3fvEXT: TglProgramUniformMatrix2x3fvEXT; - glProgramUniformMatrix3x2fvEXT: TglProgramUniformMatrix3x2fvEXT; - glProgramUniformMatrix2x4fvEXT: TglProgramUniformMatrix2x4fvEXT; - glProgramUniformMatrix4x2fvEXT: TglProgramUniformMatrix4x2fvEXT; - glProgramUniformMatrix3x4fvEXT: TglProgramUniformMatrix3x4fvEXT; - glProgramUniformMatrix4x3fvEXT: TglProgramUniformMatrix4x3fvEXT; - glProgramUniform1uiEXT: TglProgramUniform1uiEXT; - glProgramUniform2uiEXT: TglProgramUniform2uiEXT; - glProgramUniform3uiEXT: TglProgramUniform3uiEXT; - glProgramUniform4uiEXT: TglProgramUniform4uiEXT; - glProgramUniform1uivEXT: TglProgramUniform1uivEXT; - glProgramUniform2uivEXT: TglProgramUniform2uivEXT; - glProgramUniform3uivEXT: TglProgramUniform3uivEXT; - glProgramUniform4uivEXT: TglProgramUniform4uivEXT; - glNamedBufferDataEXT: TglNamedBufferDataEXT; - glNamedBufferSubDataEXT: TglNamedBufferSubDataEXT; - glMapNamedBufferEXT: TglMapNamedBufferEXT; - glUnmapNamedBufferEXT: TglUnmapNamedBufferEXT; - glGetNamedBufferParameterivEXT: TglGetNamedBufferParameterivEXT; - glGetNamedBufferPointervEXT: TglGetNamedBufferPointervEXT; - glGetNamedBufferSubDataEXT: TglGetNamedBufferSubDataEXT; - glTextureBufferEXT: TglTextureBufferEXT; - glMultiTexBufferEXT: TglMultiTexBufferEXT; - glNamedRenderbufferStorageEXT: TglNamedRenderbufferStorageEXT; - glGetNamedRenderbufferParameterivEXT: TglGetNamedRenderbufferParameterivEXT; - glCheckNamedFramebufferStatusEXT: TglCheckNamedFramebufferStatusEXT; - glNamedFramebufferTexture1DEXT: TglNamedFramebufferTexture1DEXT; - glNamedFramebufferTexture2DEXT: TglNamedFramebufferTexture2DEXT; - glNamedFramebufferTexture3DEXT: TglNamedFramebufferTexture3DEXT; - glNamedFramebufferRenderbufferEXT: TglNamedFramebufferRenderbufferEXT; - glGetNamedFramebufferAttachmentParameterivEXT: TglGetNamedFramebufferAttachmentParameterivEXT; - glGenerateTextureMipmapEXT: TglGenerateTextureMipmapEXT; - glGenerateMultiTexMipmapEXT: TglGenerateMultiTexMipmapEXT; - glFramebufferDrawBufferEXT: TglFramebufferDrawBufferEXT; - glFramebufferDrawBuffersEXT: TglFramebufferDrawBuffersEXT; - glFramebufferReadBufferEXT: TglFramebufferReadBufferEXT; - glGetFramebufferParameterivEXT: TglGetFramebufferParameterivEXT; - glNamedRenderbufferStorageMultisampleEXT: TglNamedRenderbufferStorageMultisampleEXT; - glNamedRenderbufferStorageMultisampleCoverageEXT: TglNamedRenderbufferStorageMultisampleCoverageEXT; - glNamedFramebufferTextureEXT: TglNamedFramebufferTextureEXT; - glNamedFramebufferTextureLayerEXT: TglNamedFramebufferTextureLayerEXT; - glNamedFramebufferTextureFaceEXT: TglNamedFramebufferTextureFaceEXT; - glTextureRenderbufferEXT: TglTextureRenderbufferEXT; - glMultiTexRenderbufferEXT: TglMultiTexRenderbufferEXT; - - // GL_HP_image_transform - glImageTransformParameteriHP: TglImageTransformParameteriHP; - glImageTransformParameterfHP: TglImageTransformParameterfHP; - glImageTransformParameterivHP: TglImageTransformParameterivHP; - glImageTransformParameterfvHP: TglImageTransformParameterfvHP; - glGetImageTransformParameterivHP: TglGetImageTransformParameterivHP; - glGetImageTransformParameterfvHP: TglGetImageTransformParameterfvHP; - - // GL_EXT_depth_bounds_test - glDepthBoundsEXT: TglDepthBoundsEXT; - - // GL_EXT_blend_equation_separate - glBlendEquationSeparateEXT: TglBlendEquationSeparateEXT; - - // GL_IBM_multimode_draw_arrays - glMultiModeDrawArraysIBM: TglMultiModeDrawArraysIBM; - glMultiModeDrawElementsIBM: TglMultiModeDrawElementsIBM; - - // GL_IBM_vertex_array_lists - glColorPointerListIBM: TglColorPointerListIBM; - glSecondaryColorPointerListIBM: TglSecondaryColorPointerListIBM; - glEdgeFlagPointerListIBM: TglEdgeFlagPointerListIBM; - glFogCoordPointerListIBM: TglFogCoordPointerListIBM; - glIndexPointerListIBM: TglIndexPointerListIBM; - glNormalPointerListIBM: TglNormalPointerListIBM; - glTexCoordPointerListIBM: TglTexCoordPointerListIBM; - glVertexPointerListIBM: TglVertexPointerListIBM; - - // GL_INGR_blend_func_separate - glBlendFuncSeparateINGR: TglBlendFuncSeparateINGR; - - // GL_INTEL_parallel_arrays - glVertexPointervINTEL: TglVertexPointervINTEL; - glNormalPointervINTEL: TglNormalPointervINTEL; - glColorPointervINTEL: TglColorPointervINTEL; - glTexCoordPointervINTEL: TglTexCoordPointervINTEL; - - // GL_MESA_resize_buffers - glResizeBuffersMESA: TglResizeBuffersMESA; - - // GL_MESA_window_pos - glWindowPos2dMESA: TglWindowPos2dMESA; - glWindowPos2dvMESA: TglWindowPos2dvMESA; - glWindowPos2fMESA: TglWindowPos2fMESA; - glWindowPos2fvMESA: TglWindowPos2fvMESA; - glWindowPos2iMESA: TglWindowPos2iMESA; - glWindowPos2ivMESA: TglWindowPos2ivMESA; - glWindowPos2sMESA: TglWindowPos2sMESA; - glWindowPos2svMESA: TglWindowPos2svMESA; - glWindowPos3dMESA: TglWindowPos3dMESA; - glWindowPos3dvMESA: TglWindowPos3dvMESA; - glWindowPos3fMESA: TglWindowPos3fMESA; - glWindowPos3fvMESA: TglWindowPos3fvMESA; - glWindowPos3iMESA: TglWindowPos3iMESA; - glWindowPos3ivMESA: TglWindowPos3ivMESA; - glWindowPos3sMESA: TglWindowPos3sMESA; - glWindowPos3svMESA: TglWindowPos3svMESA; - glWindowPos4dMESA: TglWindowPos4dMESA; - glWindowPos4dvMESA: TglWindowPos4dvMESA; - glWindowPos4fMESA: TglWindowPos4fMESA; - glWindowPos4fvMESA: TglWindowPos4fvMESA; - glWindowPos4iMESA: TglWindowPos4iMESA; - glWindowPos4ivMESA: TglWindowPos4ivMESA; - glWindowPos4sMESA: TglWindowPos4sMESA; - glWindowPos4svMESA: TglWindowPos4svMESA; - - // GL_NV_evaluators - glMapControlPointsNV: TglMapControlPointsNV; - glMapParameterivNV: TglMapParameterivNV; - glMapParameterfvNV: TglMapParameterfvNV; - glGetMapControlPointsNV: TglGetMapControlPointsNV; - glGetMapParameterivNV: TglGetMapParameterivNV; - glGetMapParameterfvNV: TglGetMapParameterfvNV; - glGetMapAttribParameterivNV: TglGetMapAttribParameterivNV; - glGetMapAttribParameterfvNV: TglGetMapAttribParameterfvNV; - glEvalMapsNV: TglEvalMapsNV; - - // GL_NV_fence - glDeleteFencesNV: TglDeleteFencesNV; - glGenFencesNV: TglGenFencesNV; - glIsFenceNV: TglIsFenceNV; - glTestFenceNV: TglTestFenceNV; - glGetFenceivNV: TglGetFenceivNV; - glFinishFenceNV: TglFinishFenceNV; - glSetFenceNV: TglSetFenceNV; - - // GL_NV_fragment_program - glProgramNamedParameter4fNV: TglProgramNamedParameter4fNV; - glProgramNamedParameter4dNV: TglProgramNamedParameter4dNV; - glProgramNamedParameter4fvNV: TglProgramNamedParameter4fvNV; - glProgramNamedParameter4dvNV: TglProgramNamedParameter4dvNV; - glGetProgramNamedParameterfvNV: TglGetProgramNamedParameterfvNV; - glGetProgramNamedParameterdvNV: TglGetProgramNamedParameterdvNV; - - // GL_NV_half_float - glVertex2hNV: TglVertex2hNV; - glVertex2hvNV: TglVertex2hvNV; - glVertex3hNV: TglVertex3hNV; - glVertex3hvNV: TglVertex3hvNV; - glVertex4hNV: TglVertex4hNV; - glVertex4hvNV: TglVertex4hvNV; - glNormal3hNV: TglNormal3hNV; - glNormal3hvNV: TglNormal3hvNV; - glColor3hNV: TglColor3hNV; - glColor3hvNV: TglColor3hvNV; - glColor4hNV: TglColor4hNV; - glColor4hvNV: TglColor4hvNV; - glTexCoord1hNV: TglTexCoord1hNV; - glTexCoord1hvNV: TglTexCoord1hvNV; - glTexCoord2hNV: TglTexCoord2hNV; - glTexCoord2hvNV: TglTexCoord2hvNV; - glTexCoord3hNV: TglTexCoord3hNV; - glTexCoord3hvNV: TglTexCoord3hvNV; - glTexCoord4hNV: TglTexCoord4hNV; - glTexCoord4hvNV: TglTexCoord4hvNV; - glMultiTexCoord1hNV: TglMultiTexCoord1hNV; - glMultiTexCoord1hvNV: TglMultiTexCoord1hvNV; - glMultiTexCoord2hNV: TglMultiTexCoord2hNV; - glMultiTexCoord2hvNV: TglMultiTexCoord2hvNV; - glMultiTexCoord3hNV: TglMultiTexCoord3hNV; - glMultiTexCoord3hvNV: TglMultiTexCoord3hvNV; - glMultiTexCoord4hNV: TglMultiTexCoord4hNV; - glMultiTexCoord4hvNV: TglMultiTexCoord4hvNV; - glFogCoordhNV: TglFogCoordhNV; - glFogCoordhvNV: TglFogCoordhvNV; - glSecondaryColor3hNV: TglSecondaryColor3hNV; - glSecondaryColor3hvNV: TglSecondaryColor3hvNV; - glVertexWeighthNV: TglVertexWeighthNV; - glVertexWeighthvNV: TglVertexWeighthvNV; - glVertexAttrib1hNV: TglVertexAttrib1hNV; - glVertexAttrib1hvNV: TglVertexAttrib1hvNV; - glVertexAttrib2hNV: TglVertexAttrib2hNV; - glVertexAttrib2hvNV: TglVertexAttrib2hvNV; - glVertexAttrib3hNV: TglVertexAttrib3hNV; - glVertexAttrib3hvNV: TglVertexAttrib3hvNV; - glVertexAttrib4hNV: TglVertexAttrib4hNV; - glVertexAttrib4hvNV: TglVertexAttrib4hvNV; - glVertexAttribs1hvNV: TglVertexAttribs1hvNV; - glVertexAttribs2hvNV: TglVertexAttribs2hvNV; - glVertexAttribs3hvNV: TglVertexAttribs3hvNV; - glVertexAttribs4hvNV: TglVertexAttribs4hvNV; - - // GL_NV_occlusion_query - glGenOcclusionQueriesNV: TglGenOcclusionQueriesNV; - glDeleteOcclusionQueriesNV: TglDeleteOcclusionQueriesNV; - glIsOcclusionQueryNV: TglIsOcclusionQueryNV; - glBeginOcclusionQueryNV: TglBeginOcclusionQueryNV; - glEndOcclusionQueryNV: TglEndOcclusionQueryNV; - glGetOcclusionQueryivNV: TglGetOcclusionQueryivNV; - glGetOcclusionQueryuivNV: TglGetOcclusionQueryuivNV; - - // GL_NV_pixel_data_range - glPixelDataRangeNV: TglPixelDataRangeNV; - glFlushPixelDataRangeNV: TglFlushPixelDataRangeNV; - - // GL_NV_point_sprite - glPointParameteriNV: TglPointParameteriNV; - glPointParameterivNV: TglPointParameterivNV; - - // GL_NV_primitive_restart - glPrimitiveRestartNV: TglPrimitiveRestartNV; - glPrimitiveRestartIndexNV: TglPrimitiveRestartIndexNV; - - // GL_NV_register_combiners - glCombinerParameterfvNV: TglCombinerParameterfvNV; - glCombinerParameterfNV: TglCombinerParameterfNV; - glCombinerParameterivNV: TglCombinerParameterivNV; - glCombinerParameteriNV: TglCombinerParameteriNV; - glCombinerInputNV: TglCombinerInputNV; - glCombinerOutputNV: TglCombinerOutputNV; - glFinalCombinerInputNV: TglFinalCombinerInputNV; - glGetCombinerInputParameterfvNV: TglGetCombinerInputParameterfvNV; - glGetCombinerInputParameterivNV: TglGetCombinerInputParameterivNV; - glGetCombinerOutputParameterfvNV: TglGetCombinerOutputParameterfvNV; - glGetCombinerOutputParameterivNV: TglGetCombinerOutputParameterivNV; - glGetFinalCombinerInputParameterfvNV: TglGetFinalCombinerInputParameterfvNV; - glGetFinalCombinerInputParameterivNV: TglGetFinalCombinerInputParameterivNV; - - // GL_NV_register_combiners2 - glCombinerStageParameterfvNV: TglCombinerStageParameterfvNV; - glGetCombinerStageParameterfvNV: TglGetCombinerStageParameterfvNV; - - // GL_NV_vertex_array_range - glFlushVertexArrayRangeNV: TglFlushVertexArrayRangeNV; - glVertexArrayRangeNV: TglVertexArrayRangeNV; - - // GL_NV_vertex_program - glAreProgramsResidentNV: TglAreProgramsResidentNV; - glBindProgramNV: TglBindProgramNV; - glDeleteProgramsNV: TglDeleteProgramsNV; - glExecuteProgramNV: TglExecuteProgramNV; - glGenProgramsNV: TglGenProgramsNV; - glGetProgramParameterdvNV: TglGetProgramParameterdvNV; - glGetProgramParameterfvNV: TglGetProgramParameterfvNV; - glGetProgramivNV: TglGetProgramivNV; - glGetProgramStringNV: TglGetProgramStringNV; - glGetTrackMatrixivNV: TglGetTrackMatrixivNV; - glGetVertexAttribdvNV: TglGetVertexAttribdvNV; - glGetVertexAttribfvNV: TglGetVertexAttribfvNV; - glGetVertexAttribivNV: TglGetVertexAttribivNV; - glGetVertexAttribPointervNV: TglGetVertexAttribPointervNV; - glIsProgramNV: TglIsProgramNV; - glLoadProgramNV: TglLoadProgramNV; - glProgramParameter4dNV: TglProgramParameter4dNV; - glProgramParameter4dvNV: TglProgramParameter4dvNV; - glProgramParameter4fNV: TglProgramParameter4fNV; - glProgramParameter4fvNV: TglProgramParameter4fvNV; - glProgramParameters4dvNV: TglProgramParameters4dvNV; - glProgramParameters4fvNV: TglProgramParameters4fvNV; - glRequestResidentProgramsNV: TglRequestResidentProgramsNV; - glTrackMatrixNV: TglTrackMatrixNV; - glVertexAttribPointerNV: TglVertexAttribPointerNV; - glVertexAttrib1dNV: TglVertexAttrib1dNV; - glVertexAttrib1dvNV: TglVertexAttrib1dvNV; - glVertexAttrib1fNV: TglVertexAttrib1fNV; - glVertexAttrib1fvNV: TglVertexAttrib1fvNV; - glVertexAttrib1sNV: TglVertexAttrib1sNV; - glVertexAttrib1svNV: TglVertexAttrib1svNV; - glVertexAttrib2dNV: TglVertexAttrib2dNV; - glVertexAttrib2dvNV: TglVertexAttrib2dvNV; - glVertexAttrib2fNV: TglVertexAttrib2fNV; - glVertexAttrib2fvNV: TglVertexAttrib2fvNV; - glVertexAttrib2sNV: TglVertexAttrib2sNV; - glVertexAttrib2svNV: TglVertexAttrib2svNV; - glVertexAttrib3dNV: TglVertexAttrib3dNV; - glVertexAttrib3dvNV: TglVertexAttrib3dvNV; - glVertexAttrib3fNV: TglVertexAttrib3fNV; - glVertexAttrib3fvNV: TglVertexAttrib3fvNV; - glVertexAttrib3sNV: TglVertexAttrib3sNV; - glVertexAttrib3svNV: TglVertexAttrib3svNV; - glVertexAttrib4dNV: TglVertexAttrib4dNV; - glVertexAttrib4dvNV: TglVertexAttrib4dvNV; - glVertexAttrib4fNV: TglVertexAttrib4fNV; - glVertexAttrib4fvNV: TglVertexAttrib4fvNV; - glVertexAttrib4sNV: TglVertexAttrib4sNV; - glVertexAttrib4svNV: TglVertexAttrib4svNV; - glVertexAttrib4ubNV: TglVertexAttrib4ubNV; - glVertexAttrib4ubvNV: TglVertexAttrib4ubvNV; - glVertexAttribs1dvNV: TglVertexAttribs1dvNV; - glVertexAttribs1fvNV: TglVertexAttribs1fvNV; - glVertexAttribs1svNV: TglVertexAttribs1svNV; - glVertexAttribs2dvNV: TglVertexAttribs2dvNV; - glVertexAttribs2fvNV: TglVertexAttribs2fvNV; - glVertexAttribs2svNV: TglVertexAttribs2svNV; - glVertexAttribs3dvNV: TglVertexAttribs3dvNV; - glVertexAttribs3fvNV: TglVertexAttribs3fvNV; - glVertexAttribs3svNV: TglVertexAttribs3svNV; - glVertexAttribs4dvNV: TglVertexAttribs4dvNV; - glVertexAttribs4fvNV: TglVertexAttribs4fvNV; - glVertexAttribs4svNV: TglVertexAttribs4svNV; - glVertexAttribs4ubvNV: TglVertexAttribs4ubvNV; - - // GL_NV_depth_buffer_float - glDepthRangedNV: TglDepthRangedNV; - glClearDepthdNV: TglClearDepthdNV; - glDepthBoundsdNV: TglDepthBoundsdNV; - - // GL_NV_framebuffer_multisample_coverage - glRenderbufferStorageMultsampleCoverageNV: TglRenderbufferStorageMultsampleCoverageNV; - - // GL_NV_geometry_program4 - glProgramVertexLimitNV: TglProgramVertexLimitNV; - - // GL_NV_gpu_program4 - glProgramLocalParameterI4iNV: TglProgramLocalParameterI4iNV; - glProgramLocalParameterI4ivNV: TglProgramLocalParameterI4ivNV; - glProgramLocalParametersI4ivNV: TglProgramLocalParametersI4ivNV; - glProgramLocalParameterI4uiNV: TglProgramLocalParameterI4uiNV; - glProgramLocalParameterI4uivNV: TglProgramLocalParameterI4uivNV; - glProgramLocalParametersI4uivNV: TglProgramLocalParametersI4uivNV; - glProgramEnvParameterI4iNV: TglProgramEnvParameterI4iNV; - glProgramEnvParameterI4ivNV: TglProgramEnvParameterI4ivNV; - glProgramEnvParametersI4ivNV: TglProgramEnvParametersI4ivNV; - glProgramEnvParameterI4uiNV: TglProgramEnvParameterI4uiNV; - glProgramEnvParameterI4uivNV: TglProgramEnvParameterI4uivNV; - glProgramEnvParametersI4uivNV: TglProgramEnvParametersI4uivNV; - glGetProgramLocalParameterIivNV: TglGetProgramLocalParameterIivNV; - glGetProgramLocalParameterIuivNV: TglGetProgramLocalParameterIuivNV; - glGetProgramEnvParameterIivNV: TglGetProgramEnvParameterIivNV; - glGetProgramEnvParameterIuivNV: TglGetProgramEnvParameterIuivNV; - - // GL_NV_parameter_buffer_object - glProgramBufferParametersfvNV: TglProgramBufferParametersfvNV; - glProgramBufferParametersIivNV: TglProgramBufferParametersIivNV; - glProgramBufferParametersIuivNV: TglProgramBufferParametersIuivNV; - - // GL_NV_transform_feedback - glBeginTransformFeedbackNV: TglBeginTransformFeedbackNV; - glEndTransformFeedbackNV: TglEndTransformFeedbackNV; - glTransformFeedbackAttribsNV: TglTransformFeedbackAttribsNV; - glBindBufferRangeNV: TglBindBufferRangeNV; - glBindBufferOffsetNV: TglBindBufferOffsetNV; - glBindBufferBaseNV: TglBindBufferBaseNV; - glTransformFeedbackVaryingsNV: TglTransformFeedbackVaryingsNV; - glActiveVaryingNV: TglActiveVaryingNV; - glGetVaryingLocationNV: TglGetVaryingLocationNV; - glGetActiveVaryingNV: TglGetActiveVaryingNV; - glGetTransformFeedbackVaryingNV: TglGetTransformFeedbackVaryingNV; - - // GL_NV_conditional_render - glBeginConditionalRenderNV: TglBeginConditionalRenderNV; - glEndConditionalRenderNV: TglEndConditionalRenderNV; - - // GL_NV_present_video - glPresentFrameKeyedNV: TglPresentFrameKeyedNV; - glPresentFrameDualFillNV: TglPresentFrameDualFillNV; - glGetVideoivNV: TglGetVideoivNV; - glGetVideouivNV: TglGetVideouivNV; - glGetVideoi64vNV: TglGetVideoi64vNV; - glGetVideoui64vNV: TglGetVideoui64vNV; -// glVideoParameterivNV: TglVideoParameterivNV; - - // GL_NV_explicit_multisample - glGetMultisamplefvNV: TglGetMultisamplefvNV; - glSampleMaskIndexedNV: TglSampleMaskIndexedNV; - glTexRenderbufferNV: TglTexRenderbufferNV; - - // GL_NV_transform_feedback2 - glBindTransformFeedbackNV: TglBindTransformFeedbackNV; - glDeleteTransformFeedbacksNV: TglDeleteTransformFeedbacksNV; - glGenTransformFeedbacksNV: TglGenTransformFeedbacksNV; - glIsTransformFeedbackNV: TglIsTransformFeedbackNV; - glPauseTransformFeedbackNV: TglPauseTransformFeedbackNV; - glResumeTransformFeedbackNV: TglResumeTransformFeedbackNV; - glDrawTransformFeedbackNV: TglDrawTransformFeedbackNV; - - // GL_PGI_misc_hints - glHintPGI: TglHintPGI; - - // GL_SGIS_detail_texture - glDetailTexFuncSGIS: TglDetailTexFuncSGIS; - glGetDetailTexFuncSGIS: TglGetDetailTexFuncSGIS; - - // GL_SGIS_fog_function - glFogFuncSGIS: TglFogFuncSGIS; - glGetFogFuncSGIS: TglGetFogFuncSGIS; - - // GL_SGIS_multisample - glSampleMaskSGIS: TglSampleMaskSGIS; - glSamplePatternSGIS: TglSamplePatternSGIS; - - // GL_SGIS_pixel_texture - glPixelTexGenParameteriSGIS: TglPixelTexGenParameteriSGIS; - glPixelTexGenParameterivSGIS: TglPixelTexGenParameterivSGIS; - glPixelTexGenParameterfSGIS: TglPixelTexGenParameterfSGIS; - glPixelTexGenParameterfvSGIS: TglPixelTexGenParameterfvSGIS; - glGetPixelTexGenParameterivSGIS: TglGetPixelTexGenParameterivSGIS; - glGetPixelTexGenParameterfvSGIS: TglGetPixelTexGenParameterfvSGIS; - - // GL_SGIS_point_parameters - glPointParameterfSGIS: TglPointParameterfSGIS; - glPointParameterfvSGIS: TglPointParameterfvSGIS; - - // GL_SGIS_sharpen_texture - glSharpenTexFuncSGIS: TglSharpenTexFuncSGIS; - glGetSharpenTexFuncSGIS: TglGetSharpenTexFuncSGIS; - - // GL_SGIS_texture4D - glTexImage4DSGIS: TglTexImage4DSGIS; - glTexSubImage4DSGIS: TglTexSubImage4DSGIS; - - // GL_SGIS_texture_color_mask - glTextureColorMaskSGIS: TglTextureColorMaskSGIS; - - // GL_SGIS_texture_filter4 - glGetTexFilterFuncSGIS: TglGetTexFilterFuncSGIS; - glTexFilterFuncSGIS: TglTexFilterFuncSGIS; - - // GL_SGIX_async - glAsyncMarkerSGIX: TglAsyncMarkerSGIX; - glFinishAsyncSGIX: TglFinishAsyncSGIX; - glPollAsyncSGIX: TglPollAsyncSGIX; - glGenAsyncMarkersSGIX: TglGenAsyncMarkersSGIX; - glDeleteAsyncMarkersSGIX: TglDeleteAsyncMarkersSGIX; - glIsAsyncMarkerSGIX: TglIsAsyncMarkerSGIX; - - // GL_SGIX_flush_raster - glFlushRasterSGIX: TglFlushRasterSGIX; - - // GL_SGIX_fragment_lighting - glFragmentColorMaterialSGIX: TglFragmentColorMaterialSGIX; - glFragmentLightfSGIX: TglFragmentLightfSGIX; - glFragmentLightfvSGIX: TglFragmentLightfvSGIX; - glFragmentLightiSGIX: TglFragmentLightiSGIX; - glFragmentLightivSGIX: TglFragmentLightivSGIX; - glFragmentLightModelfSGIX: TglFragmentLightModelfSGIX; - glFragmentLightModelfvSGIX: TglFragmentLightModelfvSGIX; - glFragmentLightModeliSGIX: TglFragmentLightModeliSGIX; - glFragmentLightModelivSGIX: TglFragmentLightModelivSGIX; - glFragmentMaterialfSGIX: TglFragmentMaterialfSGIX; - glFragmentMaterialfvSGIX: TglFragmentMaterialfvSGIX; - glFragmentMaterialiSGIX: TglFragmentMaterialiSGIX; - glFragmentMaterialivSGIX: TglFragmentMaterialivSGIX; - glGetFragmentLightfvSGIX: TglGetFragmentLightfvSGIX; - glGetFragmentLightivSGIX: TglGetFragmentLightivSGIX; - glGetFragmentMaterialfvSGIX: TglGetFragmentMaterialfvSGIX; - glGetFragmentMaterialivSGIX: TglGetFragmentMaterialivSGIX; - glLightEnviSGIX: TglLightEnviSGIX; - - // GL_SGIX_framezoom - glFrameZoomSGIX: TglFrameZoomSGIX; - - // GL_SGIX_igloo_interface - glIglooInterfaceSGIX: TglIglooInterfaceSGIX; - - // GL_SGIX_instruments - glGetInstrumentsSGIX: TglGetInstrumentsSGIX; - glInstrumentsBufferSGIX: TglInstrumentsBufferSGIX; - glPollInstrumentsSGIX: TglPollInstrumentsSGIX; - glReadInstrumentsSGIX: TglReadInstrumentsSGIX; - glStartInstrumentsSGIX: TglStartInstrumentsSGIX; - glStopInstrumentsSGIX: TglStopInstrumentsSGIX; - - // GL_SGIX_list_priority - glGetListParameterfvSGIX: TglGetListParameterfvSGIX; - glGetListParameterivSGIX: TglGetListParameterivSGIX; - glListParameterfSGIX: TglListParameterfSGIX; - glListParameterfvSGIX: TglListParameterfvSGIX; - glListParameteriSGIX: TglListParameteriSGIX; - glListParameterivSGIX: TglListParameterivSGIX; - - // GL_SGIX_pixel_texture - glPixelTexGenSGIX: TglPixelTexGenSGIX; - - // GL_SGIX_polynomial_ffd - glDeformationMap3dSGIX: TglDeformationMap3dSGIX; - glDeformationMap3fSGIX: TglDeformationMap3fSGIX; - glDeformSGIX: TglDeformSGIX; - glLoadIdentityDeformationMapSGIX: TglLoadIdentityDeformationMapSGIX; - - // GL_SGIX_reference_plane - glReferencePlaneSGIX: TglReferencePlaneSGIX; - - // GL_SGIX_sprite - glSpriteParameterfSGIX: TglSpriteParameterfSGIX; - glSpriteParameterfvSGIX: TglSpriteParameterfvSGIX; - glSpriteParameteriSGIX: TglSpriteParameteriSGIX; - glSpriteParameterivSGIX: TglSpriteParameterivSGIX; - - // GL_SGIX_tag_sample_buffer - glTagSampleBufferSGIX: TglTagSampleBufferSGIX; - - // GL_SGI_color_table - glColorTableSGI: TglColorTableSGI; - glColorTableParameterfvSGI: TglColorTableParameterfvSGI; - glColorTableParameterivSGI: TglColorTableParameterivSGI; - glCopyColorTableSGI: TglCopyColorTableSGI; - glGetColorTableSGI: TglGetColorTableSGI; - glGetColorTableParameterfvSGI: TglGetColorTableParameterfvSGI; - glGetColorTableParameterivSGI: TglGetColorTableParameterivSGI; - - // GL_SUNX_constant_data - glFinishTextureSUNX: TglFinishTextureSUNX; - - // GL_SUN_global_alpha - glGlobalAlphaFactorbSUN: TglGlobalAlphaFactorbSUN; - glGlobalAlphaFactorsSUN: TglGlobalAlphaFactorsSUN; - glGlobalAlphaFactoriSUN: TglGlobalAlphaFactoriSUN; - glGlobalAlphaFactorfSUN: TglGlobalAlphaFactorfSUN; - glGlobalAlphaFactordSUN: TglGlobalAlphaFactordSUN; - glGlobalAlphaFactorubSUN: TglGlobalAlphaFactorubSUN; - glGlobalAlphaFactorusSUN: TglGlobalAlphaFactorusSUN; - glGlobalAlphaFactoruiSUN: TglGlobalAlphaFactoruiSUN; - - // GL_SUN_mesh_array - glDrawMeshArraysSUN: TglDrawMeshArraysSUN; - - // GL_SUN_triangle_list - glReplacementCodeuiSUN: TglReplacementCodeuiSUN; - glReplacementCodeusSUN: TglReplacementCodeusSUN; - glReplacementCodeubSUN: TglReplacementCodeubSUN; - glReplacementCodeuivSUN: TglReplacementCodeuivSUN; - glReplacementCodeusvSUN: TglReplacementCodeusvSUN; - glReplacementCodeubvSUN: TglReplacementCodeubvSUN; - glReplacementCodePointerSUN: TglReplacementCodePointerSUN; - - // GL_SUN_vertex - glColor4ubVertex2fSUN: TglColor4ubVertex2fSUN; - glColor4ubVertex2fvSUN: TglColor4ubVertex2fvSUN; - glColor4ubVertex3fSUN: TglColor4ubVertex3fSUN; - glColor4ubVertex3fvSUN: TglColor4ubVertex3fvSUN; - glColor3fVertex3fSUN: TglColor3fVertex3fSUN; - glColor3fVertex3fvSUN: TglColor3fVertex3fvSUN; - glNormal3fVertex3fSUN: TglNormal3fVertex3fSUN; - glNormal3fVertex3fvSUN: TglNormal3fVertex3fvSUN; - glColor4fNormal3fVertex3fSUN: TglColor4fNormal3fVertex3fSUN; - glColor4fNormal3fVertex3fvSUN: TglColor4fNormal3fVertex3fvSUN; - glTexCoord2fVertex3fSUN: TglTexCoord2fVertex3fSUN; - glTexCoord2fVertex3fvSUN: TglTexCoord2fVertex3fvSUN; - glTexCoord4fVertex4fSUN: TglTexCoord4fVertex4fSUN; - glTexCoord4fVertex4fvSUN: TglTexCoord4fVertex4fvSUN; - glTexCoord2fColor4ubVertex3fSUN: TglTexCoord2fColor4ubVertex3fSUN; - glTexCoord2fColor4ubVertex3fvSUN: TglTexCoord2fColor4ubVertex3fvSUN; - glTexCoord2fColor3fVertex3fSUN: TglTexCoord2fColor3fVertex3fSUN; - glTexCoord2fColor3fVertex3fvSUN: TglTexCoord2fColor3fVertex3fvSUN; - glTexCoord2fNormal3fVertex3fSUN: TglTexCoord2fNormal3fVertex3fSUN; - glTexCoord2fNormal3fVertex3fvSUN: TglTexCoord2fNormal3fVertex3fvSUN; - glTexCoord2fColor4fNormal3fVertex3fSUN: TglTexCoord2fColor4fNormal3fVertex3fSUN; - glTexCoord2fColor4fNormal3fVertex3fvSUN: TglTexCoord2fColor4fNormal3fVertex3fvSUN; - glTexCoord4fColor4fNormal3fVertex4fSUN: TglTexCoord4fColor4fNormal3fVertex4fSUN; - glTexCoord4fColor4fNormal3fVertex4fvSUN: TglTexCoord4fColor4fNormal3fVertex4fvSUN; - glReplacementCodeuiVertex3fSUN: TglReplacementCodeuiVertex3fSUN; - glReplacementCodeuiVertex3fvSUN: TglReplacementCodeuiVertex3fvSUN; - glReplacementCodeuiColor4ubVertex3fSUN: TglReplacementCodeuiColor4ubVertex3fSUN; - glReplacementCodeuiColor4ubVertex3fvSUN: TglReplacementCodeuiColor4ubVertex3fvSUN; - glReplacementCodeuiColor3fVertex3fSUN: TglReplacementCodeuiColor3fVertex3fSUN; - glReplacementCodeuiColor3fVertex3fvSUN: TglReplacementCodeuiColor3fVertex3fvSUN; - glReplacementCodeuiNormal3fVertex3fSUN: TglReplacementCodeuiNormal3fVertex3fSUN; - glReplacementCodeuiNormal3fVertex3fvSUN: TglReplacementCodeuiNormal3fVertex3fvSUN; - glReplacementCodeuiColor4fNormal3fVertex3fSUN: TglReplacementCodeuiColor4fNormal3fVertex3fSUN; - glReplacementCodeuiColor4fNormal3fVertex3fvSUN: TglReplacementCodeuiColor4fNormal3fVertex3fvSUN; - glReplacementCodeuiTexCoord2fVertex3fSUN: TglReplacementCodeuiTexCoord2fVertex3fSUN; - glReplacementCodeuiTexCoord2fVertex3fvSUN: TglReplacementCodeuiTexCoord2fVertex3fvSUN; - glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN: TglReplacementCodeuiTexCoord2fNormal3fVertex3fSUN; - glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN: TglReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN; - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN: TglReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN; - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN: TglReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN; - -{$IFDEF DGL_WIN} - wglGetProcAddress: TwglGetProcAddress; - wglCopyContext: TwglCopyContext; - wglCreateContext: TwglCreateContext; - wglCreateLayerContext: TwglCreateLayerContext; - wglDeleteContext: TwglDeleteContext; - wglDescribeLayerPlane: TwglDescribeLayerPlane; - wglGetCurrentContext: TwglGetCurrentContext; - wglGetCurrentDC: TwglGetCurrentDC; - wglGetLayerPaletteEntries: TwglGetLayerPaletteEntries; - wglMakeCurrent: TwglMakeCurrent; - wglRealizeLayerPalette: TwglRealizeLayerPalette; - wglSetLayerPaletteEntries: TwglSetLayerPaletteEntries; - wglShareLists: TwglShareLists; - wglSwapLayerBuffers: TwglSwapLayerBuffers; - wglSwapMultipleBuffers: TwglSwapMultipleBuffers; - wglUseFontBitmapsA: TwglUseFontBitmapsA; - wglUseFontOutlinesA: TwglUseFontOutlinesA; - wglUseFontBitmapsW: TwglUseFontBitmapsW; - wglUseFontOutlinesW: TwglUseFontOutlinesW; - wglUseFontBitmaps: TwglUseFontBitmaps; - wglUseFontOutlines: TwglUseFontOutlines; - - // WGL_ARB_buffer_region - wglCreateBufferRegionARB: TwglCreateBufferRegionARB; - wglDeleteBufferRegionARB: TwglDeleteBufferRegionARB; - wglSaveBufferRegionARB: TwglSaveBufferRegionARB; - wglRestoreBufferRegionARB: TwglRestoreBufferRegionARB; - - // WGL_ARB_extensions_string - wglGetExtensionsStringARB: TwglGetExtensionsStringARB; - - // WGL_ARB_make_current_read - wglMakeContextCurrentARB: TwglMakeContextCurrentARB; - wglGetCurrentReadDCARB: TwglGetCurrentReadDCARB; - - // WGL_ARB_pbuffer - wglCreatePbufferARB: TwglCreatePbufferARB; - wglGetPbufferDCARB: TwglGetPbufferDCARB; - wglReleasePbufferDCARB: TwglReleasePbufferDCARB; - wglDestroyPbufferARB: TwglDestroyPbufferARB; - wglQueryPbufferARB: TwglQueryPbufferARB; - - // WGL_ARB_pixel_format - wglGetPixelFormatAttribivARB: TwglGetPixelFormatAttribivARB; - wglGetPixelFormatAttribfvARB: TwglGetPixelFormatAttribfvARB; - wglChoosePixelFormatARB: TwglChoosePixelFormatARB; - // WGL_ARB_color_buffer_float - wglClampColorARB: TwglClampColorARB; - - // WGL_ARB_render_texture - wglBindTexImageARB: TwglBindTexImageARB; - wglReleaseTexImageARB: TwglReleaseTexImageARB; - wglSetPbufferAttribARB: TwglSetPbufferAttribARB; - - // WGL_ARB_create_context - wglCreateContextAttribsARB: TwglCreateContextAttribsARB; - - // WGL_AMD_gpu_association - wglGetGPUIDsAMD: TwglGetGPUIDsAMD; - wglGetGPUInfoAMD: TwglGetGPUInfoAMD; - wglGetContextGPUIDAMD: TwglGetContextGPUIDAMD; - wglCreateAssociatedContextAMD: TwglCreateAssociatedContextAMD; - wglCreateAssociatedContextAttribsAMD: TwglCreateAssociatedContextAttribsAMD; - wglDeleteAssociatedContextAMD: TwglDeleteAssociatedContextAMD; - wglMakeAssociatedContextCurrentAMD: TwglMakeAssociatedContextCurrentAMD; - wglGetCurrentAssociatedContextAMD: TwglGetCurrentAssociatedContextAMD; - wglBlitContextFramebufferAMD: TwglBlitContextFramebufferAMD; - - // WGL_EXT_display_color_table - wglCreateDisplayColorTableEXT: TwglCreateDisplayColorTableEXT; - wglLoadDisplayColorTableEXT: TwglLoadDisplayColorTableEXT; - wglBindDisplayColorTableEXT: TwglBindDisplayColorTableEXT; - wglDestroyDisplayColorTableEXT: TwglDestroyDisplayColorTableEXT; - - // WGL_EXT_extensions_string - wglGetExtensionsStringEXT: TwglGetExtensionsStringEXT; - - // WGL_EXT_make_current_read - wglMakeContextCurrentEXT: TwglMakeContextCurrentEXT; - wglGetCurrentReadDCEXT: TwglGetCurrentReadDCEXT; - - // WGL_EXT_pbuffer - wglCreatePbufferEXT: TwglCreatePbufferEXT; - wglGetPbufferDCEXT: TwglGetPbufferDCEXT; - wglReleasePbufferDCEXT: TwglReleasePbufferDCEXT; - wglDestroyPbufferEXT: TwglDestroyPbufferEXT; - wglQueryPbufferEXT: TwglQueryPbufferEXT; - - // WGL_EXT_pixel_format - wglGetPixelFormatAttribivEXT: TwglGetPixelFormatAttribivEXT; - wglGetPixelFormatAttribfvEXT: TwglGetPixelFormatAttribfvEXT; - wglChoosePixelFormatEXT: TwglChoosePixelFormatEXT; - - // WGL_EXT_swap_control - wglSwapIntervalEXT: TwglSwapIntervalEXT; - wglGetSwapIntervalEXT: TwglGetSwapIntervalEXT; - - // WGL_I3D_digital_video_control - wglGetDigitalVideoParametersI3D: TwglGetDigitalVideoParametersI3D; - wglSetDigitalVideoParametersI3D: TwglSetDigitalVideoParametersI3D; - - // WGL_I3D_gamma - wglGetGammaTableParametersI3D: TwglGetGammaTableParametersI3D; - wglSetGammaTableParametersI3D: TwglSetGammaTableParametersI3D; - wglGetGammaTableI3D: TwglGetGammaTableI3D; - wglSetGammaTableI3D: TwglSetGammaTableI3D; - - // WGL_I3D_genlock - wglEnableGenlockI3D: TwglEnableGenlockI3D; - wglDisableGenlockI3D: TwglDisableGenlockI3D; - wglIsEnabledGenlockI3D: TwglIsEnabledGenlockI3D; - wglGenlockSourceI3D: TwglGenlockSourceI3D; - wglGetGenlockSourceI3D: TwglGetGenlockSourceI3D; - wglGenlockSourceEdgeI3D: TwglGenlockSourceEdgeI3D; - wglGetGenlockSourceEdgeI3D: TwglGetGenlockSourceEdgeI3D; - wglGenlockSampleRateI3D: TwglGenlockSampleRateI3D; - wglGetGenlockSampleRateI3D: TwglGetGenlockSampleRateI3D; - wglGenlockSourceDelayI3D: TwglGenlockSourceDelayI3D; - wglGetGenlockSourceDelayI3D: TwglGetGenlockSourceDelayI3D; - wglQueryGenlockMaxSourceDelayI3D: TwglQueryGenlockMaxSourceDelayI3D; - - // WGL_I3D_image_buffer - wglCreateImageBufferI3D: TwglCreateImageBufferI3D; - wglDestroyImageBufferI3D: TwglDestroyImageBufferI3D; - wglAssociateImageBufferEventsI3D: TwglAssociateImageBufferEventsI3D; - wglReleaseImageBufferEventsI3D: TwglReleaseImageBufferEventsI3D; - - // WGL_I3D_swap_frame_lock - wglEnableFrameLockI3D: TwglEnableFrameLockI3D; - wglDisableFrameLockI3D: TwglDisableFrameLockI3D; - wglIsEnabledFrameLockI3D: TwglIsEnabledFrameLockI3D; - wglQueryFrameLockMasterI3D: TwglQueryFrameLockMasterI3D; - - // WGL_I3D_swap_frame_usage - wglGetFrameUsageI3D: TwglGetFrameUsageI3D; - wglBeginFrameTrackingI3D: TwglBeginFrameTrackingI3D; - wglEndFrameTrackingI3D: TwglEndFrameTrackingI3D; - wglQueryFrameTrackingI3D: TwglQueryFrameTrackingI3D; - - // WGL_NV_vertex_array_range - wglAllocateMemoryNV: TwglAllocateMemoryNV; - wglFreeMemoryNV: TwglFreeMemoryNV; - - // WGL_NV_present_video - wglEnumerateVideoDevicesNV: TwglEnumerateVideoDevicesNV; - wglBindVideoDeviceNV: TwglBindVideoDeviceNV; - wglQueryCurrentContextNV: TwglQueryCurrentContextNV; - - // WGL_NV_video_out - wglGetVideoDeviceNV: TwglGetVideoDeviceNV; - wglReleaseVideoDeviceNV: TwglReleaseVideoDeviceNV; - wglBindVideoImageNV: TwglBindVideoImageNV; - wglReleaseVideoImageNV: TwglReleaseVideoImageNV; - wglSendPbufferToVideoNV: TwglSendPbufferToVideoNV; - wglGetVideoInfoNV: TwglGetVideoInfoNV; - - // WGL_NV_swap_group - wglJoinSwapGroupNV: TwglJoinSwapGroupNV; - wglBindSwapBarrierNV: TwglBindSwapBarrierNV; - wglQuerySwapGroupNV: TwglQuerySwapGroupNV; - wglQueryMaxSwapGroupsNV: TwglQueryMaxSwapGroupsNV; - wglQueryFrameCountNV: TwglQueryFrameCountNV; - wglResetFrameCountNV: TwglResetFrameCountNV; - - // WGL_NV_gpu_affinity - wglEnumGpusNV: TwglEnumGpusNV; - wglEnumGpuDevicesNV: TwglEnumGpuDevicesNV; - wglCreateAffinityDCNV: TwglCreateAffinityDCNV; - wglEnumGpusFromAffinityDCNV: TwglEnumGpusFromAffinityDCNV; - wglDeleteDCNV: TwglDeleteDCNV; - - // WGL_OML_sync_control - wglGetSyncValuesOML: TwglGetSyncValuesOML; - wglGetMscRateOML: TwglGetMscRateOML; - wglSwapBuffersMscOML: TwglSwapBuffersMscOML; - wglSwapLayerBuffersMscOML: TwglSwapLayerBuffersMscOML; - wglWaitForMscOML: TwglWaitForMscOML; - wglWaitForSbcOML: TwglWaitForSbcOML; - - // WGL_3DL_stereo_control - wglSetStereoEmitterState3DL: TwglSetStereoEmitterState3DL; - - // WIN_draw_range_elements - glDrawRangeElementsWIN: TglDrawRangeElementsWIN; - - // WIN_swap_hint - glAddSwapHintRectWIN: TglAddSwapHintRectWIN; -{$ENDIF} - -{$IFDEF DGL_LINUX} - glXChooseVisual: TglXChooseVisual; - glXCopyContext: TglXCopyContext; - glXCreateContext: TglXCreateContext; - glXCreateGLXPixmap: TglXCreateGLXPixmap; - glXDestroyContext: TglXDestroyContext; - glXDestroyGLXPixmap: TglXDestroyGLXPixmap; - glXGetConfig: TglXGetConfig; - glXGetCurrentContext: TglXGetCurrentContext; - glXGetCurrentDrawable: TglXGetCurrentDrawable; - glXIsDirect: TglXIsDirect; - glXMakeCurrent: TglXMakeCurrent; - glXQueryExtension: TglXQueryExtension; - glXQueryVersion: TglXQueryVersion; - glXSwapBuffers: TglXSwapBuffers; - glXUseXFont: TglXUseXFont; - glXWaitGL: TglXWaitGL; - glXWaitX: TglXWaitX; - - glXGetClientString: TglXGetClientString; - glXQueryServerString: TglXQueryServerString; - glXQueryExtensionsString: TglXQueryExtensionsString; - - // GLX_VERSION_1_3 - glXGetFBConfigs: TglXGetFBConfigs; - glXChooseFBConfig: TglXChooseFBConfig; - glXGetFBConfigAttrib: TglXGetFBConfigAttrib; - glXGetVisualFromFBConfig: TglXGetVisualFromFBConfig; - glXCreateWindow: TglXCreateWindow; - glXDestroyWindow: TglXDestroyWindow; - glXCreatePixmap: TglXCreatePixmap; - - glXDestroyPixmap: TglXDestroyPixmap; - glXCreatePbuffer: TglXCreatePbuffer; - glXDestroyPbuffer: TglXDestroyPbuffer; - glXQueryDrawable: TglXQueryDrawable; - glXCreateNewContext: TglXCreateNewContext; - glXMakeContextCurrent: TglXMakeContextCurrent; - glXGetCurrentReadDrawable: TglXGetCurrentReadDrawable; - glXGetCurreentDisplay: TglXGetCurreentDisplay; - - glXQueryContext: TglXQueryContext; - glXSelectEvent: TglXSelectEvent; - glXGetSelectedEvent: TglXGetSelectedEvent; - - // GLX_VERSION_1_4 - glXGetProcAddress: TglXGetProcAddress; - - // GLX_ARB_get_proc_address - glXGetProcAddressARB: TglXGetProcAddressARB; - - // GLX_ARB_create_context - glXCreateContextAttribsARB: TglXCreateContextAttribsARB; - - // GLX_EXT_import_context - glXGetCurrentDisplayEXT: TglXGetCurrentDisplayEXT; - glXQueryContextInfoEXT: TglXQueryContextInfoEXT; - glXGetContextIDEXT: TglXGetContextIDEXT; - glXImportContextEXT: TglXImportContextEXT; - glXFreeContextEXT: TglXFreeContextEXT; - - // GLX_EXT_texture_from_pixmap - glXBindTexImageEXT: TglXBindTexImageEXT; - glXReleaseTexImageEXT: TglXReleaseTexImageEXT; -{$ENDIF} - - // GL utility functions and procedures - gluErrorString: TgluErrorString; - gluGetString: TgluGetString; - gluOrtho2D: TgluOrtho2D; - gluPerspective: TgluPerspective; - gluPickMatrix: TgluPickMatrix; - gluLookAt: TgluLookAt; - gluProject: TgluProject; - gluUnProject: TgluUnProject; - gluScaleImage: TgluScaleImage; - gluBuild1DMipmaps: TgluBuild1DMipmaps; - gluBuild2DMipmaps: TgluBuild2DMipmaps; - gluNewQuadric: TgluNewQuadric; - gluDeleteQuadric: TgluDeleteQuadric; - gluQuadricNormals: TgluQuadricNormals; - gluQuadricTexture: TgluQuadricTexture; - gluQuadricOrientation: TgluQuadricOrientation; - gluQuadricDrawStyle: TgluQuadricDrawStyle; - gluCylinder: TgluCylinder; - gluDisk: TgluDisk; - gluPartialDisk: TgluPartialDisk; - gluSphere: TgluSphere; - gluQuadricCallback: TgluQuadricCallback; - gluNewTess: TgluNewTess; - gluDeleteTess: TgluDeleteTess; - gluTessBeginPolygon: TgluTessBeginPolygon; - gluTessBeginContour: TgluTessBeginContour; - gluTessVertex: TgluTessVertex; - gluTessEndContour: TgluTessEndContour; - gluTessEndPolygon: TgluTessEndPolygon; - gluTessProperty: TgluTessProperty; - gluTessNormal: TgluTessNormal; - gluTessCallback: TgluTessCallback; - gluGetTessProperty: TgluGetTessProperty; - gluNewNurbsRenderer: TgluNewNurbsRenderer; - gluDeleteNurbsRenderer: TgluDeleteNurbsRenderer; - gluBeginSurface: TgluBeginSurface; - gluBeginCurve: TgluBeginCurve; - gluEndCurve: TgluEndCurve; - gluEndSurface: TgluEndSurface; - gluBeginTrim: TgluBeginTrim; - gluEndTrim: TgluEndTrim; - gluPwlCurve: TgluPwlCurve; - gluNurbsCurve: TgluNurbsCurve; - gluNurbsSurface: TgluNurbsSurface; - gluLoadSamplingMatrices: TgluLoadSamplingMatrices; - gluNurbsProperty: TgluNurbsProperty; - gluGetNurbsProperty: TgluGetNurbsProperty; - gluNurbsCallback: TgluNurbsCallback; - gluBeginPolygon: TgluBeginPolygon; - gluNextContour: TgluNextContour; - gluEndPolygon: TgluEndPolygon; - - -type - TRCOptions = set of (opDoubleBuffered, opGDI, opStereo); - -var - GL_LibHandle: Pointer = nil; - GLU_LibHandle: Pointer = nil; - - LastPixelFormat: Integer; - ExtensionsRead: Boolean; - ImplementationRead: Boolean; - - -const -{$IFDEF DGL_WIN} - OPENGL_LIBNAME = 'OpenGL32.dll'; - GLU_LIBNAME = 'GLU32.dll'; -{$ELSE} - {$IFDEF darwin} - OPENGL_LIBNAME = 'libGL.dylib'; - GLU_LIBNAME = 'libGLU.dylib'; - {$ELSE} - OPENGL_LIBNAME = 'libGL.so.1'; - GLU_LIBNAME = 'libGLU.so.1'; - {$ENDIF} -{$ENDIF} - -function InitOpenGL(LibName: String = OPENGL_LIBNAME; GLULibName: String = GLU_LIBNAME): Boolean; - -function dglGetProcAddress(ProcName: PAnsiChar; LibHandle: Pointer = nil): Pointer; -function dglCheckExtension(Extension: AnsiString): Boolean; - -procedure ReadExtensions; -procedure ReadImplementationProperties; - -// ============================================================================= -// Helper-Functions -// ============================================================================= -{$IFDEF DGL_WIN} - function CreateRenderingContext(DC: HDC; Options: TRCOptions; ColorBits, ZBits, StencilBits, AccumBits, AuxBuffers: Integer; Layer: Integer): HGLRC; - procedure DestroyRenderingContext(RC: HGLRC); - - procedure ActivateRenderingContext(DC: HDC; RC: HGLRC; loadext: boolean = true); - procedure DeactivateRenderingContext; -{$ENDIF} - - -procedure ReadOpenGLCore; -procedure Read_GL_3DFX_tbuffer; -procedure Read_GL_APPLE_element_array; -procedure Read_GL_APPLE_fence; -procedure Read_GL_APPLE_vertex_array_object; -procedure Read_GL_APPLE_vertex_array_range; -procedure Read_GL_APPLE_texture_range; -procedure Read_GL_APPLE_vertex_program_evaluators; -procedure Read_GL_APPLE_object_purgeable; -procedure Read_GL_ARB_matrix_palette; -procedure Read_GL_ARB_multitexture; -procedure Read_GL_ARB_point_parameters; -procedure Read_GL_ARB_texture_compression; -procedure Read_GL_ARB_transpose_matrix; -procedure Read_GL_ARB_vertex_blend; -procedure Read_GL_ARB_vertex_buffer_object; -procedure Read_GL_ARB_vertex_program; -procedure Read_GL_ARB_window_pos; -procedure Read_GL_ARB_color_buffer_float; -procedure Read_GL_ARB_Shader_Objects; -procedure Read_GL_ARB_occlusion_query; -procedure Read_GL_ARB_draw_instanced; -procedure Read_GL_ARB_framebuffer_object; -procedure Read_GL_ARB_geometry_shader4; -procedure Read_GL_ARB_instanced_arrays; -procedure Read_GL_ARB_map_buffer_range; -procedure Read_GL_ARB_texture_buffer_object; -procedure Read_GL_ARB_vertex_array_object; -procedure Read_GL_ARB_uniform_buffer_object; -procedure Read_GL_ARB_copy_buffer; -procedure Read_GL_ARB_draw_elements_base_vertex; -procedure Read_GL_ARB_provoking_vertex; -procedure Read_GL_ARB_sync; -procedure Read_GL_ARB_texture_multisample; -procedure Read_GL_ARB_draw_buffers_blend; -procedure Read_GL_ARB_sample_shading; -procedure Read_GL_ATI_draw_buffers; -procedure Read_GL_ATI_element_array; -procedure Read_GL_ATI_envmap_bumpmap; -procedure Read_GL_ATI_fragment_shader; -procedure Read_GL_ATI_map_object_buffer; -procedure Read_GL_ATI_pn_triangles; -procedure Read_GL_ATI_separate_stencil; -procedure Read_GL_ATI_vertex_array_object; -procedure Read_GL_ATI_vertex_attrib_array_object; -procedure Read_GL_ATI_vertex_streams; -procedure Read_GL_AMD_performance_monitor; -procedure Read_GL_EXT_blend_color; -procedure Read_GL_EXT_blend_func_separate; -procedure Read_GL_EXT_blend_minmax; -procedure Read_GL_EXT_color_subtable; -procedure Read_GL_EXT_compiled_vertex_array; -procedure Read_GL_EXT_convolution; -procedure Read_GL_EXT_coordinate_frame; -procedure Read_GL_EXT_copy_texture; -procedure Read_GL_EXT_cull_vertex; -procedure Read_GL_EXT_draw_range_elements; -procedure Read_GL_EXT_fog_coord; -procedure Read_GL_EXT_framebuffer_object; -procedure Read_GL_EXT_histogram; -procedure Read_GL_EXT_index_func; -procedure Read_GL_EXT_index_material; -procedure Read_GL_EXT_multi_draw_arrays; -procedure Read_GL_EXT_multisample; -procedure Read_GL_EXT_paletted_texture; -procedure Read_GL_EXT_pixel_transform; -procedure Read_GL_EXT_point_parameters; -procedure Read_GL_EXT_polygon_offset; -procedure Read_GL_EXT_secondary_color; -procedure Read_GL_EXT_stencil_two_side; -procedure Read_GL_EXT_subtexture; -procedure Read_GL_EXT_texture3D; -procedure Read_GL_EXT_texture_object; -procedure Read_GL_EXT_texture_perturb_normal; -procedure Read_GL_EXT_vertex_array; -procedure Read_GL_EXT_vertex_shader; -procedure Read_GL_EXT_vertex_weighting; -procedure Read_GL_EXT_depth_bounds_test; -procedure Read_GL_EXT_blend_equation_separate; -procedure Read_GL_EXT_stencil_clear_tag; -procedure Read_GL_EXT_framebuffer_blit; -procedure Read_GL_EXT_framebuffer_multisample; -procedure Read_GL_EXT_timer_query; -procedure Read_GL_EXT_gpu_program_parameters; -procedure Read_GL_EXT_bindable_uniform; -procedure Read_GL_EXT_draw_buffers2; -procedure Read_GL_EXT_draw_instanced; -procedure Read_GL_EXT_geometry_shader4; -procedure Read_GL_EXT_gpu_shader4; -procedure Read_GL_EXT_texture_array; -procedure Read_GL_EXT_texture_buffer_object; -procedure Read_GL_EXT_texture_integer; -procedure Read_GL_EXT_transform_feedback; -procedure Read_GL_EXT_direct_state_access; -procedure Read_GL_HP_image_transform; -procedure Read_GL_IBM_multimode_draw_arrays; -procedure Read_GL_IBM_vertex_array_lists; -procedure Read_GL_INGR_blend_func_separate; -procedure Read_GL_INTEL_parallel_arrays; -procedure Read_GL_MESA_resize_buffers; -procedure Read_GL_MESA_window_pos; -procedure Read_GL_NV_evaluators; -procedure Read_GL_NV_fence; -procedure Read_GL_NV_fragment_program; -procedure Read_GL_NV_half_float; -procedure Read_GL_NV_occlusion_query; -procedure Read_GL_NV_pixel_data_range; -procedure Read_GL_NV_point_sprite; -procedure Read_GL_NV_primitive_restart; -procedure Read_GL_NV_register_combiners; -procedure Read_GL_NV_register_combiners2; -procedure Read_GL_NV_vertex_array_range; -procedure Read_GL_NV_vertex_program; -procedure Read_GL_NV_depth_buffer_float; -procedure Read_GL_NV_framebuffer_multisample_coverage; -procedure Read_GL_NV_geometry_program4; -procedure Read_GL_NV_gpu_program4; -procedure Read_GL_NV_parameter_buffer_object; -procedure Read_GL_NV_transform_feedback; -procedure Read_GL_NV_conditional_render; -procedure Read_GL_NV_present_video; -procedure Read_GL_NV_explicit_multisample; -procedure Read_GL_NV_transform_feedback2; -procedure Read_GL_PGI_misc_hints; -procedure Read_GL_SGIS_detail_texture; -procedure Read_GL_SGIS_fog_function; -procedure Read_GL_SGIS_multisample; -procedure Read_GL_SGIS_pixel_texture; -procedure Read_GL_SGIS_point_parameters; -procedure Read_GL_SGIS_sharpen_texture; -procedure Read_GL_SGIS_texture4D; -procedure Read_GL_SGIS_texture_color_mask; -procedure Read_GL_SGIS_texture_filter4; -procedure Read_GL_SGIX_async; -procedure Read_GL_SGIX_flush_raster; -procedure Read_GL_SGIX_fragment_lighting; -procedure Read_GL_SGIX_framezoom; -procedure Read_GL_SGIX_igloo_interface; -procedure Read_GL_SGIX_instruments; -procedure Read_GL_SGIX_list_priority; -procedure Read_GL_SGIX_pixel_texture; -procedure Read_GL_SGIX_polynomial_ffd; -procedure Read_GL_SGIX_reference_plane; -procedure Read_GL_SGIX_sprite; -procedure Read_GL_SGIX_tag_sample_buffer; -procedure Read_GL_SGI_color_table; -procedure Read_GL_SUNX_constant_data; -procedure Read_GL_SUN_global_alpha; -procedure Read_GL_SUN_mesh_array; -procedure Read_GL_SUN_triangle_list; -procedure Read_GL_SUN_vertex; - -{$IFDEF DGL_WIN} -procedure Read_WGL_ARB_buffer_region; -procedure Read_WGL_ARB_extensions_string; -procedure Read_WGL_ARB_make_current_read; -procedure Read_WGL_ARB_pbuffer; -procedure Read_WGL_ARB_pixel_format; -procedure Read_WGL_ARB_pixel_format_float; -procedure Read_WGL_ARB_render_texture; -procedure Read_WGL_ARB_create_context; -procedure Read_WGL_AMD_gpu_association; -procedure Read_WGL_EXT_display_color_table; -procedure Read_WGL_EXT_extensions_string; -procedure Read_WGL_EXT_make_current_read; -procedure Read_WGL_EXT_pbuffer; -procedure Read_WGL_EXT_pixel_format; -procedure Read_WGL_EXT_swap_control; -procedure Read_WGL_I3D_digital_video_control; -procedure Read_WGL_I3D_gamma; -procedure Read_WGL_I3D_genlock; -procedure Read_WGL_I3D_image_buffer; -procedure Read_WGL_I3D_swap_frame_lock; -procedure Read_WGL_I3D_swap_frame_usage; -procedure Read_WGL_NV_vertex_array_range; -procedure Read_WGL_NV_present_video; -procedure Read_WGL_NV_video_out; -procedure Read_WGL_NV_swap_group; -procedure Read_WGL_NV_gpu_affinity; -procedure Read_WGL_OML_sync_control; -procedure Read_WGL_3DL_stereo_control; - -procedure Read_WIN_draw_range_elements; -procedure Read_WIN_swap_hint; -{$ENDIF} - - -implementation - - -{$IFDEF DGL_LINUX} -const - RTLD_LAZY = $001; - RTLD_NOW = $002; - RTLD_BINDING_MASK = $003; - - // Seems to work on Debian / Fedora - LibraryLib = {$IFDEF Linux} 'libdl.so.2'{$ELSE} 'c'{$ENDIF}; - -function dlopen(Name: PAnsiChar; Flags: LongInt): Pointer; cdecl; external LibraryLib name 'dlopen'; -function dlclose(Lib: Pointer): LongInt; cdecl; external LibraryLib name 'dlclose'; - -function dlsym(Lib: Pointer; Name: PAnsiChar): Pointer; cdecl; external LibraryLib name 'dlsym'; -{$ENDIF} - - -function dglLoadLibrary(Name: PChar): Pointer; -begin - {$IFDEF DGL_WIN} - Result := Pointer(LoadLibrary(Name)); - {$ENDIF} - - {$IFDEF DGL_LINUX} - Result := dlopen(Name, RTLD_LAZY); - {$ENDIF} -end; - - -function dglFreeLibrary(LibHandle: Pointer): Boolean; -begin - if LibHandle = nil then - Result := False - else - {$IFDEF DGL_WIN} - Result := FreeLibrary(HMODULE(LibHandle)); - {$ENDIF} - - {$IFDEF DGL_LINUX} - Result := dlclose(LibHandle) = 0; - {$ENDIF} -end; - - -function dglGetProcAddress(ProcName: PAnsiChar; LibHandle: Pointer = nil): Pointer; -begin - if LibHandle = nil then - LibHandle := GL_LibHandle; - - {$IFDEF DGL_WIN} - Result := GetProcAddress(HMODULE(LibHandle), ProcName); - {$ENDIF} - - {$IFDEF DGL_LINUX} - Result := dlsym(LibHandle, ProcName); - {$ENDIF} - - if result <> nil then - exit; - - {$IFDEF DGL_WIN} - if Addr(wglGetProcAddress) <> nil then - Result := wglGetProcAddress(ProcName); - {$ENDIF} - - {$IFDEF DGL_LINUX} - if Addr(glXGetProcAddress) <> nil then - Result := glXGetProcAddress(ProcName); - - if result <> nil then - exit; - - if Addr(glXGetProcAddressARB) <> nil then - Result := glXGetProcAddressARB(ProcName); - {$ENDIF} -end; - - -function Int_GetExtensionString: AnsiString; -begin - // generel extension string - if not Assigned(@glGetString) then - glGetString := dglGetProcAddress('glGetString'); - - if Assigned(@glGetString) then - Result := glGetString(GL_EXTENSIONS) - else - Result := ''; - - if (GL_LibHandle <> nil) then begin - {$IFDEF DGL_WIN} - // wglGetExtensionsStringEXT - if not Assigned(@wglGetExtensionsStringEXT) then - wglGetExtensionsStringEXT := dglGetProcAddress('wglGetExtensionsStringEXT'); - - if Assigned(@wglGetExtensionsStringEXT) then - Result := Result + #32 + wglGetExtensionsStringEXT; - - // wglGetExtensionsStringARB - if not Assigned(@wglGetExtensionsStringARB) then - wglGetExtensionsStringARB := dglGetProcAddress('wglGetExtensionsStringARB'); - - if Assigned(@wglGetExtensionsStringARB) then - Result := Result + #32 + wglGetExtensionsStringARB(wglGetCurrentDC); - {$ENDIF} - end; - - Result := #32 + Result + #32; -end; - - -function Int_CheckExtension(AllExtensions, CheckExtension: AnsiString): Boolean; -begin - Result := Pos(#32 + CheckExtension + #32, AllExtensions) > 0; -end; - - -function dglCheckExtension(Extension: AnsiString): Boolean; -var - Extensions: AnsiString; -begin - Extensions := Int_GetExtensionString; - Result := Int_CheckExtension(Extensions, Extension); -end; - - - -function InitOpenGL(LibName: String; GLULibName: String): Boolean; -begin - Result := False; - - // free opened libraries - if GL_LibHandle <> nil then - dglFreeLibrary(GL_LibHandle); - - if GLU_LibHandle <> nil then - dglFreeLibrary(GLU_LibHandle); - - // load library - GL_LibHandle := dglLoadLibrary(PChar(LibName)); - GLU_LibHandle := dglLoadLibrary(PChar(GLULibName)); - - // load GL functions - if (GL_LibHandle <> nil) then begin - {$IFDEF DGL_WIN} - wglCopyContext := dglGetProcAddress('wglCopyContext'); - wglCreateLayerContext := dglGetProcAddress('wglCreateLayerContext'); - wglCreateContext := dglGetProcAddress('wglCreateContext'); - wglDeleteContext := dglGetProcAddress('wglDeleteContext'); - wglDescribeLayerPlane := dglGetProcAddress('wglDescribeLayerPlane'); - wglGetCurrentContext := dglGetProcAddress('wglGetCurrentContext'); - wglGetCurrentDC := dglGetProcAddress('wglGetCurrentDC'); - wglGetLayerPaletteEntries := dglGetProcAddress('wglGetLayerPaletteEntries'); - wglGetProcAddress := dglGetProcAddress('wglGetProcAddress'); - wglMakeCurrent := dglGetProcAddress('wglMakeCurrent'); - wglRealizeLayerPalette := dglGetProcAddress('wglRealizeLayerPalette'); - wglSetLayerPaletteEntries := dglGetProcAddress('wglSetLayerPaletteEntries'); - wglShareLists := dglGetProcAddress('wglShareLists'); - wglSwapLayerBuffers := dglGetProcAddress('wglSwapLayerBuffers'); - wglSwapMultipleBuffers := dglGetProcAddress('wglSwapMultipleBuffers'); - wglUseFontBitmapsA := dglGetProcAddress('wglUseFontBitmapsA'); - wglUseFontOutlinesA := dglGetProcAddress('wglUseFontOutlinesA'); - wglUseFontBitmapsW := dglGetProcAddress('wglUseFontBitmapsW'); - wglUseFontOutlinesW := dglGetProcAddress('wglUseFontOutlinesW'); - wglUseFontBitmaps := dglGetProcAddress('wglUseFontBitmapsA'); - wglUseFontOutlines := dglGetProcAddress('wglUseFontOutlinesA'); - {$ENDIF} - - {$IFDEF DGL_LINUX} - glXChooseVisual := dglGetProcAddress('glXChooseVisual'); - glXCopyContext := dglGetProcAddress('glXCopyContext'); - glXCreateContext := dglGetProcAddress('glXCreateContext'); - glXCreateGLXPixmap := dglGetProcAddress('glXCreateGLXPixmap'); - glXDestroyContext := dglGetProcAddress('glXDestroyContext'); - glXDestroyGLXPixmap := dglGetProcAddress('glXDestroyGLXPixmap'); - glXGetConfig := dglGetProcAddress('glXGetConfig'); - glXGetCurrentContext := dglGetProcAddress('glXGetCurrentContext'); - glXGetCurrentDrawable := dglGetProcAddress('glXGetCurrentDrawable'); - glXIsDirect := dglGetProcAddress('glXIsDirect'); - glXMakeCurrent := dglGetProcAddress('glXMakeCurrent'); - glXQueryExtension := dglGetProcAddress('glXQueryExtension'); - glXQueryVersion := dglGetProcAddress('glXQueryVersion'); - glXSwapBuffers := dglGetProcAddress('glXSwapBuffers'); - glXUseXFont := dglGetProcAddress('glXUseXFont'); - glXWaitGL := dglGetProcAddress('glXWaitGL'); - glXWaitX := dglGetProcAddress('glXWaitX'); - - glXGetClientString := dglGetProcAddress('glXGetClientString'); - glXQueryServerString := dglGetProcAddress('glXQueryServerString'); - glXQueryExtensionsString := dglGetProcAddress('glXQueryExtensionsString'); - - // GLX_VERSION_1_3 - glXGetFBConfigs := dglGetProcAddress('glXGetFBConfigs'); - glXChooseFBConfig := dglGetProcAddress('glXChooseFBConfig'); - glXGetFBConfigAttrib := dglGetProcAddress('glXGetFBConfigAttrib'); - glXGetVisualFromFBConfig := dglGetProcAddress('glXGetVisualFromFBConfig'); - glXCreateWindow := dglGetProcAddress('glXCreateWindow'); - glXDestroyWindow := dglGetProcAddress('glXDestroyWindow'); - glXCreatePixmap := dglGetProcAddress('glXCreatePixmap'); - - glXDestroyPixmap := dglGetProcAddress('glXDestroyPixmap'); - glXCreatePbuffer := dglGetProcAddress('glXCreatePbuffer'); - glXDestroyPbuffer := dglGetProcAddress('glXDestroyPbuffer'); - glXQueryDrawable := dglGetProcAddress('glXQueryDrawable'); - glXCreateNewContext := dglGetProcAddress('glXCreateNewContext'); - glXMakeContextCurrent := dglGetProcAddress('glXMakeContextCurrent'); - glXGetCurrentReadDrawable := dglGetProcAddress('glXGetCurrentReadDrawable'); - glXGetCurreentDisplay := dglGetProcAddress('glXGetCurreentDisplay'); - - glXQueryContext := dglGetProcAddress('glXQueryContext'); - glXSelectEvent := dglGetProcAddress('glXSelectEvent'); - glXGetSelectedEvent := dglGetProcAddress('glXGetSelectedEvent'); - - // GLX_VERSION_1_4 - glXGetProcAddress := dglGetProcAddress('glXGetProcAddress'); - - // GLX_ARB_get_proc_address - glXGetProcAddressARB := dglGetProcAddress('glXGetProcAddressARB'); - - // GLX_ARB_create_context - glXCreateContextAttribsARB := dglGetProcAddress('glXCreateContextAttribsARB'); - - // GLX_EXT_import_context - glXGetCurrentDisplayEXT := dglGetProcAddress('glXGetCurrentDisplayEXT'); - glXQueryContextInfoEXT := dglGetProcAddress('glXQueryContextInfoEXT'); - glXGetContextIDEXT := dglGetProcAddress('glXGetContextIDEXT'); - glXImportContextEXT := dglGetProcAddress('glXImportContextEXT'); - glXFreeContextEXT := dglGetProcAddress('glXFreeContextEXT'); - - // GLX_EXT_texture_from_pixmap - glXBindTexImageEXT := dglGetProcAddress('glXBindTexImageEXT'); - glXReleaseTexImageEXT := dglGetProcAddress('glXReleaseTexImageEXT'); - {$ENDIF} - - Result := True; - end; - - // load GLU functions - if GLU_LibHandle <> nil then begin - // GLU ======================================================================== - gluBeginCurve := dglGetProcAddress('gluBeginCurve', GLU_LibHandle); - gluBeginPolygon := dglGetProcAddress('gluBeginPolygon', GLU_LibHandle); - gluBeginSurface := dglGetProcAddress('gluBeginSurface', GLU_LibHandle); - gluBeginTrim := dglGetProcAddress('gluBeginTrim', GLU_LibHandle); - gluBuild1DMipmaps := dglGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle); - gluBuild2DMipmaps := dglGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle); - gluCylinder := dglGetProcAddress('gluCylinder', GLU_LibHandle); - gluDeleteNurbsRenderer := dglGetProcAddress('gluDeleteNurbsRenderer', GLU_LibHandle); - gluDeleteQuadric := dglGetProcAddress('gluDeleteQuadric', GLU_LibHandle); - gluDeleteTess := dglGetProcAddress('gluDeleteTess', GLU_LibHandle); - gluDisk := dglGetProcAddress('gluDisk', GLU_LibHandle); - gluEndCurve := dglGetProcAddress('gluEndCurve', GLU_LibHandle); - gluEndPolygon := dglGetProcAddress('gluEndPolygon', GLU_LibHandle); - gluEndSurface := dglGetProcAddress('gluEndSurface', GLU_LibHandle); - gluEndTrim := dglGetProcAddress('gluEndTrim', GLU_LibHandle); - gluErrorString := dglGetProcAddress('gluErrorString', GLU_LibHandle); - gluGetNurbsProperty := dglGetProcAddress('gluGetNurbsProperty', GLU_LibHandle); - gluGetString := dglGetProcAddress('gluGetString', GLU_LibHandle); - gluGetTessProperty := dglGetProcAddress('gluGetTessProperty', GLU_LibHandle); - gluLoadSamplingMatrices := dglGetProcAddress('gluLoadSamplingMatrices', GLU_LibHandle); - gluLookAt := dglGetProcAddress('gluLookAt', GLU_LibHandle); - gluNewNurbsRenderer := dglGetProcAddress('gluNewNurbsRenderer', GLU_LibHandle); - gluNewQuadric := dglGetProcAddress('gluNewQuadric', GLU_LibHandle); - gluNewTess := dglGetProcAddress('gluNewTess', GLU_LibHandle); - gluNextContour := dglGetProcAddress('gluNextContour', GLU_LibHandle); - gluNurbsCallback := dglGetProcAddress('gluNurbsCallback', GLU_LibHandle); - gluNurbsCurve := dglGetProcAddress('gluNurbsCurve', GLU_LibHandle); - gluNurbsProperty := dglGetProcAddress('gluNurbsProperty', GLU_LibHandle); - gluNurbsSurface := dglGetProcAddress('gluNurbsSurface', GLU_LibHandle); - gluOrtho2D := dglGetProcAddress('gluOrtho2D', GLU_LibHandle); - gluPartialDisk := dglGetProcAddress('gluPartialDisk', GLU_LibHandle); - gluPerspective := dglGetProcAddress('gluPerspective', GLU_LibHandle); - gluPickMatrix := dglGetProcAddress('gluPickMatrix', GLU_LibHandle); - gluProject := dglGetProcAddress('gluProject', GLU_LibHandle); - gluPwlCurve := dglGetProcAddress('gluPwlCurve', GLU_LibHandle); - gluQuadricCallback := dglGetProcAddress('gluQuadricCallback', GLU_LibHandle); - gluQuadricDrawStyle := dglGetProcAddress('gluQuadricDrawStyle', GLU_LibHandle); - gluQuadricNormals := dglGetProcAddress('gluQuadricNormals', GLU_LibHandle); - gluQuadricOrientation := dglGetProcAddress('gluQuadricOrientation', GLU_LibHandle); - gluQuadricTexture := dglGetProcAddress('gluQuadricTexture', GLU_LibHandle); - gluScaleImage := dglGetProcAddress('gluScaleImage', GLU_LibHandle); - gluSphere := dglGetProcAddress('gluSphere', GLU_LibHandle); - gluTessBeginContour := dglGetProcAddress('gluTessBeginContour', GLU_LibHandle); - gluTessBeginPolygon := dglGetProcAddress('gluTessBeginPolygon', GLU_LibHandle); - gluTessCallback := dglGetProcAddress('gluTessCallback', GLU_LibHandle); - gluTessEndContour := dglGetProcAddress('gluTessEndContour', GLU_LibHandle); - gluTessEndPolygon := dglGetProcAddress('gluTessEndPolygon', GLU_LibHandle); - gluTessNormal := dglGetProcAddress('gluTessNormal', GLU_LibHandle); - gluTessProperty := dglGetProcAddress('gluTessProperty', GLU_LibHandle); - gluTessVertex := dglGetProcAddress('gluTessVertex', GLU_LibHandle); - gluUnProject := dglGetProcAddress('gluUnProject', GLU_LibHandle); - end; -end; - -procedure ReadOpenGLCore; -begin - // GL_VERSION_1_0 - glCullFace := dglGetProcAddress('glCullFace'); - glFrontFace := dglGetProcAddress('glFrontFace'); - glHint := dglGetProcAddress('glHint'); - glLineWidth := dglGetProcAddress('glLineWidth'); - glPointSize := dglGetProcAddress('glPointSize'); - glPolygonMode := dglGetProcAddress('glPolygonMode'); - glScissor := dglGetProcAddress('glScissor'); - glTexParameterf := dglGetProcAddress('glTexParameterf'); - glTexParameterfv := dglGetProcAddress('glTexParameterfv'); - glTexParameteri := dglGetProcAddress('glTexParameteri'); - glTexParameteriv := dglGetProcAddress('glTexParameteriv'); - glTexImage1D := dglGetProcAddress('glTexImage1D'); - glTexImage2D := dglGetProcAddress('glTexImage2D'); - glDrawBuffer := dglGetProcAddress('glDrawBuffer'); - glClear := dglGetProcAddress('glClear'); - glClearColor := dglGetProcAddress('glClearColor'); - glClearStencil := dglGetProcAddress('glClearStencil'); - glClearDepth := dglGetProcAddress('glClearDepth'); - glStencilMask := dglGetProcAddress('glStencilMask'); - glColorMask := dglGetProcAddress('glColorMask'); - glDepthMask := dglGetProcAddress('glDepthMask'); - glDisable := dglGetProcAddress('glDisable'); - glEnable := dglGetProcAddress('glEnable'); - glFinish := dglGetProcAddress('glFinish'); - glFlush := dglGetProcAddress('glFlush'); - glBlendFunc := dglGetProcAddress('glBlendFunc'); - glLogicOp := dglGetProcAddress('glLogicOp'); - glStencilFunc := dglGetProcAddress('glStencilFunc'); - glStencilOp := dglGetProcAddress('glStencilOp'); - glDepthFunc := dglGetProcAddress('glDepthFunc'); - glPixelStoref := dglGetProcAddress('glPixelStoref'); - glPixelStorei := dglGetProcAddress('glPixelStorei'); - glReadBuffer := dglGetProcAddress('glReadBuffer'); - glReadPixels := dglGetProcAddress('glReadPixels'); - glGetBooleanv := dglGetProcAddress('glGetBooleanv'); - glGetDoublev := dglGetProcAddress('glGetDoublev'); - glGetError := dglGetProcAddress('glGetError'); - glGetFloatv := dglGetProcAddress('glGetFloatv'); - glGetIntegerv := dglGetProcAddress('glGetIntegerv'); - glGetString := dglGetProcAddress('glGetString'); - glGetTexImage := dglGetProcAddress('glGetTexImage'); - glGetTexParameteriv := dglGetProcAddress('glGetTexParameteriv'); - glGetTexParameterfv := dglGetProcAddress('glGetTexParameterfv'); - glGetTexLevelParameterfv := dglGetProcAddress('glGetTexLevelParameterfv'); - glGetTexLevelParameteriv := dglGetProcAddress('glGetTexLevelParameteriv'); - glIsEnabled := dglGetProcAddress('glIsEnabled'); - glDepthRange := dglGetProcAddress('glDepthRange'); - glViewport := dglGetProcAddress('glViewport'); - - // GL_VERSION_1_1 - glDrawArrays := dglGetProcAddress('glDrawArrays'); - glDrawElements := dglGetProcAddress('glDrawElements'); - glGetPointerv := dglGetProcAddress('glGetPointerv'); - glPolygonOffset := dglGetProcAddress('glPolygonOffset'); - glCopyTexImage1D := dglGetProcAddress('glCopyTexImage1D'); - glCopyTexImage2D := dglGetProcAddress('glCopyTexImage2D'); - glCopyTexSubImage1D := dglGetProcAddress('glCopyTexSubImage1D'); - glCopyTexSubImage2D := dglGetProcAddress('glCopyTexSubImage2D'); - glTexSubImage1D := dglGetProcAddress('glTexSubImage1D'); - glTexSubImage2D := dglGetProcAddress('glTexSubImage2D'); - glBindTexture := dglGetProcAddress('glBindTexture'); - glDeleteTextures := dglGetProcAddress('glDeleteTextures'); - glGenTextures := dglGetProcAddress('glGenTextures'); - -{$ifdef DGL_DEPRECATED} - glAccum := dglGetProcAddress('glAccum'); - glAlphaFunc := dglGetProcAddress('glAlphaFunc'); - glAreTexturesResident := dglGetProcAddress('glAreTexturesResident'); - glArrayElement := dglGetProcAddress('glArrayElement'); - glBegin := dglGetProcAddress('glBegin'); - glBitmap := dglGetProcAddress('glBitmap'); - glCallList := dglGetProcAddress('glCallList'); - glCallLists := dglGetProcAddress('glCallLists'); - glClearAccum := dglGetProcAddress('glClearAccum'); - glClearIndex := dglGetProcAddress('glClearIndex'); - glClipPlane := dglGetProcAddress('glClipPlane'); - glColor3b := dglGetProcAddress('glColor3b'); - glColor3bv := dglGetProcAddress('glColor3bv'); - glColor3d := dglGetProcAddress('glColor3d'); - glColor3dv := dglGetProcAddress('glColor3dv'); - glColor3f := dglGetProcAddress('glColor3f'); - glColor3fv := dglGetProcAddress('glColor3fv'); - glColor3i := dglGetProcAddress('glColor3i'); - glColor3iv := dglGetProcAddress('glColor3iv'); - glColor3s := dglGetProcAddress('glColor3s'); - glColor3sv := dglGetProcAddress('glColor3sv'); - glColor3ub := dglGetProcAddress('glColor3ub'); - glColor3ubv := dglGetProcAddress('glColor3ubv'); - glColor3ui := dglGetProcAddress('glColor3ui'); - glColor3uiv := dglGetProcAddress('glColor3uiv'); - glColor3us := dglGetProcAddress('glColor3us'); - glColor3usv := dglGetProcAddress('glColor3usv'); - glColor4b := dglGetProcAddress('glColor4b'); - glColor4bv := dglGetProcAddress('glColor4bv'); - glColor4d := dglGetProcAddress('glColor4d'); - glColor4dv := dglGetProcAddress('glColor4dv'); - glColor4f := dglGetProcAddress('glColor4f'); - glColor4fv := dglGetProcAddress('glColor4fv'); - glColor4i := dglGetProcAddress('glColor4i'); - glColor4iv := dglGetProcAddress('glColor4iv'); - glColor4s := dglGetProcAddress('glColor4s'); - glColor4sv := dglGetProcAddress('glColor4sv'); - glColor4ub := dglGetProcAddress('glColor4ub'); - glColor4ubv := dglGetProcAddress('glColor4ubv'); - glColor4ui := dglGetProcAddress('glColor4ui'); - glColor4uiv := dglGetProcAddress('glColor4uiv'); - glColor4us := dglGetProcAddress('glColor4us'); - glColor4usv := dglGetProcAddress('glColor4usv'); - glColorMaterial := dglGetProcAddress('glColorMaterial'); - glColorPointer := dglGetProcAddress('glColorPointer'); - glCopyPixels := dglGetProcAddress('glCopyPixels'); - glDeleteLists := dglGetProcAddress('glDeleteLists'); - glDisableClientState := dglGetProcAddress('glDisableClientState'); - glDrawPixels := dglGetProcAddress('glDrawPixels'); - glEdgeFlag := dglGetProcAddress('glEdgeFlag'); - glEdgeFlagPointer := dglGetProcAddress('glEdgeFlagPointer'); - glEdgeFlagv := dglGetProcAddress('glEdgeFlagv'); - glEnableClientState := dglGetProcAddress('glEnableClientState'); - glEnd := dglGetProcAddress('glEnd'); - glEndList := dglGetProcAddress('glEndList'); - glEvalCoord1d := dglGetProcAddress('glEvalCoord1d'); - glEvalCoord1dv := dglGetProcAddress('glEvalCoord1dv'); - glEvalCoord1f := dglGetProcAddress('glEvalCoord1f'); - glEvalCoord1fv := dglGetProcAddress('glEvalCoord1fv'); - glEvalCoord2d := dglGetProcAddress('glEvalCoord2d'); - glEvalCoord2dv := dglGetProcAddress('glEvalCoord2dv'); - glEvalCoord2f := dglGetProcAddress('glEvalCoord2f'); - glEvalCoord2fv := dglGetProcAddress('glEvalCoord2fv'); - glEvalMesh1 := dglGetProcAddress('glEvalMesh1'); - glEvalMesh2 := dglGetProcAddress('glEvalMesh2'); - glEvalPoint1 := dglGetProcAddress('glEvalPoint1'); - glEvalPoint2 := dglGetProcAddress('glEvalPoint2'); - glFeedbackBuffer := dglGetProcAddress('glFeedbackBuffer'); - glFogf := dglGetProcAddress('glFogf'); - glFogfv := dglGetProcAddress('glFogfv'); - glFogi := dglGetProcAddress('glFogi'); - glFogiv := dglGetProcAddress('glFogiv'); - glFrustum := dglGetProcAddress('glFrustum'); - glGenLists := dglGetProcAddress('glGenLists'); - glGetClipPlane := dglGetProcAddress('glGetClipPlane'); - glGetLightfv := dglGetProcAddress('glGetLightfv'); - glGetLightiv := dglGetProcAddress('glGetLightiv'); - glGetMapdv := dglGetProcAddress('glGetMapdv'); - glGetMapfv := dglGetProcAddress('glGetMapfv'); - glGetMapiv := dglGetProcAddress('glGetMapiv'); - glGetMaterialfv := dglGetProcAddress('glGetMaterialfv'); - glGetMaterialiv := dglGetProcAddress('glGetMaterialiv'); - glGetPixelMapfv := dglGetProcAddress('glGetPixelMapfv'); - glGetPixelMapuiv := dglGetProcAddress('glGetPixelMapuiv'); - glGetPixelMapusv := dglGetProcAddress('glGetPixelMapusv'); - glGetPolygonStipple := dglGetProcAddress('glGetPolygonStipple'); - glGetTexEnvfv := dglGetProcAddress('glGetTexEnvfv'); - glGetTexEnviv := dglGetProcAddress('glGetTexEnviv'); - glGetTexGendv := dglGetProcAddress('glGetTexGendv'); - glGetTexGenfv := dglGetProcAddress('glGetTexGenfv'); - glGetTexGeniv := dglGetProcAddress('glGetTexGeniv'); - glIndexMask := dglGetProcAddress('glIndexMask'); - glIndexPointer := dglGetProcAddress('glIndexPointer'); - glIndexd := dglGetProcAddress('glIndexd'); - glIndexdv := dglGetProcAddress('glIndexdv'); - glIndexf := dglGetProcAddress('glIndexf'); - glIndexfv := dglGetProcAddress('glIndexfv'); - glIndexi := dglGetProcAddress('glIndexi'); - glIndexiv := dglGetProcAddress('glIndexiv'); - glIndexs := dglGetProcAddress('glIndexs'); - glIndexsv := dglGetProcAddress('glIndexsv'); - glIndexub := dglGetProcAddress('glIndexub'); - glIndexubv := dglGetProcAddress('glIndexubv'); - glInitNames := dglGetProcAddress('glInitNames'); - glInterleavedArrays := dglGetProcAddress('glInterleavedArrays'); - glIsList := dglGetProcAddress('glIsList'); - glIsTexture := dglGetProcAddress('glIsTexture'); - glLightModelf := dglGetProcAddress('glLightModelf'); - glLightModelfv := dglGetProcAddress('glLightModelfv'); - glLightModeli := dglGetProcAddress('glLightModeli'); - glLightModeliv := dglGetProcAddress('glLightModeliv'); - glLightf := dglGetProcAddress('glLightf'); - glLightfv := dglGetProcAddress('glLightfv'); - glLighti := dglGetProcAddress('glLighti'); - glLightiv := dglGetProcAddress('glLightiv'); - glLineStipple := dglGetProcAddress('glLineStipple'); - glListBase := dglGetProcAddress('glListBase'); - glLoadIdentity := dglGetProcAddress('glLoadIdentity'); - glLoadMatrixd := dglGetProcAddress('glLoadMatrixd'); - glLoadMatrixf := dglGetProcAddress('glLoadMatrixf'); - glLoadName := dglGetProcAddress('glLoadName'); - glMap1d := dglGetProcAddress('glMap1d'); - glMap1f := dglGetProcAddress('glMap1f'); - glMap2d := dglGetProcAddress('glMap2d'); - glMap2f := dglGetProcAddress('glMap2f'); - glMapGrid1d := dglGetProcAddress('glMapGrid1d'); - glMapGrid1f := dglGetProcAddress('glMapGrid1f'); - glMapGrid2d := dglGetProcAddress('glMapGrid2d'); - glMapGrid2f := dglGetProcAddress('glMapGrid2f'); - glMaterialf := dglGetProcAddress('glMaterialf'); - glMaterialfv := dglGetProcAddress('glMaterialfv'); - glMateriali := dglGetProcAddress('glMateriali'); - glMaterialiv := dglGetProcAddress('glMaterialiv'); - glMatrixMode := dglGetProcAddress('glMatrixMode'); - glMultMatrixd := dglGetProcAddress('glMultMatrixd'); - glMultMatrixf := dglGetProcAddress('glMultMatrixf'); - glNewList := dglGetProcAddress('glNewList'); - glNormal3b := dglGetProcAddress('glNormal3b'); - glNormal3bv := dglGetProcAddress('glNormal3bv'); - glNormal3d := dglGetProcAddress('glNormal3d'); - glNormal3dv := dglGetProcAddress('glNormal3dv'); - glNormal3f := dglGetProcAddress('glNormal3f'); - glNormal3fv := dglGetProcAddress('glNormal3fv'); - glNormal3i := dglGetProcAddress('glNormal3i'); - glNormal3iv := dglGetProcAddress('glNormal3iv'); - glNormal3s := dglGetProcAddress('glNormal3s'); - glNormal3sv := dglGetProcAddress('glNormal3sv'); - glNormalPointer := dglGetProcAddress('glNormalPointer'); - glOrtho := dglGetProcAddress('glOrtho'); - glPassThrough := dglGetProcAddress('glPassThrough'); - glPixelMapfv := dglGetProcAddress('glPixelMapfv'); - glPixelMapuiv := dglGetProcAddress('glPixelMapuiv'); - glPixelMapusv := dglGetProcAddress('glPixelMapusv'); - glPixelTransferf := dglGetProcAddress('glPixelTransferf'); - glPixelTransferi := dglGetProcAddress('glPixelTransferi'); - glPixelZoom := dglGetProcAddress('glPixelZoom'); - glPolygonStipple := dglGetProcAddress('glPolygonStipple'); - glPopAttrib := dglGetProcAddress('glPopAttrib'); - glPopClientAttrib := dglGetProcAddress('glPopClientAttrib'); - glPopMatrix := dglGetProcAddress('glPopMatrix'); - glPopName := dglGetProcAddress('glPopName'); - glPrioritizeTextures := dglGetProcAddress('glPrioritizeTextures'); - glPushAttrib := dglGetProcAddress('glPushAttrib'); - glPushClientAttrib := dglGetProcAddress('glPushClientAttrib'); - glPushMatrix := dglGetProcAddress('glPushMatrix'); - glPushName := dglGetProcAddress('glPushName'); - glRasterPos2d := dglGetProcAddress('glRasterPos2d'); - glRasterPos2dv := dglGetProcAddress('glRasterPos2dv'); - glRasterPos2f := dglGetProcAddress('glRasterPos2f'); - glRasterPos2fv := dglGetProcAddress('glRasterPos2fv'); - glRasterPos2i := dglGetProcAddress('glRasterPos2i'); - glRasterPos2iv := dglGetProcAddress('glRasterPos2iv'); - glRasterPos2s := dglGetProcAddress('glRasterPos2s'); - glRasterPos2sv := dglGetProcAddress('glRasterPos2sv'); - glRasterPos3d := dglGetProcAddress('glRasterPos3d'); - glRasterPos3dv := dglGetProcAddress('glRasterPos3dv'); - glRasterPos3f := dglGetProcAddress('glRasterPos3f'); - glRasterPos3fv := dglGetProcAddress('glRasterPos3fv'); - glRasterPos3i := dglGetProcAddress('glRasterPos3i'); - glRasterPos3iv := dglGetProcAddress('glRasterPos3iv'); - glRasterPos3s := dglGetProcAddress('glRasterPos3s'); - glRasterPos3sv := dglGetProcAddress('glRasterPos3sv'); - glRasterPos4d := dglGetProcAddress('glRasterPos4d'); - glRasterPos4dv := dglGetProcAddress('glRasterPos4dv'); - glRasterPos4f := dglGetProcAddress('glRasterPos4f'); - glRasterPos4fv := dglGetProcAddress('glRasterPos4fv'); - glRasterPos4i := dglGetProcAddress('glRasterPos4i'); - glRasterPos4iv := dglGetProcAddress('glRasterPos4iv'); - glRasterPos4s := dglGetProcAddress('glRasterPos4s'); - glRasterPos4sv := dglGetProcAddress('glRasterPos4sv'); - glRectd := dglGetProcAddress('glRectd'); - glRectdv := dglGetProcAddress('glRectdv'); - glRectf := dglGetProcAddress('glRectf'); - glRectfv := dglGetProcAddress('glRectfv'); - glRecti := dglGetProcAddress('glRecti'); - glRectiv := dglGetProcAddress('glRectiv'); - glRects := dglGetProcAddress('glRects'); - glRectsv := dglGetProcAddress('glRectsv'); - glRenderMode := dglGetProcAddress('glRenderMode'); - glRotated := dglGetProcAddress('glRotated'); - glRotatef := dglGetProcAddress('glRotatef'); - glScaled := dglGetProcAddress('glScaled'); - glScalef := dglGetProcAddress('glScalef'); - glSelectBuffer := dglGetProcAddress('glSelectBuffer'); - glShadeModel := dglGetProcAddress('glShadeModel'); - glTexCoord1d := dglGetProcAddress('glTexCoord1d'); - glTexCoord1dv := dglGetProcAddress('glTexCoord1dv'); - glTexCoord1f := dglGetProcAddress('glTexCoord1f'); - glTexCoord1fv := dglGetProcAddress('glTexCoord1fv'); - glTexCoord1i := dglGetProcAddress('glTexCoord1i'); - glTexCoord1iv := dglGetProcAddress('glTexCoord1iv'); - glTexCoord1s := dglGetProcAddress('glTexCoord1s'); - glTexCoord1sv := dglGetProcAddress('glTexCoord1sv'); - glTexCoord2d := dglGetProcAddress('glTexCoord2d'); - glTexCoord2dv := dglGetProcAddress('glTexCoord2dv'); - glTexCoord2f := dglGetProcAddress('glTexCoord2f'); - glTexCoord2fv := dglGetProcAddress('glTexCoord2fv'); - glTexCoord2i := dglGetProcAddress('glTexCoord2i'); - glTexCoord2iv := dglGetProcAddress('glTexCoord2iv'); - glTexCoord2s := dglGetProcAddress('glTexCoord2s'); - glTexCoord2sv := dglGetProcAddress('glTexCoord2sv'); - glTexCoord3d := dglGetProcAddress('glTexCoord3d'); - glTexCoord3dv := dglGetProcAddress('glTexCoord3dv'); - glTexCoord3f := dglGetProcAddress('glTexCoord3f'); - glTexCoord3fv := dglGetProcAddress('glTexCoord3fv'); - glTexCoord3i := dglGetProcAddress('glTexCoord3i'); - glTexCoord3iv := dglGetProcAddress('glTexCoord3iv'); - glTexCoord3s := dglGetProcAddress('glTexCoord3s'); - glTexCoord3sv := dglGetProcAddress('glTexCoord3sv'); - glTexCoord4d := dglGetProcAddress('glTexCoord4d'); - glTexCoord4dv := dglGetProcAddress('glTexCoord4dv'); - glTexCoord4f := dglGetProcAddress('glTexCoord4f'); - glTexCoord4fv := dglGetProcAddress('glTexCoord4fv'); - glTexCoord4i := dglGetProcAddress('glTexCoord4i'); - glTexCoord4iv := dglGetProcAddress('glTexCoord4iv'); - glTexCoord4s := dglGetProcAddress('glTexCoord4s'); - glTexCoord4sv := dglGetProcAddress('glTexCoord4sv'); - glTexCoordPointer := dglGetProcAddress('glTexCoordPointer'); - glTexEnvf := dglGetProcAddress('glTexEnvf'); - glTexEnvfv := dglGetProcAddress('glTexEnvfv'); - glTexEnvi := dglGetProcAddress('glTexEnvi'); - glTexEnviv := dglGetProcAddress('glTexEnviv'); - glTexGend := dglGetProcAddress('glTexGend'); - glTexGendv := dglGetProcAddress('glTexGendv'); - glTexGenf := dglGetProcAddress('glTexGenf'); - glTexGenfv := dglGetProcAddress('glTexGenfv'); - glTexGeni := dglGetProcAddress('glTexGeni'); - glTexGeniv := dglGetProcAddress('glTexGeniv'); - glTranslated := dglGetProcAddress('glTranslated'); - glTranslatef := dglGetProcAddress('glTranslatef'); - glVertex2d := dglGetProcAddress('glVertex2d'); - glVertex2dv := dglGetProcAddress('glVertex2dv'); - glVertex2f := dglGetProcAddress('glVertex2f'); - glVertex2fv := dglGetProcAddress('glVertex2fv'); - glVertex2i := dglGetProcAddress('glVertex2i'); - glVertex2iv := dglGetProcAddress('glVertex2iv'); - glVertex2s := dglGetProcAddress('glVertex2s'); - glVertex2sv := dglGetProcAddress('glVertex2sv'); - glVertex3d := dglGetProcAddress('glVertex3d'); - glVertex3dv := dglGetProcAddress('glVertex3dv'); - glVertex3f := dglGetProcAddress('glVertex3f'); - glVertex3fv := dglGetProcAddress('glVertex3fv'); - glVertex3i := dglGetProcAddress('glVertex3i'); - glVertex3iv := dglGetProcAddress('glVertex3iv'); - glVertex3s := dglGetProcAddress('glVertex3s'); - glVertex3sv := dglGetProcAddress('glVertex3sv'); - glVertex4d := dglGetProcAddress('glVertex4d'); - glVertex4dv := dglGetProcAddress('glVertex4dv'); - glVertex4f := dglGetProcAddress('glVertex4f'); - glVertex4fv := dglGetProcAddress('glVertex4fv'); - glVertex4i := dglGetProcAddress('glVertex4i'); - glVertex4iv := dglGetProcAddress('glVertex4iv'); - glVertex4s := dglGetProcAddress('glVertex4s'); - glVertex4sv := dglGetProcAddress('glVertex4sv'); - glVertexPointer := dglGetProcAddress('glVertexPointer'); -{$endif} - - // GL_VERSION_1_2 - glBlendColor := dglGetProcAddress('glBlendColor'); - glBlendEquation := dglGetProcAddress('glBlendEquation'); - glDrawRangeElements := dglGetProcAddress('glDrawRangeElements'); - glTexImage3D := dglGetProcAddress('glTexImage3D'); - glTexSubImage3D := dglGetProcAddress('glTexSubImage3D'); - glCopyTexSubImage3D := dglGetProcAddress('glCopyTexSubImage3D'); -{$ifdef DGL_DEPRECATED} - glColorTable := dglGetProcAddress('glColorTable'); - glColorTableParameterfv := dglGetProcAddress('glColorTableParameterfv'); - glColorTableParameteriv := dglGetProcAddress('glColorTableParameteriv'); - glCopyColorTable := dglGetProcAddress('glCopyColorTable'); - glGetColorTable := dglGetProcAddress('glGetColorTable'); - glGetColorTableParameterfv := dglGetProcAddress('glGetColorTableParameterfv'); - glGetColorTableParameteriv := dglGetProcAddress('glGetColorTableParameteriv'); - glColorSubTable := dglGetProcAddress('glColorSubTable'); - glCopyColorSubTable := dglGetProcAddress('glCopyColorSubTable'); - glConvolutionFilter1D := dglGetProcAddress('glConvolutionFilter1D'); - glConvolutionFilter2D := dglGetProcAddress('glConvolutionFilter2D'); - glConvolutionParameterf := dglGetProcAddress('glConvolutionParameterf'); - glConvolutionParameterfv := dglGetProcAddress('glConvolutionParameterfv'); - glConvolutionParameteri := dglGetProcAddress('glConvolutionParameteri'); - glConvolutionParameteriv := dglGetProcAddress('glConvolutionParameteriv'); - glCopyConvolutionFilter1D := dglGetProcAddress('glCopyConvolutionFilter1D'); - glCopyConvolutionFilter2D := dglGetProcAddress('glCopyConvolutionFilter2D'); - glGetConvolutionFilter := dglGetProcAddress('glGetConvolutionFilter'); - glGetConvolutionParameterfv := dglGetProcAddress('glGetConvolutionParameterfv'); - glGetConvolutionParameteriv := dglGetProcAddress('glGetConvolutionParameteriv'); - glGetSeparableFilter := dglGetProcAddress('glGetSeparableFilter'); - glSeparableFilter2D := dglGetProcAddress('glSeparableFilter2D'); - glGetHistogram := dglGetProcAddress('glGetHistogram'); - glGetHistogramParameterfv := dglGetProcAddress('glGetHistogramParameterfv'); - glGetHistogramParameteriv := dglGetProcAddress('glGetHistogramParameteriv'); - glGetMinmax := dglGetProcAddress('glGetMinmax'); - glGetMinmaxParameterfv := dglGetProcAddress('glGetMinmaxParameterfv'); - glGetMinmaxParameteriv := dglGetProcAddress('glGetMinmaxParameteriv'); - glHistogram := dglGetProcAddress('glHistogram'); - glMinmax := dglGetProcAddress('glMinmax'); - glResetHistogram := dglGetProcAddress('glResetHistogram'); - glResetMinmax := dglGetProcAddress('glResetMinmax'); -{$endif} - - // GL_VERSION_1_3 - glActiveTexture := dglGetProcAddress('glActiveTexture'); - glSampleCoverage := dglGetProcAddress('glSampleCoverage'); - glCompressedTexImage3D := dglGetProcAddress('glCompressedTexImage3D'); - glCompressedTexImage2D := dglGetProcAddress('glCompressedTexImage2D'); - glCompressedTexImage1D := dglGetProcAddress('glCompressedTexImage1D'); - glCompressedTexSubImage3D := dglGetProcAddress('glCompressedTexSubImage3D'); - glCompressedTexSubImage2D := dglGetProcAddress('glCompressedTexSubImage2D'); - glCompressedTexSubImage1D := dglGetProcAddress('glCompressedTexSubImage1D'); - glGetCompressedTexImage := dglGetProcAddress('glGetCompressedTexImage'); -{$ifdef DGL_DEPRECATED} - glClientActiveTexture := dglGetProcAddress('glClientActiveTexture'); - glMultiTexCoord1d := dglGetProcAddress('glMultiTexCoord1d'); - glMultiTexCoord1dv := dglGetProcAddress('glMultiTexCoord1dv'); - glMultiTexCoord1f := dglGetProcAddress('glMultiTexCoord1f'); - glMultiTexCoord1fv := dglGetProcAddress('glMultiTexCoord1fv'); - glMultiTexCoord1i := dglGetProcAddress('glMultiTexCoord1i'); - glMultiTexCoord1iv := dglGetProcAddress('glMultiTexCoord1iv'); - glMultiTexCoord1s := dglGetProcAddress('glMultiTexCoord1s'); - glMultiTexCoord1sv := dglGetProcAddress('glMultiTexCoord1sv'); - glMultiTexCoord2d := dglGetProcAddress('glMultiTexCoord2d'); - glMultiTexCoord2dv := dglGetProcAddress('glMultiTexCoord2dv'); - glMultiTexCoord2f := dglGetProcAddress('glMultiTexCoord2f'); - glMultiTexCoord2fv := dglGetProcAddress('glMultiTexCoord2fv'); - glMultiTexCoord2i := dglGetProcAddress('glMultiTexCoord2i'); - glMultiTexCoord2iv := dglGetProcAddress('glMultiTexCoord2iv'); - glMultiTexCoord2s := dglGetProcAddress('glMultiTexCoord2s'); - glMultiTexCoord2sv := dglGetProcAddress('glMultiTexCoord2sv'); - glMultiTexCoord3d := dglGetProcAddress('glMultiTexCoord3d'); - glMultiTexCoord3dv := dglGetProcAddress('glMultiTexCoord3dv'); - glMultiTexCoord3f := dglGetProcAddress('glMultiTexCoord3f'); - glMultiTexCoord3fv := dglGetProcAddress('glMultiTexCoord3fv'); - glMultiTexCoord3i := dglGetProcAddress('glMultiTexCoord3i'); - glMultiTexCoord3iv := dglGetProcAddress('glMultiTexCoord3iv'); - glMultiTexCoord3s := dglGetProcAddress('glMultiTexCoord3s'); - glMultiTexCoord3sv := dglGetProcAddress('glMultiTexCoord3sv'); - glMultiTexCoord4d := dglGetProcAddress('glMultiTexCoord4d'); - glMultiTexCoord4dv := dglGetProcAddress('glMultiTexCoord4dv'); - glMultiTexCoord4f := dglGetProcAddress('glMultiTexCoord4f'); - glMultiTexCoord4fv := dglGetProcAddress('glMultiTexCoord4fv'); - glMultiTexCoord4i := dglGetProcAddress('glMultiTexCoord4i'); - glMultiTexCoord4iv := dglGetProcAddress('glMultiTexCoord4iv'); - glMultiTexCoord4s := dglGetProcAddress('glMultiTexCoord4s'); - glMultiTexCoord4sv := dglGetProcAddress('glMultiTexCoord4sv'); - glLoadTransposeMatrixf := dglGetProcAddress('glLoadTransposeMatrixf'); - glLoadTransposeMatrixd := dglGetProcAddress('glLoadTransposeMatrixd'); - glMultTransposeMatrixf := dglGetProcAddress('glMultTransposeMatrixf'); - glMultTransposeMatrixd := dglGetProcAddress('glMultTransposeMatrixd'); -{$endif} - - // GL_VERSION_1_4 - glBlendFuncSeparate := dglGetProcAddress('glBlendFuncSeparate'); - glMultiDrawArrays := dglGetProcAddress('glMultiDrawArrays'); - glMultiDrawElements := dglGetProcAddress('glMultiDrawElements'); - glPointParameterf := dglGetProcAddress('glPointParameterf'); - glPointParameterfv := dglGetProcAddress('glPointParameterfv'); - glPointParameteri := dglGetProcAddress('glPointParameteri'); - glPointParameteriv := dglGetProcAddress('glPointParameteriv'); -{$ifdef DGL_DEPRECATED} - glFogCoordf := dglGetProcAddress('glFogCoordf'); - glFogCoordfv := dglGetProcAddress('glFogCoordfv'); - glFogCoordd := dglGetProcAddress('glFogCoordd'); - glFogCoorddv := dglGetProcAddress('glFogCoorddv'); - glFogCoordPointer := dglGetProcAddress('glFogCoordPointer'); - glSecondaryColor3b := dglGetProcAddress('glSecondaryColor3b'); - glSecondaryColor3bv := dglGetProcAddress('glSecondaryColor3bv'); - glSecondaryColor3d := dglGetProcAddress('glSecondaryColor3d'); - glSecondaryColor3dv := dglGetProcAddress('glSecondaryColor3dv'); - glSecondaryColor3f := dglGetProcAddress('glSecondaryColor3f'); - glSecondaryColor3fv := dglGetProcAddress('glSecondaryColor3fv'); - glSecondaryColor3i := dglGetProcAddress('glSecondaryColor3i'); - glSecondaryColor3iv := dglGetProcAddress('glSecondaryColor3iv'); - glSecondaryColor3s := dglGetProcAddress('glSecondaryColor3s'); - glSecondaryColor3sv := dglGetProcAddress('glSecondaryColor3sv'); - glSecondaryColor3ub := dglGetProcAddress('glSecondaryColor3ub'); - glSecondaryColor3ubv := dglGetProcAddress('glSecondaryColor3ubv'); - glSecondaryColor3ui := dglGetProcAddress('glSecondaryColor3ui'); - glSecondaryColor3uiv := dglGetProcAddress('glSecondaryColor3uiv'); - glSecondaryColor3us := dglGetProcAddress('glSecondaryColor3us'); - glSecondaryColor3usv := dglGetProcAddress('glSecondaryColor3usv'); - glSecondaryColorPointer := dglGetProcAddress('glSecondaryColorPointer'); - glWindowPos2d := dglGetProcAddress('glWindowPos2d'); - glWindowPos2dv := dglGetProcAddress('glWindowPos2dv'); - glWindowPos2f := dglGetProcAddress('glWindowPos2f'); - glWindowPos2fv := dglGetProcAddress('glWindowPos2fv'); - glWindowPos2i := dglGetProcAddress('glWindowPos2i'); - glWindowPos2iv := dglGetProcAddress('glWindowPos2iv'); - glWindowPos2s := dglGetProcAddress('glWindowPos2s'); - glWindowPos2sv := dglGetProcAddress('glWindowPos2sv'); - glWindowPos3d := dglGetProcAddress('glWindowPos3d'); - glWindowPos3dv := dglGetProcAddress('glWindowPos3dv'); - glWindowPos3f := dglGetProcAddress('glWindowPos3f'); - glWindowPos3fv := dglGetProcAddress('glWindowPos3fv'); - glWindowPos3i := dglGetProcAddress('glWindowPos3i'); - glWindowPos3iv := dglGetProcAddress('glWindowPos3iv'); - glWindowPos3s := dglGetProcAddress('glWindowPos3s'); - glWindowPos3sv := dglGetProcAddress('glWindowPos3sv'); -{$endif} - - // GL_VERSION_1_5 - glGenQueries := dglGetProcAddress('glGenQueries'); - glDeleteQueries := dglGetProcAddress('glDeleteQueries'); - glIsQuery := dglGetProcAddress('glIsQuery'); - glBeginQuery := dglGetProcAddress('glBeginQuery'); - glEndQuery := dglGetProcAddress('glEndQuery'); - glGetQueryiv := dglGetProcAddress('glGetQueryiv'); - glGetQueryObjectiv := dglGetProcAddress('glGetQueryObjectiv'); - glGetQueryObjectuiv := dglGetProcAddress('glGetQueryObjectuiv'); - glBindBuffer := dglGetProcAddress('glBindBuffer'); - glDeleteBuffers := dglGetProcAddress('glDeleteBuffers'); - glGenBuffers := dglGetProcAddress('glGenBuffers'); - glIsBuffer := dglGetProcAddress('glIsBuffer'); - glBufferData := dglGetProcAddress('glBufferData'); - glBufferSubData := dglGetProcAddress('glBufferSubData'); - glGetBufferSubData := dglGetProcAddress('glGetBufferSubData'); - glMapBuffer := dglGetProcAddress('glMapBuffer'); - glUnmapBuffer := dglGetProcAddress('glUnmapBuffer'); - glGetBufferParameteriv := dglGetProcAddress('glGetBufferParameteriv'); - glGetBufferPointerv := dglGetProcAddress('glGetBufferPointerv'); - - // GL_VERSION_2_0 - glBlendEquationSeparate := dglGetProcAddress('glBlendEquationSeparate'); - glDrawBuffers := dglGetProcAddress('glDrawBuffers'); - glStencilOpSeparate := dglGetProcAddress('glStencilOpSeparate'); - glStencilFuncSeparate := dglGetProcAddress('glStencilFuncSeparate'); - glStencilMaskSeparate := dglGetProcAddress('glStencilMaskSeparate'); - glAttachShader := dglGetProcAddress('glAttachShader'); - glBindAttribLocation := dglGetProcAddress('glBindAttribLocation'); - glCompileShader := dglGetProcAddress('glCompileShader'); - glCreateProgram := dglGetProcAddress('glCreateProgram'); - glCreateShader := dglGetProcAddress('glCreateShader'); - glDeleteProgram := dglGetProcAddress('glDeleteProgram'); - glDeleteShader := dglGetProcAddress('glDeleteShader'); - glDetachShader := dglGetProcAddress('glDetachShader'); - glDisableVertexAttribArray := dglGetProcAddress('glDisableVertexAttribArray'); - glEnableVertexAttribArray := dglGetProcAddress('glEnableVertexAttribArray'); - glGetActiveAttrib := dglGetProcAddress('glGetActiveAttrib'); - glGetActiveUniform := dglGetProcAddress('glGetActiveUniform'); - glGetAttachedShaders := dglGetProcAddress('glGetAttachedShaders'); - glGetAttribLocation := dglGetProcAddress('glGetAttribLocation'); - glGetProgramiv := dglGetProcAddress('glGetProgramiv'); - glGetProgramInfoLog := dglGetProcAddress('glGetProgramInfoLog'); - glGetShaderiv := dglGetProcAddress('glGetShaderiv'); - glGetShaderInfoLog := dglGetProcAddress('glGetShaderInfoLog'); - glGetShaderSource := dglGetProcAddress('glGetShaderSource'); - glGetUniformLocation := dglGetProcAddress('glGetUniformLocation'); - glGetUniformfv := dglGetProcAddress('glGetUniformfv'); - glGetUniformiv := dglGetProcAddress('glGetUniformiv'); - glGetVertexAttribfv := dglGetProcAddress('glGetVertexAttribfv'); - glGetVertexAttribiv := dglGetProcAddress('glGetVertexAttribiv'); - glGetVertexAttribPointerv := dglGetProcAddress('glGetVertexAttribPointerv'); - glIsProgram := dglGetProcAddress('glIsProgram'); - glIsShader := dglGetProcAddress('glIsShader'); - glLinkProgram := dglGetProcAddress('glLinkProgram'); - glShaderSource := dglGetProcAddress('glShaderSource'); - glUseProgram := dglGetProcAddress('glUseProgram'); - glUniform1f := dglGetProcAddress('glUniform1f'); - glUniform2f := dglGetProcAddress('glUniform2f'); - glUniform3f := dglGetProcAddress('glUniform3f'); - glUniform4f := dglGetProcAddress('glUniform4f'); - glUniform1i := dglGetProcAddress('glUniform1i'); - glUniform2i := dglGetProcAddress('glUniform2i'); - glUniform3i := dglGetProcAddress('glUniform3i'); - glUniform4i := dglGetProcAddress('glUniform4i'); - glUniform1fv := dglGetProcAddress('glUniform1fv'); - glUniform2fv := dglGetProcAddress('glUniform2fv'); - glUniform3fv := dglGetProcAddress('glUniform3fv'); - glUniform4fv := dglGetProcAddress('glUniform4fv'); - glUniform1iv := dglGetProcAddress('glUniform1iv'); - glUniform2iv := dglGetProcAddress('glUniform2iv'); - glUniform3iv := dglGetProcAddress('glUniform3iv'); - glUniform4iv := dglGetProcAddress('glUniform4iv'); - glUniformMatrix2fv := dglGetProcAddress('glUniformMatrix2fv'); - glUniformMatrix3fv := dglGetProcAddress('glUniformMatrix3fv'); - glUniformMatrix4fv := dglGetProcAddress('glUniformMatrix4fv'); - glValidateProgram := dglGetProcAddress('glValidateProgram'); - glVertexAttrib1d := dglGetProcAddress('glVertexAttrib1d'); - glVertexAttrib1dv := dglGetProcAddress('glVertexAttrib1dv'); - glVertexAttrib1f := dglGetProcAddress('glVertexAttrib1f'); - glVertexAttrib1fv := dglGetProcAddress('glVertexAttrib1fv'); - glVertexAttrib1s := dglGetProcAddress('glVertexAttrib1s'); - glVertexAttrib1sv := dglGetProcAddress('glVertexAttrib1sv'); - glVertexAttrib2d := dglGetProcAddress('glVertexAttrib2d'); - glVertexAttrib2dv := dglGetProcAddress('glVertexAttrib2dv'); - glVertexAttrib2f := dglGetProcAddress('glVertexAttrib2f'); - glVertexAttrib2fv := dglGetProcAddress('glVertexAttrib2fv'); - glVertexAttrib2s := dglGetProcAddress('glVertexAttrib2s'); - glVertexAttrib2sv := dglGetProcAddress('glVertexAttrib2sv'); - glVertexAttrib3d := dglGetProcAddress('glVertexAttrib3d'); - glVertexAttrib3dv := dglGetProcAddress('glVertexAttrib3dv'); - glVertexAttrib3f := dglGetProcAddress('glVertexAttrib3f'); - glVertexAttrib3fv := dglGetProcAddress('glVertexAttrib3fv'); - glVertexAttrib3s := dglGetProcAddress('glVertexAttrib3s'); - glVertexAttrib3sv := dglGetProcAddress('glVertexAttrib3sv'); - glVertexAttrib4Nbv := dglGetProcAddress('glVertexAttrib4Nbv'); - glVertexAttrib4Niv := dglGetProcAddress('glVertexAttrib4Niv'); - glVertexAttrib4Nsv := dglGetProcAddress('glVertexAttrib4Nsv'); - glVertexAttrib4Nub := dglGetProcAddress('glVertexAttrib4Nub'); - glVertexAttrib4Nubv := dglGetProcAddress('glVertexAttrib4Nubv'); - glVertexAttrib4Nuiv := dglGetProcAddress('glVertexAttrib4Nuiv'); - glVertexAttrib4Nusv := dglGetProcAddress('glVertexAttrib4Nusv'); - glVertexAttrib4bv := dglGetProcAddress('glVertexAttrib4bv'); - glVertexAttrib4d := dglGetProcAddress('glVertexAttrib4d'); - glVertexAttrib4dv := dglGetProcAddress('glVertexAttrib4dv'); - glVertexAttrib4f := dglGetProcAddress('glVertexAttrib4f'); - glVertexAttrib4fv := dglGetProcAddress('glVertexAttrib4fv'); - glVertexAttrib4iv := dglGetProcAddress('glVertexAttrib4iv'); - glVertexAttrib4s := dglGetProcAddress('glVertexAttrib4s'); - glVertexAttrib4sv := dglGetProcAddress('glVertexAttrib4sv'); - glVertexAttrib4ubv := dglGetProcAddress('glVertexAttrib4ubv'); - glVertexAttrib4uiv := dglGetProcAddress('glVertexAttrib4uiv'); - glVertexAttrib4usv := dglGetProcAddress('glVertexAttrib4usv'); - glVertexAttribPointer := dglGetProcAddress('glVertexAttribPointer'); - - // GL_VERSION_2_1 - glUniformMatrix2x3fv := dglGetProcAddress('glUniformMatrix2x3fv'); - glUniformMatrix3x2fv := dglGetProcAddress('glUniformMatrix3x2fv'); - glUniformMatrix2x4fv := dglGetProcAddress('glUniformMatrix2x4fv'); - glUniformMatrix4x2fv := dglGetProcAddress('glUniformMatrix4x2fv'); - glUniformMatrix3x4fv := dglGetProcAddress('glUniformMatrix3x4fv'); - glUniformMatrix4x3fv := dglGetProcAddress('glUniformMatrix4x3fv'); - - // GL_VERSION_3_0 - { OpenGL 3.0 also reuses entry points from these extensions: } - Read_GL_ARB_framebuffer_object; - Read_GL_ARB_map_buffer_range; - Read_GL_ARB_vertex_array_object; - - glColorMaski := dglGetProcAddress('glColorMaski'); - glGetBooleani_v := dglGetProcAddress('glGetBooleani_v'); - glGetIntegeri_v := dglGetProcAddress('glGetIntegeri_v'); - glEnablei := dglGetProcAddress('glEnablei'); - glDisablei := dglGetProcAddress('glDisablei'); - glIsEnabledi := dglGetProcAddress('glIsEnabledi'); - glBeginTransformFeedback := dglGetProcAddress('glBeginTransformFeedback'); - glEndTransformFeedback := dglGetProcAddress('glEndTransformFeedback'); - glBindBufferRange := dglGetProcAddress('glBindBufferRange'); - glBindBufferBase := dglGetProcAddress('glBindBufferBase'); - glTransformFeedbackVaryings := dglGetProcAddress('glTransformFeedbackVaryings'); - glGetTransformFeedbackVarying := dglGetProcAddress('glGetTransformFeedbackVarying'); - glClampColor := dglGetProcAddress('glClampColor'); - glBeginConditionalRender := dglGetProcAddress('glBeginConditionalRender'); - glEndConditionalRender := dglGetProcAddress('glEndConditionalRender'); - glVertexAttribI1i := dglGetProcAddress('glVertexAttribI1i'); - glVertexAttribI2i := dglGetProcAddress('glVertexAttribI2i'); - glVertexAttribI3i := dglGetProcAddress('glVertexAttribI3i'); - glVertexAttribI4i := dglGetProcAddress('glVertexAttribI4i'); - glVertexAttribI1ui := dglGetProcAddress('glVertexAttribI1ui'); - glVertexAttribI2ui := dglGetProcAddress('glVertexAttribI2ui'); - glVertexAttribI3ui := dglGetProcAddress('glVertexAttribI3ui'); - glVertexAttribI4ui := dglGetProcAddress('glVertexAttribI4ui'); - glVertexAttribI1iv := dglGetProcAddress('glVertexAttribI1iv'); - glVertexAttribI2iv := dglGetProcAddress('glVertexAttribI2iv'); - glVertexAttribI3iv := dglGetProcAddress('glVertexAttribI3iv'); - glVertexAttribI4iv := dglGetProcAddress('glVertexAttribI4iv'); - glVertexAttribI1uiv := dglGetProcAddress('glVertexAttribI1uiv'); - glVertexAttribI2uiv := dglGetProcAddress('glVertexAttribI2uiv'); - glVertexAttribI3uiv := dglGetProcAddress('glVertexAttribI3uiv'); - glVertexAttribI4uiv := dglGetProcAddress('glVertexAttribI4uiv'); - glVertexAttribI4bv := dglGetProcAddress('glVertexAttribI4bv'); - glVertexAttribI4sv := dglGetProcAddress('glVertexAttribI4sv'); - glVertexAttribI4ubv := dglGetProcAddress('glVertexAttribI4ubv'); - glVertexAttribI4usv := dglGetProcAddress('glVertexAttribI4usv'); - glVertexAttribIPointer := dglGetProcAddress('glVertexAttribIPointer'); - glGetVertexAttribIiv := dglGetProcAddress('glGetVertexAttribIiv'); - glGetVertexAttribIuiv := dglGetProcAddress('glGetVertexAttribIuiv'); - glGetUniformuiv := dglGetProcAddress('glGetUniformuiv'); - glBindFragDataLocation := dglGetProcAddress('glBindFragDataLocation'); - glGetFragDataLocation := dglGetProcAddress('glGetFragDataLocation'); - glUniform1ui := dglGetProcAddress('glUniform1ui'); - glUniform2ui := dglGetProcAddress('glUniform2ui'); - glUniform3ui := dglGetProcAddress('glUniform3ui'); - glUniform4ui := dglGetProcAddress('glUniform4ui'); - glUniform1uiv := dglGetProcAddress('glUniform1uiv'); - glUniform2uiv := dglGetProcAddress('glUniform2uiv'); - glUniform3uiv := dglGetProcAddress('glUniform3uiv'); - glUniform4uiv := dglGetProcAddress('glUniform4uiv'); - glTexParameterIiv := dglGetProcAddress('glTexParameterIiv'); - glTexParameterIuiv := dglGetProcAddress('glTexParameterIuiv'); - glGetTexParameterIiv := dglGetProcAddress('glGetTexParameterIiv'); - glGetTexParameterIuiv := dglGetProcAddress('glGetTexParameterIuiv'); - glClearBufferiv := dglGetProcAddress('glClearBufferiv'); - glClearBufferuiv := dglGetProcAddress('glClearBufferuiv'); - glClearBufferfv := dglGetProcAddress('glClearBufferfv'); - glClearBufferfi := dglGetProcAddress('glClearBufferfi'); - glGetStringi := dglGetProcAddress('glGetStringi'); - - // GL_VERSION_3_1 - { OpenGL 3.1 also reuses entry points from these extensions: } - Read_GL_ARB_copy_buffer; - Read_GL_ARB_uniform_buffer_object; - - glDrawArraysInstanced := dglGetProcAddress('glDrawArraysInstanced'); - glDrawElementsInstanced := dglGetProcAddress('glDrawElementsInstanced'); - glTexBuffer := dglGetProcAddress('glTexBuffer'); - glPrimitiveRestartIndex := dglGetProcAddress('glPrimitiveRestartIndex'); - - // GL_VERSION_3_2 - { OpenGL 3.2 also reuses entry points from these extensions: } - Read_GL_ARB_draw_elements_base_vertex; - Read_GL_ARB_provoking_vertex; - Read_GL_ARB_sync; - Read_GL_ARB_texture_multisample; - - glGetInteger64i_v := dglGetProcAddress('glGetInteger64i_v'); - glGetBufferParameteri64v := dglGetProcAddress('glGetBufferParameteri64v'); - glProgramParameteri := dglGetProcAddress('glProgramParameteri'); - glFramebufferTexture := dglGetProcAddress('glFramebufferTexture'); - glFramebufferTextureFace := dglGetProcAddress('glFramebufferTextureFace'); -end; - -procedure Read_GL_3DFX_tbuffer; -begin - glTbufferMask3DFX := dglGetProcAddress('glTbufferMask3DFX'); -end; - -procedure Read_GL_APPLE_element_array; -begin - glElementPointerAPPLE := dglGetProcAddress('glElementPointerAPPLE'); - glDrawElementArrayAPPLE := dglGetProcAddress('glDrawElementArrayAPPLE'); - glDrawRangeElementArrayAPPLE := dglGetProcAddress('glDrawRangeElementArrayAPPLE'); - glMultiDrawElementArrayAPPLE := dglGetProcAddress('glMultiDrawElementArrayAPPLE'); - glMultiDrawRangeElementArrayAPPLE := dglGetProcAddress('glMultiDrawRangeElementArrayAPPLE'); -end; - -procedure Read_GL_APPLE_fence; -begin - glGenFencesAPPLE := dglGetProcAddress('glGenFencesAPPLE'); - glDeleteFencesAPPLE := dglGetProcAddress('glDeleteFencesAPPLE'); - glSetFenceAPPLE := dglGetProcAddress('glSetFenceAPPLE'); - glIsFenceAPPLE := dglGetProcAddress('glIsFenceAPPLE'); - glTestFenceAPPLE := dglGetProcAddress('glTestFenceAPPLE'); - glFinishFenceAPPLE := dglGetProcAddress('glFinishFenceAPPLE'); - glTestObjectAPPLE := dglGetProcAddress('glTestObjectAPPLE'); - glFinishObjectAPPLE := dglGetProcAddress('glFinishObjectAPPLE'); -end; - -procedure Read_GL_APPLE_vertex_array_object; -begin - glBindVertexArrayAPPLE := dglGetProcAddress('glBindVertexArrayAPPLE'); - glDeleteVertexArraysAPPLE := dglGetProcAddress('glDeleteVertexArraysAPPLE'); - glGenVertexArraysAPPLE := dglGetProcAddress('glGenVertexArraysAPPLE'); - glIsVertexArrayAPPLE := dglGetProcAddress('glIsVertexArrayAPPLE'); -end; - -procedure Read_GL_APPLE_vertex_array_range; -begin - glVertexArrayRangeAPPLE := dglGetProcAddress('glVertexArrayRangeAPPLE'); - glFlushVertexArrayRangeAPPLE := dglGetProcAddress('glFlushVertexArrayRangeAPPLE'); - glVertexArrayParameteriAPPLE := dglGetProcAddress('glVertexArrayParameteriAPPLE'); -end; - -procedure Read_GL_APPLE_texture_range; -begin - glTextureRangeAPPLE := dglGetProcAddress('glTextureRangeAPPLE'); - glGetTexParameterPointervAPPLE := dglGetProcAddress('glGetTexParameterPointervAPPLE'); -end; - -procedure Read_GL_APPLE_vertex_program_evaluators; -begin - glEnableVertexAttribAPPLE := dglGetProcAddress('glEnableVertexAttribAPPLE'); - glDisableVertexAttribAPPLE := dglGetProcAddress('glDisableVertexAttribAPPLE'); - glIsVertexAttribEnabledAPPLE := dglGetProcAddress('glIsVertexAttribEnabledAPPLE'); - glMapVertexAttrib1dAPPLE := dglGetProcAddress('glMapVertexAttrib1dAPPLE'); - glMapVertexAttrib1fAPPLE := dglGetProcAddress('glMapVertexAttrib1fAPPLE'); - glMapVertexAttrib2dAPPLE := dglGetProcAddress('glMapVertexAttrib2dAPPLE'); - glMapVertexAttrib2fAPPLE := dglGetProcAddress('glMapVertexAttrib2fAPPLE'); -end; - -procedure Read_GL_APPLE_object_purgeable; -begin - glObjectPurgeableAPPLE := dglGetProcAddress('glObjectPurgeableAPPLE'); - glObjectUnpurgeableAPPLE := dglGetProcAddress('glObjectUnpurgeableAPPLE'); - glGetObjectParameterivAPPLE := dglGetProcAddress('glGetObjectParameterivAPPLE'); -end; - -procedure Read_GL_ARB_matrix_palette; -begin - glCurrentPaletteMatrixARB := dglGetProcAddress('glCurrentPaletteMatrixARB'); - glMatrixIndexubvARB := dglGetProcAddress('glMatrixIndexubvARB'); - glMatrixIndexusvARB := dglGetProcAddress('glMatrixIndexusvARB'); - glMatrixIndexuivARB := dglGetProcAddress('glMatrixIndexuivARB'); - glMatrixIndexPointerARB := dglGetProcAddress('glMatrixIndexPointerARB'); -end; - -procedure Read_GL_ARB_multisample; -begin - glSampleCoverageARB := dglGetProcAddress('glSampleCoverageARB'); -end; - -procedure Read_GL_ARB_multitexture; -begin - glActiveTextureARB := dglGetProcAddress('glActiveTextureARB'); - glClientActiveTextureARB := dglGetProcAddress('glClientActiveTextureARB'); - glMultiTexCoord1dARB := dglGetProcAddress('glMultiTexCoord1dARB'); - glMultiTexCoord1dvARB := dglGetProcAddress('glMultiTexCoord1dvARB'); - glMultiTexCoord1fARB := dglGetProcAddress('glMultiTexCoord1fARB'); - glMultiTexCoord1fvARB := dglGetProcAddress('glMultiTexCoord1fvARB'); - glMultiTexCoord1iARB := dglGetProcAddress('glMultiTexCoord1iARB'); - glMultiTexCoord1ivARB := dglGetProcAddress('glMultiTexCoord1ivARB'); - glMultiTexCoord1sARB := dglGetProcAddress('glMultiTexCoord1sARB'); - glMultiTexCoord1svARB := dglGetProcAddress('glMultiTexCoord1svARB'); - glMultiTexCoord2dARB := dglGetProcAddress('glMultiTexCoord2dARB'); - glMultiTexCoord2dvARB := dglGetProcAddress('glMultiTexCoord2dvARB'); - glMultiTexCoord2fARB := dglGetProcAddress('glMultiTexCoord2fARB'); - glMultiTexCoord2fvARB := dglGetProcAddress('glMultiTexCoord2fvARB'); - glMultiTexCoord2iARB := dglGetProcAddress('glMultiTexCoord2iARB'); - glMultiTexCoord2ivARB := dglGetProcAddress('glMultiTexCoord2ivARB'); - glMultiTexCoord2sARB := dglGetProcAddress('glMultiTexCoord2sARB'); - glMultiTexCoord2svARB := dglGetProcAddress('glMultiTexCoord2svARB'); - glMultiTexCoord3dARB := dglGetProcAddress('glMultiTexCoord3dARB'); - glMultiTexCoord3dvARB := dglGetProcAddress('glMultiTexCoord3dvARB'); - glMultiTexCoord3fARB := dglGetProcAddress('glMultiTexCoord3fARB'); - glMultiTexCoord3fvARB := dglGetProcAddress('glMultiTexCoord3fvARB'); - glMultiTexCoord3iARB := dglGetProcAddress('glMultiTexCoord3iARB'); - glMultiTexCoord3ivARB := dglGetProcAddress('glMultiTexCoord3ivARB'); - glMultiTexCoord3sARB := dglGetProcAddress('glMultiTexCoord3sARB'); - glMultiTexCoord3svARB := dglGetProcAddress('glMultiTexCoord3svARB'); - glMultiTexCoord4dARB := dglGetProcAddress('glMultiTexCoord4dARB'); - glMultiTexCoord4dvARB := dglGetProcAddress('glMultiTexCoord4dvARB'); - glMultiTexCoord4fARB := dglGetProcAddress('glMultiTexCoord4fARB'); - glMultiTexCoord4fvARB := dglGetProcAddress('glMultiTexCoord4fvARB'); - glMultiTexCoord4iARB := dglGetProcAddress('glMultiTexCoord4iARB'); - glMultiTexCoord4ivARB := dglGetProcAddress('glMultiTexCoord4ivARB'); - glMultiTexCoord4sARB := dglGetProcAddress('glMultiTexCoord4sARB'); - glMultiTexCoord4svARB := dglGetProcAddress('glMultiTexCoord4svARB'); -end; - -procedure Read_GL_ARB_point_parameters; -begin - glPointParameterfARB := dglGetProcAddress('glPointParameterfARB'); - glPointParameterfvARB := dglGetProcAddress('glPointParameterfvARB'); -end; - -procedure Read_GL_ARB_texture_compression; -begin - glCompressedTexImage3DARB := dglGetProcAddress('glCompressedTexImage3DARB'); - glCompressedTexImage2DARB := dglGetProcAddress('glCompressedTexImage2DARB'); - glCompressedTexImage1DARB := dglGetProcAddress('glCompressedTexImage1DARB'); - glCompressedTexSubImage3DARB := dglGetProcAddress('glCompressedTexSubImage3DARB'); - glCompressedTexSubImage2DARB := dglGetProcAddress('glCompressedTexSubImage2DARB'); - glCompressedTexSubImage1DARB := dglGetProcAddress('glCompressedTexSubImage1DARB'); - glGetCompressedTexImageARB := dglGetProcAddress('glGetCompressedTexImageARB'); -end; - -procedure Read_GL_ARB_transpose_matrix; -begin - glLoadTransposeMatrixfARB := dglGetProcAddress('glLoadTransposeMatrixfARB'); - glLoadTransposeMatrixdARB := dglGetProcAddress('glLoadTransposeMatrixdARB'); - glMultTransposeMatrixfARB := dglGetProcAddress('glMultTransposeMatrixfARB'); - glMultTransposeMatrixdARB := dglGetProcAddress('glMultTransposeMatrixdARB'); -end; - -procedure Read_GL_ARB_vertex_blend; -begin - glWeightbvARB := dglGetProcAddress('glWeightbvARB'); - glWeightsvARB := dglGetProcAddress('glWeightsvARB'); - glWeightivARB := dglGetProcAddress('glWeightivARB'); - glWeightfvARB := dglGetProcAddress('glWeightfvARB'); - glWeightdvARB := dglGetProcAddress('glWeightdvARB'); - glWeightubvARB := dglGetProcAddress('glWeightubvARB'); - glWeightusvARB := dglGetProcAddress('glWeightusvARB'); - glWeightuivARB := dglGetProcAddress('glWeightuivARB'); - glWeightPointerARB := dglGetProcAddress('glWeightPointerARB'); - glVertexBlendARB := dglGetProcAddress('glVertexBlendARB'); -end; - -procedure Read_GL_ARB_vertex_buffer_object; -begin - glBindBufferARB := dglGetProcAddress('glBindBufferARB'); - glDeleteBuffersARB := dglGetProcAddress('glDeleteBuffersARB'); - glGenBuffersARB := dglGetProcAddress('glGenBuffersARB'); - glIsBufferARB := dglGetProcAddress('glIsBufferARB'); - glBufferDataARB := dglGetProcAddress('glBufferDataARB'); - glBufferSubDataARB := dglGetProcAddress('glBufferSubDataARB'); - glGetBufferSubDataARB := dglGetProcAddress('glGetBufferSubDataARB'); - glMapBufferARB := dglGetProcAddress('glMapBufferARB'); - glUnmapBufferARB := dglGetProcAddress('glUnmapBufferARB'); - glGetBufferParameterivARB := dglGetProcAddress('glGetBufferParameterivARB'); - glGetBufferPointervARB := dglGetProcAddress('glGetBufferPointervARB'); -end; - -procedure Read_GL_ARB_vertex_program; -begin - glVertexAttrib1dARB := dglGetProcAddress('glVertexAttrib1dARB'); - glVertexAttrib1dvARB := dglGetProcAddress('glVertexAttrib1dvARB'); - glVertexAttrib1fARB := dglGetProcAddress('glVertexAttrib1fARB'); - glVertexAttrib1fvARB := dglGetProcAddress('glVertexAttrib1fvARB'); - glVertexAttrib1sARB := dglGetProcAddress('glVertexAttrib1sARB'); - glVertexAttrib1svARB := dglGetProcAddress('glVertexAttrib1svARB'); - glVertexAttrib2dARB := dglGetProcAddress('glVertexAttrib2dARB'); - glVertexAttrib2dvARB := dglGetProcAddress('glVertexAttrib2dvARB'); - glVertexAttrib2fARB := dglGetProcAddress('glVertexAttrib2fARB'); - glVertexAttrib2fvARB := dglGetProcAddress('glVertexAttrib2fvARB'); - glVertexAttrib2sARB := dglGetProcAddress('glVertexAttrib2sARB'); - glVertexAttrib2svARB := dglGetProcAddress('glVertexAttrib2svARB'); - glVertexAttrib3dARB := dglGetProcAddress('glVertexAttrib3dARB'); - glVertexAttrib3dvARB := dglGetProcAddress('glVertexAttrib3dvARB'); - glVertexAttrib3fARB := dglGetProcAddress('glVertexAttrib3fARB'); - glVertexAttrib3fvARB := dglGetProcAddress('glVertexAttrib3fvARB'); - glVertexAttrib3sARB := dglGetProcAddress('glVertexAttrib3sARB'); - glVertexAttrib3svARB := dglGetProcAddress('glVertexAttrib3svARB'); - glVertexAttrib4NbvARB := dglGetProcAddress('glVertexAttrib4NbvARB'); - glVertexAttrib4NivARB := dglGetProcAddress('glVertexAttrib4NivARB'); - glVertexAttrib4NsvARB := dglGetProcAddress('glVertexAttrib4NsvARB'); - glVertexAttrib4NubARB := dglGetProcAddress('glVertexAttrib4NubARB'); - glVertexAttrib4NubvARB := dglGetProcAddress('glVertexAttrib4NubvARB'); - glVertexAttrib4NuivARB := dglGetProcAddress('glVertexAttrib4NuivARB'); - glVertexAttrib4NusvARB := dglGetProcAddress('glVertexAttrib4NusvARB'); - glVertexAttrib4bvARB := dglGetProcAddress('glVertexAttrib4bvARB'); - glVertexAttrib4dARB := dglGetProcAddress('glVertexAttrib4dARB'); - glVertexAttrib4dvARB := dglGetProcAddress('glVertexAttrib4dvARB'); - glVertexAttrib4fARB := dglGetProcAddress('glVertexAttrib4fARB'); - glVertexAttrib4fvARB := dglGetProcAddress('glVertexAttrib4fvARB'); - glVertexAttrib4ivARB := dglGetProcAddress('glVertexAttrib4ivARB'); - glVertexAttrib4sARB := dglGetProcAddress('glVertexAttrib4sARB'); - glVertexAttrib4svARB := dglGetProcAddress('glVertexAttrib4svARB'); - glVertexAttrib4ubvARB := dglGetProcAddress('glVertexAttrib4ubvARB'); - glVertexAttrib4uivARB := dglGetProcAddress('glVertexAttrib4uivARB'); - glVertexAttrib4usvARB := dglGetProcAddress('glVertexAttrib4usvARB'); - glVertexAttribPointerARB := dglGetProcAddress('glVertexAttribPointerARB'); - glEnableVertexAttribArrayARB := dglGetProcAddress('glEnableVertexAttribArrayARB'); - glDisableVertexAttribArrayARB := dglGetProcAddress('glDisableVertexAttribArrayARB'); - glProgramStringARB := dglGetProcAddress('glProgramStringARB'); - glBindProgramARB := dglGetProcAddress('glBindProgramARB'); - glDeleteProgramsARB := dglGetProcAddress('glDeleteProgramsARB'); - glGenProgramsARB := dglGetProcAddress('glGenProgramsARB'); - glProgramEnvParameter4dARB := dglGetProcAddress('glProgramEnvParameter4dARB'); - glProgramEnvParameter4dvARB := dglGetProcAddress('glProgramEnvParameter4dvARB'); - glProgramEnvParameter4fARB := dglGetProcAddress('glProgramEnvParameter4fARB'); - glProgramEnvParameter4fvARB := dglGetProcAddress('glProgramEnvParameter4fvARB'); - glProgramLocalParameter4dARB := dglGetProcAddress('glProgramLocalParameter4dARB'); - glProgramLocalParameter4dvARB := dglGetProcAddress('glProgramLocalParameter4dvARB'); - glProgramLocalParameter4fARB := dglGetProcAddress('glProgramLocalParameter4fARB'); - glProgramLocalParameter4fvARB := dglGetProcAddress('glProgramLocalParameter4fvARB'); - glGetProgramEnvParameterdvARB := dglGetProcAddress('glGetProgramEnvParameterdvARB'); - glGetProgramEnvParameterfvARB := dglGetProcAddress('glGetProgramEnvParameterfvARB'); - glGetProgramLocalParameterdvARB := dglGetProcAddress('glGetProgramLocalParameterdvARB'); - glGetProgramLocalParameterfvARB := dglGetProcAddress('glGetProgramLocalParameterfvARB'); - glGetProgramivARB := dglGetProcAddress('glGetProgramivARB'); - glGetProgramStringARB := dglGetProcAddress('glGetProgramStringARB'); - glGetVertexAttribdvARB := dglGetProcAddress('glGetVertexAttribdvARB'); - glGetVertexAttribfvARB := dglGetProcAddress('glGetVertexAttribfvARB'); - glGetVertexAttribivARB := dglGetProcAddress('glGetVertexAttribivARB'); - glGetVertexAttribPointervARB := dglGetProcAddress('glGetVertexAttribPointervARB'); - glIsProgramARB := dglGetProcAddress('glIsProgramARB'); -end; - -procedure Read_GL_ARB_window_pos; -begin - glWindowPos2dARB := dglGetProcAddress('glWindowPos2dARB'); - glWindowPos2dvARB := dglGetProcAddress('glWindowPos2dvARB'); - glWindowPos2fARB := dglGetProcAddress('glWindowPos2fARB'); - glWindowPos2fvARB := dglGetProcAddress('glWindowPos2fvARB'); - glWindowPos2iARB := dglGetProcAddress('glWindowPos2iARB'); - glWindowPos2ivARB := dglGetProcAddress('glWindowPos2ivARB'); - glWindowPos2sARB := dglGetProcAddress('glWindowPos2sARB'); - glWindowPos2svARB := dglGetProcAddress('glWindowPos2svARB'); - glWindowPos3dARB := dglGetProcAddress('glWindowPos3dARB'); - glWindowPos3dvARB := dglGetProcAddress('glWindowPos3dvARB'); - glWindowPos3fARB := dglGetProcAddress('glWindowPos3fARB'); - glWindowPos3fvARB := dglGetProcAddress('glWindowPos3fvARB'); - glWindowPos3iARB := dglGetProcAddress('glWindowPos3iARB'); - glWindowPos3ivARB := dglGetProcAddress('glWindowPos3ivARB'); - glWindowPos3sARB := dglGetProcAddress('glWindowPos3sARB'); - glWindowPos3svARB := dglGetProcAddress('glWindowPos3svARB'); -end; - -procedure Read_GL_ARB_draw_buffers; -begin - glDrawBuffersARB := dglGetProcAddress('glDrawBuffersARB'); -end; - -procedure Read_GL_ARB_color_buffer_float; -begin - glClampColorARB := dglGetProcAddress('glClampColorARB'); -end; - -procedure Read_GL_ARB_Shader_Objects; -begin - // GL_ARB_Shader_Objects - glCreateShaderObjectARB := dglGetProcAddress('glCreateShaderObjectARB'); - glShaderSourceARB := dglGetProcAddress('glShaderSourceARB'); - glCompileShaderARB := dglGetProcAddress('glCompileShaderARB'); - glDeleteObjectARB := dglGetProcAddress('glDeleteObjectARB'); - glGetHandleARB := dglGetProcAddress('glGetHandleARB'); - glDetachObjectARB := dglGetProcAddress('glDetachObjectARB'); - glCreateProgramObjectARB := dglGetProcAddress('glCreateProgramObjectARB'); - glAttachObjectARB := dglGetProcAddress('glAttachObjectARB'); - glLinkProgramARB := dglGetProcAddress('glLinkProgramARB'); - glUseProgramObjectARB := dglGetProcAddress('glUseProgramObjectARB'); - glValidateProgramARB := dglGetProcAddress('glValidateProgramARB'); - glGetObjectParameterfvARB := dglGetProcAddress('glGetObjectParameterfvARB'); - glGetObjectParameterivARB := dglGetProcAddress('glGetObjectParameterivARB'); - glGetActiveUniformARB := dglGetProcAddress('glGetActiveUniformARB'); - glGetAttachedObjectsARB := dglGetProcAddress('glGetAttachedObjectsARB'); - glGetShaderSourceARB := dglGetProcAddress('glGetShaderSourceARB'); - glGetUniformfvARB := dglGetProcAddress('glGetUniformfvARB'); - glGetUniformivARB := dglGetProcAddress('glGetUniformivARB'); - glGetUniformLocationARB := dglGetProcAddress('glGetUniformLocationARB'); - glGetInfoLogARB := dglGetProcAddress('glGetInfoLogARB'); - glUniform1fARB := dglGetProcAddress('glUniform1fARB'); - glUniform2fARB := dglGetProcAddress('glUniform2fARB'); - glUniform3fARB := dglGetProcAddress('glUniform3fARB'); - glUniform4fARB := dglGetProcAddress('glUniform4fARB'); - glUniform1iARB := dglGetProcAddress('glUniform1iARB'); - glUniform2iARB := dglGetProcAddress('glUniform2iARB'); - glUniform3iARB := dglGetProcAddress('glUniform3iARB'); - glUniform4iARB := dglGetProcAddress('glUniform4iARB'); - glUniform1fvARB := dglGetProcAddress('glUniform1fvARB'); - glUniform2fvARB := dglGetProcAddress('glUniform2fvARB'); - glUniform3fvARB := dglGetProcAddress('glUniform3fvARB'); - glUniform4fvARB := dglGetProcAddress('glUniform4fvARB'); - glUniform1ivARB := dglGetProcAddress('glUniform1ivARB'); - glUniform2ivARB := dglGetProcAddress('glUniform2ivARB'); - glUniform3ivARB := dglGetProcAddress('glUniform3ivARB'); - glUniform4ivARB := dglGetProcAddress('glUniform4ivARB'); - glUniformMatrix2fvARB := dglGetProcAddress('glUniformMatrix2fvARB'); - glUniformMatrix3fvARB := dglGetProcAddress('glUniformMatrix3fvARB'); - glUniformMatrix4fvARB := dglGetProcAddress('glUniformMatrix4fvARB'); - - // GL_ARB_vertex_shader - glGetActiveAttribARB := dglGetProcAddress('glGetActiveAttribARB'); - glGetAttribLocationARB := dglGetProcAddress('glGetAttribLocationARB'); - glBindAttribLocationARB := dglGetProcAddress('glBindAttribLocationARB'); - glGetVertexAttribPointervARB := dglGetProcAddress('glGetVertexAttribPointervARB'); -end; - -procedure Read_GL_ARB_occlusion_query; -begin - glGenQueriesARB := dglGetProcAddress('glGenQueriesARB'); - glDeleteQueriesARB := dglGetProcAddress('glDeleteQueriesARB'); - glIsQueryARB := dglGetProcAddress('glIsQueryARB'); - glBeginQueryARB := dglGetProcAddress('glBeginQueryARB'); - glEndQueryARB := dglGetProcAddress('glEndQueryARB'); - glGetQueryivARB := dglGetProcAddress('glGetQueryivARB'); - glGetQueryObjectivARB := dglGetProcAddress('glGetQueryObjectivARB'); - glGetQueryObjectuivARB := dglGetProcAddress('glGetQueryObjectuivARB'); -end; - -procedure Read_GL_ARB_draw_instanced; -begin - glDrawArraysInstancedARB := dglGetProcAddress('glDrawArraysInstancedARB'); - glDrawElementsInstancedARB := dglGetProcAddress('glDrawElementsInstancedARB'); -end; - -procedure Read_GL_ARB_framebuffer_object; -begin - glIsRenderbuffer := dglGetProcAddress('glIsRenderbuffer'); - glBindRenderbuffer := dglGetProcAddress('glBindRenderbuffer'); - glDeleteRenderbuffers := dglGetProcAddress('glDeleteRenderbuffers'); - glGenRenderbuffers := dglGetProcAddress('glGenRenderbuffers'); - glRenderbufferStorage := dglGetProcAddress('glRenderbufferStorage'); - glGetRenderbufferParameteriv := dglGetProcAddress('glGetRenderbufferParameteriv'); - glIsFramebuffer := dglGetProcAddress('glIsFramebuffer'); - glBindFramebuffer := dglGetProcAddress('glBindFramebuffer'); - glDeleteFramebuffers := dglGetProcAddress('glDeleteFramebuffers'); - glGenFramebuffers := dglGetProcAddress('glGenFramebuffers'); - glCheckFramebufferStatus := dglGetProcAddress('glCheckFramebufferStatus'); - glFramebufferTexture1D := dglGetProcAddress('glFramebufferTexture1D'); - glFramebufferTexture2D := dglGetProcAddress('glFramebufferTexture2D'); - glFramebufferTexture3D := dglGetProcAddress('glFramebufferTexture3D'); - glFramebufferRenderbuffer := dglGetProcAddress('glFramebufferRenderbuffer'); - glGetFramebufferAttachmentParameteriv := dglGetProcAddress('glGetFramebufferAttachmentParameteriv'); - glGenerateMipmap := dglGetProcAddress('glGenerateMipmap'); - glBlitFramebuffer := dglGetProcAddress('glBlitFramebuffer'); - glRenderbufferStorageMultisample := dglGetProcAddress('glRenderbufferStorageMultisample'); - glFramebufferTextureLayer := dglGetProcAddress('glFramebufferTextureLayer'); -end; - -procedure Read_GL_ARB_geometry_shader4; -begin - glProgramParameteriARB := dglGetProcAddress('glProgramParameteriARB'); - glFramebufferTextureARB := dglGetProcAddress('glFramebufferTextureARB'); - glFramebufferTextureLayerARB := dglGetProcAddress('glFramebufferTextureLayerARB'); - glFramebufferTextureFaceARB := dglGetProcAddress('glFramebufferTextureFaceARB'); -end; - -procedure Read_GL_ARB_instanced_arrays; -begin - glVertexAttribDivisorARB := dglGetProcAddress('glVertexAttribDivisorARB'); -end; - -procedure Read_GL_ARB_map_buffer_range; -begin - glMapBufferRange := dglGetProcAddress('glMapBufferRange'); - glFlushMappedBufferRange := dglGetProcAddress('glFlushMappedBufferRange'); -end; - -procedure Read_GL_ARB_texture_buffer_object; -begin - glTexBufferARB := dglGetProcAddress('glTexBufferARB'); -end; - -procedure Read_GL_ARB_vertex_array_object; -begin - glBindVertexArray := dglGetProcAddress('glBindVertexArray'); - glDeleteVertexArrays := dglGetProcAddress('glDeleteVertexArrays'); - glGenVertexArrays := dglGetProcAddress('glGenVertexArrays'); - glIsVertexArray := dglGetProcAddress('glIsVertexArray'); -end; - -procedure Read_GL_ARB_uniform_buffer_object; -begin - glGetUniformIndices := dglGetProcAddress('glGetUniformIndices'); - glGetActiveUniformsiv := dglGetProcAddress('glGetActiveUniformsiv'); - glGetActiveUniformName := dglGetProcAddress('glGetActiveUniformName'); - glGetUniformBlockIndex := dglGetProcAddress('glGetUniformBlockIndex'); - glGetActiveUniformBlockiv := dglGetProcAddress('glGetActiveUniformBlockiv'); - glGetActiveUniformBlockName := dglGetProcAddress('glGetActiveUniformBlockName'); - glUniformBlockBinding := dglGetProcAddress('glUniformBlockBinding'); -end; - -procedure Read_GL_ARB_copy_buffer; -begin - glCopyBufferSubData := dglGetProcAddress('glCopyBufferSubData'); -end; - -procedure Read_GL_ARB_draw_elements_base_vertex; -begin - glDrawElementsBaseVertex := dglGetProcAddress('glDrawElementsBaseVertex'); - glDrawRangeElementsBaseVertex := dglGetProcAddress('glDrawRangeElementsBaseVertex'); - glDrawElementsInstancedBaseVertex := dglGetProcAddress('glDrawElementsInstancedBaseVertex'); - glMultiDrawElementsBaseVertex := dglGetProcAddress('glMultiDrawElementsBaseVertex'); -end; - -procedure Read_GL_ARB_provoking_vertex; -begin - glProvokingVertex := dglGetProcAddress('glProvokingVertex'); -end; - -procedure Read_GL_ARB_sync; -begin - glFenceSync := dglGetProcAddress('glFenceSync'); - glIsSync := dglGetProcAddress('glIsSync'); - glDeleteSync := dglGetProcAddress('glDeleteSync'); - glClientWaitSync := dglGetProcAddress('glClientWaitSync'); - glWaitSync := dglGetProcAddress('glWaitSync'); - glGetInteger64v := dglGetProcAddress('glGetInteger64v'); - glGetSynciv := dglGetProcAddress('glGetSynciv'); -end; - -procedure Read_GL_ARB_texture_multisample; -begin - glTexImage2DMultisample := dglGetProcAddress('glTexImage2DMultisample'); - glTexImage3DMultisample := dglGetProcAddress('glTexImage3DMultisample'); - glGetMultisamplefv := dglGetProcAddress('glGetMultisamplefv'); - glSampleMaski := dglGetProcAddress('glSampleMaski'); -end; - -procedure Read_GL_ARB_draw_buffers_blend; -begin - glBlendEquationi := dglGetProcAddress('glBlendEquationi'); - glBlendEquationSeparatei := dglGetProcAddress('glBlendEquationSeparatei'); - glBlendFunci := dglGetProcAddress('glBlendFunci'); - glBlendFuncSeparatei := dglGetProcAddress('glBlendFuncSeparatei'); -end; - -procedure Read_GL_ARB_sample_shading; -begin - glMinSampleShading := dglGetProcAddress('glMinSampleShading');; -end; - -procedure Read_GL_ATI_draw_buffers; -begin - glDrawBuffersATI := dglGetProcAddress('glDrawBuffersATI'); -end; - -procedure Read_GL_ATI_element_array; -begin - glElementPointerATI := dglGetProcAddress('glElementPointerATI'); - glDrawElementArrayATI := dglGetProcAddress('glDrawElementArrayATI'); - glDrawRangeElementArrayATI := dglGetProcAddress('glDrawRangeElementArrayATI'); -end; - -procedure Read_GL_ATI_envmap_bumpmap; -begin - glTexBumpParameterivATI := dglGetProcAddress('glTexBumpParameterivATI'); - glTexBumpParameterfvATI := dglGetProcAddress('glTexBumpParameterfvATI'); - glGetTexBumpParameterivATI := dglGetProcAddress('glGetTexBumpParameterivATI'); - glGetTexBumpParameterfvATI := dglGetProcAddress('glGetTexBumpParameterfvATI'); -end; - -procedure Read_GL_ATI_fragment_shader; -begin - glGenFragmentShadersATI := dglGetProcAddress('glGenFragmentShadersATI'); - glBindFragmentShaderATI := dglGetProcAddress('glBindFragmentShaderATI'); - glDeleteFragmentShaderATI := dglGetProcAddress('glDeleteFragmentShaderATI'); - glBeginFragmentShaderATI := dglGetProcAddress('glBeginFragmentShaderATI'); - glEndFragmentShaderATI := dglGetProcAddress('glEndFragmentShaderATI'); - glPassTexCoordATI := dglGetProcAddress('glPassTexCoordATI'); - glSampleMapATI := dglGetProcAddress('glSampleMapATI'); - glColorFragmentOp1ATI := dglGetProcAddress('glColorFragmentOp1ATI'); - glColorFragmentOp2ATI := dglGetProcAddress('glColorFragmentOp2ATI'); - glColorFragmentOp3ATI := dglGetProcAddress('glColorFragmentOp3ATI'); - glAlphaFragmentOp1ATI := dglGetProcAddress('glAlphaFragmentOp1ATI'); - glAlphaFragmentOp2ATI := dglGetProcAddress('glAlphaFragmentOp2ATI'); - glAlphaFragmentOp3ATI := dglGetProcAddress('glAlphaFragmentOp3ATI'); - glSetFragmentShaderConstantATI := dglGetProcAddress('glSetFragmentShaderConstantATI'); -end; - -procedure Read_GL_ATI_map_object_buffer; -begin - glMapObjectBufferATI := dglGetProcAddress('glMapObjectBufferATI'); - glUnmapObjectBufferATI := dglGetProcAddress('glUnmapObjectBufferATI'); -end; - -procedure Read_GL_ATI_pn_triangles; -begin - glPNTrianglesiATI := dglGetProcAddress('glPNTrianglesiATI'); - glPNTrianglesfATI := dglGetProcAddress('glPNTrianglesfATI'); -end; - -procedure Read_GL_ATI_separate_stencil; -begin - glStencilOpSeparateATI := dglGetProcAddress('glStencilOpSeparateATI'); - glStencilFuncSeparateATI := dglGetProcAddress('glStencilFuncSeparateATI'); -end; - -procedure Read_GL_ATI_vertex_array_object; -begin - glNewObjectBufferATI := dglGetProcAddress('glNewObjectBufferATI'); - glIsObjectBufferATI := dglGetProcAddress('glIsObjectBufferATI'); - glUpdateObjectBufferATI := dglGetProcAddress('glUpdateObjectBufferATI'); - glGetObjectBufferfvATI := dglGetProcAddress('glGetObjectBufferfvATI'); - glGetObjectBufferivATI := dglGetProcAddress('glGetObjectBufferivATI'); - glFreeObjectBufferATI := dglGetProcAddress('glFreeObjectBufferATI'); - glArrayObjectATI := dglGetProcAddress('glArrayObjectATI'); - glGetArrayObjectfvATI := dglGetProcAddress('glGetArrayObjectfvATI'); - glGetArrayObjectivATI := dglGetProcAddress('glGetArrayObjectivATI'); - glVariantArrayObjectATI := dglGetProcAddress('glVariantArrayObjectATI'); - glGetVariantArrayObjectfvATI := dglGetProcAddress('glGetVariantArrayObjectfvATI'); - glGetVariantArrayObjectivATI := dglGetProcAddress('glGetVariantArrayObjectivATI'); - -end; - -procedure Read_GL_ATI_vertex_attrib_array_object; -begin - glVertexAttribArrayObjectATI := dglGetProcAddress('glVertexAttribArrayObjectATI'); - glGetVertexAttribArrayObjectfvATI := dglGetProcAddress('glGetVertexAttribArrayObjectfvATI'); - glGetVertexAttribArrayObjectivATI := dglGetProcAddress('glGetVertexAttribArrayObjectivATI'); -end; - -procedure Read_GL_ATI_vertex_streams; -begin - glVertexStream1sATI := dglGetProcAddress('glVertexStream1sATI'); - glVertexStream1svATI := dglGetProcAddress('glVertexStream1svATI'); - glVertexStream1iATI := dglGetProcAddress('glVertexStream1iATI'); - glVertexStream1ivATI := dglGetProcAddress('glVertexStream1ivATI'); - glVertexStream1fATI := dglGetProcAddress('glVertexStream1fATI'); - glVertexStream1fvATI := dglGetProcAddress('glVertexStream1fvATI'); - glVertexStream1dATI := dglGetProcAddress('glVertexStream1dATI'); - glVertexStream1dvATI := dglGetProcAddress('glVertexStream1dvATI'); - glVertexStream2sATI := dglGetProcAddress('glVertexStream2sATI'); - glVertexStream2svATI := dglGetProcAddress('glVertexStream2svATI'); - glVertexStream2iATI := dglGetProcAddress('glVertexStream2iATI'); - glVertexStream2ivATI := dglGetProcAddress('glVertexStream2ivATI'); - glVertexStream2fATI := dglGetProcAddress('glVertexStream2fATI'); - glVertexStream2fvATI := dglGetProcAddress('glVertexStream2fvATI'); - glVertexStream2dATI := dglGetProcAddress('glVertexStream2dATI'); - glVertexStream2dvATI := dglGetProcAddress('glVertexStream2dvATI'); - glVertexStream3sATI := dglGetProcAddress('glVertexStream3sATI'); - glVertexStream3svATI := dglGetProcAddress('glVertexStream3svATI'); - glVertexStream3iATI := dglGetProcAddress('glVertexStream3iATI'); - glVertexStream3ivATI := dglGetProcAddress('glVertexStream3ivATI'); - glVertexStream3fATI := dglGetProcAddress('glVertexStream3fATI'); - glVertexStream3fvATI := dglGetProcAddress('glVertexStream3fvATI'); - glVertexStream3dATI := dglGetProcAddress('glVertexStream3dATI'); - glVertexStream3dvATI := dglGetProcAddress('glVertexStream3dvATI'); - glVertexStream4sATI := dglGetProcAddress('glVertexStream4sATI'); - glVertexStream4svATI := dglGetProcAddress('glVertexStream4svATI'); - glVertexStream4iATI := dglGetProcAddress('glVertexStream4iATI'); - glVertexStream4ivATI := dglGetProcAddress('glVertexStream4ivATI'); - glVertexStream4fATI := dglGetProcAddress('glVertexStream4fATI'); - glVertexStream4fvATI := dglGetProcAddress('glVertexStream4fvATI'); - glVertexStream4dATI := dglGetProcAddress('glVertexStream4dATI'); - glVertexStream4dvATI := dglGetProcAddress('glVertexStream4dvATI'); - glNormalStream3bATI := dglGetProcAddress('glNormalStream3bATI'); - glNormalStream3bvATI := dglGetProcAddress('glNormalStream3bvATI'); - glNormalStream3sATI := dglGetProcAddress('glNormalStream3sATI'); - glNormalStream3svATI := dglGetProcAddress('glNormalStream3svATI'); - glNormalStream3iATI := dglGetProcAddress('glNormalStream3iATI'); - glNormalStream3ivATI := dglGetProcAddress('glNormalStream3ivATI'); - glNormalStream3fATI := dglGetProcAddress('glNormalStream3fATI'); - glNormalStream3fvATI := dglGetProcAddress('glNormalStream3fvATI'); - glNormalStream3dATI := dglGetProcAddress('glNormalStream3dATI'); - glNormalStream3dvATI := dglGetProcAddress('glNormalStream3dvATI'); - glClientActiveVertexStreamATI := dglGetProcAddress('glClientActiveVertexStreamATI'); - glVertexBlendEnviATI := dglGetProcAddress('glVertexBlendEnviATI'); - glVertexBlendEnvfATI := dglGetProcAddress('glVertexBlendEnvfATI'); -end; - -procedure Read_GL_AMD_performance_monitor; -begin - glGetPerfMonitorGroupsAMD := dglGetProcAddress('glGetPerfMonitorGroupsAMD'); - glGetPerfMonitorCountersAMD := dglGetProcAddress('glGetPerfMonitorCountersAMD'); - glGetPerfMonitorGroupStringAMD := dglGetProcAddress('glGetPerfMonitorGroupStringAMD'); - glGetPerfMonitorCounterStringAMD := dglGetProcAddress('glGetPerfMonitorCounterStringAMD'); - glGetPerfMonitorCounterInfoAMD := dglGetProcAddress('glGetPerfMonitorCounterInfoAMD'); - glGenPerfMonitorsAMD := dglGetProcAddress('glGenPerfMonitorsAMD'); - glDeletePerfMonitorsAMD := dglGetProcAddress('glDeletePerfMonitorsAMD'); - glSelectPerfMonitorCountersAMD := dglGetProcAddress('glSelectPerfMonitorCountersAMD'); - glBeginPerfMonitorAMD := dglGetProcAddress('glBeginPerfMonitorAMD'); - glEndPerfMonitorAMD := dglGetProcAddress('glEndPerfMonitorAMD'); - glGetPerfMonitorCounterDataAMD := dglGetProcAddress('glGetPerfMonitorCounterDataAMD'); -end; - -procedure Read_GL_EXT_blend_color; -begin - glBlendColorEXT := dglGetProcAddress('glBlendColorEXT'); -end; - -procedure Read_GL_EXT_blend_func_separate; -begin - glBlendFuncSeparateEXT := dglGetProcAddress('glBlendFuncSeparateEXT'); -end; - -procedure Read_GL_EXT_blend_minmax; -begin - glBlendEquationEXT := dglGetProcAddress('glBlendEquationEXT'); -end; - -procedure Read_GL_EXT_color_subtable; -begin - glColorSubTableEXT := dglGetProcAddress('glColorSubTableEXT'); - glCopyColorSubTableEXT := dglGetProcAddress('glCopyColorSubTableEXT'); -end; - -procedure Read_GL_EXT_compiled_vertex_array; -begin - glLockArraysEXT := dglGetProcAddress('glLockArraysEXT'); - glUnlockArraysEXT := dglGetProcAddress('glUnlockArraysEXT'); -end; - -procedure Read_GL_EXT_convolution; -begin - glConvolutionFilter1DEXT := dglGetProcAddress('glConvolutionFilter1DEXT'); - glConvolutionFilter2DEXT := dglGetProcAddress('glConvolutionFilter2DEXT'); - glConvolutionParameterfEXT := dglGetProcAddress('glConvolutionParameterfEXT'); - glConvolutionParameterfvEXT := dglGetProcAddress('glConvolutionParameterfvEXT'); - glConvolutionParameteriEXT := dglGetProcAddress('glConvolutionParameteriEXT'); - glConvolutionParameterivEXT := dglGetProcAddress('glConvolutionParameterivEXT'); - glCopyConvolutionFilter1DEXT := dglGetProcAddress('glCopyConvolutionFilter1DEXT'); - glCopyConvolutionFilter2DEXT := dglGetProcAddress('glCopyConvolutionFilter2DEXT'); - glGetConvolutionFilterEXT := dglGetProcAddress('glGetConvolutionFilterEXT'); - glGetConvolutionParameterfvEXT := dglGetProcAddress('glGetConvolutionParameterfvEXT'); - glGetConvolutionParameterivEXT := dglGetProcAddress('glGetConvolutionParameterivEXT'); - glGetSeparableFilterEXT := dglGetProcAddress('glGetSeparableFilterEXT'); - glSeparableFilter2DEXT := dglGetProcAddress('glSeparableFilter2DEXT'); -end; - -procedure Read_GL_EXT_coordinate_frame; -begin - glTangent3bEXT := dglGetProcAddress('glTangent3bEXT'); - glTangent3bvEXT := dglGetProcAddress('glTangent3bvEXT'); - glTangent3dEXT := dglGetProcAddress('glTangent3dEXT'); - glTangent3dvEXT := dglGetProcAddress('glTangent3dvEXT'); - glTangent3fEXT := dglGetProcAddress('glTangent3fEXT'); - glTangent3fvEXT := dglGetProcAddress('glTangent3fvEXT'); - glTangent3iEXT := dglGetProcAddress('glTangent3iEXT'); - glTangent3ivEXT := dglGetProcAddress('glTangent3ivEXT'); - glTangent3sEXT := dglGetProcAddress('glTangent3sEXT'); - glTangent3svEXT := dglGetProcAddress('glTangent3svEXT'); - glBinormal3bEXT := dglGetProcAddress('glBinormal3bEXT'); - glBinormal3bvEXT := dglGetProcAddress('glBinormal3bvEXT'); - glBinormal3dEXT := dglGetProcAddress('glBinormal3dEXT'); - glBinormal3dvEXT := dglGetProcAddress('glBinormal3dvEXT'); - glBinormal3fEXT := dglGetProcAddress('glBinormal3fEXT'); - glBinormal3fvEXT := dglGetProcAddress('glBinormal3fvEXT'); - glBinormal3iEXT := dglGetProcAddress('glBinormal3iEXT'); - glBinormal3ivEXT := dglGetProcAddress('glBinormal3ivEXT'); - glBinormal3sEXT := dglGetProcAddress('glBinormal3sEXT'); - glBinormal3svEXT := dglGetProcAddress('glBinormal3svEXT'); - glTangentPointerEXT := dglGetProcAddress('glTangentPointerEXT'); - glBinormalPointerEXT := dglGetProcAddress('glBinormalPointerEXT'); -end; - -procedure Read_GL_EXT_copy_texture; -begin - glCopyTexImage1DEXT := dglGetProcAddress('glCopyTexImage1DEXT'); - glCopyTexImage2DEXT := dglGetProcAddress('glCopyTexImage2DEXT'); - glCopyTexSubImage1DEXT := dglGetProcAddress('glCopyTexSubImage1DEXT'); - glCopyTexSubImage2DEXT := dglGetProcAddress('glCopyTexSubImage2DEXT'); - glCopyTexSubImage3DEXT := dglGetProcAddress('glCopyTexSubImage3DEXT'); -end; - -procedure Read_GL_EXT_cull_vertex; -begin - glCullParameterdvEXT := dglGetProcAddress('glCullParameterdvEXT'); - glCullParameterfvEXT := dglGetProcAddress('glCullParameterfvEXT'); -end; - -procedure Read_GL_EXT_draw_range_elements; -begin - glDrawRangeElementsEXT := dglGetProcAddress('glDrawRangeElementsEXT'); -end; - -procedure Read_GL_EXT_fog_coord; -begin - glFogCoordfEXT := dglGetProcAddress('glFogCoordfEXT'); - glFogCoordfvEXT := dglGetProcAddress('glFogCoordfvEXT'); - glFogCoorddEXT := dglGetProcAddress('glFogCoorddEXT'); - glFogCoorddvEXT := dglGetProcAddress('glFogCoorddvEXT'); - glFogCoordPointerEXT := dglGetProcAddress('glFogCoordPointerEXT'); -end; - -procedure Read_GL_EXT_framebuffer_object; -begin - glIsRenderbufferEXT := dglGetProcAddress('glIsRenderbufferEXT'); - glBindRenderbufferEXT := dglGetProcAddress('glBindRenderbufferEXT'); - glDeleteRenderbuffersEXT := dglGetProcAddress('glDeleteRenderbuffersEXT'); - glGenRenderbuffersEXT := dglGetProcAddress('glGenRenderbuffersEXT'); - glRenderbufferStorageEXT := dglGetProcAddress('glRenderbufferStorageEXT'); - glGetRenderbufferParameterivEXT := dglGetProcAddress('glGetRenderbufferParameterivEXT'); - glIsFramebufferEXT := dglGetProcAddress('glIsFramebufferEXT'); - glBindFramebufferEXT := dglGetProcAddress('glBindFramebufferEXT'); - glDeleteFramebuffersEXT := dglGetProcAddress('glDeleteFramebuffersEXT'); - glGenFramebuffersEXT := dglGetProcAddress('glGenFramebuffersEXT'); - glCheckFramebufferStatusEXT := dglGetProcAddress('glCheckFramebufferStatusEXT'); - glFramebufferTexture1DEXT := dglGetProcAddress('glFramebufferTexture1DEXT'); - glFramebufferTexture2DEXT := dglGetProcAddress('glFramebufferTexture2DEXT'); - glFramebufferTexture3DEXT := dglGetProcAddress('glFramebufferTexture3DEXT'); - glFramebufferRenderbufferEXT := dglGetProcAddress('glFramebufferRenderbufferEXT'); - glGetFramebufferAttachmentParameterivEXT := dglGetProcAddress('glGetFramebufferAttachmentParameterivEXT'); - glGenerateMipmapEXT := dglGetProcAddress('glGenerateMipmapEXT'); -end; - -procedure Read_GL_EXT_histogram; -begin - glGetHistogramEXT := dglGetProcAddress('glGetHistogramEXT'); - glGetHistogramParameterfvEXT := dglGetProcAddress('glGetHistogramParameterfvEXT'); - glGetHistogramParameterivEXT := dglGetProcAddress('glGetHistogramParameterivEXT'); - glGetMinmaxEXT := dglGetProcAddress('glGetMinmaxEXT'); - glGetMinmaxParameterfvEXT := dglGetProcAddress('glGetMinmaxParameterfvEXT'); - glGetMinmaxParameterivEXT := dglGetProcAddress('glGetMinmaxParameterivEXT'); - glHistogramEXT := dglGetProcAddress('glHistogramEXT'); - glMinmaxEXT := dglGetProcAddress('glMinmaxEXT'); - glResetHistogramEXT := dglGetProcAddress('glResetHistogramEXT'); - glResetMinmaxEXT := dglGetProcAddress('glResetMinmaxEXT'); -end; - -procedure Read_GL_EXT_index_func; -begin - glIndexFuncEXT := dglGetProcAddress('glIndexFuncEXT'); -end; - -procedure Read_GL_EXT_index_material; -begin - glIndexMaterialEXT := dglGetProcAddress('glIndexMaterialEXT'); -end; - -procedure Read_GL_EXT_light_texture; -begin - glApplyTextureEXT := dglGetProcAddress('glApplyTextureEXT'); - glTextureLightEXT := dglGetProcAddress('glTextureLightEXT'); - glTextureMaterialEXT := dglGetProcAddress('glTextureMaterialEXT'); -end; - -procedure Read_GL_EXT_multi_draw_arrays; -begin - glMultiDrawArraysEXT := dglGetProcAddress('glMultiDrawArraysEXT'); - glMultiDrawElementsEXT := dglGetProcAddress('glMultiDrawElementsEXT'); -end; - -procedure Read_GL_EXT_multisample; -begin - glSampleMaskEXT := dglGetProcAddress('glSampleMaskEXT'); - glSamplePatternEXT := dglGetProcAddress('glSamplePatternEXT'); -end; - -procedure Read_GL_EXT_paletted_texture; -begin - glColorTableEXT := dglGetProcAddress('glColorTableEXT'); - glGetColorTableEXT := dglGetProcAddress('glGetColorTableEXT'); - glGetColorTableParameterivEXT := dglGetProcAddress('glGetColorTableParameterivEXT'); - glGetColorTableParameterfvEXT := dglGetProcAddress('glGetColorTableParameterfvEXT'); -end; - -procedure Read_GL_EXT_pixel_transform; -begin - glPixelTransformParameteriEXT := dglGetProcAddress('glPixelTransformParameteriEXT'); - glPixelTransformParameterfEXT := dglGetProcAddress('glPixelTransformParameterfEXT'); - glPixelTransformParameterivEXT := dglGetProcAddress('glPixelTransformParameterivEXT'); - glPixelTransformParameterfvEXT := dglGetProcAddress('glPixelTransformParameterfvEXT'); -end; - -procedure Read_GL_EXT_point_parameters; -begin - glPointParameterfEXT := dglGetProcAddress('glPointParameterfEXT'); - glPointParameterfvEXT := dglGetProcAddress('glPointParameterfvEXT'); -end; - -procedure Read_GL_EXT_polygon_offset; -begin - glPolygonOffsetEXT := dglGetProcAddress('glPolygonOffsetEXT'); -end; - -procedure Read_GL_EXT_secondary_color; -begin - glSecondaryColor3bEXT := dglGetProcAddress('glSecondaryColor3bEXT'); - glSecondaryColor3bvEXT := dglGetProcAddress('glSecondaryColor3bvEXT'); - glSecondaryColor3dEXT := dglGetProcAddress('glSecondaryColor3dEXT'); - glSecondaryColor3dvEXT := dglGetProcAddress('glSecondaryColor3dvEXT'); - glSecondaryColor3fEXT := dglGetProcAddress('glSecondaryColor3fEXT'); - glSecondaryColor3fvEXT := dglGetProcAddress('glSecondaryColor3fvEXT'); - glSecondaryColor3iEXT := dglGetProcAddress('glSecondaryColor3iEXT'); - glSecondaryColor3ivEXT := dglGetProcAddress('glSecondaryColor3ivEXT'); - glSecondaryColor3sEXT := dglGetProcAddress('glSecondaryColor3sEXT'); - glSecondaryColor3svEXT := dglGetProcAddress('glSecondaryColor3svEXT'); - glSecondaryColor3ubEXT := dglGetProcAddress('glSecondaryColor3ubEXT'); - glSecondaryColor3ubvEXT := dglGetProcAddress('glSecondaryColor3ubvEXT'); - glSecondaryColor3uiEXT := dglGetProcAddress('glSecondaryColor3uiEXT'); - glSecondaryColor3uivEXT := dglGetProcAddress('glSecondaryColor3uivEXT'); - glSecondaryColor3usEXT := dglGetProcAddress('glSecondaryColor3usEXT'); - glSecondaryColor3usvEXT := dglGetProcAddress('glSecondaryColor3usvEXT'); - glSecondaryColorPointerEXT := dglGetProcAddress('glSecondaryColorPointerEXT'); -end; - -procedure Read_GL_EXT_stencil_two_side; -begin - glActiveStencilFaceEXT := dglGetProcAddress('glActiveStencilFaceEXT'); -end; - -procedure Read_GL_EXT_subtexture; -begin - glTexSubImage1DEXT := dglGetProcAddress('glTexSubImage1DEXT'); - glTexSubImage2DEXT := dglGetProcAddress('glTexSubImage2DEXT'); -end; - -procedure Read_GL_EXT_texture3D; -begin - glTexImage3DEXT := dglGetProcAddress('glTexImage3DEXT'); - glTexSubImage3DEXT := dglGetProcAddress('glTexSubImage3DEXT'); -end; - -procedure Read_GL_EXT_texture_object; -begin - glAreTexturesResidentEXT := dglGetProcAddress('glAreTexturesResidentEXT'); - glBindTextureEXT := dglGetProcAddress('glBindTextureEXT'); - glDeleteTexturesEXT := dglGetProcAddress('glDeleteTexturesEXT'); - glGenTexturesEXT := dglGetProcAddress('glGenTexturesEXT'); - glIsTextureEXT := dglGetProcAddress('glIsTextureEXT'); - glPrioritizeTexturesEXT := dglGetProcAddress('glPrioritizeTexturesEXT'); -end; - -procedure Read_GL_EXT_texture_perturb_normal; -begin - glTextureNormalEXT := dglGetProcAddress('glTextureNormalEXT'); -end; - -procedure Read_GL_EXT_vertex_array; -begin - glArrayElementEXT := dglGetProcAddress('glArrayElementEXT'); - glColorPointerEXT := dglGetProcAddress('glColorPointerEXT'); - glDrawArraysEXT := dglGetProcAddress('glDrawArraysEXT'); - glEdgeFlagPointerEXT := dglGetProcAddress('glEdgeFlagPointerEXT'); - glGetPointervEXT := dglGetProcAddress('glGetPointervEXT'); - glIndexPointerEXT := dglGetProcAddress('glIndexPointerEXT'); - glNormalPointerEXT := dglGetProcAddress('glNormalPointerEXT'); - glTexCoordPointerEXT := dglGetProcAddress('glTexCoordPointerEXT'); - glVertexPointerEXT := dglGetProcAddress('glVertexPointerEXT'); -end; - -procedure Read_GL_EXT_vertex_shader; -begin - glBeginVertexShaderEXT := dglGetProcAddress('glBeginVertexShaderEXT'); - glEndVertexShaderEXT := dglGetProcAddress('glEndVertexShaderEXT'); - glBindVertexShaderEXT := dglGetProcAddress('glBindVertexShaderEXT'); - glGenVertexShadersEXT := dglGetProcAddress('glGenVertexShadersEXT'); - glDeleteVertexShaderEXT := dglGetProcAddress('glDeleteVertexShaderEXT'); - glShaderOp1EXT := dglGetProcAddress('glShaderOp1EXT'); - glShaderOp2EXT := dglGetProcAddress('glShaderOp2EXT'); - glShaderOp3EXT := dglGetProcAddress('glShaderOp3EXT'); - glSwizzleEXT := dglGetProcAddress('glSwizzleEXT'); - glWriteMaskEXT := dglGetProcAddress('glWriteMaskEXT'); - glInsertComponentEXT := dglGetProcAddress('glInsertComponentEXT'); - glExtractComponentEXT := dglGetProcAddress('glExtractComponentEXT'); - glGenSymbolsEXT := dglGetProcAddress('glGenSymbolsEXT'); - glSetInvariantEXT := dglGetProcAddress('glSetInvariantEXT'); - glSetLocalConstantEXT := dglGetProcAddress('glSetLocalConstantEXT'); - glVariantbvEXT := dglGetProcAddress('glVariantbvEXT'); - glVariantsvEXT := dglGetProcAddress('glVariantsvEXT'); - glVariantivEXT := dglGetProcAddress('glVariantivEXT'); - glVariantfvEXT := dglGetProcAddress('glVariantfvEXT'); - glVariantdvEXT := dglGetProcAddress('glVariantdvEXT'); - glVariantubvEXT := dglGetProcAddress('glVariantubvEXT'); - glVariantusvEXT := dglGetProcAddress('glVariantusvEXT'); - glVariantuivEXT := dglGetProcAddress('glVariantuivEXT'); - glVariantPointerEXT := dglGetProcAddress('glVariantPointerEXT'); - glEnableVariantClientStateEXT := dglGetProcAddress('glEnableVariantClientStateEXT'); - glDisableVariantClientStateEXT := dglGetProcAddress('glDisableVariantClientStateEXT'); - glBindLightParameterEXT := dglGetProcAddress('glBindLightParameterEXT'); - glBindMaterialParameterEXT := dglGetProcAddress('glBindMaterialParameterEXT'); - glBindTexGenParameterEXT := dglGetProcAddress('glBindTexGenParameterEXT'); - glBindTextureUnitParameterEXT := dglGetProcAddress('glBindTextureUnitParameterEXT'); - glBindParameterEXT := dglGetProcAddress('glBindParameterEXT'); - glIsVariantEnabledEXT := dglGetProcAddress('glIsVariantEnabledEXT'); - glGetVariantBooleanvEXT := dglGetProcAddress('glGetVariantBooleanvEXT'); - glGetVariantIntegervEXT := dglGetProcAddress('glGetVariantIntegervEXT'); - glGetVariantFloatvEXT := dglGetProcAddress('glGetVariantFloatvEXT'); - glGetVariantPointervEXT := dglGetProcAddress('glGetVariantPointervEXT'); - glGetInvariantBooleanvEXT := dglGetProcAddress('glGetInvariantBooleanvEXT'); - glGetInvariantIntegervEXT := dglGetProcAddress('glGetInvariantIntegervEXT'); - glGetInvariantFloatvEXT := dglGetProcAddress('glGetInvariantFloatvEXT'); - glGetLocalConstantBooleanvEXT := dglGetProcAddress('glGetLocalConstantBooleanvEXT'); - glGetLocalConstantIntegervEXT := dglGetProcAddress('glGetLocalConstantIntegervEXT'); - glGetLocalConstantFloatvEXT := dglGetProcAddress('glGetLocalConstantFloatvEXT'); -end; - -procedure Read_GL_EXT_vertex_weighting; -begin - glVertexWeightfEXT := dglGetProcAddress('glVertexWeightfEXT'); - glVertexWeightfvEXT := dglGetProcAddress('glVertexWeightfvEXT'); - glVertexWeightPointerEXT := dglGetProcAddress('glVertexWeightPointerEXT'); -end; - -procedure Read_GL_EXT_depth_bounds_test; -begin - glImageTransformParameteriHP := dglGetProcAddress('glImageTransformParameteriHP'); - glDepthBoundsEXT := dglGetProcAddress('glDepthBoundsEXT'); -end; - -procedure Read_GL_EXT_blend_equation_separate; -begin - glBlendEquationSeparateEXT := dglGetProcAddress('glBlendEquationSeparateEXT'); -end; - -procedure Read_GL_EXT_stencil_clear_tag; -begin - glStencilClearTagEXT := dglGetProcAddress('glStencilClearTagEXT'); -end; - -procedure Read_GL_EXT_framebuffer_blit; -begin - glBlitFramebufferEXT := dglGetProcAddress('glBlitFramebufferEXT'); -end; - -procedure Read_GL_EXT_framebuffer_multisample; -begin - glRenderbufferStorageMultisampleEXT := dglGetProcAddress('glRenderbufferStorageMultisampleEXT'); -end; - -procedure Read_GL_EXT_timer_query; -begin - glGetQueryObjecti64vEXT := dglGetProcAddress('glGetQueryObjecti64vEXT'); - glGetQueryObjectui64vEXT := dglGetProcAddress('glGetQueryObjectui64vEXT'); -end; - -procedure Read_GL_EXT_gpu_program_parameters; -begin - glProgramEnvParameters4fvEXT := dglGetProcAddress('glProgramEnvParameters4fvEXT'); - glProgramLocalParameters4fvEXT := dglGetProcAddress('glProgramLocalParameters4fvEXT'); -end; - -procedure Read_GL_EXT_bindable_uniform; -begin - glUniformBufferEXT := dglGetProcAddress('glUniformBufferEXT'); - glGetUniformBufferSizeEXT := dglGetProcAddress('glGetUniformBufferSizeEXT'); - glGetUniformOffsetEXT := dglGetProcAddress('glGetUniformOffsetEXT'); -end; - -procedure Read_GL_EXT_draw_buffers2; -begin - glColorMaskIndexedEXT := dglGetProcAddress('glColorMaskIndexedEXT'); - glGetBooleanIndexedvEXT := dglGetProcAddress('glGetBooleanIndexedvEXT'); - glGetIntegerIndexedvEXT := dglGetProcAddress('glGetIntegerIndexedvEXT'); - glEnableIndexedEXT := dglGetProcAddress('glEnableIndexedEXT'); - glDisableIndexedEXT := dglGetProcAddress('glDisableIndexedEXT'); - glIsEnabledIndexedEXT := dglGetProcAddress('glIsEnabledIndexedEXT'); -end; - -procedure Read_GL_EXT_draw_instanced; -begin - glDrawArraysInstancedEXT := dglGetProcAddress('glDrawArraysInstancedEXT'); - glDrawElementsInstancedEXT := dglGetProcAddress('glDrawElementsInstancedEXT'); -end; - -procedure Read_GL_EXT_geometry_shader4; -begin - glProgramParameteriEXT := dglGetProcAddress('glProgramParameteriEXT'); - glFramebufferTextureEXT := dglGetProcAddress('glFramebufferTextureEXT'); -// glFramebufferTextureLayerEXT := dglGetProcAddress('glFramebufferTextureLayerEXT'); - glFramebufferTextureFaceEXT := dglGetProcAddress('glFramebufferTextureFaceEXT'); -end; - -procedure Read_GL_EXT_gpu_shader4; -begin - glVertexAttribI1iEXT := dglGetProcAddress('glVertexAttribI1iEXT'); - glVertexAttribI2iEXT := dglGetProcAddress('glVertexAttribI2iEXT'); - glVertexAttribI3iEXT := dglGetProcAddress('glVertexAttribI3iEXT'); - glVertexAttribI4iEXT := dglGetProcAddress('glVertexAttribI4iEXT'); - glVertexAttribI1uiEXT := dglGetProcAddress('glVertexAttribI1uiEXT'); - glVertexAttribI2uiEXT := dglGetProcAddress('glVertexAttribI2uiEXT'); - glVertexAttribI3uiEXT := dglGetProcAddress('glVertexAttribI3uiEXT'); - glVertexAttribI4uiEXT := dglGetProcAddress('glVertexAttribI4uiEXT'); - glVertexAttribI1ivEXT := dglGetProcAddress('glVertexAttribI1ivEXT'); - glVertexAttribI2ivEXT := dglGetProcAddress('glVertexAttribI2ivEXT'); - glVertexAttribI3ivEXT := dglGetProcAddress('glVertexAttribI3ivEXT'); - glVertexAttribI4ivEXT := dglGetProcAddress('glVertexAttribI4ivEXT'); - glVertexAttribI1uivEXT := dglGetProcAddress('glVertexAttribI1uivEXT'); - glVertexAttribI2uivEXT := dglGetProcAddress('glVertexAttribI2uivEXT'); - glVertexAttribI3uivEXT := dglGetProcAddress('glVertexAttribI3uivEXT'); - glVertexAttribI4uivEXT := dglGetProcAddress('glVertexAttribI4uivEXT'); - glVertexAttribI4bvEXT := dglGetProcAddress('glVertexAttribI4bvEXT'); - glVertexAttribI4svEXT := dglGetProcAddress('glVertexAttribI4svEXT'); - glVertexAttribI4ubvEXT := dglGetProcAddress('glVertexAttribI4ubvEXT'); - glVertexAttribI4usvEXT := dglGetProcAddress('glVertexAttribI4usvEXT'); - glVertexAttribIPointerEXT := dglGetProcAddress('glVertexAttribIPointerEXT'); - glGetVertexAttribIivEXT := dglGetProcAddress('glGetVertexAttribIivEXT'); - glGetVertexAttribIuivEXT := dglGetProcAddress('glGetVertexAttribIuivEXT'); - glUniform1uiEXT := dglGetProcAddress('glUniform1uiEXT'); - glUniform2uiEXT := dglGetProcAddress('glUniform2uiEXT'); - glUniform3uiEXT := dglGetProcAddress('glUniform3uiEXT'); - glUniform4uiEXT := dglGetProcAddress('glUniform4uiEXT'); - glUniform1uivEXT := dglGetProcAddress('glUniform1uivEXT'); - glUniform2uivEXT := dglGetProcAddress('glUniform2uivEXT'); - glUniform3uivEXT := dglGetProcAddress('glUniform3uivEXT'); - glUniform4uivEXT := dglGetProcAddress('glUniform4uivEXT'); - glGetUniformuivEXT := dglGetProcAddress('glGetUniformuivEXT'); - glBindFragDataLocationEXT := dglGetProcAddress('glBindFragDataLocationEXT'); - glGetFragDataLocationEXT := dglGetProcAddress('glGetFragDataLocationEXT'); -end; - -procedure Read_GL_EXT_texture_array; -begin - glFramebufferTextureLayerEXT := dglGetProcAddress('glFramebufferTextureLayerEXT'); -end; - -procedure Read_GL_EXT_texture_buffer_object; -begin - glTexBufferEXT := dglGetProcAddress('glTexBufferEXT'); -end; - -procedure Read_GL_EXT_texture_integer; -begin - glClearColorIiEXT := dglGetProcAddress('glClearColorIiEXT'); - glClearColorIuiEXT := dglGetProcAddress('glClearColorIuiEXT'); - glTexParameterIivEXT := dglGetProcAddress('glTexParameterIivEXT'); - glTexParameterIuivEXT := dglGetProcAddress('glTexParameterIuivEXT'); - glGetTexParameterIivEXT := dglGetProcAddress('glGetTexParameterIivEXT'); - glGetTexParameterIiuvEXT := dglGetProcAddress('glGetTexParameterIiuvEXT'); -end; - -procedure Read_GL_EXT_transform_feedback; -begin - glBeginTransformFeedbackEXT := dglGetProcAddress('lBeginTransformFeedbackEXT'); - glEndTransformFeedbackEXT := dglGetProcAddress('glEndTransformFeedbackEXT'); - glBindBufferRangeEXT := dglGetProcAddress('glBindBufferRangeEXT'); - glBindBufferOffsetEXT := dglGetProcAddress('glBindBufferOffsetEXT'); - glBindBufferBaseEXT := dglGetProcAddress('glBindBufferBaseEXT'); - glTransformFeedbackVaryingsEXT := dglGetProcAddress('glTransformFeedbackVaryingsEXT'); - glGetTransformFeedbackVaryingEXT := dglGetProcAddress('glGetTransformFeedbackVaryingEXT'); -end; - -procedure Read_GL_EXT_direct_state_access; -begin - glClientAttribDefaultEXT := dglGetProcAddress('glClientAttribDefaultEXT'); - glPushClientAttribDefaultEXT := dglGetProcAddress('glPushClientAttribDefaultEXT'); - glMatrixLoadfEXT := dglGetProcAddress('glMatrixLoadfEXT'); - glMatrixLoaddEXT := dglGetProcAddress('glMatrixLoaddEXT'); - glMatrixMultfEXT := dglGetProcAddress('glMatrixMultfEXT'); - glMatrixMultdEXT := dglGetProcAddress('glMatrixMultdEXT'); - glMatrixLoadIdentityEXT := dglGetProcAddress('glMatrixLoadIdentityEXT'); - glMatrixRotatefEXT := dglGetProcAddress('glMatrixRotatefEXT'); - glMatrixRotatedEXT := dglGetProcAddress('glMatrixRotatedEXT'); - glMatrixScalefEXT := dglGetProcAddress('glMatrixScalefEXT'); - glMatrixScaledEXT := dglGetProcAddress('glMatrixScaledEXT'); - glMatrixTranslatefEXT := dglGetProcAddress('glMatrixTranslatefEXT'); - glMatrixTranslatedEXT := dglGetProcAddress('glMatrixTranslatedEXT'); - glMatrixFrustumEXT := dglGetProcAddress('glMatrixFrustumEXT'); - glMatrixOrthoEXT := dglGetProcAddress('glMatrixOrthoEXT'); - glMatrixPopEXT := dglGetProcAddress('glMatrixPopEXT'); - glMatrixPushEXT := dglGetProcAddress('glMatrixPushEXT'); - glMatrixLoadTransposefEXT := dglGetProcAddress('glMatrixLoadTransposefEXT'); - glMatrixLoadTransposedEXT := dglGetProcAddress('glMatrixLoadTransposedEXT'); - glMatrixMultTransposefEXT := dglGetProcAddress('glMatrixMultTransposefEXT'); - glMatrixMultTransposedEXT := dglGetProcAddress('glMatrixMultTransposedEXT'); - glTextureParameterfEXT := dglGetProcAddress('glTextureParameterfEXT'); - glTextureParameterfvEXT := dglGetProcAddress('glTextureParameterfvEXT'); - glTextureParameteriEXT := dglGetProcAddress('glTextureParameteriEXT'); - glTextureParameterivEXT := dglGetProcAddress('glTextureParameterivEXT'); - glTextureImage1DEXT := dglGetProcAddress('glTextureImage1DEXT'); - glTextureImage2DEXT := dglGetProcAddress('glTextureImage2DEXT'); - glTextureSubImage1DEXT := dglGetProcAddress('glTextureSubImage1DEXT'); - glTextureSubImage2DEXT := dglGetProcAddress('glTextureSubImage2DEXT'); - glCopyTextureImage1DEXT := dglGetProcAddress('glCopyTextureImage1DEXT'); - glCopyTextureImage2DEXT := dglGetProcAddress('glCopyTextureImage2DEXT'); - glCopyTextureSubImage1DEXT := dglGetProcAddress('glCopyTextureSubImage1DEXT'); - glCopyTextureSubImage2DEXT := dglGetProcAddress('glCopyTextureSubImage2DEXT'); - glGetTextureImageEXT := dglGetProcAddress('glGetTextureImageEXT'); - glGetTextureParameterfvEXT := dglGetProcAddress('glGetTextureParameterfvEXT'); - glGetTextureParameterivEXT := dglGetProcAddress('glGetTextureParameterivEXT'); - glGetTextureLevelParameterfvEXT := dglGetProcAddress('glGetTextureLevelParameterfvEXT'); - glGetTextureLevelParameterivEXT := dglGetProcAddress('glGetTextureLevelParameterivEXT'); - glTextureImage3DEXT := dglGetProcAddress('glTextureImage3DEXT'); - glTextureSubImage3DEXT := dglGetProcAddress('glTextureSubImage3DEXT'); - glCopyTextureSubImage3DEXT := dglGetProcAddress('glCopyTextureSubImage3DEXT'); - glMultiTexParameterfEXT := dglGetProcAddress('glMultiTexParameterfEXT'); - glMultiTexParameterfvEXT := dglGetProcAddress('glMultiTexParameterfvEXT'); - glMultiTexParameteriEXT := dglGetProcAddress('glMultiTexParameteriEXT'); - glMultiTexParameterivEXT := dglGetProcAddress('glMultiTexParameterivEXT'); - glMultiTexImage1DEXT := dglGetProcAddress('glMultiTexImage1DEXT'); - glMultiTexImage2DEXT := dglGetProcAddress('glMultiTexImage2DEXT'); - glMultiTexSubImage1DEXT := dglGetProcAddress('glMultiTexSubImage1DEXT'); - glMultiTexSubImage2DEXT := dglGetProcAddress('glMultiTexSubImage2DEXT'); - glCopyMultiTexImage1DEXT := dglGetProcAddress('glCopyMultiTexImage1DEXT'); - glCopyMultiTexImage2DEXT := dglGetProcAddress('glCopyMultiTexImage2DEXT'); - glCopyMultiTexSubImage1DEXT := dglGetProcAddress('glCopyMultiTexSubImage1DEXT'); - glCopyMultiTexSubImage2DEXT := dglGetProcAddress('glCopyMultiTexSubImage2DEXT'); - glGetMultiTexImageEXT := dglGetProcAddress('glGetMultiTexImageEXT'); - glGetMultiTexParameterfvEXT := dglGetProcAddress('glGetMultiTexParameterfvEXT'); - glGetMultiTexParameterivEXT := dglGetProcAddress('glGetMultiTexParameterivEXT'); - glGetMultiTexLevelParameterfvEXT := dglGetProcAddress('glGetMultiTexLevelParameterfvEXT'); - glGetMultiTexLevelParameterivEXT := dglGetProcAddress('glGetMultiTexLevelParameterivEXT'); - glMultiTexImage3DEXT := dglGetProcAddress('glMultiTexImage3DEXT'); - glMultiTexSubImage3DEXT := dglGetProcAddress('glMultiTexSubImage3DEXT'); - glCopyMultiTexSubImage3DEXT := dglGetProcAddress('glCopyMultiTexSubImage3DEXT'); - glBindMultiTextureEXT := dglGetProcAddress('glBindMultiTextureEXT'); - glEnableClientStateIndexedEXT := dglGetProcAddress('glEnableClientStateIndexedEXT'); - glDisableClientStateIndexedEXT := dglGetProcAddress('glDisableClientStateIndexedEXT'); - glMultiTexCoordPointerEXT := dglGetProcAddress('glMultiTexCoordPointerEXT'); - glMultiTexEnvfEXT := dglGetProcAddress('glMultiTexEnvfEXT'); - glMultiTexEnvfvEXT := dglGetProcAddress('glMultiTexEnvfvEXT'); - glMultiTexEnviEXT := dglGetProcAddress('glMultiTexEnviEXT'); - glMultiTexEnvivEXT := dglGetProcAddress('glMultiTexEnvivEXT'); - glMultiTexGendEXT := dglGetProcAddress('glMultiTexGendEXT'); - glMultiTexGendvEXT := dglGetProcAddress('glMultiTexGendvEXT'); - glMultiTexGenfEXT := dglGetProcAddress('glMultiTexGenfEXT'); - glMultiTexGenfvEXT := dglGetProcAddress('glMultiTexGenfvEXT'); - glMultiTexGeniEXT := dglGetProcAddress('glMultiTexGeniEXT'); - glMultiTexGenivEXT := dglGetProcAddress('glMultiTexGenivEXT'); - glGetMultiTexEnvfvEXT := dglGetProcAddress('glGetMultiTexEnvfvEXT'); - glGetMultiTexEnvivEXT := dglGetProcAddress('glGetMultiTexEnvivEXT'); - glGetMultiTexGendvEXT := dglGetProcAddress('glGetMultiTexGendvEXT'); - glGetMultiTexGenfvEXT := dglGetProcAddress('glGetMultiTexGenfvEXT'); - glGetMultiTexGenivEXT := dglGetProcAddress('glGetMultiTexGenivEXT'); - glGetFloatIndexedvEXT := dglGetProcAddress('glGetFloatIndexedvEXT'); - glGetDoubleIndexedvEXT := dglGetProcAddress('glGetDoubleIndexedvEXT'); - glGetPointerIndexedvEXT := dglGetProcAddress('glGetPointerIndexedvEXT'); - glCompressedTextureImage3DEXT := dglGetProcAddress('glCompressedTextureImage3DEXT'); - glCompressedTextureImage2DEXT := dglGetProcAddress('glCompressedTextureImage2DEXT'); - glCompressedTextureImage1DEXT := dglGetProcAddress('glCompressedTextureImage1DEXT'); - glCompressedTextureSubImage3DEXT := dglGetProcAddress('glCompressedTextureSubImage3DEXT'); - glCompressedTextureSubImage2DEXT := dglGetProcAddress('glCompressedTextureSubImage2DEXT'); - glCompressedTextureSubImage1DEXT := dglGetProcAddress('glCompressedTextureSubImage1DEXT'); - glGetCompressedTextureImageEXT := dglGetProcAddress('glGetCompressedTextureImageEXT'); - glCompressedMultiTexImage3DEXT := dglGetProcAddress('glCompressedMultiTexImage3DEXT'); - glCompressedMultiTexImage2DEXT := dglGetProcAddress('glCompressedMultiTexImage2DEXT'); - glCompressedMultiTexImage1DEXT := dglGetProcAddress('glCompressedMultiTexImage1DEXT'); - glCompressedMultiTexSubImage3DEXT := dglGetProcAddress('glCompressedMultiTexSubImage3DEXT'); - glCompressedMultiTexSubImage2DEXT := dglGetProcAddress('glCompressedMultiTexSubImage2DEXT'); - glCompressedMultiTexSubImage1DEXT := dglGetProcAddress('glCompressedMultiTexSubImage1DEXT'); - glGetCompressedMultiTexImageEXT := dglGetProcAddress('glGetCompressedMultiTexImageEXT'); - glNamedProgramStringEXT := dglGetProcAddress('glNamedProgramStringEXT'); - glNamedProgramLocalParameter4dEXT := dglGetProcAddress('glNamedProgramLocalParameter4dEXT'); - glNamedProgramLocalParameter4dvEXT := dglGetProcAddress('glNamedProgramLocalParameter4dvEXT'); - glNamedProgramLocalParameter4fEXT := dglGetProcAddress('glNamedProgramLocalParameter4fEXT'); - glNamedProgramLocalParameter4fvEXT := dglGetProcAddress('glNamedProgramLocalParameter4fvEXT'); - glGetNamedProgramLocalParameterdvEXT := dglGetProcAddress('glGetNamedProgramLocalParameterdvEXT'); - glGetNamedProgramLocalParameterfvEXT := dglGetProcAddress('glGetNamedProgramLocalParameterfvEXT'); - glGetNamedProgramivEXT := dglGetProcAddress('glGetNamedProgramivEXT'); - glGetNamedProgramStringEXT := dglGetProcAddress('glGetNamedProgramStringEXT'); - glNamedProgramLocalParameters4fvEXT := dglGetProcAddress('glNamedProgramLocalParameters4fvEXT'); - glNamedProgramLocalParameterI4iEXT := dglGetProcAddress('glNamedProgramLocalParameterI4iEXT'); - glNamedProgramLocalParameterI4ivEXT := dglGetProcAddress('glNamedProgramLocalParameterI4ivEXT'); - glNamedProgramLocalParametersI4ivEXT := dglGetProcAddress('glNamedProgramLocalParametersI4ivEXT'); - glNamedProgramLocalParameterI4uiEXT := dglGetProcAddress('glNamedProgramLocalParameterI4uiEXT'); - glNamedProgramLocalParameterI4uivEXT := dglGetProcAddress('glNamedProgramLocalParameterI4uivEXT'); - glNamedProgramLocalParametersI4uivEXT := dglGetProcAddress('glNamedProgramLocalParametersI4uivEXT'); - glGetNamedProgramLocalParameterIivEXT := dglGetProcAddress('glGetNamedProgramLocalParameterIivEXT'); - glGetNamedProgramLocalParameterIuivEXT := dglGetProcAddress('glGetNamedProgramLocalParameterIuivEXT'); - glTextureParameterIivEXT := dglGetProcAddress('glTextureParameterIivEXT'); - glTextureParameterIuivEXT := dglGetProcAddress('glTextureParameterIuivEXT'); - glGetTextureParameterIivEXT := dglGetProcAddress('glGetTextureParameterIivEXT'); - glGetTextureParameterIuivEXT := dglGetProcAddress('glGetTextureParameterIuivEXT'); - glMultiTexParameterIivEXT := dglGetProcAddress('glMultiTexParameterIivEXT'); - glMultiTexParameterIuivEXT := dglGetProcAddress('glMultiTexParameterIuivEXT'); - glGetMultiTexParameterIivEXT := dglGetProcAddress('glGetMultiTexParameterIivEXT'); - glGetMultiTexParameterIuivEXT := dglGetProcAddress('glGetMultiTexParameterIuivEXT'); - glProgramUniform1fEXT := dglGetProcAddress('glProgramUniform1fEXT'); - glProgramUniform2fEXT := dglGetProcAddress('glProgramUniform2fEXT'); - glProgramUniform3fEXT := dglGetProcAddress('glProgramUniform3fEXT'); - glProgramUniform4fEXT := dglGetProcAddress('glProgramUniform4fEXT'); - glProgramUniform1iEXT := dglGetProcAddress('glProgramUniform1iEXT'); - glProgramUniform2iEXT := dglGetProcAddress('glProgramUniform2iEXT'); - glProgramUniform3iEXT := dglGetProcAddress('glProgramUniform3iEXT'); - glProgramUniform4iEXT := dglGetProcAddress('glProgramUniform4iEXT'); - glProgramUniform1fvEXT := dglGetProcAddress('glProgramUniform1fvEXT'); - glProgramUniform2fvEXT := dglGetProcAddress('glProgramUniform2fvEXT'); - glProgramUniform3fvEXT := dglGetProcAddress('glProgramUniform3fvEXT'); - glProgramUniform4fvEXT := dglGetProcAddress('glProgramUniform4fvEXT'); - glProgramUniform1ivEXT := dglGetProcAddress('glProgramUniform1ivEXT'); - glProgramUniform2ivEXT := dglGetProcAddress('glProgramUniform2ivEXT'); - glProgramUniform3ivEXT := dglGetProcAddress('glProgramUniform3ivEXT'); - glProgramUniform4ivEXT := dglGetProcAddress('glProgramUniform4ivEXT'); - glProgramUniformMatrix2fvEXT := dglGetProcAddress('glProgramUniformMatrix2fvEXT'); - glProgramUniformMatrix3fvEXT := dglGetProcAddress('glProgramUniformMatrix3fvEXT'); - glProgramUniformMatrix4fvEXT := dglGetProcAddress('glProgramUniformMatrix4fvEXT'); - glProgramUniformMatrix2x3fvEXT := dglGetProcAddress('glProgramUniformMatrix2x3fvEXT'); - glProgramUniformMatrix3x2fvEXT := dglGetProcAddress('glProgramUniformMatrix3x2fvEXT'); - glProgramUniformMatrix2x4fvEXT := dglGetProcAddress('glProgramUniformMatrix2x4fvEXT'); - glProgramUniformMatrix4x2fvEXT := dglGetProcAddress('glProgramUniformMatrix4x2fvEXT'); - glProgramUniformMatrix3x4fvEXT := dglGetProcAddress('glProgramUniformMatrix3x4fvEXT'); - glProgramUniformMatrix4x3fvEXT := dglGetProcAddress('glProgramUniformMatrix4x3fvEXT'); - glProgramUniform1uiEXT := dglGetProcAddress('glProgramUniform1uiEXT'); - glProgramUniform2uiEXT := dglGetProcAddress('glProgramUniform2uiEXT'); - glProgramUniform3uiEXT := dglGetProcAddress('glProgramUniform3uiEXT'); - glProgramUniform4uiEXT := dglGetProcAddress('glProgramUniform4uiEXT'); - glProgramUniform1uivEXT := dglGetProcAddress('glProgramUniform1uivEXT'); - glProgramUniform2uivEXT := dglGetProcAddress('glProgramUniform2uivEXT'); - glProgramUniform3uivEXT := dglGetProcAddress('glProgramUniform3uivEXT'); - glProgramUniform4uivEXT := dglGetProcAddress('glProgramUniform4uivEXT'); - glNamedBufferDataEXT := dglGetProcAddress('glNamedBufferDataEXT'); - glNamedBufferSubDataEXT := dglGetProcAddress('glNamedBufferSubDataEXT'); - glMapNamedBufferEXT := dglGetProcAddress('glMapNamedBufferEXT'); - glUnmapNamedBufferEXT := dglGetProcAddress('glUnmapNamedBufferEXT'); - glGetNamedBufferParameterivEXT := dglGetProcAddress('glGetNamedBufferParameterivEXT'); - glGetNamedBufferPointervEXT := dglGetProcAddress('glGetNamedBufferPointervEXT'); - glGetNamedBufferSubDataEXT := dglGetProcAddress('glGetNamedBufferSubDataEXT'); - glTextureBufferEXT := dglGetProcAddress('glTextureBufferEXT'); - glMultiTexBufferEXT := dglGetProcAddress('glMultiTexBufferEXT'); - glNamedRenderbufferStorageEXT := dglGetProcAddress('glNamedRenderbufferStorageEXT'); - glGetNamedRenderbufferParameterivEXT := dglGetProcAddress('glGetNamedRenderbufferParameterivEXT'); - glCheckNamedFramebufferStatusEXT := dglGetProcAddress('glCheckNamedFramebufferStatusEXT'); - glNamedFramebufferTexture1DEXT := dglGetProcAddress('glNamedFramebufferTexture1DEXT'); - glNamedFramebufferTexture2DEXT := dglGetProcAddress('glNamedFramebufferTexture2DEXT'); - glNamedFramebufferTexture3DEXT := dglGetProcAddress('glNamedFramebufferTexture3DEXT'); - glNamedFramebufferRenderbufferEXT := dglGetProcAddress('glNamedFramebufferRenderbufferEXT'); - glGetNamedFramebufferAttachmentParameterivEXT := dglGetProcAddress('glGetNamedFramebufferAttachmentParameterivEXT'); - glGenerateTextureMipmapEXT := dglGetProcAddress('glGenerateTextureMipmapEXT'); - glGenerateMultiTexMipmapEXT := dglGetProcAddress('glGenerateMultiTexMipmapEXT'); - glFramebufferDrawBufferEXT := dglGetProcAddress('glFramebufferDrawBufferEXT'); - glFramebufferDrawBuffersEXT := dglGetProcAddress('glFramebufferDrawBuffersEXT'); - glFramebufferReadBufferEXT := dglGetProcAddress('glFramebufferReadBufferEXT'); - glGetFramebufferParameterivEXT := dglGetProcAddress('glGetFramebufferParameterivEXT'); - glNamedRenderbufferStorageMultisampleEXT := dglGetProcAddress('glNamedRenderbufferStorageMultisampleEXT'); - glNamedRenderbufferStorageMultisampleCoverageEXT := dglGetProcAddress('glNamedRenderbufferStorageMultisampleCoverageEXT'); - glNamedFramebufferTextureEXT := dglGetProcAddress('glNamedFramebufferTextureEXT'); - glNamedFramebufferTextureLayerEXT := dglGetProcAddress('glNamedFramebufferTextureLayerEXT'); - glNamedFramebufferTextureFaceEXT := dglGetProcAddress('glNamedFramebufferTextureFaceEXT'); - glTextureRenderbufferEXT := dglGetProcAddress('glTextureRenderbufferEXT'); - glMultiTexRenderbufferEXT := dglGetProcAddress('glMultiTexRenderbufferEXT'); -end; - -procedure Read_GL_HP_image_transform; -begin - glImageTransformParameteriHP := dglGetProcAddress('glImageTransformParameteriHP'); - glImageTransformParameterfHP := dglGetProcAddress('glImageTransformParameterfHP'); - glImageTransformParameterivHP := dglGetProcAddress('glImageTransformParameterivHP'); - glImageTransformParameterfvHP := dglGetProcAddress('glImageTransformParameterfvHP'); - glGetImageTransformParameterivHP := dglGetProcAddress('glGetImageTransformParameterivHP'); - glGetImageTransformParameterfvHP := dglGetProcAddress('glGetImageTransformParameterfvHP'); -end; - -procedure Read_GL_IBM_multimode_draw_arrays; -begin - glMultiModeDrawArraysIBM := dglGetProcAddress('glMultiModeDrawArraysIBM'); - glMultiModeDrawElementsIBM := dglGetProcAddress('glMultiModeDrawElementsIBM'); -end; - -procedure Read_GL_IBM_vertex_array_lists; -begin - glColorPointerListIBM := dglGetProcAddress('glColorPointerListIBM'); - glSecondaryColorPointerListIBM := dglGetProcAddress('glSecondaryColorPointerListIBM'); - glEdgeFlagPointerListIBM := dglGetProcAddress('glEdgeFlagPointerListIBM'); - glFogCoordPointerListIBM := dglGetProcAddress('glFogCoordPointerListIBM'); - glIndexPointerListIBM := dglGetProcAddress('glIndexPointerListIBM'); - glNormalPointerListIBM := dglGetProcAddress('glNormalPointerListIBM'); - glTexCoordPointerListIBM := dglGetProcAddress('glTexCoordPointerListIBM'); - glVertexPointerListIBM := dglGetProcAddress('glVertexPointerListIBM'); -end; - -procedure Read_GL_INGR_blend_func_separate; -begin - glBlendFuncSeparateINGR := dglGetProcAddress('glBlendFuncSeparateINGR'); -end; - -procedure Read_GL_INTEL_parallel_arrays; -begin - glVertexPointervINTEL := dglGetProcAddress('glVertexPointervINTEL'); - glNormalPointervINTEL := dglGetProcAddress('glNormalPointervINTEL'); - glColorPointervINTEL := dglGetProcAddress('glColorPointervINTEL'); - glTexCoordPointervINTEL := dglGetProcAddress('glTexCoordPointervINTEL'); -end; - -procedure Read_GL_MESA_resize_buffers; -begin - glResizeBuffersMESA := dglGetProcAddress('glResizeBuffersMESA'); -end; - -procedure Read_GL_MESA_window_pos; -begin - glWindowPos2dMESA := dglGetProcAddress('glWindowPos2dMESA'); - glWindowPos2dvMESA := dglGetProcAddress('glWindowPos2dvMESA'); - glWindowPos2fMESA := dglGetProcAddress('glWindowPos2fMESA'); - glWindowPos2fvMESA := dglGetProcAddress('glWindowPos2fvMESA'); - glWindowPos2iMESA := dglGetProcAddress('glWindowPos2iMESA'); - glWindowPos2ivMESA := dglGetProcAddress('glWindowPos2ivMESA'); - glWindowPos2sMESA := dglGetProcAddress('glWindowPos2sMESA'); - glWindowPos2svMESA := dglGetProcAddress('glWindowPos2svMESA'); - glWindowPos3dMESA := dglGetProcAddress('glWindowPos3dMESA'); - glWindowPos3dvMESA := dglGetProcAddress('glWindowPos3dvMESA'); - glWindowPos3fMESA := dglGetProcAddress('glWindowPos3fMESA'); - glWindowPos3fvMESA := dglGetProcAddress('glWindowPos3fvMESA'); - glWindowPos3iMESA := dglGetProcAddress('glWindowPos3iMESA'); - glWindowPos3ivMESA := dglGetProcAddress('glWindowPos3ivMESA'); - glWindowPos3sMESA := dglGetProcAddress('glWindowPos3sMESA'); - glWindowPos3svMESA := dglGetProcAddress('glWindowPos3svMESA'); - glWindowPos4dMESA := dglGetProcAddress('glWindowPos4dMESA'); - glWindowPos4dvMESA := dglGetProcAddress('glWindowPos4dvMESA'); - glWindowPos4fMESA := dglGetProcAddress('glWindowPos4fMESA'); - glWindowPos4fvMESA := dglGetProcAddress('glWindowPos4fvMESA'); - glWindowPos4iMESA := dglGetProcAddress('glWindowPos4iMESA'); - glWindowPos4ivMESA := dglGetProcAddress('glWindowPos4ivMESA'); - glWindowPos4sMESA := dglGetProcAddress('glWindowPos4sMESA'); - glWindowPos4svMESA := dglGetProcAddress('glWindowPos4svMESA'); -end; - -procedure Read_GL_NV_evaluators; -begin - glMapControlPointsNV := dglGetProcAddress('glMapControlPointsNV'); - glMapParameterivNV := dglGetProcAddress('glMapParameterivNV'); - glMapParameterfvNV := dglGetProcAddress('glMapParameterfvNV'); - glGetMapControlPointsNV := dglGetProcAddress('glGetMapControlPointsNV'); - glGetMapParameterivNV := dglGetProcAddress('glGetMapParameterivNV'); - glGetMapParameterfvNV := dglGetProcAddress('glGetMapParameterfvNV'); - glGetMapAttribParameterivNV := dglGetProcAddress('glGetMapAttribParameterivNV'); - glGetMapAttribParameterfvNV := dglGetProcAddress('glGetMapAttribParameterfvNV'); - glEvalMapsNV := dglGetProcAddress('glEvalMapsNV'); -end; - -procedure Read_GL_NV_fence; -begin - glDeleteFencesNV := dglGetProcAddress('glDeleteFencesNV'); - glGenFencesNV := dglGetProcAddress('glGenFencesNV'); - glIsFenceNV := dglGetProcAddress('glIsFenceNV'); - glTestFenceNV := dglGetProcAddress('glTestFenceNV'); - glGetFenceivNV := dglGetProcAddress('glGetFenceivNV'); - glFinishFenceNV := dglGetProcAddress('glFinishFenceNV'); - glSetFenceNV := dglGetProcAddress('glSetFenceNV'); -end; - -procedure Read_GL_NV_fragment_program; -begin - glProgramNamedParameter4fNV := dglGetProcAddress('glProgramNamedParameter4fNV'); - glProgramNamedParameter4dNV := dglGetProcAddress('glProgramNamedParameter4dNV'); - glProgramNamedParameter4fvNV := dglGetProcAddress('glProgramNamedParameter4fvNV'); - glProgramNamedParameter4dvNV := dglGetProcAddress('glProgramNamedParameter4dvNV'); - glGetProgramNamedParameterfvNV := dglGetProcAddress('glGetProgramNamedParameterfvNV'); - glGetProgramNamedParameterdvNV := dglGetProcAddress('glGetProgramNamedParameterdvNV'); -end; - -procedure Read_GL_NV_half_float; -begin - glVertex2hNV := dglGetProcAddress('glVertex2hNV'); - glVertex2hvNV := dglGetProcAddress('glVertex2hvNV'); - glVertex3hNV := dglGetProcAddress('glVertex3hNV'); - glVertex3hvNV := dglGetProcAddress('glVertex3hvNV'); - glVertex4hNV := dglGetProcAddress('glVertex4hNV'); - glVertex4hvNV := dglGetProcAddress('glVertex4hvNV'); - glNormal3hNV := dglGetProcAddress('glNormal3hNV'); - glNormal3hvNV := dglGetProcAddress('glNormal3hvNV'); - glColor3hNV := dglGetProcAddress('glColor3hNV'); - glColor3hvNV := dglGetProcAddress('glColor3hvNV'); - glColor4hNV := dglGetProcAddress('glColor4hNV'); - glColor4hvNV := dglGetProcAddress('glColor4hvNV'); - glTexCoord1hNV := dglGetProcAddress('glTexCoord1hNV'); - glTexCoord1hvNV := dglGetProcAddress('glTexCoord1hvNV'); - glTexCoord2hNV := dglGetProcAddress('glTexCoord2hNV'); - glTexCoord2hvNV := dglGetProcAddress('glTexCoord2hvNV'); - glTexCoord3hNV := dglGetProcAddress('glTexCoord3hNV'); - glTexCoord3hvNV := dglGetProcAddress('glTexCoord3hvNV'); - glTexCoord4hNV := dglGetProcAddress('glTexCoord4hNV'); - glTexCoord4hvNV := dglGetProcAddress('glTexCoord4hvNV'); - glMultiTexCoord1hNV := dglGetProcAddress('glMultiTexCoord1hNV'); - glMultiTexCoord1hvNV := dglGetProcAddress('glMultiTexCoord1hvNV'); - glMultiTexCoord2hNV := dglGetProcAddress('glMultiTexCoord2hNV'); - glMultiTexCoord2hvNV := dglGetProcAddress('glMultiTexCoord2hvNV'); - glMultiTexCoord3hNV := dglGetProcAddress('glMultiTexCoord3hNV'); - glMultiTexCoord3hvNV := dglGetProcAddress('glMultiTexCoord3hvNV'); - glMultiTexCoord4hNV := dglGetProcAddress('glMultiTexCoord4hNV'); - glMultiTexCoord4hvNV := dglGetProcAddress('glMultiTexCoord4hvNV'); - glFogCoordhNV := dglGetProcAddress('glFogCoordhNV'); - glFogCoordhvNV := dglGetProcAddress('glFogCoordhvNV'); - glSecondaryColor3hNV := dglGetProcAddress('glSecondaryColor3hNV'); - glSecondaryColor3hvNV := dglGetProcAddress('glSecondaryColor3hvNV'); - glVertexWeighthNV := dglGetProcAddress('glVertexWeighthNV'); - glVertexWeighthvNV := dglGetProcAddress('glVertexWeighthvNV'); - glVertexAttrib1hNV := dglGetProcAddress('glVertexAttrib1hNV'); - glVertexAttrib1hvNV := dglGetProcAddress('glVertexAttrib1hvNV'); - glVertexAttrib2hNV := dglGetProcAddress('glVertexAttrib2hNV'); - glVertexAttrib2hvNV := dglGetProcAddress('glVertexAttrib2hvNV'); - glVertexAttrib3hNV := dglGetProcAddress('glVertexAttrib3hNV'); - glVertexAttrib3hvNV := dglGetProcAddress('glVertexAttrib3hvNV'); - glVertexAttrib4hNV := dglGetProcAddress('glVertexAttrib4hNV'); - glVertexAttrib4hvNV := dglGetProcAddress('glVertexAttrib4hvNV'); - glVertexAttribs1hvNV := dglGetProcAddress('glVertexAttribs1hvNV'); - glVertexAttribs2hvNV := dglGetProcAddress('glVertexAttribs2hvNV'); - glVertexAttribs3hvNV := dglGetProcAddress('glVertexAttribs3hvNV'); - glVertexAttribs4hvNV := dglGetProcAddress('glVertexAttribs4hvNV'); -end; - -procedure Read_GL_NV_occlusion_query; -begin - glGenOcclusionQueriesNV := dglGetProcAddress('glGenOcclusionQueriesNV'); - glDeleteOcclusionQueriesNV := dglGetProcAddress('glDeleteOcclusionQueriesNV'); - glIsOcclusionQueryNV := dglGetProcAddress('glIsOcclusionQueryNV'); - glBeginOcclusionQueryNV := dglGetProcAddress('glBeginOcclusionQueryNV'); - glEndOcclusionQueryNV := dglGetProcAddress('glEndOcclusionQueryNV'); - glGetOcclusionQueryivNV := dglGetProcAddress('glGetOcclusionQueryivNV'); - glGetOcclusionQueryuivNV := dglGetProcAddress('glGetOcclusionQueryuivNV'); -end; - -procedure Read_GL_NV_pixel_data_range; -begin - glPixelDataRangeNV := dglGetProcAddress('glPixelDataRangeNV'); - glFlushPixelDataRangeNV := dglGetProcAddress('glFlushPixelDataRangeNV'); -end; - -procedure Read_GL_NV_point_sprite; -begin - glPointParameteriNV := dglGetProcAddress('glPointParameteriNV'); - glPointParameterivNV := dglGetProcAddress('glPointParameterivNV'); -end; - -procedure Read_GL_NV_primitive_restart; -begin - glPrimitiveRestartNV := dglGetProcAddress('glPrimitiveRestartNV'); - glPrimitiveRestartIndexNV := dglGetProcAddress('glPrimitiveRestartIndexNV'); -end; - -procedure Read_GL_NV_register_combiners; -begin - glCombinerParameterfvNV := dglGetProcAddress('glCombinerParameterfvNV'); - glCombinerParameterfNV := dglGetProcAddress('glCombinerParameterfNV'); - glCombinerParameterivNV := dglGetProcAddress('glCombinerParameterivNV'); - glCombinerParameteriNV := dglGetProcAddress('glCombinerParameteriNV'); - glCombinerInputNV := dglGetProcAddress('glCombinerInputNV'); - glCombinerOutputNV := dglGetProcAddress('glCombinerOutputNV'); - glFinalCombinerInputNV := dglGetProcAddress('glFinalCombinerInputNV'); - glGetCombinerInputParameterfvNV := dglGetProcAddress('glGetCombinerInputParameterfvNV'); - glGetCombinerInputParameterivNV := dglGetProcAddress('glGetCombinerInputParameterivNV'); - glGetCombinerOutputParameterfvNV := dglGetProcAddress('glGetCombinerOutputParameterfvNV'); - glGetCombinerOutputParameterivNV := dglGetProcAddress('glGetCombinerOutputParameterivNV'); - glGetFinalCombinerInputParameterfvNV := dglGetProcAddress('glGetFinalCombinerInputParameterfvNV'); - glGetFinalCombinerInputParameterivNV := dglGetProcAddress('glGetFinalCombinerInputParameterivNV'); -end; - -procedure Read_GL_NV_register_combiners2; -begin - glCombinerStageParameterfvNV := dglGetProcAddress('glCombinerStageParameterfvNV'); - glGetCombinerStageParameterfvNV := dglGetProcAddress('glGetCombinerStageParameterfvNV'); -end; - -procedure Read_GL_NV_vertex_array_range; -begin - glFlushVertexArrayRangeNV := dglGetProcAddress('glFlushVertexArrayRangeNV'); - glVertexArrayRangeNV := dglGetProcAddress('glVertexArrayRangeNV'); -end; - -procedure Read_GL_NV_vertex_program; -begin - glAreProgramsResidentNV := dglGetProcAddress('glAreProgramsResidentNV'); - glBindProgramNV := dglGetProcAddress('glBindProgramNV'); - glDeleteProgramsNV := dglGetProcAddress('glDeleteProgramsNV'); - glExecuteProgramNV := dglGetProcAddress('glExecuteProgramNV'); - glGenProgramsNV := dglGetProcAddress('glGenProgramsNV'); - glGetProgramParameterdvNV := dglGetProcAddress('glGetProgramParameterdvNV'); - glGetProgramParameterfvNV := dglGetProcAddress('glGetProgramParameterfvNV'); - glGetProgramivNV := dglGetProcAddress('glGetProgramivNV'); - glGetProgramStringNV := dglGetProcAddress('glGetProgramStringNV'); - glGetTrackMatrixivNV := dglGetProcAddress('glGetTrackMatrixivNV'); - glGetVertexAttribdvNV := dglGetProcAddress('glGetVertexAttribdvNV'); - glGetVertexAttribfvNV := dglGetProcAddress('glGetVertexAttribfvNV'); - glGetVertexAttribivNV := dglGetProcAddress('glGetVertexAttribivNV'); - glGetVertexAttribPointervNV := dglGetProcAddress('glGetVertexAttribPointervNV'); - glIsProgramNV := dglGetProcAddress('glIsProgramNV'); - glLoadProgramNV := dglGetProcAddress('glLoadProgramNV'); - glProgramParameter4dNV := dglGetProcAddress('glProgramParameter4dNV'); - glProgramParameter4dvNV := dglGetProcAddress('glProgramParameter4dvNV'); - glProgramParameter4fNV := dglGetProcAddress('glProgramParameter4fNV'); - glProgramParameter4fvNV := dglGetProcAddress('glProgramParameter4fvNV'); - glProgramParameters4dvNV := dglGetProcAddress('glProgramParameters4dvNV'); - glProgramParameters4fvNV := dglGetProcAddress('glProgramParameters4fvNV'); - glRequestResidentProgramsNV := dglGetProcAddress('glRequestResidentProgramsNV'); - glTrackMatrixNV := dglGetProcAddress('glTrackMatrixNV'); - glVertexAttribPointerNV := dglGetProcAddress('glVertexAttribPointerNV'); - glVertexAttrib1dNV := dglGetProcAddress('glVertexAttrib1dNV'); - glVertexAttrib1dvNV := dglGetProcAddress('glVertexAttrib1dvNV'); - glVertexAttrib1fNV := dglGetProcAddress('glVertexAttrib1fNV'); - glVertexAttrib1fvNV := dglGetProcAddress('glVertexAttrib1fvNV'); - glVertexAttrib1sNV := dglGetProcAddress('glVertexAttrib1sNV'); - glVertexAttrib1svNV := dglGetProcAddress('glVertexAttrib1svNV'); - glVertexAttrib2dNV := dglGetProcAddress('glVertexAttrib2dNV'); - glVertexAttrib2dvNV := dglGetProcAddress('glVertexAttrib2dvNV'); - glVertexAttrib2fNV := dglGetProcAddress('glVertexAttrib2fNV'); - glVertexAttrib2fvNV := dglGetProcAddress('glVertexAttrib2fvNV'); - glVertexAttrib2sNV := dglGetProcAddress('glVertexAttrib2sNV'); - glVertexAttrib2svNV := dglGetProcAddress('glVertexAttrib2svNV'); - glVertexAttrib3dNV := dglGetProcAddress('glVertexAttrib3dNV'); - glVertexAttrib3dvNV := dglGetProcAddress('glVertexAttrib3dvNV'); - glVertexAttrib3fNV := dglGetProcAddress('glVertexAttrib3fNV'); - glVertexAttrib3fvNV := dglGetProcAddress('glVertexAttrib3fvNV'); - glVertexAttrib3sNV := dglGetProcAddress('glVertexAttrib3sNV'); - glVertexAttrib3svNV := dglGetProcAddress('glVertexAttrib3svNV'); - glVertexAttrib4dNV := dglGetProcAddress('glVertexAttrib4dNV'); - glVertexAttrib4dvNV := dglGetProcAddress('glVertexAttrib4dvNV'); - glVertexAttrib4fNV := dglGetProcAddress('glVertexAttrib4fNV'); - glVertexAttrib4fvNV := dglGetProcAddress('glVertexAttrib4fvNV'); - glVertexAttrib4sNV := dglGetProcAddress('glVertexAttrib4sNV'); - glVertexAttrib4svNV := dglGetProcAddress('glVertexAttrib4svNV'); - glVertexAttrib4ubNV := dglGetProcAddress('glVertexAttrib4ubNV'); - glVertexAttrib4ubvNV := dglGetProcAddress('glVertexAttrib4ubvNV'); - glVertexAttribs1dvNV := dglGetProcAddress('glVertexAttribs1dvNV'); - glVertexAttribs1fvNV := dglGetProcAddress('glVertexAttribs1fvNV'); - glVertexAttribs1svNV := dglGetProcAddress('glVertexAttribs1svNV'); - glVertexAttribs2dvNV := dglGetProcAddress('glVertexAttribs2dvNV'); - glVertexAttribs2fvNV := dglGetProcAddress('glVertexAttribs2fvNV'); - glVertexAttribs2svNV := dglGetProcAddress('glVertexAttribs2svNV'); - glVertexAttribs3dvNV := dglGetProcAddress('glVertexAttribs3dvNV'); - glVertexAttribs3fvNV := dglGetProcAddress('glVertexAttribs3fvNV'); - glVertexAttribs3svNV := dglGetProcAddress('glVertexAttribs3svNV'); - glVertexAttribs4dvNV := dglGetProcAddress('glVertexAttribs4dvNV'); - glVertexAttribs4fvNV := dglGetProcAddress('glVertexAttribs4fvNV'); - glVertexAttribs4svNV := dglGetProcAddress('glVertexAttribs4svNV'); - glVertexAttribs4ubvNV := dglGetProcAddress('glVertexAttribs4ubvNV'); -end; - -procedure Read_GL_NV_depth_buffer_float; -begin - glDepthRangedNV := dglGetProcAddress('glDepthRangedNV'); - glClearDepthdNV := dglGetProcAddress('glClearDepthdNV'); - glDepthBoundsdNV := dglGetProcAddress('glDepthBoundsdNV'); -end; - -procedure Read_GL_NV_framebuffer_multisample_coverage; -begin - glRenderbufferStorageMultsampleCoverageNV := dglGetProcAddress('glRenderbufferStorageMultsampleCoverageNV'); -end; - -procedure Read_GL_NV_geometry_program4; -begin - glProgramVertexLimitNV := dglGetProcAddress('glProgramVertexLimitNV'); -end; - -procedure Read_GL_NV_gpu_program4; -begin - glProgramLocalParameterI4iNV := dglGetProcAddress('glProgramLocalParameterI4iNV'); - glProgramLocalParameterI4ivNV := dglGetProcAddress('glProgramLocalParameterI4ivNV'); - glProgramLocalParametersI4ivNV := dglGetProcAddress('glProgramLocalParametersI4ivNV'); - glProgramLocalParameterI4uiNV := dglGetProcAddress('glProgramLocalParameterI4uiNV'); - glProgramLocalParameterI4uivNV := dglGetProcAddress('glProgramLocalParameterI4uivNV'); - glProgramLocalParametersI4uivNV := dglGetProcAddress('glProgramLocalParametersI4uivNV'); - glProgramEnvParameterI4iNV := dglGetProcAddress('glProgramEnvParameterI4iNV'); - glProgramEnvParameterI4ivNV := dglGetProcAddress('glProgramEnvParameterI4ivNV'); - glProgramEnvParametersI4ivNV := dglGetProcAddress('glProgramEnvParametersI4ivNV'); - glProgramEnvParameterI4uiNV := dglGetProcAddress('glProgramEnvParameterI4uiNV'); - glProgramEnvParameterI4uivNV := dglGetProcAddress('glProgramEnvParameterI4uivNV'); - glProgramEnvParametersI4uivNV := dglGetProcAddress('glProgramEnvParametersI4uivNV'); - glGetProgramLocalParameterIivNV := dglGetProcAddress('glGetProgramLocalParameterIivNV'); - glGetProgramLocalParameterIuivNV := dglGetProcAddress('glGetProgramLocalParameterIuivNV'); - glGetProgramEnvParameterIivNV := dglGetProcAddress('glGetProgramEnvParameterIivNV'); - glGetProgramEnvParameterIuivNV := dglGetProcAddress('glGetProgramEnvParameterIuivNV'); -end; - -procedure Read_GL_NV_parameter_buffer_object; -begin - glProgramBufferParametersfvNV := dglGetProcAddress('glProgramBufferParametersfvNV'); - glProgramBufferParametersIivNV := dglGetProcAddress('glProgramBufferParametersIivNV'); - glProgramBufferParametersIuivNV := dglGetProcAddress('glProgramBufferParametersIuivNV'); -end; - -procedure Read_GL_NV_transform_feedback; -begin - glBeginTransformFeedbackNV := dglGetProcAddress('glBeginTransformFeedbackNV'); - glEndTransformFeedbackNV := dglGetProcAddress('glEndTransformFeedbackNV'); - glTransformFeedbackAttribsNV := dglGetProcAddress('glTransformFeedbackAttribsNV'); - glBindBufferRangeNV := dglGetProcAddress('glBindBufferRangeNV'); - glBindBufferOffsetNV := dglGetProcAddress('glBindBufferOffsetNV'); - glBindBufferBaseNV := dglGetProcAddress('glBindBufferBaseNV'); - glTransformFeedbackVaryingsNV := dglGetProcAddress('glTransformFeedbackVaryingsNV'); - glActiveVaryingNV := dglGetProcAddress('glActiveVaryingNV'); - glGetVaryingLocationNV := dglGetProcAddress('glGetVaryingLocationNV'); - glGetActiveVaryingNV := dglGetProcAddress('glGetActiveVaryingNV'); - glGetTransformFeedbackVaryingNV := dglGetProcAddress('glGetTransformFeedbackVaryingNV'); -end; - -procedure Read_GL_NV_conditional_render; -begin - glBeginConditionalRenderNV := dglGetProcAddress('glBeginConditionalRenderNV'); - glEndConditionalRenderNV := dglGetProcAddress('glEndConditionalRenderNV'); -end; - -procedure Read_GL_NV_present_video; -begin - glPresentFrameKeyedNV := dglGetProcAddress('glPresentFrameKeyedNV'); - glPresentFrameDualFillNV := dglGetProcAddress('glPresentFrameDualFillNV'); - glGetVideoivNV := dglGetProcAddress('glGetVideoivNV'); - glGetVideouivNV := dglGetProcAddress('glGetVideouivNV'); - glGetVideoi64vNV := dglGetProcAddress('glGetVideoi64vNV'); - glGetVideoui64vNV := dglGetProcAddress('glGetVideoui64vNV'); -// glVideoParameterivNV := dglGetProcAddress('glVideoParameterivNV'); -end; - -procedure Read_GL_NV_explicit_multisample; -begin - glGetMultisamplefvNV := dglGetProcAddress('glGetMultisamplefvNV'); - glSampleMaskIndexedNV := dglGetProcAddress('glSampleMaskIndexedNV'); - glTexRenderbufferNV := dglGetProcAddress('glTexRenderbufferNV'); -end; - -procedure Read_GL_NV_transform_feedback2; -begin - glBindTransformFeedbackNV := dglGetProcAddress('glBindTransformFeedbackNV'); - glDeleteTransformFeedbacksNV := dglGetProcAddress('glDeleteTransformFeedbacksNV'); - glGenTransformFeedbacksNV := dglGetProcAddress('glGenTransformFeedbacksNV'); - glIsTransformFeedbackNV := dglGetProcAddress('glIsTransformFeedbackNV'); - glPauseTransformFeedbackNV := dglGetProcAddress('glPauseTransformFeedbackNV'); - glResumeTransformFeedbackNV := dglGetProcAddress('glResumeTransformFeedbackNV'); - glDrawTransformFeedbackNV := dglGetProcAddress('glDrawTransformFeedbackNV'); -end; - -procedure Read_GL_PGI_misc_hints; -begin - glHintPGI := dglGetProcAddress('glHintPGI'); -end; - -procedure Read_GL_SGIS_detail_texture; -begin - glDetailTexFuncSGIS := dglGetProcAddress('glDetailTexFuncSGIS'); - glGetDetailTexFuncSGIS := dglGetProcAddress('glGetDetailTexFuncSGIS'); -end; - -procedure Read_GL_SGIS_fog_function; -begin - glFogFuncSGIS := dglGetProcAddress('glFogFuncSGIS'); - glGetFogFuncSGIS := dglGetProcAddress('glGetFogFuncSGIS'); -end; - -procedure Read_GL_SGIS_multisample; -begin - glSampleMaskSGIS := dglGetProcAddress('glSampleMaskSGIS'); - glSamplePatternSGIS := dglGetProcAddress('glSamplePatternSGIS'); -end; - -procedure Read_GL_SGIS_pixel_texture; -begin - glPixelTexGenParameteriSGIS := dglGetProcAddress('glPixelTexGenParameteriSGIS'); - glPixelTexGenParameterivSGIS := dglGetProcAddress('glPixelTexGenParameterivSGIS'); - glPixelTexGenParameterfSGIS := dglGetProcAddress('glPixelTexGenParameterfSGIS'); - glPixelTexGenParameterfvSGIS := dglGetProcAddress('glPixelTexGenParameterfvSGIS'); - glGetPixelTexGenParameterivSGIS := dglGetProcAddress('glGetPixelTexGenParameterivSGIS'); - glGetPixelTexGenParameterfvSGIS := dglGetProcAddress('glGetPixelTexGenParameterfvSGIS'); -end; - -procedure Read_GL_SGIS_point_parameters; -begin - glPointParameterfSGIS := dglGetProcAddress('glPointParameterfSGIS'); - glPointParameterfvSGIS := dglGetProcAddress('glPointParameterfvSGIS'); -end; - -procedure Read_GL_SGIS_sharpen_texture; -begin - glSharpenTexFuncSGIS := dglGetProcAddress('glSharpenTexFuncSGIS'); - glGetSharpenTexFuncSGIS := dglGetProcAddress('glGetSharpenTexFuncSGIS'); -end; - -procedure Read_GL_SGIS_texture4D; -begin - glTexImage4DSGIS := dglGetProcAddress('glTexImage4DSGIS'); - glTexSubImage4DSGIS := dglGetProcAddress('glTexSubImage4DSGIS'); -end; - -procedure Read_GL_SGIS_texture_color_mask; -begin - glTextureColorMaskSGIS := dglGetProcAddress('glTextureColorMaskSGIS'); -end; - -procedure Read_GL_SGIS_texture_filter4; -begin - glGetTexFilterFuncSGIS := dglGetProcAddress('glGetTexFilterFuncSGIS'); - glTexFilterFuncSGIS := dglGetProcAddress('glTexFilterFuncSGIS'); -end; - -procedure Read_GL_SGIX_async; -begin - glAsyncMarkerSGIX := dglGetProcAddress('glAsyncMarkerSGIX'); - glFinishAsyncSGIX := dglGetProcAddress('glFinishAsyncSGIX'); - glPollAsyncSGIX := dglGetProcAddress('glPollAsyncSGIX'); - glGenAsyncMarkersSGIX := dglGetProcAddress('glGenAsyncMarkersSGIX'); - glDeleteAsyncMarkersSGIX := dglGetProcAddress('glDeleteAsyncMarkersSGIX'); - glIsAsyncMarkerSGIX := dglGetProcAddress('glIsAsyncMarkerSGIX'); -end; - -procedure Read_GL_SGIX_flush_raster; -begin - glFlushRasterSGIX := dglGetProcAddress('glFlushRasterSGIX'); -end; - -procedure Read_GL_SGIX_fragment_lighting; -begin - glFragmentColorMaterialSGIX := dglGetProcAddress('glFragmentColorMaterialSGIX'); - glFragmentLightfSGIX := dglGetProcAddress('glFragmentLightfSGIX'); - glFragmentLightfvSGIX := dglGetProcAddress('glFragmentLightfvSGIX'); - glFragmentLightiSGIX := dglGetProcAddress('glFragmentLightiSGIX'); - glFragmentLightivSGIX := dglGetProcAddress('glFragmentLightivSGIX'); - glFragmentLightModelfSGIX := dglGetProcAddress('glFragmentLightModelfSGIX'); - glFragmentLightModelfvSGIX := dglGetProcAddress('glFragmentLightModelfvSGIX'); - glFragmentLightModeliSGIX := dglGetProcAddress('glFragmentLightModeliSGIX'); - glFragmentLightModelivSGIX := dglGetProcAddress('glFragmentLightModelivSGIX'); - glFragmentMaterialfSGIX := dglGetProcAddress('glFragmentMaterialfSGIX'); - glFragmentMaterialfvSGIX := dglGetProcAddress('glFragmentMaterialfvSGIX'); - glFragmentMaterialiSGIX := dglGetProcAddress('glFragmentMaterialiSGIX'); - glFragmentMaterialivSGIX := dglGetProcAddress('glFragmentMaterialivSGIX'); - glGetFragmentLightfvSGIX := dglGetProcAddress('glGetFragmentLightfvSGIX'); - glGetFragmentLightivSGIX := dglGetProcAddress('glGetFragmentLightivSGIX'); - glGetFragmentMaterialfvSGIX := dglGetProcAddress('glGetFragmentMaterialfvSGIX'); - glGetFragmentMaterialivSGIX := dglGetProcAddress('glGetFragmentMaterialivSGIX'); - glLightEnviSGIX := dglGetProcAddress('glLightEnviSGIX'); -end; - -procedure Read_GL_SGIX_framezoom; -begin - glFrameZoomSGIX := dglGetProcAddress('glFrameZoomSGIX'); -end; - -procedure Read_GL_SGIX_igloo_interface; -begin - glIglooInterfaceSGIX := dglGetProcAddress('glIglooInterfaceSGIX'); -end; - -procedure Read_GL_SGIX_instruments; -begin - glGetInstrumentsSGIX := dglGetProcAddress('glGetInstrumentsSGIX'); - glInstrumentsBufferSGIX := dglGetProcAddress('glInstrumentsBufferSGIX'); - glPollInstrumentsSGIX := dglGetProcAddress('glPollInstrumentsSGIX'); - glReadInstrumentsSGIX := dglGetProcAddress('glReadInstrumentsSGIX'); - glStartInstrumentsSGIX := dglGetProcAddress('glStartInstrumentsSGIX'); - glStopInstrumentsSGIX := dglGetProcAddress('glStopInstrumentsSGIX'); -end; - -procedure Read_GL_SGIX_list_priority; -begin - glGetListParameterfvSGIX := dglGetProcAddress('glGetListParameterfvSGIX'); - glGetListParameterivSGIX := dglGetProcAddress('glGetListParameterivSGIX'); - glListParameterfSGIX := dglGetProcAddress('glListParameterfSGIX'); - glListParameterfvSGIX := dglGetProcAddress('glListParameterfvSGIX'); - glListParameteriSGIX := dglGetProcAddress('glListParameteriSGIX'); - glListParameterivSGIX := dglGetProcAddress('glListParameterivSGIX'); -end; - -procedure Read_GL_SGIX_pixel_texture; -begin - glPixelTexGenSGIX := dglGetProcAddress('glPixelTexGenSGIX'); -end; - -procedure Read_GL_SGIX_polynomial_ffd; -begin - glDeformationMap3dSGIX := dglGetProcAddress('glDeformationMap3dSGIX'); - glDeformationMap3fSGIX := dglGetProcAddress('glDeformationMap3fSGIX'); - glDeformSGIX := dglGetProcAddress('glDeformSGIX'); - glLoadIdentityDeformationMapSGIX := dglGetProcAddress('glLoadIdentityDeformationMapSGIX'); -end; - -procedure Read_GL_SGIX_reference_plane; -begin - glReferencePlaneSGIX := dglGetProcAddress('glReferencePlaneSGIX'); -end; - -procedure Read_GL_SGIX_sprite; -begin - glSpriteParameterfSGIX := dglGetProcAddress('glSpriteParameterfSGIX'); - glSpriteParameterfvSGIX := dglGetProcAddress('glSpriteParameterfvSGIX'); - glSpriteParameteriSGIX := dglGetProcAddress('glSpriteParameteriSGIX'); - glSpriteParameterivSGIX := dglGetProcAddress('glSpriteParameterivSGIX'); -end; - -procedure Read_GL_SGIX_tag_sample_buffer; -begin - glTagSampleBufferSGIX := dglGetProcAddress('glTagSampleBufferSGIX'); -end; - -procedure Read_GL_SGI_color_table; -begin - glColorTableSGI := dglGetProcAddress('glColorTableSGI'); - glColorTableParameterfvSGI := dglGetProcAddress('glColorTableParameterfvSGI'); - glColorTableParameterivSGI := dglGetProcAddress('glColorTableParameterivSGI'); - glCopyColorTableSGI := dglGetProcAddress('glCopyColorTableSGI'); - glGetColorTableSGI := dglGetProcAddress('glGetColorTableSGI'); - glGetColorTableParameterfvSGI := dglGetProcAddress('glGetColorTableParameterfvSGI'); - glGetColorTableParameterivSGI := dglGetProcAddress('glGetColorTableParameterivSGI'); -end; - -procedure Read_GL_SUNX_constant_data; -begin - glFinishTextureSUNX := dglGetProcAddress('glFinishTextureSUNX'); -end; - -procedure Read_GL_SUN_global_alpha; -begin - glGlobalAlphaFactorbSUN := dglGetProcAddress('glGlobalAlphaFactorbSUN'); - glGlobalAlphaFactorsSUN := dglGetProcAddress('glGlobalAlphaFactorsSUN'); - glGlobalAlphaFactoriSUN := dglGetProcAddress('glGlobalAlphaFactoriSUN'); - glGlobalAlphaFactorfSUN := dglGetProcAddress('glGlobalAlphaFactorfSUN'); - glGlobalAlphaFactordSUN := dglGetProcAddress('glGlobalAlphaFactordSUN'); - glGlobalAlphaFactorubSUN := dglGetProcAddress('glGlobalAlphaFactorubSUN'); - glGlobalAlphaFactorusSUN := dglGetProcAddress('glGlobalAlphaFactorusSUN'); - glGlobalAlphaFactoruiSUN := dglGetProcAddress('glGlobalAlphaFactoruiSUN'); -end; - -procedure Read_GL_SUN_mesh_array; -begin - glDrawMeshArraysSUN := dglGetProcAddress('glDrawMeshArraysSUN'); -end; - -procedure Read_GL_SUN_triangle_list; -begin - glReplacementCodeuiSUN := dglGetProcAddress('glReplacementCodeuiSUN'); - glReplacementCodeusSUN := dglGetProcAddress('glReplacementCodeusSUN'); - glReplacementCodeubSUN := dglGetProcAddress('glReplacementCodeubSUN'); - glReplacementCodeuivSUN := dglGetProcAddress('glReplacementCodeuivSUN'); - glReplacementCodeusvSUN := dglGetProcAddress('glReplacementCodeusvSUN'); - glReplacementCodeubvSUN := dglGetProcAddress('glReplacementCodeubvSUN'); - glReplacementCodePointerSUN := dglGetProcAddress('glReplacementCodePointerSUN'); -end; - -procedure Read_GL_SUN_vertex; -begin - glColor4ubVertex2fSUN := dglGetProcAddress('glColor4ubVertex2fSUN'); - glColor4ubVertex2fvSUN := dglGetProcAddress('glColor4ubVertex2fvSUN'); - glColor4ubVertex3fSUN := dglGetProcAddress('glColor4ubVertex3fSUN'); - glColor4ubVertex3fvSUN := dglGetProcAddress('glColor4ubVertex3fvSUN'); - glColor3fVertex3fSUN := dglGetProcAddress('glColor3fVertex3fSUN'); - glColor3fVertex3fvSUN := dglGetProcAddress('glColor3fVertex3fvSUN'); - glNormal3fVertex3fSUN := dglGetProcAddress('glNormal3fVertex3fSUN'); - glNormal3fVertex3fvSUN := dglGetProcAddress('glNormal3fVertex3fvSUN'); - glColor4fNormal3fVertex3fSUN := dglGetProcAddress('glColor4fNormal3fVertex3fSUN'); - glColor4fNormal3fVertex3fvSUN := dglGetProcAddress('glColor4fNormal3fVertex3fvSUN'); - glTexCoord2fVertex3fSUN := dglGetProcAddress('glTexCoord2fVertex3fSUN'); - glTexCoord2fVertex3fvSUN := dglGetProcAddress('glTexCoord2fVertex3fvSUN'); - glTexCoord4fVertex4fSUN := dglGetProcAddress('glTexCoord4fVertex4fSUN'); - glTexCoord4fVertex4fvSUN := dglGetProcAddress('glTexCoord4fVertex4fvSUN'); - glTexCoord2fColor4ubVertex3fSUN := dglGetProcAddress('glTexCoord2fColor4ubVertex3fSUN'); - glTexCoord2fColor4ubVertex3fvSUN := dglGetProcAddress('glTexCoord2fColor4ubVertex3fvSUN'); - glTexCoord2fColor3fVertex3fSUN := dglGetProcAddress('glTexCoord2fColor3fVertex3fSUN'); - glTexCoord2fColor3fVertex3fvSUN := dglGetProcAddress('glTexCoord2fColor3fVertex3fvSUN'); - glTexCoord2fNormal3fVertex3fSUN := dglGetProcAddress('glTexCoord2fNormal3fVertex3fSUN'); - glTexCoord2fNormal3fVertex3fvSUN := dglGetProcAddress('glTexCoord2fNormal3fVertex3fvSUN'); - glTexCoord2fColor4fNormal3fVertex3fSUN := dglGetProcAddress('glTexCoord2fColor4fNormal3fVertex3fSUN'); - glTexCoord2fColor4fNormal3fVertex3fvSUN := dglGetProcAddress('glTexCoord2fColor4fNormal3fVertex3fvSUN'); - glTexCoord4fColor4fNormal3fVertex4fSUN := dglGetProcAddress('glTexCoord4fColor4fNormal3fVertex4fSUN'); - glTexCoord4fColor4fNormal3fVertex4fvSUN := dglGetProcAddress('glTexCoord4fColor4fNormal3fVertex4fvSUN'); - glReplacementCodeuiVertex3fSUN := dglGetProcAddress('glReplacementCodeuiVertex3fSUN'); - glReplacementCodeuiVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiVertex3fvSUN'); - glReplacementCodeuiColor4ubVertex3fSUN := dglGetProcAddress('glReplacementCodeuiColor4ubVertex3fSUN'); - glReplacementCodeuiColor4ubVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiColor4ubVertex3fvSUN'); - glReplacementCodeuiColor3fVertex3fSUN := dglGetProcAddress('glReplacementCodeuiColor3fVertex3fSUN'); - glReplacementCodeuiColor3fVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiColor3fVertex3fvSUN'); - glReplacementCodeuiNormal3fVertex3fSUN := dglGetProcAddress('glReplacementCodeuiNormal3fVertex3fSUN'); - glReplacementCodeuiNormal3fVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiNormal3fVertex3fvSUN'); - glReplacementCodeuiColor4fNormal3fVertex3fSUN := dglGetProcAddress('glReplacementCodeuiColor4fNormal3fVertex3fSUN'); - glReplacementCodeuiColor4fNormal3fVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiColor4fNormal3fVertex3fvSUN'); - glReplacementCodeuiTexCoord2fVertex3fSUN := dglGetProcAddress('glReplacementCodeuiTexCoord2fVertex3fSUN'); - glReplacementCodeuiTexCoord2fVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiTexCoord2fVertex3fvSUN'); - glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN := dglGetProcAddress('glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN'); - glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN'); - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN := dglGetProcAddress('glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN'); - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN := dglGetProcAddress('glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN'); -end; - -{$IFDEF DGL_WIN} -procedure Read_WGL_ARB_buffer_region; -begin - wglCreateBufferRegionARB := dglGetProcAddress('wglCreateBufferRegionARB'); - wglDeleteBufferRegionARB := dglGetProcAddress('wglDeleteBufferRegionARB'); - wglSaveBufferRegionARB := dglGetProcAddress('wglSaveBufferRegionARB'); - wglRestoreBufferRegionARB := dglGetProcAddress('wglRestoreBufferRegionARB'); -end; - -procedure Read_WGL_ARB_extensions_string; -begin - wglGetExtensionsStringARB := dglGetProcAddress('wglGetExtensionsStringARB'); -end; - -procedure Read_WGL_ARB_make_current_read; -begin - wglMakeContextCurrentARB := dglGetProcAddress('wglMakeContextCurrentARB'); - wglGetCurrentReadDCARB := dglGetProcAddress('wglGetCurrentReadDCARB'); -end; - -procedure Read_WGL_ARB_pbuffer; -begin - wglCreatePbufferARB := dglGetProcAddress('wglCreatePbufferARB'); - wglGetPbufferDCARB := dglGetProcAddress('wglGetPbufferDCARB'); - wglReleasePbufferDCARB := dglGetProcAddress('wglReleasePbufferDCARB'); - wglDestroyPbufferARB := dglGetProcAddress('wglDestroyPbufferARB'); - wglQueryPbufferARB := dglGetProcAddress('wglQueryPbufferARB'); -end; - -procedure Read_WGL_ARB_pixel_format; -begin - wglGetPixelFormatAttribivARB := dglGetProcAddress('wglGetPixelFormatAttribivARB'); - wglGetPixelFormatAttribfvARB := dglGetProcAddress('wglGetPixelFormatAttribfvARB'); - wglChoosePixelFormatARB := dglGetProcAddress('wglChoosePixelFormatARB'); -end; - -procedure Read_WGL_ARB_pixel_format_float; -begin - wglClampColorARB := dglGetProcAddress('wglClampColorARB'); -end; - -procedure Read_WGL_ARB_render_texture; -begin - wglBindTexImageARB := dglGetProcAddress('wglBindTexImageARB'); - wglReleaseTexImageARB := dglGetProcAddress('wglReleaseTexImageARB'); - wglSetPbufferAttribARB := dglGetProcAddress('wglSetPbufferAttribARB'); -end; - -procedure Read_WGL_ARB_create_context; -begin - wglCreateContextAttribsARB := dglGetProcAddress('wglCreateContextAttribsARB'); -end; - -procedure Read_WGL_AMD_gpu_association; -begin - wglGetGPUIDsAMD := dglGetProcAddress('wglGetGPUIDsAMD'); - wglGetGPUInfoAMD := dglGetProcAddress('wglGetGPUInfoAMD'); - wglGetContextGPUIDAMD := dglGetProcAddress('wglGetContextGPUIDAMD'); - wglCreateAssociatedContextAMD := dglGetProcAddress('wglCreateAssociatedContextAMD'); - wglCreateAssociatedContextAttribsAMD := dglGetProcAddress('wglCreateAssociatedContextAttribsAMD'); - wglDeleteAssociatedContextAMD := dglGetProcAddress('wglDeleteAssociatedContextAMD'); - wglMakeAssociatedContextCurrentAMD := dglGetProcAddress('wglMakeAssociatedContextCurrentAMD'); - wglGetCurrentAssociatedContextAMD := dglGetProcAddress('wglGetCurrentAssociatedContextAMD'); - wglBlitContextFramebufferAMD := dglGetProcAddress('wglBlitContextFramebufferAMD'); -end; - -procedure Read_WGL_EXT_display_color_table; -begin - wglCreateDisplayColorTableEXT := dglGetProcAddress('wglCreateDisplayColorTableEXT'); - wglLoadDisplayColorTableEXT := dglGetProcAddress('wglLoadDisplayColorTableEXT'); - wglBindDisplayColorTableEXT := dglGetProcAddress('wglBindDisplayColorTableEXT'); - wglDestroyDisplayColorTableEXT := dglGetProcAddress('wglDestroyDisplayColorTableEXT'); -end; - -procedure Read_WGL_EXT_extensions_string; -begin - wglGetExtensionsStringEXT := dglGetProcAddress('wglGetExtensionsStringEXT'); -end; - -procedure Read_WGL_EXT_make_current_read; -begin - wglMakeContextCurrentEXT := dglGetProcAddress('wglMakeContextCurrentEXT'); - wglGetCurrentReadDCEXT := dglGetProcAddress('wglGetCurrentReadDCEXT'); -end; - -procedure Read_WGL_EXT_pbuffer; -begin - wglCreatePbufferEXT := dglGetProcAddress('wglCreatePbufferEXT'); - wglGetPbufferDCEXT := dglGetProcAddress('wglGetPbufferDCEXT'); - wglReleasePbufferDCEXT := dglGetProcAddress('wglReleasePbufferDCEXT'); - wglDestroyPbufferEXT := dglGetProcAddress('wglDestroyPbufferEXT'); - wglQueryPbufferEXT := dglGetProcAddress('wglQueryPbufferEXT'); -end; - -procedure Read_WGL_EXT_pixel_format; -begin - wglGetPixelFormatAttribivEXT := dglGetProcAddress('wglGetPixelFormatAttribivEXT'); - wglGetPixelFormatAttribfvEXT := dglGetProcAddress('wglGetPixelFormatAttribfvEXT'); - wglChoosePixelFormatEXT := dglGetProcAddress('wglChoosePixelFormatEXT'); -end; - -procedure Read_WGL_EXT_swap_control; -begin - wglSwapIntervalEXT := dglGetProcAddress('wglSwapIntervalEXT'); - wglGetSwapIntervalEXT := dglGetProcAddress('wglGetSwapIntervalEXT'); -end; - -procedure Read_WGL_I3D_digital_video_control; -begin - wglGetDigitalVideoParametersI3D := dglGetProcAddress('wglGetDigitalVideoParametersI3D'); - wglSetDigitalVideoParametersI3D := dglGetProcAddress('wglSetDigitalVideoParametersI3D'); -end; - -procedure Read_WGL_I3D_gamma; -begin - wglGetGammaTableParametersI3D := dglGetProcAddress('wglGetGammaTableParametersI3D'); - wglSetGammaTableParametersI3D := dglGetProcAddress('wglSetGammaTableParametersI3D'); - wglGetGammaTableI3D := dglGetProcAddress('wglGetGammaTableI3D'); - wglSetGammaTableI3D := dglGetProcAddress('wglSetGammaTableI3D'); -end; - -procedure Read_WGL_I3D_genlock; -begin - wglEnableGenlockI3D := dglGetProcAddress('wglEnableGenlockI3D'); - wglDisableGenlockI3D := dglGetProcAddress('wglDisableGenlockI3D'); - wglIsEnabledGenlockI3D := dglGetProcAddress('wglIsEnabledGenlockI3D'); - wglGenlockSourceI3D := dglGetProcAddress('wglGenlockSourceI3D'); - wglGetGenlockSourceI3D := dglGetProcAddress('wglGetGenlockSourceI3D'); - wglGenlockSourceEdgeI3D := dglGetProcAddress('wglGenlockSourceEdgeI3D'); - wglGetGenlockSourceEdgeI3D := dglGetProcAddress('wglGetGenlockSourceEdgeI3D'); - wglGenlockSampleRateI3D := dglGetProcAddress('wglGenlockSampleRateI3D'); - wglGetGenlockSampleRateI3D := dglGetProcAddress('wglGetGenlockSampleRateI3D'); - wglGenlockSourceDelayI3D := dglGetProcAddress('wglGenlockSourceDelayI3D'); - wglGetGenlockSourceDelayI3D := dglGetProcAddress('wglGetGenlockSourceDelayI3D'); - wglQueryGenlockMaxSourceDelayI3D := dglGetProcAddress('wglQueryGenlockMaxSourceDelayI3D'); -end; - -procedure Read_WGL_I3D_image_buffer; -begin - wglCreateImageBufferI3D := dglGetProcAddress('wglCreateImageBufferI3D'); - wglDestroyImageBufferI3D := dglGetProcAddress('wglDestroyImageBufferI3D'); - wglAssociateImageBufferEventsI3D := dglGetProcAddress('wglAssociateImageBufferEventsI3D'); - wglReleaseImageBufferEventsI3D := dglGetProcAddress('wglReleaseImageBufferEventsI3D'); -end; - -procedure Read_WGL_I3D_swap_frame_lock; -begin - wglEnableFrameLockI3D := dglGetProcAddress('wglEnableFrameLockI3D'); - wglDisableFrameLockI3D := dglGetProcAddress('wglDisableFrameLockI3D'); - wglIsEnabledFrameLockI3D := dglGetProcAddress('wglIsEnabledFrameLockI3D'); - wglQueryFrameLockMasterI3D := dglGetProcAddress('wglQueryFrameLockMasterI3D'); -end; - -procedure Read_WGL_I3D_swap_frame_usage; -begin - wglGetFrameUsageI3D := dglGetProcAddress('wglGetFrameUsageI3D'); - wglBeginFrameTrackingI3D := dglGetProcAddress('wglBeginFrameTrackingI3D'); - wglEndFrameTrackingI3D := dglGetProcAddress('wglEndFrameTrackingI3D'); - wglQueryFrameTrackingI3D := dglGetProcAddress('wglQueryFrameTrackingI3D'); -end; - -procedure Read_WGL_NV_vertex_array_range; -begin - wglAllocateMemoryNV := dglGetProcAddress('wglAllocateMemoryNV'); - wglFreeMemoryNV := dglGetProcAddress('wglFreeMemoryNV'); -end; - -procedure Read_WGL_NV_present_video; -begin - wglEnumerateVideoDevicesNV := dglGetProcAddress('wglEnumerateVideoDevicesNV'); - wglBindVideoDeviceNV := dglGetProcAddress('wglBindVideoDeviceNV'); - wglQueryCurrentContextNV := dglGetProcAddress('wglQueryCurrentContextNV'); -end; - -procedure Read_WGL_NV_video_out; -begin - wglGetVideoDeviceNV := dglGetProcAddress('wglGetVideoDeviceNV'); - wglReleaseVideoDeviceNV := dglGetProcAddress('wglReleaseVideoDeviceNV'); - wglBindVideoImageNV := dglGetProcAddress('wglBindVideoImageNV'); - wglReleaseVideoImageNV := dglGetProcAddress('wglReleaseVideoImageNV'); - wglSendPbufferToVideoNV := dglGetProcAddress('wglSendPbufferToVideoNV'); - wglGetVideoInfoNV := dglGetProcAddress('wglGetVideoInfoNV'); -end; - -procedure Read_WGL_NV_swap_group; -begin - wglJoinSwapGroupNV := dglGetProcAddress('wglJoinSwapGroupNV'); - wglBindSwapBarrierNV := dglGetProcAddress('wglBindSwapBarrierNV'); - wglQuerySwapGroupNV := dglGetProcAddress('wglQuerySwapGroupNV'); - wglQueryMaxSwapGroupsNV := dglGetProcAddress('wglQueryMaxSwapGroupsNV'); - wglQueryFrameCountNV := dglGetProcAddress('wglQueryFrameCountNV'); - wglResetFrameCountNV := dglGetProcAddress('wglResetFrameCountNV'); -end; - -procedure Read_WGL_NV_gpu_affinity; -begin - wglEnumGpusNV := dglGetProcAddress('wglEnumGpusNV'); - wglEnumGpuDevicesNV := dglGetProcAddress('wglEnumGpuDevicesNV'); - wglCreateAffinityDCNV := dglGetProcAddress('wglCreateAffinityDCNV'); - wglEnumGpusFromAffinityDCNV := dglGetProcAddress('wglEnumGpusFromAffinityDCNV'); - wglDeleteDCNV := dglGetProcAddress('wglDeleteDCNV'); -end; - -procedure Read_WGL_OML_sync_control; -begin - wglGetSyncValuesOML := dglGetProcAddress('wglGetSyncValuesOML'); - wglGetMscRateOML := dglGetProcAddress('wglGetMscRateOML'); - wglSwapBuffersMscOML := dglGetProcAddress('wglSwapBuffersMscOML'); - wglSwapLayerBuffersMscOML := dglGetProcAddress('wglSwapLayerBuffersMscOML'); - wglWaitForMscOML := dglGetProcAddress('wglWaitForMscOML'); - wglWaitForSbcOML := dglGetProcAddress('wglWaitForSbcOML'); -end; - -procedure Read_WGL_3DL_stereo_control; -begin - wglSetStereoEmitterState3DL := dglGetProcAddress('wglSetStereoEmitterState3DL'); -end; - -procedure Read_WIN_draw_range_elements; -begin - glDrawRangeElementsWIN := dglGetProcAddress('glDrawRangeElementsWIN'); -end; - -procedure Read_WIN_swap_hint; -begin - glAddSwapHintRectWIN := dglGetProcAddress('glAddSwapHintRectWIN'); -end; -{$ENDIF} - - -procedure ReadExtensions; -begin - ReadOpenGLCore; - - Read_GL_3DFX_tbuffer; - Read_GL_APPLE_element_array; - Read_GL_APPLE_fence; - Read_GL_APPLE_vertex_array_object; - Read_GL_APPLE_vertex_array_range; - Read_GL_APPLE_texture_range; - Read_GL_APPLE_vertex_program_evaluators; - Read_GL_APPLE_object_purgeable; - Read_GL_ARB_matrix_palette; - Read_GL_ARB_multitexture; - Read_GL_ARB_point_parameters; - Read_GL_ARB_texture_compression; - Read_GL_ARB_transpose_matrix; - Read_GL_ARB_vertex_blend; - Read_GL_ARB_vertex_buffer_object; - Read_GL_ARB_vertex_program; - Read_GL_ARB_window_pos; - Read_GL_ARB_color_buffer_float; - Read_GL_ARB_Shader_Objects; - Read_GL_ARB_occlusion_query; - Read_GL_ARB_draw_instanced; - Read_GL_ARB_framebuffer_object; - Read_GL_ARB_geometry_shader4; - Read_GL_ARB_instanced_arrays; - Read_GL_ARB_map_buffer_range; - Read_GL_ARB_texture_buffer_object; - Read_GL_ARB_vertex_array_object; - Read_GL_ARB_uniform_buffer_object; - Read_GL_ARB_copy_buffer; - Read_GL_ARB_draw_elements_base_vertex; - Read_GL_ARB_provoking_vertex; - Read_GL_ARB_sync; - Read_GL_ARB_texture_multisample; - Read_GL_ARB_draw_buffers_blend; - Read_GL_ARB_sample_shading; - Read_GL_ATI_draw_buffers; - Read_GL_ATI_element_array; - Read_GL_ATI_envmap_bumpmap; - Read_GL_ATI_fragment_shader; - Read_GL_ATI_map_object_buffer; - Read_GL_ATI_pn_triangles; - Read_GL_ATI_separate_stencil; - Read_GL_ATI_vertex_array_object; - Read_GL_ATI_vertex_attrib_array_object; - Read_GL_ATI_vertex_streams; - Read_GL_AMD_performance_monitor; - Read_GL_EXT_blend_color; - Read_GL_EXT_blend_func_separate; - Read_GL_EXT_blend_minmax; - Read_GL_EXT_color_subtable; - Read_GL_EXT_compiled_vertex_array; - Read_GL_EXT_convolution; - Read_GL_EXT_coordinate_frame; - Read_GL_EXT_copy_texture; - Read_GL_EXT_cull_vertex; - Read_GL_EXT_draw_range_elements; - Read_GL_EXT_fog_coord; - Read_GL_EXT_framebuffer_object; - Read_GL_EXT_histogram; - Read_GL_EXT_index_func; - Read_GL_EXT_index_material; - Read_GL_EXT_multi_draw_arrays; - Read_GL_EXT_multisample; - Read_GL_EXT_paletted_texture; - Read_GL_EXT_pixel_transform; - Read_GL_EXT_point_parameters; - Read_GL_EXT_polygon_offset; - Read_GL_EXT_secondary_color; - Read_GL_EXT_stencil_two_side; - Read_GL_EXT_subtexture; - Read_GL_EXT_texture3D; - Read_GL_EXT_texture_object; - Read_GL_EXT_texture_perturb_normal; - Read_GL_EXT_vertex_array; - Read_GL_EXT_vertex_shader; - Read_GL_EXT_vertex_weighting; - Read_GL_EXT_depth_bounds_test; - Read_GL_EXT_blend_equation_separate; - Read_GL_EXT_stencil_clear_tag; - Read_GL_EXT_framebuffer_blit; - Read_GL_EXT_framebuffer_multisample; - Read_GL_EXT_timer_query; - Read_GL_EXT_gpu_program_parameters; - Read_GL_EXT_bindable_uniform; - Read_GL_EXT_draw_buffers2; - Read_GL_EXT_draw_instanced; - Read_GL_EXT_geometry_shader4; - Read_GL_EXT_gpu_shader4; - Read_GL_EXT_texture_array; - Read_GL_EXT_texture_buffer_object; - Read_GL_EXT_texture_integer; - Read_GL_EXT_transform_feedback; - Read_GL_EXT_direct_state_access; - Read_GL_HP_image_transform; - Read_GL_IBM_multimode_draw_arrays; - Read_GL_IBM_vertex_array_lists; - Read_GL_INGR_blend_func_separate; - Read_GL_INTEL_parallel_arrays; - Read_GL_MESA_resize_buffers; - Read_GL_MESA_window_pos; - Read_GL_NV_evaluators; - Read_GL_NV_fence; - Read_GL_NV_fragment_program; - Read_GL_NV_half_float; - Read_GL_NV_occlusion_query; - Read_GL_NV_pixel_data_range; - Read_GL_NV_point_sprite; - Read_GL_NV_primitive_restart; - Read_GL_NV_register_combiners; - Read_GL_NV_register_combiners2; - Read_GL_NV_vertex_array_range; - Read_GL_NV_vertex_program; - Read_GL_NV_depth_buffer_float; - Read_GL_NV_framebuffer_multisample_coverage; - Read_GL_NV_geometry_program4; - Read_GL_NV_gpu_program4; - Read_GL_NV_parameter_buffer_object; - Read_GL_NV_transform_feedback; - Read_GL_NV_conditional_render; - Read_GL_NV_present_video; - Read_GL_NV_explicit_multisample; - Read_GL_NV_transform_feedback2; - Read_GL_PGI_misc_hints; - Read_GL_SGIS_detail_texture; - Read_GL_SGIS_fog_function; - Read_GL_SGIS_multisample; - Read_GL_SGIS_pixel_texture; - Read_GL_SGIS_point_parameters; - Read_GL_SGIS_sharpen_texture; - Read_GL_SGIS_texture4D; - Read_GL_SGIS_texture_color_mask; - Read_GL_SGIS_texture_filter4; - Read_GL_SGIX_async; - Read_GL_SGIX_flush_raster; - Read_GL_SGIX_fragment_lighting; - Read_GL_SGIX_framezoom; - Read_GL_SGIX_igloo_interface; - Read_GL_SGIX_instruments; - Read_GL_SGIX_list_priority; - Read_GL_SGIX_pixel_texture; - Read_GL_SGIX_polynomial_ffd; - Read_GL_SGIX_reference_plane; - Read_GL_SGIX_sprite; - Read_GL_SGIX_tag_sample_buffer; - Read_GL_SGI_color_table; - Read_GL_SUNX_constant_data; - Read_GL_SUN_global_alpha; - Read_GL_SUN_mesh_array; - Read_GL_SUN_triangle_list; - Read_GL_SUN_vertex; - -{$IFDEF DGL_WIN} - Read_WGL_ARB_buffer_region; - Read_WGL_ARB_extensions_string; - Read_WGL_ARB_make_current_read; - Read_WGL_ARB_pbuffer; - Read_WGL_ARB_pixel_format; - Read_WGL_ARB_pixel_format_float; - Read_WGL_ARB_render_texture; - Read_WGL_ARB_create_context; - Read_WGL_AMD_gpu_association; - Read_WGL_EXT_display_color_table; - Read_WGL_EXT_extensions_string; - Read_WGL_EXT_make_current_read; - Read_WGL_EXT_pbuffer; - Read_WGL_EXT_pixel_format; - Read_WGL_EXT_swap_control; - Read_WGL_I3D_digital_video_control; - Read_WGL_I3D_gamma; - Read_WGL_I3D_genlock; - Read_WGL_I3D_image_buffer; - Read_WGL_I3D_swap_frame_lock; - Read_WGL_I3D_swap_frame_usage; - Read_WGL_NV_vertex_array_range; - Read_WGL_NV_present_video; - Read_WGL_NV_video_out; - Read_WGL_NV_swap_group; - Read_WGL_NV_gpu_affinity; - Read_WGL_OML_sync_control; - Read_WGL_3DL_stereo_control; - - Read_WIN_draw_range_elements; - Read_WIN_swap_hint; -{$ENDIF} - - ExtensionsRead := True; -end; - -// ============================================================================= -// ReadCoreVersion -// ============================================================================= - -procedure ReadCoreVersion; -var - AnsiBuffer: AnsiString; - Buffer: String; - MajorVersion, MinorVersion: Integer; - - procedure TrimAndSplitVersionString(Buffer: String; var Max, Min: Integer); - // Peels out the X.Y form from the given Buffer which must contain a version string like "text Minor.Major.Build text" - // at least however "Major.Minor". - var - Separator: Integer; - begin - try - // There must be at least one dot to separate major and minor version number. - Separator := Pos('.', Buffer); - // At least one number must be before and one after the dot. - if (Separator > 1) and (Separator < Length(Buffer)) and (AnsiChar(Buffer[Separator - 1]) in ['0'..'9']) and - (AnsiChar(Buffer[Separator + 1]) in ['0'..'9']) then - begin - // OK, it's a valid version string. Now remove unnecessary parts. - Dec(Separator); - // Find last non-numeric character before version number. - while (Separator > 0) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do - Dec(Separator); - // Delete leading characters which do not belong to the version string. - Delete(Buffer, 1, Separator); - Separator := Pos('.', Buffer) + 1; - // Find first non-numeric character after version number - while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do - Inc(Separator); - // delete trailing characters not belonging to the version string - Delete(Buffer, Separator, 255); - // Now translate the numbers. - Separator := Pos('.', Buffer); // This is necessary because the buffer length might have changed. - Max := StrToInt(Copy(Buffer, 1, Separator - 1)); - Min := StrToInt(Copy(Buffer, Separator + 1, 1)); - end - else - Abort; - except - Min := 0; - Max := 0; - end; - end; - - -begin - // determine version of implementation - // GL - if not Assigned(@glGetString) then - glGetString := dglGetProcAddress('glGetString'); - - AnsiBuffer := glGetString(GL_VERSION); - Buffer := String(AnsiBuffer); - - TrimAndSplitVersionString(Buffer, MajorVersion, MinorVersion); - - GL_VERSION_1_0 := True; - GL_VERSION_1_1 := False; - GL_VERSION_1_2 := False; - GL_VERSION_1_3 := False; - GL_VERSION_1_4 := False; - GL_VERSION_1_5 := False; - GL_VERSION_2_0 := False; - GL_VERSION_2_1 := False; - GL_VERSION_3_0 := False; - GL_VERSION_3_1 := False; - GL_VERSION_3_2 := False; - - if MajorVersion = 1 then - begin - if MinorVersion >= 1 then - GL_VERSION_1_1 := True; - if MinorVersion >= 2 then - GL_VERSION_1_2 := True; - if MinorVersion >= 3 then - GL_VERSION_1_3 := True; - if MinorVersion >= 4 then - GL_VERSION_1_4 := True; - if MinorVersion >= 5 then - GL_VERSION_1_5 := True; - end; - - if MajorVersion >= 2 then - begin - GL_VERSION_1_1 := True; - GL_VERSION_1_2 := True; - GL_VERSION_1_3 := True; - GL_VERSION_1_4 := True; - GL_VERSION_1_5 := True; - GL_VERSION_2_0 := True; - - if MinorVersion >= 1 then - GL_VERSION_2_1 := True; - end; - - if MajorVersion >= 3 then - begin - GL_VERSION_2_1 := True; - GL_VERSION_3_0 := True; - - if MinorVersion >= 1 then - GL_VERSION_3_1 := True; - if MinorVersion >= 2 then - GL_VERSION_3_2 := True; - end; - - - // GLU - GLU_VERSION_1_1 := False; - GLU_VERSION_1_2 := False; - GLU_VERSION_1_3 := False; - - if Assigned(gluGetString) then begin - AnsiBuffer := gluGetString(GLU_VERSION); - Buffer := String(AnsiBuffer); - - TrimAndSplitVersionString(Buffer, Majorversion, MinorVersion); - - GLU_VERSION_1_1 := True; - - if MinorVersion >= 2 then - GLU_VERSION_1_2 := True; - - if MinorVersion >= 3 then - GLU_VERSION_1_3 := True; - end; -end; - - -// ============================================================================= -// ReadImplementationProperties -// ============================================================================= - -procedure ReadImplementationProperties; -var - Buffer: Ansistring; -begin - ReadCoreVersion; - - // Check all extensions - Buffer := Int_GetExtensionString; - - // === 3DFX ==================================================================== - GL_3DFX_multisample := Int_CheckExtension(Buffer, 'GL_3DFX_multisample'); - GL_3DFX_tbuffer := Int_CheckExtension(Buffer, 'GL_3DFX_tbuffer'); - GL_3DFX_texture_compression_FXT1 := Int_CheckExtension(Buffer, 'GL_3DFX_texture_compression_FXT1'); - - // === APPLE =================================================================== - GL_APPLE_client_storage := Int_CheckExtension(Buffer, 'GL_APPLE_client_storage'); - GL_APPLE_element_array := Int_CheckExtension(Buffer, 'GL_APPLE_element_array'); - GL_APPLE_fence := Int_CheckExtension(Buffer, 'GL_APPLE_fence'); - GL_APPLE_specular_vector := Int_CheckExtension(Buffer, 'GL_APPLE_specular_vector'); - GL_APPLE_transform_hint := Int_CheckExtension(Buffer, 'GL_APPLE_transform_hint'); - GL_APPLE_vertex_array_object := Int_CheckExtension(Buffer, 'GL_APPLE_vertex_array_object'); - GL_APPLE_vertex_array_range := Int_CheckExtension(Buffer, 'GL_APPLE_vertex_array_range'); - GL_APPLE_ycbcr_422 := Int_CheckExtension(Buffer, 'GL_APPLE_ycbcr_422'); - GL_APPLE_texture_range := Int_CheckExtension(Buffer, 'GL_APPLE_texture_range'); - GL_APPLE_float_pixels := Int_CheckExtension(Buffer, 'GL_APPLE_float_pixels'); - GL_APPLE_vertex_program_evaluators := Int_CheckExtension(Buffer, 'GL_APPLE_vertex_program_evaluators'); - GL_APPLE_aux_depth_stencil := Int_CheckExtension(Buffer, 'GL_APPLE_aux_depth_stencil'); - GL_APPLE_object_purgeable := Int_CheckExtension(Buffer, 'GL_APPLE_object_purgeable'); - - // === ARB ===================================================================== - GL_ARB_depth_texture := Int_CheckExtension(Buffer, 'GL_ARB_depth_texture'); - GL_ARB_fragment_program := Int_CheckExtension(Buffer, 'GL_ARB_fragment_program'); - GL_ARB_imaging := Int_CheckExtension(Buffer, 'GL_ARB_imaging'); - GL_ARB_matrix_palette := Int_CheckExtension(Buffer, 'GL_ARB_matrix_palette'); - GL_ARB_multisample := Int_CheckExtension(Buffer, 'GL_ARB_multisample'); - GL_ARB_multitexture := Int_CheckExtension(Buffer, 'GL_ARB_multitexture'); - GL_ARB_point_parameters := Int_CheckExtension(Buffer, 'GL_ARB_point_parameters'); - GL_ARB_shadow := Int_CheckExtension(Buffer, 'GL_ARB_shadow'); - GL_ARB_shadow_ambient := Int_CheckExtension(Buffer, 'GL_ARB_shadow_ambient'); - GL_ARB_texture_border_clamp := Int_CheckExtension(Buffer, 'GL_ARB_texture_border_clamp'); - GL_ARB_texture_compression := Int_CheckExtension(Buffer, 'GL_ARB_texture_compression'); - GL_ARB_texture_cube_map := Int_CheckExtension(Buffer, 'GL_ARB_texture_cube_map'); - GL_ARB_texture_env_add := Int_CheckExtension(Buffer, 'GL_ARB_texture_env_add'); - GL_ARB_texture_env_combine := Int_CheckExtension(Buffer, 'GL_ARB_texture_env_combine'); - GL_ARB_texture_env_crossbar := Int_CheckExtension(Buffer, 'GL_ARB_texture_env_crossbar'); - GL_ARB_texture_env_dot3 := Int_CheckExtension(Buffer, 'GL_ARB_texture_env_dot3'); - GL_ARB_texture_mirrored_repeat := Int_CheckExtension(Buffer, 'GL_ARB_texture_mirrored_repeat'); - GL_ARB_transpose_matrix := Int_CheckExtension(Buffer, 'GL_ARB_transpose_matrix'); - GL_ARB_vertex_blend := Int_CheckExtension(Buffer, 'GL_ARB_vertex_blend'); - GL_ARB_vertex_buffer_object := Int_CheckExtension(Buffer, 'GL_ARB_vertex_buffer_object'); - GL_ARB_vertex_program := Int_CheckExtension(Buffer, 'GL_ARB_vertex_program'); - GL_ARB_window_pos := Int_CheckExtension(Buffer, 'GL_ARB_window_pos'); - GL_ARB_shader_objects := Int_CheckExtension(Buffer, 'GL_ARB_shader_objects'); - GL_ARB_vertex_shader := Int_CheckExtension(Buffer, 'GL_ARB_vertex_shader'); - GL_ARB_fragment_shader := Int_CheckExtension(Buffer, 'GL_ARB_fragment_shader'); - GL_ARB_occlusion_query := Int_CheckExtension(Buffer, 'GL_ARB_occlusion_query'); - GL_ARB_shading_language_100 := Int_CheckExtension(Buffer, 'GL_ARB_shading_language_100'); - GL_ARB_point_sprite := Int_CheckExtension(Buffer, 'GL_ARB_point_sprite'); - GL_ARB_texture_non_power_of_two := Int_CheckExtension(Buffer, 'GL_ARB_texture_non_power_of_two'); - GL_ARB_fragment_program_shadow := Int_CheckExtension(Buffer, 'GL_ARB_fragment_program_shadow'); - GL_ARB_draw_buffers := Int_CheckExtension(Buffer, 'GL_ARB_draw_buffers'); - GL_ARB_texture_rectangle := Int_CheckExtension(Buffer, 'GL_ARB_texture_rectangle'); - GL_ARB_color_buffer_float := Int_CheckExtension(Buffer, 'GL_ARB_color_buffer_float'); - GL_ARB_half_float_pixel := Int_CheckExtension(Buffer, 'GL_ARB_half_float_pixel'); - GL_ARB_texture_float := Int_CheckExtension(Buffer, 'GL_ARB_texture_float'); - GL_ARB_pixel_buffer_object := Int_CheckExtension(Buffer, 'GL_ARB_pixel_buffer_object'); - GL_ARB_depth_buffer_float := Int_CheckExtension(Buffer, 'GL_ARB_depth_buffer_float'); - GL_ARB_draw_instanced := Int_CheckExtension(Buffer, 'GL_ARB_draw_instanced'); - GL_ARB_framebuffer_object := Int_CheckExtension(Buffer, 'GL_ARB_framebuffer_object'); - GL_ARB_framebuffer_sRGB := Int_CheckExtension(Buffer, 'GL_ARB_framebuffer_sRGB'); - GL_ARB_geometry_shader4 := Int_CheckExtension(Buffer, 'GL_ARB_geometry_shader4'); - GL_ARB_half_float_vertex := Int_CheckExtension(Buffer, 'GL_ARB_half_float_vertex'); - GL_ARB_instanced_arrays := Int_CheckExtension(Buffer, 'GL_ARB_instanced_arrays'); - GL_ARB_map_buffer_range := Int_CheckExtension(Buffer, 'GL_ARB_map_buffer_range'); - GL_ARB_texture_buffer_object := Int_CheckExtension(Buffer, 'GL_ARB_texture_buffer_object'); - GL_ARB_texture_compression_rgtc := Int_CheckExtension(Buffer, 'GL_ARB_texture_compression_rgtc'); - GL_ARB_texture_rg := Int_CheckExtension(Buffer, 'GL_ARB_texture_rg'); - GL_ARB_vertex_array_object := Int_CheckExtension(Buffer, 'GL_ARB_vertex_array_object'); - GL_ARB_uniform_buffer_object := Int_CheckExtension(Buffer, 'GL_ARB_uniform_buffer_object'); - GL_ARB_compatibility := Int_CheckExtension(Buffer, 'GL_ARB_compatibility'); - GL_ARB_copy_buffer := Int_CheckExtension(Buffer, 'GL_ARB_copy_buffer'); - GL_ARB_shader_texture_lod := Int_CheckExtension(Buffer, 'GL_ARB_shader_texture_lod'); - GL_ARB_depth_clamp := Int_CheckExtension(Buffer, 'GL_ARB_depth_clamp'); - GL_ARB_draw_elements_base_vertex := Int_CheckExtension(Buffer, 'GL_ARB_draw_elements_base_vertex'); - GL_ARB_fragment_coord_conventions := Int_CheckExtension(Buffer, 'GL_ARB_fragment_coord_conventions'); - GL_ARB_provoking_vertex := Int_CheckExtension(Buffer, 'GL_ARB_provoking_vertex'); - GL_ARB_seamless_cube_map := Int_CheckExtension(Buffer, 'GL_ARB_seamless_cube_map'); - GL_ARB_sync := Int_CheckExtension(Buffer, 'GL_ARB_sync'); - GL_ARB_texture_multisample := Int_CheckExtension(Buffer, 'GL_ARB_texture_multisample'); - GL_ARB_vertex_array_bgra := Int_CheckExtension(Buffer, 'GL_ARB_vertex_array_bgra'); - GL_ARB_draw_buffers_blend := Int_CheckExtension(Buffer, 'GL_ARB_draw_buffers_blend'); - GL_ARB_sample_shading := Int_CheckExtension(Buffer, 'GL_ARB_sample_shading'); - GL_ARB_texture_cube_map_array := Int_CheckExtension(Buffer, 'GL_ARB_texture_cube_map_array'); - GL_ARB_texture_gather := Int_CheckExtension(Buffer, 'GL_ARB_texture_gather'); - GL_ARB_texture_query_lod := Int_CheckExtension(Buffer, 'GL_ARB_texture_query_lod'); - - // === ATI/AMD ================================================================= - GL_ATI_draw_buffers := Int_CheckExtension(Buffer, 'GL_ATI_draw_buffers'); - GL_ATI_element_array := Int_CheckExtension(Buffer, 'GL_ATI_element_array'); - GL_ATI_envmap_bumpmap := Int_CheckExtension(Buffer, 'GL_ATI_envmap_bumpmap'); - GL_ATI_fragment_shader := Int_CheckExtension(Buffer, 'GL_ATI_fragment_shader'); - GL_ATI_map_object_buffer := Int_CheckExtension(Buffer, 'GL_ATI_map_object_buffer'); - GL_ATI_pn_triangles := Int_CheckExtension(Buffer, 'GL_ATI_pn_triangles'); - GL_ATI_separate_stencil := Int_CheckExtension(Buffer, 'GL_ATI_separate_stencil'); - GL_ATI_text_fragment_shader := Int_CheckExtension(Buffer, 'GL_ATI_text_fragment_shader'); - GL_ATI_texture_env_combine3 := Int_CheckExtension(Buffer, 'GL_ATI_texture_env_combine3'); - GL_ATI_texture_float := Int_CheckExtension(Buffer, 'GL_ATI_texture_float'); - GL_ATI_texture_mirror_once := Int_CheckExtension(Buffer, 'GL_ATI_texture_mirror_once'); - GL_ATI_vertex_array_object := Int_CheckExtension(Buffer, 'GL_ATI_vertex_array_object'); - GL_ATI_vertex_attrib_array_object := Int_CheckExtension(Buffer, 'GL_ATI_vertex_attrib_array_object'); - GL_ATI_vertex_streams := Int_CheckExtension(Buffer, 'GL_ATI_vertex_streams'); - GL_ATI_meminfo := Int_CheckExtension(Buffer, 'GL_ATI_meminfo'); - GL_AMD_performance_monitor := Int_CheckExtension(Buffer, 'GL_AMD_performance_monitor'); - GL_AMD_texture_texture4 := Int_CheckExtension(Buffer, 'GL_AMD_texture_texture4'); - GL_AMD_vertex_shader_tesselator := Int_CheckExtension(Buffer, 'GL_AMD_vertex_shader_tesselator'); - - // === EXT ===================================================================== - GL_EXT_422_pixels := Int_CheckExtension(Buffer, 'GL_EXT_422_pixels'); - GL_EXT_abgr := Int_CheckExtension(Buffer, 'GL_EXT_abgr'); - GL_EXT_bgra := Int_CheckExtension(Buffer, 'GL_EXT_bgra'); - GL_EXT_blend_color := Int_CheckExtension(Buffer, 'GL_EXT_blend_color'); - GL_EXT_blend_func_separate := Int_CheckExtension(Buffer, 'GL_EXT_blend_func_separate'); - GL_EXT_blend_logic_op := Int_CheckExtension(Buffer, 'GL_EXT_blend_logic_op'); - GL_EXT_blend_minmax := Int_CheckExtension(Buffer, 'GL_EXT_blend_minmax'); - GL_EXT_blend_subtract := Int_CheckExtension(Buffer, 'GL_EXT_blend_subtract'); - GL_EXT_clip_volume_hint := Int_CheckExtension(Buffer, 'GL_EXT_clip_volume_hint'); - GL_EXT_cmyka := Int_CheckExtension(Buffer, 'GL_EXT_cmyka'); - GL_EXT_color_matrix := Int_CheckExtension(Buffer, 'GL_EXT_color_matrix'); - GL_EXT_color_subtable := Int_CheckExtension(Buffer, 'GL_EXT_color_subtable'); - GL_EXT_compiled_vertex_array := Int_CheckExtension(Buffer, 'GL_EXT_compiled_vertex_array'); - GL_EXT_convolution := Int_CheckExtension(Buffer, 'GL_EXT_convolution'); - GL_EXT_coordinate_frame := Int_CheckExtension(Buffer, 'GL_EXT_coordinate_frame'); - GL_EXT_copy_texture := Int_CheckExtension(Buffer, 'GL_EXT_copy_texture'); - GL_EXT_cull_vertex := Int_CheckExtension(Buffer, 'GL_EXT_cull_vertex'); - GL_EXT_draw_range_elements := Int_CheckExtension(Buffer, 'GL_EXT_draw_range_elements'); - GL_EXT_fog_coord := Int_CheckExtension(Buffer, 'GL_EXT_fog_coord'); - GL_EXT_framebuffer_object := Int_CheckExtension(Buffer, 'GL_EXT_framebuffer_object'); - GL_EXT_histogram := Int_CheckExtension(Buffer, 'GL_EXT_histogram'); - GL_EXT_index_array_formats := Int_CheckExtension(Buffer, 'GL_EXT_index_array_formats'); - GL_EXT_index_func := Int_CheckExtension(Buffer, 'GL_EXT_index_func'); - GL_EXT_index_material := Int_CheckExtension(Buffer, 'GL_EXT_index_material'); - GL_EXT_index_texture := Int_CheckExtension(Buffer, 'GL_EXT_index_texture'); - GL_EXT_light_texture := Int_CheckExtension(Buffer, 'GL_EXT_light_texture'); - GL_EXT_misc_attribute := Int_CheckExtension(Buffer, 'GL_EXT_misc_attribute'); - GL_EXT_multi_draw_arrays := Int_CheckExtension(Buffer, 'GL_EXT_multi_draw_arrays'); - GL_EXT_multisample := Int_CheckExtension(Buffer, 'GL_EXT_multisample'); - GL_EXT_packed_pixels := Int_CheckExtension(Buffer, 'GL_EXT_packed_pixels'); - GL_EXT_paletted_texture := Int_CheckExtension(Buffer, 'GL_EXT_paletted_texture'); - GL_EXT_pixel_transform := Int_CheckExtension(Buffer, 'GL_EXT_pixel_transform'); - GL_EXT_pixel_transform_color_table := Int_CheckExtension(Buffer, 'GL_EXT_pixel_transform_color_table'); - GL_EXT_point_parameters := Int_CheckExtension(Buffer, 'GL_EXT_point_parameters'); - GL_EXT_polygon_offset := Int_CheckExtension(Buffer, 'GL_EXT_polygon_offset'); - GL_EXT_rescale_normal := Int_CheckExtension(Buffer, 'GL_EXT_rescale_normal'); - GL_EXT_secondary_color := Int_CheckExtension(Buffer, 'GL_EXT_secondary_color'); - GL_EXT_separate_specular_color := Int_CheckExtension(Buffer, 'GL_EXT_separate_specular_color'); - GL_EXT_shadow_funcs := Int_CheckExtension(Buffer, 'GL_EXT_shadow_funcs'); - GL_EXT_shared_texture_palette := Int_CheckExtension(Buffer, 'GL_EXT_shared_texture_palette'); - GL_EXT_stencil_two_side := Int_CheckExtension(Buffer, 'GL_EXT_stencil_two_side'); - GL_EXT_stencil_wrap := Int_CheckExtension(Buffer, 'GL_EXT_stencil_wrap'); - GL_EXT_subtexture := Int_CheckExtension(Buffer, 'GL_EXT_subtexture'); - GL_EXT_texture := Int_CheckExtension(Buffer, 'GL_EXT_texture'); - GL_EXT_texture3D := Int_CheckExtension(Buffer, 'GL_EXT_texture3D'); - GL_EXT_texture_compression_s3tc := Int_CheckExtension(Buffer, 'GL_EXT_texture_compression_s3tc'); - GL_EXT_texture_cube_map := Int_CheckExtension(Buffer, 'GL_EXT_texture_cube_map'); - GL_EXT_texture_edge_clamp := Int_CheckExtension(Buffer, 'GL_EXT_texture_edge_clamp'); - GL_EXT_texture_env_add := Int_CheckExtension(Buffer, 'GL_EXT_texture_env_add'); - GL_EXT_texture_env_combine := Int_CheckExtension(Buffer, 'GL_EXT_texture_env_combine'); - GL_EXT_texture_env_dot3 := Int_CheckExtension(Buffer, 'GL_EXT_texture_env_dot3'); - GL_EXT_texture_filter_anisotropic := Int_CheckExtension(Buffer, 'GL_EXT_texture_filter_anisotropic'); - GL_EXT_texture_lod_bias := Int_CheckExtension(Buffer, 'GL_EXT_texture_lod_bias'); - GL_EXT_texture_object := Int_CheckExtension(Buffer, 'GL_EXT_texture_object'); - GL_EXT_texture_perturb_normal := Int_CheckExtension(Buffer, 'GL_EXT_texture_perturb_normal'); - GL_EXT_texture_rectangle := Int_CheckExtension(Buffer, 'GL_EXT_texture_rectangle'); - GL_EXT_vertex_array := Int_CheckExtension(Buffer, 'GL_EXT_vertex_array'); - GL_EXT_vertex_shader := Int_CheckExtension(Buffer, 'GL_EXT_vertex_shader'); - GL_EXT_vertex_weighting := Int_CheckExtension(Buffer, 'GL_EXT_vertex_weighting'); - GL_EXT_depth_bounds_test := Int_CheckExtension(Buffer, 'GL_EXT_depth_bounds_test'); - GL_EXT_texture_mirror_clamp := Int_CheckExtension(Buffer, 'GL_EXT_texture_mirror_clamp'); - GL_EXT_blend_equation_separate := Int_CheckExtension(Buffer, 'GL_EXT_blend_equation_separate'); - GL_EXT_pixel_buffer_object := Int_CheckExtension(Buffer, 'GL_EXT_pixel_buffer_object'); - GL_EXT_texture_compression_dxt1 := Int_CheckExtension(Buffer, 'GL_EXT_texture_compression_dxt1'); - GL_EXT_stencil_clear_tag := Int_CheckExtension(Buffer, 'GL_EXT_stencil_clear_tag'); - GL_EXT_packed_depth_stencil := Int_CheckExtension(Buffer, 'GL_EXT_packed_depth_stencil'); - GL_EXT_texture_sRGB := Int_CheckExtension(Buffer, 'GL_EXT_texture_sRGB'); - GL_EXT_framebuffer_blit := Int_CheckExtension(Buffer, 'GL_EXT_framebuffer_blit'); - GL_EXT_framebuffer_multisample := Int_CheckExtension(Buffer, 'GL_EXT_framebuffer_multisample'); - GL_EXT_timer_query := Int_CheckExtension(Buffer, 'GL_EXT_timer_query'); - GL_EXT_gpu_program_parameters := Int_CheckExtension(Buffer, 'GL_EXT_gpu_program_parameters'); - GL_EXT_bindable_uniform := Int_CheckExtension(Buffer, 'GL_EXT_bindable_uniform'); - GL_EXT_draw_buffers2 := Int_CheckExtension(Buffer, 'GL_EXT_draw_buffers2'); - GL_EXT_draw_instanced := Int_CheckExtension(Buffer, 'GL_EXT_draw_instanced'); - GL_EXT_framebuffer_sRGB := Int_CheckExtension(Buffer, 'GL_EXT_framebuffer_sRGB'); - GL_EXT_geometry_shader4 := Int_CheckExtension(Buffer, 'GL_EXT_geometry_shader4'); - GL_EXT_gpu_shader4 := Int_CheckExtension(Buffer, 'GL_EXT_gpu_shader4'); - GL_EXT_packed_float := Int_CheckExtension(Buffer, 'GL_EXT_packed_float'); - GL_EXT_texture_array := Int_CheckExtension(Buffer, 'GL_EXT_texture_array'); - GL_EXT_texture_buffer_object := Int_CheckExtension(Buffer, 'GL_EXT_texture_buffer_object'); - GL_EXT_texture_compression_latc := Int_CheckExtension(Buffer, 'GL_EXT_texture_compression_latc'); - GL_EXT_texture_compression_rgtc := Int_CheckExtension(Buffer, 'GL_EXT_texture_compression_rgtc'); - GL_EXT_texture_integer := Int_CheckExtension(Buffer, 'GL_EXT_texture_integer'); - GL_EXT_texture_shared_exponent := Int_CheckExtension(Buffer, 'GL_EXT_texture_shared_exponent'); - GL_EXT_transform_feedback := Int_CheckExtension(Buffer, 'GL_EXT_transform_feedback'); - GL_EXT_direct_state_access := Int_CheckExtension(Buffer, 'GL_EXT_direct_state_access'); - GL_EXT_vertex_array_bgra := Int_CheckExtension(Buffer, 'GL_EXT_vertex_array_bgra'); - GL_EXT_texture_swizzle := Int_CheckExtension(Buffer, 'GL_EXT_texture_swizzle'); - GL_EXT_provoking_vertex := Int_CheckExtension(Buffer, 'GL_EXT_provoking_vertex'); - - // === HP ====================================================================== - GL_HP_convolution_border_modes := Int_CheckExtension(Buffer, 'GL_HP_convolution_border_modes'); - GL_HP_image_transform := Int_CheckExtension(Buffer, 'GL_HP_image_transform'); - GL_HP_occlusion_test := Int_CheckExtension(Buffer, 'GL_HP_occlusion_test'); - GL_HP_texture_lighting := Int_CheckExtension(Buffer, 'GL_HP_texture_lighting'); - - // === IBM ===================================================================== - GL_IBM_cull_vertex := Int_CheckExtension(Buffer, 'GL_IBM_cull_vertex'); - GL_IBM_multimode_draw_arrays := Int_CheckExtension(Buffer, 'GL_IBM_multimode_draw_arrays'); - GL_IBM_rasterpos_clip := Int_CheckExtension(Buffer, 'GL_IBM_rasterpos_clip'); - GL_IBM_texture_mirrored_repeat := Int_CheckExtension(Buffer, 'GL_IBM_texture_mirrored_repeat'); - GL_IBM_vertex_array_lists := Int_CheckExtension(Buffer, 'GL_IBM_vertex_array_lists'); - - // === INGR ==================================================================== - GL_INGR_blend_func_separate := Int_CheckExtension(Buffer, 'GL_INGR_blend_func_separate'); - GL_INGR_color_clamp := Int_CheckExtension(Buffer, 'GL_INGR_color_clamp'); - GL_INGR_interlace_read := Int_CheckExtension(Buffer, 'GL_INGR_interlace_read'); - GL_INGR_palette_buffer := Int_CheckExtension(Buffer, 'GL_INGR_palette_buffer'); - - // === INTEL =================================================================== - GL_INTEL_parallel_arrays := Int_CheckExtension(Buffer, 'GL_INTEL_parallel_arrays'); - GL_INTEL_texture_scissor := Int_CheckExtension(Buffer, 'GL_INTEL_texture_scissor'); - - // === MESA ==================================================================== - GL_MESA_resize_buffers := Int_CheckExtension(Buffer, 'GL_MESA_resize_buffers'); - GL_MESA_window_pos := Int_CheckExtension(Buffer, 'GL_MESA_window_pos'); - - // === NVIDIA ================================================================== - GL_NV_blend_square := Int_CheckExtension(Buffer, 'GL_NV_blend_square'); - GL_NV_copy_depth_to_color := Int_CheckExtension(Buffer, 'GL_NV_copy_depth_to_color'); - GL_NV_depth_clamp := Int_CheckExtension(Buffer, 'GL_NV_depth_clamp'); - GL_NV_evaluators := Int_CheckExtension(Buffer, 'GL_NV_evaluators'); - GL_NV_fence := Int_CheckExtension(Buffer, 'GL_NV_fence'); - GL_NV_float_buffer := Int_CheckExtension(Buffer, 'GL_NV_float_buffer'); - GL_NV_fog_distance := Int_CheckExtension(Buffer, 'GL_NV_fog_distance'); - GL_NV_fragment_program := Int_CheckExtension(Buffer, 'GL_NV_fragment_program'); - GL_NV_half_float := Int_CheckExtension(Buffer, 'GL_NV_half_float'); - GL_NV_light_max_exponent := Int_CheckExtension(Buffer, 'GL_NV_light_max_exponent'); - GL_NV_multisample_filter_hint := Int_CheckExtension(Buffer, 'GL_NV_multisample_filter_hint'); - GL_NV_occlusion_query := Int_CheckExtension(Buffer, 'GL_NV_occlusion_query'); - GL_NV_packed_depth_stencil := Int_CheckExtension(Buffer, 'GL_NV_packed_depth_stencil'); - GL_NV_pixel_data_range := Int_CheckExtension(Buffer, 'GL_NV_pixel_data_range'); - GL_NV_point_sprite := Int_CheckExtension(Buffer, 'GL_NV_point_sprite'); - GL_NV_primitive_restart := Int_CheckExtension(Buffer, 'GL_NV_primitive_restart'); - GL_NV_register_combiners := Int_CheckExtension(Buffer, 'GL_NV_register_combiners'); - GL_NV_register_combiners2 := Int_CheckExtension(Buffer, 'GL_NV_register_combiners2'); - GL_NV_texgen_emboss := Int_CheckExtension(Buffer, 'GL_NV_texgen_emboss'); - GL_NV_texgen_reflection := Int_CheckExtension(Buffer, 'GL_NV_texgen_reflection'); - GL_NV_texture_compression_vtc := Int_CheckExtension(Buffer, 'GL_NV_texture_compression_vtc'); - GL_NV_texture_env_combine4 := Int_CheckExtension(Buffer, 'GL_NV_texture_env_combine4'); - GL_NV_texture_expand_normal := Int_CheckExtension(Buffer, 'GL_NV_texture_expand_normal'); - GL_NV_texture_rectangle := Int_CheckExtension(Buffer, 'GL_NV_texture_rectangle'); - GL_NV_texture_shader := Int_CheckExtension(Buffer, 'GL_NV_texture_shader'); - GL_NV_texture_shader2 := Int_CheckExtension(Buffer, 'GL_NV_texture_shader2'); - GL_NV_texture_shader3 := Int_CheckExtension(Buffer, 'GL_NV_texture_shader3'); - GL_NV_vertex_array_range := Int_CheckExtension(Buffer, 'GL_NV_vertex_array_range'); - GL_NV_vertex_array_range2 := Int_CheckExtension(Buffer, 'GL_NV_vertex_array_range2'); - GL_NV_vertex_program := Int_CheckExtension(Buffer, 'GL_NV_vertex_program'); - GL_NV_vertex_program1_1 := Int_CheckExtension(Buffer, 'GL_NV_vertex_program1_1'); - GL_NV_vertex_program2 := Int_CheckExtension(Buffer, 'GL_NV_vertex_program2'); - GL_NV_fragment_program_option := Int_CheckExtension(Buffer, 'GL_NV_fragment_program_option'); - GL_NV_fragment_program2 := Int_CheckExtension(Buffer, 'GL_NV_fragment_program2'); - GL_NV_vertex_program2_option := Int_CheckExtension(Buffer, 'GL_NV_vertex_program2_option'); - GL_NV_vertex_program3 := Int_CheckExtension(Buffer, 'GL_NV_vertex_program3'); - GL_NV_depth_buffer_float := Int_CheckExtension(Buffer, 'GL_NV_depth_buffer_float'); - GL_NV_fragment_program4 := Int_CheckExtension(Buffer, 'GL_NV_fragment_program4'); - GL_NV_framebuffer_multisample_coverage := Int_CheckExtension(Buffer, 'GL_NV_framebuffer_multisample_coverage'); - GL_NV_geometry_program4 := Int_CheckExtension(Buffer, 'GL_NV_geometry_program4'); - GL_NV_gpu_program4 := Int_CheckExtension(Buffer, 'GL_NV_gpu_program4'); - GL_NV_parameter_buffer_object := Int_CheckExtension(Buffer, 'GL_NV_parameter_buffer_object'); - GL_NV_transform_feedback := Int_CheckExtension(Buffer, 'GL_NV_transform_feedback'); - GL_NV_vertex_program4 := Int_CheckExtension(Buffer, 'GL_NV_vertex_program4'); - GL_NV_conditional_render := Int_CheckExtension(Buffer, 'GL_NV_conditional_render'); - GL_NV_present_video := Int_CheckExtension(Buffer, 'GL_NV_present_video'); - GL_NV_explicit_multisample := Int_CheckExtension(Buffer, 'GL_NV_explicit_multisample'); - GL_NV_transform_feedback2 := Int_CheckExtension(Buffer, 'GL_NV_transform_feedback2'); - - // === OML ===================================================================== - GL_OML_interlace := Int_CheckExtension(Buffer, 'GL_OML_interlace'); - GL_OML_resample := Int_CheckExtension(Buffer, 'GL_OML_resample'); - GL_OML_subsample := Int_CheckExtension(Buffer, 'GL_OML_subsample'); - - // === PGI ===================================================================== - GL_PGI_misc_hints := Int_CheckExtension(Buffer, 'GL_PGI_misc_hints'); - GL_PGI_vertex_hints := Int_CheckExtension(Buffer, 'GL_PGI_vertex_hints'); - - // === REND ==================================================================== - GL_REND_screen_coordinates := Int_CheckExtension(Buffer, 'GL_REND_screen_coordinates'); - - // === S3 ====================================================================== - GL_S3_s3tc := Int_CheckExtension(Buffer, 'GL_S3_s3tc'); - - // === SGIS ==================================================================== - GL_SGIS_detail_texture := Int_CheckExtension(Buffer, 'GL_SGIS_detail_texture'); - GL_SGIS_fog_function := Int_CheckExtension(Buffer, 'GL_SGIS_fog_function'); - GL_SGIS_generate_mipmap := Int_CheckExtension(Buffer, 'GL_SGIS_generate_mipmap'); - GL_SGIS_multisample := Int_CheckExtension(Buffer, 'GL_SGIS_multisample'); - GL_SGIS_pixel_texture := Int_CheckExtension(Buffer, 'GL_SGIS_pixel_texture'); - GL_SGIS_point_line_texgen := Int_CheckExtension(Buffer, 'GL_SGIS_point_line_texgen'); - GL_SGIS_point_parameters := Int_CheckExtension(Buffer, 'GL_SGIS_point_parameters'); - GL_SGIS_sharpen_texture := Int_CheckExtension(Buffer, 'GL_SGIS_sharpen_texture'); - GL_SGIS_texture4D := Int_CheckExtension(Buffer, 'GL_SGIS_texture4D'); - GL_SGIS_texture_border_clamp := Int_CheckExtension(Buffer, 'GL_SGIS_texture_border_clamp'); - GL_SGIS_texture_color_mask := Int_CheckExtension(Buffer, 'GL_SGIS_texture_color_mask'); - GL_SGIS_texture_edge_clamp := Int_CheckExtension(Buffer, 'GL_SGIS_texture_edge_clamp'); - GL_SGIS_texture_filter4 := Int_CheckExtension(Buffer, 'GL_SGIS_texture_filter4'); - GL_SGIS_texture_lod := Int_CheckExtension(Buffer, 'GL_SGIS_texture_lod'); - GL_SGIS_texture_select := Int_CheckExtension(Buffer, 'GL_SGIS_texture_select'); - - // === SGIX ==================================================================== - GL_FfdMaskSGIX := Int_CheckExtension(Buffer, 'GL_FfdMaskSGIX'); - GL_SGIX_async := Int_CheckExtension(Buffer, 'GL_SGIX_async'); - GL_SGIX_async_histogram := Int_CheckExtension(Buffer, 'GL_SGIX_async_histogram'); - GL_SGIX_async_pixel := Int_CheckExtension(Buffer, 'GL_SGIX_async_pixel'); - GL_SGIX_blend_alpha_minmax := Int_CheckExtension(Buffer, 'GL_SGIX_blend_alpha_minmax'); - GL_SGIX_calligraphic_fragment := Int_CheckExtension(Buffer, 'GL_SGIX_calligraphic_fragment'); - GL_SGIX_clipmap := Int_CheckExtension(Buffer, 'GL_SGIX_clipmap'); - GL_SGIX_convolution_accuracy := Int_CheckExtension(Buffer, 'GL_SGIX_convolution_accuracy'); - GL_SGIX_depth_pass_instrument := Int_CheckExtension(Buffer, 'GL_SGIX_depth_pass_instrument'); - GL_SGIX_depth_texture := Int_CheckExtension(Buffer, 'GL_SGIX_depth_texture'); - GL_SGIX_flush_raster := Int_CheckExtension(Buffer, 'GL_SGIX_flush_raster'); - GL_SGIX_fog_offset := Int_CheckExtension(Buffer, 'GL_SGIX_fog_offset'); - GL_SGIX_fog_scale := Int_CheckExtension(Buffer, 'GL_SGIX_fog_scale'); - GL_SGIX_fragment_lighting := Int_CheckExtension(Buffer, 'GL_SGIX_fragment_lighting'); - GL_SGIX_framezoom := Int_CheckExtension(Buffer, 'GL_SGIX_framezoom'); - GL_SGIX_igloo_interface := Int_CheckExtension(Buffer, 'GL_SGIX_igloo_interface'); - GL_SGIX_impact_pixel_texture := Int_CheckExtension(Buffer, 'GL_SGIX_impact_pixel_texture'); - GL_SGIX_instruments := Int_CheckExtension(Buffer, 'GL_SGIX_instruments'); - GL_SGIX_interlace := Int_CheckExtension(Buffer, 'GL_SGIX_interlace'); - GL_SGIX_ir_instrument1 := Int_CheckExtension(Buffer, 'GL_SGIX_ir_instrument1'); - GL_SGIX_list_priority := Int_CheckExtension(Buffer, 'GL_SGIX_list_priority'); - GL_SGIX_pixel_texture := Int_CheckExtension(Buffer, 'GL_SGIX_pixel_texture'); - GL_SGIX_pixel_tiles := Int_CheckExtension(Buffer, 'GL_SGIX_pixel_tiles'); - GL_SGIX_polynomial_ffd := Int_CheckExtension(Buffer, 'GL_SGIX_polynomial_ffd'); - GL_SGIX_reference_plane := Int_CheckExtension(Buffer, 'GL_SGIX_reference_plane'); - GL_SGIX_resample := Int_CheckExtension(Buffer, 'GL_SGIX_resample'); - GL_SGIX_scalebias_hint := Int_CheckExtension(Buffer, 'GL_SGIX_scalebias_hint'); - GL_SGIX_shadow := Int_CheckExtension(Buffer, 'GL_SGIX_shadow'); - GL_SGIX_shadow_ambient := Int_CheckExtension(Buffer, 'GL_SGIX_shadow_ambient'); - GL_SGIX_sprite := Int_CheckExtension(Buffer, 'GL_SGIX_sprite'); - GL_SGIX_subsample := Int_CheckExtension(Buffer, 'GL_SGIX_subsample'); - GL_SGIX_tag_sample_buffer := Int_CheckExtension(Buffer, 'GL_SGIX_tag_sample_buffer'); - GL_SGIX_texture_add_env := Int_CheckExtension(Buffer, 'GL_SGIX_texture_add_env'); - GL_SGIX_texture_coordinate_clamp := Int_CheckExtension(Buffer, 'GL_SGIX_texture_coordinate_clamp'); - GL_SGIX_texture_lod_bias := Int_CheckExtension(Buffer, 'GL_SGIX_texture_lod_bias'); - GL_SGIX_texture_multi_buffer := Int_CheckExtension(Buffer, 'GL_SGIX_texture_multi_buffer'); - GL_SGIX_texture_scale_bias := Int_CheckExtension(Buffer, 'GL_SGIX_texture_scale_bias'); - GL_SGIX_texture_select := Int_CheckExtension(Buffer, 'GL_SGIX_texture_select'); - GL_SGIX_vertex_preclip := Int_CheckExtension(Buffer, 'GL_SGIX_vertex_preclip'); - GL_SGIX_ycrcb := Int_CheckExtension(Buffer, 'GL_SGIX_ycrcb'); - GL_SGIX_ycrcb_subsample := Int_CheckExtension(Buffer, 'GL_SGIX_ycrcb_subsample'); - GL_SGIX_ycrcba := Int_CheckExtension(Buffer, 'GL_SGIX_ycrcba'); - - // === SGI ===================================================================== - GL_SGI_color_matrix := Int_CheckExtension(Buffer, 'GL_SGI_color_matrix'); - GL_SGI_color_table := Int_CheckExtension(Buffer, 'GL_SGI_color_table'); - GL_SGI_depth_pass_instrument := Int_CheckExtension(Buffer, 'GL_SGI_depth_pass_instrument'); - GL_SGI_texture_color_table := Int_CheckExtension(Buffer, 'GL_SGI_texture_color_table'); - - // === SUN ===================================================================== - GL_SUNX_constant_data := Int_CheckExtension(Buffer, 'GL_SUNX_constant_data'); - GL_SUN_convolution_border_modes := Int_CheckExtension(Buffer, 'GL_SUN_convolution_border_modes'); - GL_SUN_global_alpha := Int_CheckExtension(Buffer, 'GL_SUN_global_alpha'); - GL_SUN_mesh_array := Int_CheckExtension(Buffer, 'GL_SUN_mesh_array'); - GL_SUN_slice_accum := Int_CheckExtension(Buffer, 'GL_SUN_slice_accum'); - GL_SUN_triangle_list := Int_CheckExtension(Buffer, 'GL_SUN_triangle_list'); - GL_SUN_vertex := Int_CheckExtension(Buffer, 'GL_SUN_vertex'); - - // === WIN ===================================================================== - GL_WIN_phong_shading := Int_CheckExtension(Buffer, 'GL_WIN_phong_shading'); - GL_WIN_specular_fog := Int_CheckExtension(Buffer, 'GL_WIN_specular_fog'); - - {$IFDEF DGL_WIN} - // === WGL ===================================================================== - WGL_3DFX_multisample := Int_CheckExtension(Buffer, 'WGL_3DFX_multisample'); - WGL_ARB_buffer_region := Int_CheckExtension(Buffer, 'WGL_ARB_buffer_region'); - WGL_ARB_extensions_string := Int_CheckExtension(Buffer, 'WGL_ARB_extensions_string'); - WGL_ARB_make_current_read := Int_CheckExtension(Buffer, 'WGL_ARB_make_current_read'); - WGL_ARB_multisample := Int_CheckExtension(Buffer, 'WGL_ARB_multisample'); - WGL_ARB_pbuffer := Int_CheckExtension(Buffer, 'WGL_ARB_pbuffer'); - WGL_ARB_pixel_format := Int_CheckExtension(Buffer, 'WGL_ARB_pixel_format'); - WGL_ARB_pixel_format_float := Int_CheckExtension(Buffer, 'WGL_ARB_pixel_format_float'); - WGL_ARB_render_texture := Int_CheckExtension(Buffer, 'WGL_ARB_render_texture'); - WGL_ARB_create_context := Int_CheckExtension(Buffer, 'WGL_ARB_create_context'); - WGL_ARB_create_context_profile := Int_CheckExtension(Buffer, 'WGL_ARB_create_context_profile'); - WGL_ATI_pixel_format_float := Int_CheckExtension(Buffer, 'WGL_ATI_pixel_format_float'); - WGL_AMD_gpu_association := Int_CheckExtension(Buffer, 'WGL_AMD_gpu_association'); - WGL_EXT_depth_float := Int_CheckExtension(Buffer, 'WGL_EXT_depth_float'); - WGL_EXT_display_color_table := Int_CheckExtension(Buffer, 'WGL_EXT_display_color_table'); - WGL_EXT_extensions_string := Int_CheckExtension(Buffer, 'WGL_EXT_extensions_string'); - WGL_EXT_make_current_read := Int_CheckExtension(Buffer, 'WGL_EXT_make_current_read'); - WGL_EXT_multisample := Int_CheckExtension(Buffer, 'WGL_EXT_multisample'); - WGL_EXT_pbuffer := Int_CheckExtension(Buffer, 'WGL_EXT_pbuffer'); - WGL_EXT_pixel_format := Int_CheckExtension(Buffer, 'WGL_EXT_pixel_format'); - WGL_EXT_swap_control := Int_CheckExtension(Buffer, 'WGL_EXT_swap_control'); - WGL_I3D_digital_video_control := Int_CheckExtension(Buffer, 'WGL_I3D_digital_video_control'); - WGL_I3D_gamma := Int_CheckExtension(Buffer, 'WGL_I3D_gamma'); - WGL_I3D_genlock := Int_CheckExtension(Buffer, 'WGL_I3D_genlock'); - WGL_I3D_image_buffer := Int_CheckExtension(Buffer, 'WGL_I3D_image_buffer'); - WGL_I3D_swap_frame_lock := Int_CheckExtension(Buffer, 'WGL_I3D_swap_frame_lock'); - WGL_I3D_swap_frame_usage := Int_CheckExtension(Buffer, 'WGL_I3D_swap_frame_usage'); - WGL_NV_float_buffer := Int_CheckExtension(Buffer, 'WGL_NV_float_buffer'); - WGL_NV_render_depth_texture := Int_CheckExtension(Buffer, 'WGL_NV_render_depth_texture'); - WGL_NV_render_texture_rectangle := Int_CheckExtension(Buffer, 'WGL_NV_render_texture_rectangle'); - WGL_NV_vertex_array_range := Int_CheckExtension(Buffer, 'WGL_NV_vertex_array_range'); - WGL_NV_present_video := Int_CheckExtension(Buffer, 'WGL_NV_present_video'); - WGL_NV_video_out := Int_CheckExtension(Buffer, 'WGL_NV_video_out'); - WGL_NV_swap_group := Int_CheckExtension(Buffer, 'WGL_NV_swap_group'); - WGL_NV_gpu_affinity := Int_CheckExtension(Buffer, 'WGL_NV_gpu_affinity'); - WGL_OML_sync_control := Int_CheckExtension(Buffer, 'WGL_OML_sync_control'); - WGL_3DL_stereo_control := Int_CheckExtension(Buffer, 'WGL_3DL_stereo_control'); - - WIN_draw_range_elements := Int_CheckExtension(Buffer, 'WIN_draw_range_elements'); - WIN_swap_hint := Int_CheckExtension(Buffer, 'WIN_swap_hint'); - {$ENDIF} - - {$IFDEF DGL_LINUX} - // === GLX ===================================================================== - GLX_ARB_multisample := Int_CheckExtension(Buffer, 'GLX_ARB_multisample'); - GLX_ARB_fbconfig_float := Int_CheckExtension(Buffer, 'GLX_ARB_fbconfig_float'); - GLX_ARB_get_proc_address := Int_CheckExtension(Buffer, 'GLX_ARB_get_proc_address'); - GLX_ARB_create_context := Int_CheckExtension(Buffer, 'GLX_ARB_create_context'); - GLX_ARB_create_context_profile := Int_CheckExtension(Buffer, 'GLX_ARB_create_context_profile'); - GLX_EXT_visual_info := Int_CheckExtension(Buffer, 'GLX_EXT_visual_info'); - GLX_EXT_visual_rating := Int_CheckExtension(Buffer, 'GLX_EXT_visual_rating'); - GLX_EXT_import_context := Int_CheckExtension(Buffer, 'GLX_EXT_import_context'); - GLX_EXT_fbconfig_packed_float := Int_CheckExtension(Buffer, 'GLX_EXT_fbconfig_packed_float'); - GLX_EXT_framebuffer_sRGB := Int_CheckExtension(Buffer, 'GLX_EXT_framebuffer_sRGB'); - GLX_EXT_texture_from_pixmap := Int_CheckExtension(Buffer, 'GLX_EXT_texture_from_pixmap'); - {$ENDIF} - ImplementationRead := True; -end; - -{$IFDEF DGL_WIN} -// ============================================================================= -// RaiseLastOSError -// ============================================================================= -// Needed for compatibility with older Delphiversions -// ============================================================================= - -procedure RaiseLastOSError; -begin -{$IFDEF FPC} - raise Exception.Create('RaiseLastOSError!'); // To-Do: find a better solution -{$ELSE} - {$IFDEF DELPHI6_AND_DOWN} // If Delphi 6 or later - SysUtils.RaiseLastWin32Error; - {$ELSE} - SysUtils.RaiseLastOSError; - {$ENDIF} -{$ENDIF} -end; - -// ============================================================================= -// CreateRenderingContext -// ============================================================================= - -function CreateRenderingContext(DC: HDC; Options: TRCOptions; ColorBits, ZBits, StencilBits, AccumBits, AuxBuffers: Integer; Layer: Integer): HGLRC; -const - OBJ_MEMDC = 10; - OBJ_ENHMETADC = 12; - OBJ_METADC = 4; - PFD_DOUBLEBUFFER = $00000001; - PFD_STEREO = $00000002; - PFD_DRAW_TO_WINDOW = $00000004; - PFD_DRAW_TO_BITMAP = $00000008; - PFD_SUPPORT_GDI = $00000010; - PFD_SUPPORT_OPENGL = $00000020; - PFD_TYPE_RGBA = 0; - PFD_MAIN_PLANE = 0; - PFD_OVERLAY_PLANE = 1; - PFD_UNDERLAY_PLANE = LongWord(-1); - MemoryDCs = [OBJ_MEMDC, OBJ_METADC, OBJ_ENHMETADC]; -var - PFDescriptor: TPixelFormatDescriptor; - PixelFormat: Integer; - AType: DWORD; -begin - if GL_LibHandle = nil then - InitOpenGL; - - FillChar(PFDescriptor, SizeOf(PFDescriptor), 0); - - with PFDescriptor do - begin - nSize := SizeOf(PFDescriptor); - nVersion := 1; - dwFlags := PFD_SUPPORT_OPENGL; - - AType := GetObjectType(DC); - - if AType = 0 then - RaiseLastOSError; - - if AType in MemoryDCs then - dwFlags := dwFlags or PFD_DRAW_TO_BITMAP - else - dwFlags := dwFlags or PFD_DRAW_TO_WINDOW; - - if opDoubleBuffered in Options then - dwFlags := dwFlags or PFD_DOUBLEBUFFER; - - if opGDI in Options then - dwFlags := dwFlags or PFD_SUPPORT_GDI; - - if opStereo in Options then - dwFlags := dwFlags or PFD_STEREO; - - iPixelType := PFD_TYPE_RGBA; - cColorBits := ColorBits; - cDepthBits := zBits; - cStencilBits := StencilBits; - cAccumBits := AccumBits; - cAuxBuffers := AuxBuffers; - - if Layer = 0 then - iLayerType := PFD_MAIN_PLANE - else - if Layer > 0 then - iLayerType := PFD_OVERLAY_PLANE - else - iLayerType := Byte(PFD_UNDERLAY_PLANE); - end; - - PixelFormat := ChoosePixelFormat(DC, @PFDescriptor); - - if PixelFormat = 0 then - RaiseLastOSError; - - if GetPixelFormat(DC) <> PixelFormat then - if not SetPixelFormat(DC, PixelFormat, @PFDescriptor) then - RaiseLastOSError; - - DescribePixelFormat(DC, PixelFormat, SizeOf(PFDescriptor), PFDescriptor); - - Result := wglCreateContext(DC); - - if Result = 0 then - RaiseLastOSError - else - LastPixelFormat := 0; -end; - -// ============================================================================= -// DestroyRenderingContext -// ============================================================================= - -procedure DestroyRenderingContext(RC: HGLRC); -begin - wglDeleteContext(RC); -end; - - -// ============================================================================= -// ActivateRenderingContext -// ============================================================================= - -procedure ActivateRenderingContext(DC: HDC; RC: HGLRC; loadext: boolean = true); -begin - Assert((DC <> 0), 'DC must not be 0'); - Assert((RC <> 0), 'RC must not be 0'); - - wglMakeCurrent(DC, RC); - - {$ifdef DGL_TINY_HEADER} - ReadCoreVersion; - {$else} - ReadImplementationProperties; - - if (loadext) then - ReadExtensions; - {$endif} -end; - -// ============================================================================= -// DeactivateRenderingContext -// ============================================================================= - -procedure DeactivateRenderingContext; -begin - wglMakeCurrent(0, 0); -end; -{$ENDIF} - - -initialization - -{$IFDEF CPU386} - Set8087CW($133F); -{$ENDIF} - -finalization - -end. - diff --git a/src/lib/dgl/glExt.pas b/src/lib/dgl/glExt.pas deleted file mode 100644 index 462db17..0000000 --- a/src/lib/dgl/glExt.pas +++ /dev/null @@ -1,9483 +0,0 @@ -unit GLext; - -(************************************************** - * OpenGL extension loading library * - * Generated by MetaGLext, written by Tom Nuydens * - * (tom@delphi3d.net -- http://www.delphi3d.net * - **************************************************) - -//*** Generated on 2/22/2005 - -interface - -uses - Windows, SysUtils, GL; - -// Not present in Windows.pas. -function wglGetProcAddress(proc: PChar): Pointer; stdcall; external 'OpenGL32.dll'; - -// Test if the given extension name is present in the given extension string. -function glext_ExtensionSupported(const extension: String; const searchIn: String): Boolean; - -// Load the extension with the given name. -function glext_LoadExtension(ext: String): Boolean; - -// Some types that were introduced by extensions: -type - GLintptrARB = Integer; - PGLintptrARB = ^GLintptrARB; - - GLsizeiptrARB = Integer; - PGLsizeiptrARB = ^GLsizeiptrARB; - - GLcharARB = Char; - PGLcharARB = ^GLcharARB; - - GLhandleARB = Cardinal; - PGLhandleARB = ^GLhandleARB; - - GLintptr = Integer; - PGLintptr = ^GLintptr; - - GLsizeiptr = Integer; - PGLsizeiptr = ^GLsizeiptr; - - GLchar = Char; - PGLchar = ^GLchar; - -//***** GL_version_1_2 *****// -const - GL_UNSIGNED_BYTE_3_3_2 = $8032; - GL_UNSIGNED_SHORT_4_4_4_4 = $8033; - GL_UNSIGNED_SHORT_5_5_5_1 = $8034; - GL_UNSIGNED_INT_8_8_8_8 = $8035; - GL_UNSIGNED_INT_10_10_10_2 = $8036; - GL_RESCALE_NORMAL = $803A; - GL_UNSIGNED_BYTE_2_3_3_REV = $8362; - GL_UNSIGNED_SHORT_5_6_5 = $8363; - GL_UNSIGNED_SHORT_5_6_5_REV = $8364; - GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365; - GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366; - GL_UNSIGNED_INT_8_8_8_8_REV = $8367; - GL_UNSIGNED_INT_2_10_10_10_REV = $8368; - GL_BGR = $80E0; - GL_BGRA = $80E1; - GL_MAX_ELEMENTS_VERTICES = $80E8; - GL_MAX_ELEMENTS_INDICES = $80E9; - GL_CLAMP_TO_EDGE = $812F; - GL_TEXTURE_MIN_LOD = $813A; - GL_TEXTURE_MAX_LOD = $813B; - GL_TEXTURE_BASE_LEVEL = $813C; - GL_TEXTURE_MAX_LEVEL = $813D; - GL_LIGHT_MODEL_COLOR_CONTROL = $81F8; - GL_SINGLE_COLOR = $81F9; - GL_SEPARATE_SPECULAR_COLOR = $81FA; - GL_SMOOTH_POINT_SIZE_RANGE = $0B12; - GL_SMOOTH_POINT_SIZE_GRANULARITY = $0B13; - GL_SMOOTH_LINE_WIDTH_RANGE = $0B22; - GL_SMOOTH_LINE_WIDTH_GRANULARITY = $0B23; - GL_ALIASED_POINT_SIZE_RANGE = $846D; - GL_ALIASED_LINE_WIDTH_RANGE = $846E; - GL_PACK_SKIP_IMAGES = $806B; - GL_PACK_IMAGE_HEIGHT = $806C; - GL_UNPACK_SKIP_IMAGES = $806D; - GL_UNPACK_IMAGE_HEIGHT = $806E; - GL_TEXTURE_3D = $806F; - GL_PROXY_TEXTURE_3D = $8070; - GL_TEXTURE_DEPTH = $8071; - GL_TEXTURE_WRAP_R = $8072; - GL_MAX_3D_TEXTURE_SIZE = $8073; -var - glDrawRangeElements: procedure(mode: GLenum; start: GLuint; _end: GLuint; count: GLsizei; _type: GLenum; const indices: PGLvoid); stdcall = nil; - glTexImage3D: procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); stdcall = nil; - glTexSubImage3D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); stdcall = nil; - glCopyTexSubImage3D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; x: GLint; y: GLint; width: GLsizei; height: GLsizei); stdcall = nil; - -function Load_GL_version_1_2: Boolean; - -//***** GL_ARB_imaging *****// -const - GL_CONSTANT_COLOR = $8001; - GL_ONE_MINUS_CONSTANT_COLOR = $8002; - GL_CONSTANT_ALPHA = $8003; - GL_ONE_MINUS_CONSTANT_ALPHA = $8004; - GL_BLEND_COLOR = $8005; - GL_FUNC_ADD = $8006; - GL_MIN = $8007; - GL_MAX = $8008; - GL_BLEND_EQUATION = $8009; - GL_FUNC_SUBTRACT = $800A; - GL_FUNC_REVERSE_SUBTRACT = $800B; - GL_CONVOLUTION_1D = $8010; - GL_CONVOLUTION_2D = $8011; - GL_SEPARABLE_2D = $8012; - GL_CONVOLUTION_BORDER_MODE = $8013; - GL_CONVOLUTION_FILTER_SCALE = $8014; - GL_CONVOLUTION_FILTER_BIAS = $8015; - GL_REDUCE = $8016; - GL_CONVOLUTION_FORMAT = $8017; - GL_CONVOLUTION_WIDTH = $8018; - GL_CONVOLUTION_HEIGHT = $8019; - GL_MAX_CONVOLUTION_WIDTH = $801A; - GL_MAX_CONVOLUTION_HEIGHT = $801B; - GL_POST_CONVOLUTION_RED_SCALE = $801C; - GL_POST_CONVOLUTION_GREEN_SCALE = $801D; - GL_POST_CONVOLUTION_BLUE_SCALE = $801E; - GL_POST_CONVOLUTION_ALPHA_SCALE = $801F; - GL_POST_CONVOLUTION_RED_BIAS = $8020; - GL_POST_CONVOLUTION_GREEN_BIAS = $8021; - GL_POST_CONVOLUTION_BLUE_BIAS = $8022; - GL_POST_CONVOLUTION_ALPHA_BIAS = $8023; - GL_HISTOGRAM = $8024; - GL_PROXY_HISTOGRAM = $8025; - GL_HISTOGRAM_WIDTH = $8026; - GL_HISTOGRAM_FORMAT = $8027; - GL_HISTOGRAM_RED_SIZE = $8028; - GL_HISTOGRAM_GREEN_SIZE = $8029; - GL_HISTOGRAM_BLUE_SIZE = $802A; - GL_HISTOGRAM_ALPHA_SIZE = $802B; - GL_HISTOGRAM_LUMINANCE_SIZE = $802C; - GL_HISTOGRAM_SINK = $802D; - GL_MINMAX = $802E; - GL_MINMAX_FORMAT = $802F; - GL_MINMAX_SINK = $8030; - GL_TABLE_TOO_LARGE = $8031; - GL_COLOR_MATRIX = $80B1; - GL_COLOR_MATRIX_STACK_DEPTH = $80B2; - GL_MAX_COLOR_MATRIX_STACK_DEPTH = $80B3; - GL_POST_COLOR_MATRIX_RED_SCALE = $80B4; - GL_POST_COLOR_MATRIX_GREEN_SCALE = $80B5; - GL_POST_COLOR_MATRIX_BLUE_SCALE = $80B6; - GL_POST_COLOR_MATRIX_ALPHA_SCALE = $80B7; - GL_POST_COLOR_MATRIX_RED_BIAS = $80B8; - GL_POST_COLOR_MATRIX_GREEN_BIAS = $80B9; - GL_POST_COLOR_MATRIX_BLUE_BIAS = $80BA; - GL_POST_COLOR_MATIX_ALPHA_BIAS = $80BB; - GL_COLOR_TABLE = $80D0; - GL_POST_CONVOLUTION_COLOR_TABLE = $80D1; - GL_POST_COLOR_MATRIX_COLOR_TABLE = $80D2; - GL_PROXY_COLOR_TABLE = $80D3; - GL_PROXY_POST_CONVOLUTION_COLOR_TABLE = $80D4; - GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE = $80D5; - GL_COLOR_TABLE_SCALE = $80D6; - GL_COLOR_TABLE_BIAS = $80D7; - GL_COLOR_TABLE_FORMAT = $80D8; - GL_COLOR_TABLE_WIDTH = $80D9; - GL_COLOR_TABLE_RED_SIZE = $80DA; - GL_COLOR_TABLE_GREEN_SIZE = $80DB; - GL_COLOR_TABLE_BLUE_SIZE = $80DC; - GL_COLOR_TABLE_ALPHA_SIZE = $80DD; - GL_COLOR_TABLE_LUMINANCE_SIZE = $80DE; - GL_COLOR_TABLE_INTENSITY_SIZE = $80DF; - GL_IGNORE_BORDER = $8150; - GL_CONSTANT_BORDER = $8151; - GL_WRAP_BORDER = $8152; - GL_REPLICATE_BORDER = $8153; - GL_CONVOLUTION_BORDER_COLOR = $8154; -var - glColorTable: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const table: PGLvoid); stdcall = nil; - glColorTableParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); stdcall = nil; - glColorTableParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); stdcall = nil; - glCopyColorTable: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); stdcall = nil; - glGetColorTable: procedure(target: GLenum; format: GLenum; _type: GLenum; table: PGLvoid); stdcall = nil; - glGetColorTableParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetColorTableParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glColorSubTable: procedure(target: GLenum; start: GLsizei; count: GLsizei; format: GLenum; _type: GLenum; const data: PGLvoid); stdcall = nil; - glCopyColorSubTable: procedure(target: GLenum; start: GLsizei; x: GLint; y: GLint; width: GLsizei); stdcall = nil; - glConvolutionFilter1D: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); stdcall = nil; - glConvolutionFilter2D: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); stdcall = nil; - glConvolutionParameterf: procedure(target: GLenum; pname: GLenum; params: GLfloat); stdcall = nil; - glConvolutionParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); stdcall = nil; - glConvolutionParameteri: procedure(target: GLenum; pname: GLenum; params: GLint); stdcall = nil; - glConvolutionParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); stdcall = nil; - glCopyConvolutionFilter1D: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); stdcall = nil; - glCopyConvolutionFilter2D: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; height: GLsizei); stdcall = nil; - glGetConvolutionFilter: procedure(target: GLenum; format: GLenum; _type: GLenum; image: PGLvoid); stdcall = nil; - glGetConvolutionParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetConvolutionParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetSeparableFilter: procedure(target: GLenum; format: GLenum; _type: GLenum; row: PGLvoid; column: PGLvoid; span: PGLvoid); stdcall = nil; - glSeparableFilter2D: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const row: PGLvoid; const column: PGLvoid); stdcall = nil; - glGetHistogram: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); stdcall = nil; - glGetHistogramParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetHistogramParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetMinmax: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); stdcall = nil; - glGetMinmaxParameterfv: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetMinmaxParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glHistogram: procedure(target: GLenum; width: GLsizei; internalformat: GLenum; sink: GLboolean); stdcall = nil; - glMinmax: procedure(target: GLenum; internalformat: GLenum; sink: GLboolean); stdcall = nil; - glResetHistogram: procedure(target: GLenum); stdcall = nil; - glResetMinmax: procedure(target: GLenum); stdcall = nil; - glBlendEquation: procedure(mode: GLenum); stdcall = nil; - glBlendColor: procedure(red: GLclampf; green: GLclampf; blue: GLclampf; alpha: GLclampf); stdcall = nil; - -function Load_GL_ARB_imaging: Boolean; - -//***** GL_version_1_3 *****// -const - GL_TEXTURE0 = $84C0; - GL_TEXTURE1 = $84C1; - GL_TEXTURE2 = $84C2; - GL_TEXTURE3 = $84C3; - GL_TEXTURE4 = $84C4; - GL_TEXTURE5 = $84C5; - GL_TEXTURE6 = $84C6; - GL_TEXTURE7 = $84C7; - GL_TEXTURE8 = $84C8; - GL_TEXTURE9 = $84C9; - GL_TEXTURE10 = $84CA; - GL_TEXTURE11 = $84CB; - GL_TEXTURE12 = $84CC; - GL_TEXTURE13 = $84CD; - GL_TEXTURE14 = $84CE; - GL_TEXTURE15 = $84CF; - GL_TEXTURE16 = $84D0; - GL_TEXTURE17 = $84D1; - GL_TEXTURE18 = $84D2; - GL_TEXTURE19 = $84D3; - GL_TEXTURE20 = $84D4; - GL_TEXTURE21 = $84D5; - GL_TEXTURE22 = $84D6; - GL_TEXTURE23 = $84D7; - GL_TEXTURE24 = $84D8; - GL_TEXTURE25 = $84D9; - GL_TEXTURE26 = $84DA; - GL_TEXTURE27 = $84DB; - GL_TEXTURE28 = $84DC; - GL_TEXTURE29 = $84DD; - GL_TEXTURE30 = $84DE; - GL_TEXTURE31 = $84DF; - GL_ACTIVE_TEXTURE = $84E0; - GL_CLIENT_ACTIVE_TEXTURE = $84E1; - GL_MAX_TEXTURE_UNITS = $84E2; - GL_TRANSPOSE_MODELVIEW_MATRIX = $84E3; - GL_TRANSPOSE_PROJECTION_MATRIX = $84E4; - GL_TRANSPOSE_TEXTURE_MATRIX = $84E5; - GL_TRANSPOSE_COLOR_MATRIX = $84E6; - GL_MULTISAMPLE = $809D; - GL_SAMPLE_ALPHA_TO_COVERAGE = $809E; - GL_SAMPLE_ALPHA_TO_ONE = $809F; - GL_SAMPLE_COVERAGE = $80A0; - GL_SAMPLE_BUFFERS = $80A8; - GL_SAMPLES = $80A9; - GL_SAMPLE_COVERAGE_VALUE = $80AA; - GL_SAMPLE_COVERAGE_INVERT = $80AB; - GL_MULTISAMPLE_BIT = $20000000; - GL_NORMAL_MAP = $8511; - GL_REFLECTION_MAP = $8512; - GL_TEXTURE_CUBE_MAP = $8513; - GL_TEXTURE_BINDING_CUBE_MAP = $8514; - GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515; - GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516; - GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518; - GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A; - GL_PROXY_TEXTURE_CUBE_MAP = $851B; - GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C; - GL_COMPRESSED_ALPHA = $84E9; - GL_COMPRESSED_LUMINANCE = $84EA; - GL_COMPRESSED_LUMINANCE_ALPHA = $84EB; - GL_COMPRESSED_INTENSITY = $84EC; - GL_COMPRESSED_RGB = $84ED; - GL_COMPRESSED_RGBA = $84EE; - GL_TEXTURE_COMPRESSION_HINT = $84EF; - GL_TEXTURE_COMPRESSED_IMAGE_SIZE = $86A0; - GL_TEXTURE_COMPRESSED = $86A1; - GL_NUM_COMPRESSED_TEXTURE_FORMATS = $86A2; - GL_COMPRESSED_TEXTURE_FORMATS = $86A3; - GL_CLAMP_TO_BORDER = $812D; - GL_CLAMP_TO_BORDER_SGIS = $812D; - GL_COMBINE = $8570; - GL_COMBINE_RGB = $8571; - GL_COMBINE_ALPHA = $8572; - GL_SOURCE0_RGB = $8580; - GL_SOURCE1_RGB = $8581; - GL_SOURCE2_RGB = $8582; - GL_SOURCE0_ALPHA = $8588; - GL_SOURCE1_ALPHA = $8589; - GL_SOURCE2_ALPHA = $858A; - GL_OPERAND0_RGB = $8590; - GL_OPERAND1_RGB = $8591; - GL_OPERAND2_RGB = $8592; - GL_OPERAND0_ALPHA = $8598; - GL_OPERAND1_ALPHA = $8599; - GL_OPERAND2_ALPHA = $859A; - GL_RGB_SCALE = $8573; - GL_ADD_SIGNED = $8574; - GL_INTERPOLATE = $8575; - GL_SUBTRACT = $84E7; - GL_CONSTANT = $8576; - GL_PRIMARY_COLOR = $8577; - GL_PREVIOUS = $8578; - GL_DOT3_RGB = $86AE; - GL_DOT3_RGBA = $86AF; -var - glActiveTexture: procedure(texture: GLenum); stdcall = nil; - glClientActiveTexture: procedure(texture: GLenum); stdcall = nil; - glMultiTexCoord1d: procedure(target: GLenum; s: GLdouble); stdcall = nil; - glMultiTexCoord1dv: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord1f: procedure(target: GLenum; s: GLfloat); stdcall = nil; - glMultiTexCoord1fv: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord1i: procedure(target: GLenum; s: GLint); stdcall = nil; - glMultiTexCoord1iv: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord1s: procedure(target: GLenum; s: GLshort); stdcall = nil; - glMultiTexCoord1sv: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - glMultiTexCoord2d: procedure(target: GLenum; s: GLdouble; t: GLdouble); stdcall = nil; - glMultiTexCoord2dv: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord2f: procedure(target: GLenum; s: GLfloat; t: GLfloat); stdcall = nil; - glMultiTexCoord2fv: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord2i: procedure(target: GLenum; s: GLint; t: GLint); stdcall = nil; - glMultiTexCoord2iv: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord2s: procedure(target: GLenum; s: GLshort; t: GLshort); stdcall = nil; - glMultiTexCoord2sv: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - glMultiTexCoord3d: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble); stdcall = nil; - glMultiTexCoord3dv: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord3f: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat); stdcall = nil; - glMultiTexCoord3fv: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord3i: procedure(target: GLenum; s: GLint; t: GLint; r: GLint); stdcall = nil; - glMultiTexCoord3iv: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord3s: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort); stdcall = nil; - glMultiTexCoord3sv: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - glMultiTexCoord4d: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble; q: GLdouble); stdcall = nil; - glMultiTexCoord4dv: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord4f: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat; q: GLfloat); stdcall = nil; - glMultiTexCoord4fv: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord4i: procedure(target: GLenum; s: GLint; t: GLint; r: GLint; q: GLint); stdcall = nil; - glMultiTexCoord4iv: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord4s: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort; q: GLshort); stdcall = nil; - glMultiTexCoord4sv: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - glLoadTransposeMatrixf: procedure(const m: PGLfloat); stdcall = nil; - glLoadTransposeMatrixd: procedure(const m: PGLdouble); stdcall = nil; - glMultTransposeMatrixf: procedure(const m: PGLfloat); stdcall = nil; - glMultTransposeMatrixd: procedure(const m: PGLdouble); stdcall = nil; - glSampleCoverage: procedure(value: GLclampf; invert: GLboolean); stdcall = nil; - glCompressedTexImage3D: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexImage2D: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexImage1D: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexSubImage3D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexSubImage2D: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexSubImage1D: procedure(target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glGetCompressedTexImage: procedure(target: GLenum; level: GLint; img: PGLvoid); stdcall = nil; - -function Load_GL_version_1_3: Boolean; - -//***** GL_ARB_multitexture *****// -const - GL_TEXTURE0_ARB = $84C0; - GL_TEXTURE1_ARB = $84C1; - GL_TEXTURE2_ARB = $84C2; - GL_TEXTURE3_ARB = $84C3; - GL_TEXTURE4_ARB = $84C4; - GL_TEXTURE5_ARB = $84C5; - GL_TEXTURE6_ARB = $84C6; - GL_TEXTURE7_ARB = $84C7; - GL_TEXTURE8_ARB = $84C8; - GL_TEXTURE9_ARB = $84C9; - GL_TEXTURE10_ARB = $84CA; - GL_TEXTURE11_ARB = $84CB; - GL_TEXTURE12_ARB = $84CC; - GL_TEXTURE13_ARB = $84CD; - GL_TEXTURE14_ARB = $84CE; - GL_TEXTURE15_ARB = $84CF; - GL_TEXTURE16_ARB = $84D0; - GL_TEXTURE17_ARB = $84D1; - GL_TEXTURE18_ARB = $84D2; - GL_TEXTURE19_ARB = $84D3; - GL_TEXTURE20_ARB = $84D4; - GL_TEXTURE21_ARB = $84D5; - GL_TEXTURE22_ARB = $84D6; - GL_TEXTURE23_ARB = $84D7; - GL_TEXTURE24_ARB = $84D8; - GL_TEXTURE25_ARB = $84D9; - GL_TEXTURE26_ARB = $84DA; - GL_TEXTURE27_ARB = $84DB; - GL_TEXTURE28_ARB = $84DC; - GL_TEXTURE29_ARB = $84DD; - GL_TEXTURE30_ARB = $84DE; - GL_TEXTURE31_ARB = $84DF; - GL_ACTIVE_TEXTURE_ARB = $84E0; - GL_CLIENT_ACTIVE_TEXTURE_ARB = $84E1; - GL_MAX_TEXTURE_UNITS_ARB = $84E2; -var - glActiveTextureARB: procedure(texture: GLenum); stdcall = nil; - glClientActiveTextureARB: procedure(texture: GLenum); stdcall = nil; - glMultiTexCoord1dARB: procedure(target: GLenum; s: GLdouble); stdcall = nil; - glMultiTexCoord1dvARB: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord1fARB: procedure(target: GLenum; s: GLfloat); stdcall = nil; - glMultiTexCoord1fvARB: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord1iARB: procedure(target: GLenum; s: GLint); stdcall = nil; - glMultiTexCoord1ivARB: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord1sARB: procedure(target: GLenum; s: GLshort); stdcall = nil; - glMultiTexCoord1svARB: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - glMultiTexCoord2dARB: procedure(target: GLenum; s: GLdouble; t: GLdouble); stdcall = nil; - glMultiTexCoord2dvARB: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord2fARB: procedure(target: GLenum; s: GLfloat; t: GLfloat); stdcall = nil; - glMultiTexCoord2fvARB: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord2iARB: procedure(target: GLenum; s: GLint; t: GLint); stdcall = nil; - glMultiTexCoord2ivARB: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord2sARB: procedure(target: GLenum; s: GLshort; t: GLshort); stdcall = nil; - glMultiTexCoord2svARB: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - glMultiTexCoord3dARB: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble); stdcall = nil; - glMultiTexCoord3dvARB: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord3fARB: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat); stdcall = nil; - glMultiTexCoord3fvARB: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord3iARB: procedure(target: GLenum; s: GLint; t: GLint; r: GLint); stdcall = nil; - glMultiTexCoord3ivARB: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord3sARB: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort); stdcall = nil; - glMultiTexCoord3svARB: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - glMultiTexCoord4dARB: procedure(target: GLenum; s: GLdouble; t: GLdouble; r: GLdouble; q: GLdouble); stdcall = nil; - glMultiTexCoord4dvARB: procedure(target: GLenum; const v: PGLdouble); stdcall = nil; - glMultiTexCoord4fARB: procedure(target: GLenum; s: GLfloat; t: GLfloat; r: GLfloat; q: GLfloat); stdcall = nil; - glMultiTexCoord4fvARB: procedure(target: GLenum; const v: PGLfloat); stdcall = nil; - glMultiTexCoord4iARB: procedure(target: GLenum; s: GLint; t: GLint; r: GLint; q: GLint); stdcall = nil; - glMultiTexCoord4ivARB: procedure(target: GLenum; const v: PGLint); stdcall = nil; - glMultiTexCoord4sARB: procedure(target: GLenum; s: GLshort; t: GLshort; r: GLshort; q: GLshort); stdcall = nil; - glMultiTexCoord4svARB: procedure(target: GLenum; const v: PGLshort); stdcall = nil; - -function Load_GL_ARB_multitexture: Boolean; - -//***** GL_ARB_transpose_matrix *****// -const - GL_TRANSPOSE_MODELVIEW_MATRIX_ARB = $84E3; - GL_TRANSPOSE_PROJECTION_MATRIX_ARB = $84E4; - GL_TRANSPOSE_TEXTURE_MATRIX_ARB = $84E5; - GL_TRANSPOSE_COLOR_MATRIX_ARB = $84E6; -var - glLoadTransposeMatrixfARB: procedure(m: PGLfloat); stdcall = nil; - glLoadTransposeMatrixdARB: procedure(m: PGLdouble); stdcall = nil; - glMultTransposeMatrixfARB: procedure(m: PGLfloat); stdcall = nil; - glMultTransposeMatrixdARB: procedure(m: PGLdouble); stdcall = nil; - -function Load_GL_ARB_transpose_matrix: Boolean; - -//***** GL_ARB_multisample *****// -const - WGL_SAMPLE_BUFFERS_ARB = $2041; - WGL_SAMPLES_ARB = $2042; - GL_MULTISAMPLE_ARB = $809D; - GL_SAMPLE_ALPHA_TO_COVERAGE_ARB = $809E; - GL_SAMPLE_ALPHA_TO_ONE_ARB = $809F; - GL_SAMPLE_COVERAGE_ARB = $80A0; - GL_MULTISAMPLE_BIT_ARB = $20000000; - GL_SAMPLE_BUFFERS_ARB = $80A8; - GL_SAMPLES_ARB = $80A9; - GL_SAMPLE_COVERAGE_VALUE_ARB = $80AA; - GL_SAMPLE_COVERAGE_INVERT_ARB = $80AB; -var - glSampleCoverageARB: procedure(value: GLclampf; invert: GLboolean); stdcall = nil; - -function Load_GL_ARB_multisample: Boolean; - -//***** GL_ARB_texture_env_add *****// - -function Load_GL_ARB_texture_env_add: Boolean; - -//***** WGL_ARB_extensions_string *****// -var - wglGetExtensionsStringARB: function(hdc: HDC): Pchar; stdcall = nil; - -function Load_WGL_ARB_extensions_string: Boolean; - -//***** WGL_ARB_buffer_region *****// -const - WGL_FRONT_COLOR_BUFFER_BIT_ARB = $0001; - WGL_BACK_COLOR_BUFFER_BIT_ARB = $0002; - WGL_DEPTH_BUFFER_BIT_ARB = $0004; - WGL_STENCIL_BUFFER_BIT_ARB = $0008; -var - wglCreateBufferRegionARB: function(hDC: HDC; iLayerPlane: GLint; uType: GLuint): THandle; stdcall = nil; - wglDeleteBufferRegionARB: procedure(hRegion: THandle); stdcall = nil; - wglSaveBufferRegionARB: function(hRegion: THandle; x: GLint; y: GLint; width: GLint; height: GLint): BOOL; stdcall = nil; - wglRestoreBufferRegionARB: function(hRegion: THandle; x: GLint; y: GLint; width: GLint; height: GLint; xSrc: GLint; ySrc: GLint): BOOL; stdcall = nil; - -function Load_WGL_ARB_buffer_region: Boolean; - -//***** GL_ARB_texture_cube_map *****// -const - GL_NORMAL_MAP_ARB = $8511; - GL_REFLECTION_MAP_ARB = $8512; - GL_TEXTURE_CUBE_MAP_ARB = $8513; - GL_TEXTURE_BINDING_CUBE_MAP_ARB = $8514; - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB = $8515; - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB = $8516; - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB = $8517; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB = $8518; - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB = $8519; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB = $851A; - GL_PROXY_TEXTURE_CUBE_MAP_ARB = $851B; - GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB = $851C; - -function Load_GL_ARB_texture_cube_map: Boolean; - -//***** GL_ARB_depth_texture *****// -const - GL_DEPTH_COMPONENT16_ARB = $81A5; - GL_DEPTH_COMPONENT24_ARB = $81A6; - GL_DEPTH_COMPONENT32_ARB = $81A7; - GL_TEXTURE_DEPTH_SIZE_ARB = $884A; - GL_DEPTH_TEXTURE_MODE_ARB = $884B; - -function Load_GL_ARB_depth_texture: Boolean; - -//***** GL_ARB_point_parameters *****// -const - GL_POINT_SIZE_MIN_ARB = $8126; - GL_POINT_SIZE_MAX_ARB = $8127; - GL_POINT_FADE_THRESHOLD_SIZE_ARB = $8128; - GL_POINT_DISTANCE_ATTENUATION_ARB = $8129; -var - glPointParameterfARB: procedure(pname: GLenum; param: GLfloat); stdcall = nil; - glPointParameterfvARB: procedure(pname: GLenum; params: PGLfloat); stdcall = nil; - -function Load_GL_ARB_point_parameters: Boolean; - -//***** GL_ARB_shadow *****// -const - GL_TEXTURE_COMPARE_MODE_ARB = $884C; - GL_TEXTURE_COMPARE_FUNC_ARB = $884D; - GL_COMPARE_R_TO_TEXTURE_ARB = $884E; - -function Load_GL_ARB_shadow: Boolean; - -//***** GL_ARB_shadow_ambient *****// -const - GL_TEXTURE_COMPARE_FAIL_VALUE_ARB = $80BF; - -function Load_GL_ARB_shadow_ambient: Boolean; - -//***** GL_ARB_texture_border_clamp *****// -const - GL_CLAMP_TO_BORDER_ARB = $812D; - -function Load_GL_ARB_texture_border_clamp: Boolean; - -//***** GL_ARB_texture_compression *****// -const - GL_COMPRESSED_ALPHA_ARB = $84E9; - GL_COMPRESSED_LUMINANCE_ARB = $84EA; - GL_COMPRESSED_LUMINANCE_ALPHA_ARB = $84EB; - GL_COMPRESSED_INTENSITY_ARB = $84EC; - GL_COMPRESSED_RGB_ARB = $84ED; - GL_COMPRESSED_RGBA_ARB = $84EE; - GL_TEXTURE_COMPRESSION_HINT_ARB = $84EF; - GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB = $86A0; - GL_TEXTURE_COMPRESSED_ARB = $86A1; - GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB = $86A2; - GL_COMPRESSED_TEXTURE_FORMATS_ARB = $86A3; -var - glCompressedTexImage3DARB: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexImage2DARB: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexImage1DARB: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexSubImage3DARB: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexSubImage2DARB: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glCompressedTexSubImage1DARB: procedure(target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; imageSize: GLsizei; const data: PGLvoid); stdcall = nil; - glGetCompressedTexImageARB: procedure(target: GLenum; lod: GLint; img: PGLvoid); stdcall = nil; - -function Load_GL_ARB_texture_compression: Boolean; - -//***** GL_ARB_texture_env_combine *****// -const - GL_COMBINE_ARB = $8570; - GL_COMBINE_RGB_ARB = $8571; - GL_COMBINE_ALPHA_ARB = $8572; - GL_SOURCE0_RGB_ARB = $8580; - GL_SOURCE1_RGB_ARB = $8581; - GL_SOURCE2_RGB_ARB = $8582; - GL_SOURCE0_ALPHA_ARB = $8588; - GL_SOURCE1_ALPHA_ARB = $8589; - GL_SOURCE2_ALPHA_ARB = $858A; - GL_OPERAND0_RGB_ARB = $8590; - GL_OPERAND1_RGB_ARB = $8591; - GL_OPERAND2_RGB_ARB = $8592; - GL_OPERAND0_ALPHA_ARB = $8598; - GL_OPERAND1_ALPHA_ARB = $8599; - GL_OPERAND2_ALPHA_ARB = $859A; - GL_RGB_SCALE_ARB = $8573; - GL_ADD_SIGNED_ARB = $8574; - GL_INTERPOLATE_ARB = $8575; - GL_SUBTRACT_ARB = $84E7; - GL_CONSTANT_ARB = $8576; - GL_PRIMARY_COLOR_ARB = $8577; - GL_PREVIOUS_ARB = $8578; - -function Load_GL_ARB_texture_env_combine: Boolean; - -//***** GL_ARB_texture_env_crossbar *****// - -function Load_GL_ARB_texture_env_crossbar: Boolean; - -//***** GL_ARB_texture_env_dot3 *****// -const - GL_DOT3_RGB_ARB = $86AE; - GL_DOT3_RGBA_ARB = $86AF; - -function Load_GL_ARB_texture_env_dot3: Boolean; - -//***** GL_ARB_texture_mirrored_repeat *****// -const - GL_MIRRORED_REPEAT_ARB = $8370; - -function Load_GL_ARB_texture_mirrored_repeat: Boolean; - -//***** GL_ARB_vertex_blend *****// -const - GL_MAX_VERTEX_UNITS_ARB = $86A4; - GL_ACTIVE_VERTEX_UNITS_ARB = $86A5; - GL_WEIGHT_SUM_UNITY_ARB = $86A6; - GL_VERTEX_BLEND_ARB = $86A7; - GL_MODELVIEW0_ARB = $1700; - GL_MODELVIEW1_ARB = $850A; - GL_MODELVIEW2_ARB = $8722; - GL_MODELVIEW3_ARB = $8723; - GL_MODELVIEW4_ARB = $8724; - GL_MODELVIEW5_ARB = $8725; - GL_MODELVIEW6_ARB = $8726; - GL_MODELVIEW7_ARB = $8727; - GL_MODELVIEW8_ARB = $8728; - GL_MODELVIEW9_ARB = $8729; - GL_MODELVIEW10_ARB = $872A; - GL_MODELVIEW11_ARB = $872B; - GL_MODELVIEW12_ARB = $872C; - GL_MODELVIEW13_ARB = $872D; - GL_MODELVIEW14_ARB = $872E; - GL_MODELVIEW15_ARB = $872F; - GL_MODELVIEW16_ARB = $8730; - GL_MODELVIEW17_ARB = $8731; - GL_MODELVIEW18_ARB = $8732; - GL_MODELVIEW19_ARB = $8733; - GL_MODELVIEW20_ARB = $8734; - GL_MODELVIEW21_ARB = $8735; - GL_MODELVIEW22_ARB = $8736; - GL_MODELVIEW23_ARB = $8737; - GL_MODELVIEW24_ARB = $8738; - GL_MODELVIEW25_ARB = $8739; - GL_MODELVIEW26_ARB = $873A; - GL_MODELVIEW27_ARB = $873B; - GL_MODELVIEW28_ARB = $873C; - GL_MODELVIEW29_ARB = $873D; - GL_MODELVIEW30_ARB = $873E; - GL_MODELVIEW31_ARB = $873F; - GL_CURRENT_WEIGHT_ARB = $86A8; - GL_WEIGHT_ARRAY_TYPE_ARB = $86A9; - GL_WEIGHT_ARRAY_STRIDE_ARB = $86AA; - GL_WEIGHT_ARRAY_SIZE_ARB = $86AB; - GL_WEIGHT_ARRAY_POINTER_ARB = $86AC; - GL_WEIGHT_ARRAY_ARB = $86AD; -var - glWeightbvARB: procedure(size: GLint; weights: PGLbyte); stdcall = nil; - glWeightsvARB: procedure(size: GLint; weights: PGLshort); stdcall = nil; - glWeightivARB: procedure(size: GLint; weights: PGLint); stdcall = nil; - glWeightfvARB: procedure(size: GLint; weights: PGLfloat); stdcall = nil; - glWeightdvARB: procedure(size: GLint; weights: PGLdouble); stdcall = nil; - glWeightvARB: procedure(size: GLint; weights: PGLdouble); stdcall = nil; - glWeightubvARB: procedure(size: GLint; weights: PGLubyte); stdcall = nil; - glWeightusvARB: procedure(size: GLint; weights: PGLushort); stdcall = nil; - glWeightuivARB: procedure(size: GLint; weights: PGLuint); stdcall = nil; - glWeightPointerARB: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); stdcall = nil; - glVertexBlendARB: procedure(count: GLint); stdcall = nil; - -function Load_GL_ARB_vertex_blend: Boolean; - -//***** GL_ARB_vertex_program *****// -const - GL_VERTEX_PROGRAM_ARB = $8620; - GL_VERTEX_PROGRAM_POINT_SIZE_ARB = $8642; - GL_VERTEX_PROGRAM_TWO_SIDE_ARB = $8643; - GL_COLOR_SUM_ARB = $8458; - GL_PROGRAM_FORMAT_ASCII_ARB = $8875; - GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB = $8622; - GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB = $8623; - GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB = $8624; - GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB = $8625; - GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB = $886A; - GL_CURRENT_VERTEX_ATTRIB_ARB = $8626; - GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB = $8645; - GL_PROGRAM_LENGTH_ARB = $8627; - GL_PROGRAM_FORMAT_ARB = $8876; - GL_PROGRAM_BINDING_ARB = $8677; - GL_PROGRAM_INSTRUCTIONS_ARB = $88A0; - GL_MAX_PROGRAM_INSTRUCTIONS_ARB = $88A1; - GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB = $88A2; - GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB = $88A3; - GL_PROGRAM_TEMPORARIES_ARB = $88A4; - GL_MAX_PROGRAM_TEMPORARIES_ARB = $88A5; - GL_PROGRAM_NATIVE_TEMPORARIES_ARB = $88A6; - GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB = $88A7; - GL_PROGRAM_PARAMETERS_ARB = $88A8; - GL_MAX_PROGRAM_PARAMETERS_ARB = $88A9; - GL_PROGRAM_NATIVE_PARAMETERS_ARB = $88AA; - GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB = $88AB; - GL_PROGRAM_ATTRIBS_ARB = $88AC; - GL_MAX_PROGRAM_ATTRIBS_ARB = $88AD; - GL_PROGRAM_NATIVE_ATTRIBS_ARB = $88AE; - GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB = $88AF; - GL_PROGRAM_ADDRESS_REGISTERS_ARB = $88B0; - GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB = $88B1; - GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = $88B2; - GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB = $88B3; - GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB = $88B4; - GL_MAX_PROGRAM_ENV_PARAMETERS_ARB = $88B5; - GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB = $88B6; - GL_PROGRAM_STRING_ARB = $8628; - GL_PROGRAM_ERROR_POSITION_ARB = $864B; - GL_CURRENT_MATRIX_ARB = $8641; - GL_TRANSPOSE_CURRENT_MATRIX_ARB = $88B7; - GL_CURRENT_MATRIX_STACK_DEPTH_ARB = $8640; - GL_MAX_VERTEX_ATTRIBS_ARB = $8869; - GL_MAX_PROGRAM_MATRICES_ARB = $862F; - GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB = $862E; - GL_PROGRAM_ERROR_STRING_ARB = $8874; - GL_MATRIX0_ARB = $88C0; - GL_MATRIX1_ARB = $88C1; - GL_MATRIX2_ARB = $88C2; - GL_MATRIX3_ARB = $88C3; - GL_MATRIX4_ARB = $88C4; - GL_MATRIX5_ARB = $88C5; - GL_MATRIX6_ARB = $88C6; - GL_MATRIX7_ARB = $88C7; - GL_MATRIX8_ARB = $88C8; - GL_MATRIX9_ARB = $88C9; - GL_MATRIX10_ARB = $88CA; - GL_MATRIX11_ARB = $88CB; - GL_MATRIX12_ARB = $88CC; - GL_MATRIX13_ARB = $88CD; - GL_MATRIX14_ARB = $88CE; - GL_MATRIX15_ARB = $88CF; - GL_MATRIX16_ARB = $88D0; - GL_MATRIX17_ARB = $88D1; - GL_MATRIX18_ARB = $88D2; - GL_MATRIX19_ARB = $88D3; - GL_MATRIX20_ARB = $88D4; - GL_MATRIX21_ARB = $88D5; - GL_MATRIX22_ARB = $88D6; - GL_MATRIX23_ARB = $88D7; - GL_MATRIX24_ARB = $88D8; - GL_MATRIX25_ARB = $88D9; - GL_MATRIX26_ARB = $88DA; - GL_MATRIX27_ARB = $88DB; - GL_MATRIX28_ARB = $88DC; - GL_MATRIX29_ARB = $88DD; - GL_MATRIX30_ARB = $88DE; - GL_MATRIX31_ARB = $88DF; -var - glVertexAttrib1sARB: procedure(index: GLuint; x: GLshort); stdcall = nil; - glVertexAttrib1fARB: procedure(index: GLuint; x: GLfloat); stdcall = nil; - glVertexAttrib1dARB: procedure(index: GLuint; x: GLdouble); stdcall = nil; - glVertexAttrib2sARB: procedure(index: GLuint; x: GLshort; y: GLshort); stdcall = nil; - glVertexAttrib2fARB: procedure(index: GLuint; x: GLfloat; y: GLfloat); stdcall = nil; - glVertexAttrib2dARB: procedure(index: GLuint; x: GLdouble; y: GLdouble); stdcall = nil; - glVertexAttrib3sARB: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort); stdcall = nil; - glVertexAttrib3fARB: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glVertexAttrib3dARB: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble); stdcall = nil; - glVertexAttrib4sARB: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort; w: GLshort); stdcall = nil; - glVertexAttrib4fARB: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glVertexAttrib4dARB: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); stdcall = nil; - glVertexAttrib4NubARB: procedure(index: GLuint; x: GLubyte; y: GLubyte; z: GLubyte; w: GLubyte); stdcall = nil; - glVertexAttrib1svARB: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib1fvARB: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib1dvARB: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib2svARB: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib2fvARB: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib2dvARB: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib3svARB: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib3fvARB: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib3dvARB: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib4bvARB: procedure(index: GLuint; const v: PGLbyte); stdcall = nil; - glVertexAttrib4svARB: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib4ivARB: procedure(index: GLuint; const v: PGLint); stdcall = nil; - glVertexAttrib4ubvARB: procedure(index: GLuint; const v: PGLubyte); stdcall = nil; - glVertexAttrib4usvARB: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttrib4uivARB: procedure(index: GLuint; const v: PGLuint); stdcall = nil; - glVertexAttrib4fvARB: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib4dvARB: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib4NbvARB: procedure(index: GLuint; const v: PGLbyte); stdcall = nil; - glVertexAttrib4NsvARB: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib4NivARB: procedure(index: GLuint; const v: PGLint); stdcall = nil; - glVertexAttrib4NubvARB: procedure(index: GLuint; const v: PGLubyte); stdcall = nil; - glVertexAttrib4NusvARB: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttrib4NuivARB: procedure(index: GLuint; const v: PGLuint); stdcall = nil; - glVertexAttribPointerARB: procedure(index: GLuint; size: GLint; _type: GLenum; normalized: GLboolean; stride: GLsizei; const pointer: PGLvoid); stdcall = nil; - glEnableVertexAttribArrayARB: procedure(index: GLuint); stdcall = nil; - glDisableVertexAttribArrayARB: procedure(index: GLuint); stdcall = nil; - glProgramStringARB: procedure(target: GLenum; format: GLenum; len: GLsizei; const _string: PGLvoid); stdcall = nil; - glBindProgramARB: procedure(target: GLenum; _program: GLuint); stdcall = nil; - glDeleteProgramsARB: procedure(n: GLsizei; const programs: PGLuint); stdcall = nil; - glGenProgramsARB: procedure(n: GLsizei; programs: PGLuint); stdcall = nil; - glProgramEnvParameter4dARB: procedure(target: GLenum; index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); stdcall = nil; - glProgramEnvParameter4dvARB: procedure(target: GLenum; index: GLuint; const params: PGLdouble); stdcall = nil; - glProgramEnvParameter4fARB: procedure(target: GLenum; index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glProgramEnvParameter4fvARB: procedure(target: GLenum; index: GLuint; const params: PGLfloat); stdcall = nil; - glProgramLocalParameter4dARB: procedure(target: GLenum; index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); stdcall = nil; - glProgramLocalParameter4dvARB: procedure(target: GLenum; index: GLuint; const params: PGLdouble); stdcall = nil; - glProgramLocalParameter4fARB: procedure(target: GLenum; index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glProgramLocalParameter4fvARB: procedure(target: GLenum; index: GLuint; const params: PGLfloat); stdcall = nil; - glGetProgramEnvParameterdvARB: procedure(target: GLenum; index: GLuint; params: PGLdouble); stdcall = nil; - glGetProgramEnvParameterfvARB: procedure(target: GLenum; index: GLuint; params: PGLfloat); stdcall = nil; - glGetProgramLocalParameterdvARB: procedure(target: GLenum; index: GLuint; params: PGLdouble); stdcall = nil; - glGetProgramLocalParameterfvARB: procedure(target: GLenum; index: GLuint; params: PGLfloat); stdcall = nil; - glGetProgramivARB: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetProgramStringARB: procedure(target: GLenum; pname: GLenum; _string: PGLvoid); stdcall = nil; - glGetVertexAttribdvARB: procedure(index: GLuint; pname: GLenum; params: PGLdouble); stdcall = nil; - glGetVertexAttribfvARB: procedure(index: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetVertexAttribivARB: procedure(index: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetVertexAttribPointervARB: procedure(index: GLuint; pname: GLenum; pointer: PGLvoid); stdcall = nil; - glIsProgramARB: function(_program: GLuint): GLboolean; stdcall = nil; - -function Load_GL_ARB_vertex_program: Boolean; - -//***** GL_ARB_window_pos *****// -var - glWindowPos2dARB: procedure(x: GLdouble; y: GLdouble); stdcall = nil; - glWindowPos2fARB: procedure(x: GLfloat; y: GLfloat); stdcall = nil; - glWindowPos2iARB: procedure(x: GLint; y: GLint); stdcall = nil; - glWindowPos2sARB: procedure(x: GLshort; y: GLshort); stdcall = nil; - glWindowPos2dvARB: procedure(const p: PGLdouble); stdcall = nil; - glWindowPos2fvARB: procedure(const p: PGLfloat); stdcall = nil; - glWindowPos2ivARB: procedure(const p: PGLint); stdcall = nil; - glWindowPos2svARB: procedure(const p: PGLshort); stdcall = nil; - glWindowPos3dARB: procedure(x: GLdouble; y: GLdouble; z: GLdouble); stdcall = nil; - glWindowPos3fARB: procedure(x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glWindowPos3iARB: procedure(x: GLint; y: GLint; z: GLint); stdcall = nil; - glWindowPos3sARB: procedure(x: GLshort; y: GLshort; z: GLshort); stdcall = nil; - glWindowPos3dvARB: procedure(const p: PGLdouble); stdcall = nil; - glWindowPos3fvARB: procedure(const p: PGLfloat); stdcall = nil; - glWindowPos3ivARB: procedure(const p: PGLint); stdcall = nil; - glWindowPos3svARB: procedure(const p: PGLshort); stdcall = nil; - -function Load_GL_ARB_window_pos: Boolean; - -//***** GL_EXT_422_pixels *****// -const - GL_422_EXT = $80CC; - GL_422_REV_EXT = $80CD; - GL_422_AVERAGE_EXT = $80CE; - GL_422_REV_AVERAGE_EXT = $80CF; - -function Load_GL_EXT_422_pixels: Boolean; - -//***** GL_EXT_abgr *****// -const - GL_ABGR_EXT = $8000; - -function Load_GL_EXT_abgr: Boolean; - -//***** GL_EXT_bgra *****// -const - GL_BGR_EXT = $80E0; - GL_BGRA_EXT = $80E1; - -function Load_GL_EXT_bgra: Boolean; - -//***** GL_EXT_blend_color *****// -const - GL_CONSTANT_COLOR_EXT = $8001; - GL_ONE_MINUS_CONSTANT_COLOR_EXT = $8002; - GL_CONSTANT_ALPHA_EXT = $8003; - GL_ONE_MINUS_CONSTANT_ALPHA_EXT = $8004; - GL_BLEND_COLOR_EXT = $8005; -var - glBlendColorEXT: procedure(red: GLclampf; green: GLclampf; blue: GLclampf; alpha: GLclampf); stdcall = nil; - -function Load_GL_EXT_blend_color: Boolean; - -//***** GL_EXT_blend_func_separate *****// -const - GL_BLEND_DST_RGB_EXT = $80C8; - GL_BLEND_SRC_RGB_EXT = $80C9; - GL_BLEND_DST_ALPHA_EXT = $80CA; - GL_BLEND_SRC_ALPHA_EXT = $80CB; -var - glBlendFuncSeparateEXT: procedure(sfactorRGB: GLenum; dfactorRGB: GLenum; sfactorAlpha: GLenum; dfactorAlpha: GLenum); stdcall = nil; - -function Load_GL_EXT_blend_func_separate: Boolean; - -//***** GL_EXT_blend_logic_op *****// - -function Load_GL_EXT_blend_logic_op: Boolean; - -//***** GL_EXT_blend_minmax *****// -const - GL_FUNC_ADD_EXT = $8006; - GL_MIN_EXT = $8007; - GL_MAX_EXT = $8008; - GL_BLEND_EQUATION_EXT = $8009; -var - glBlendEquationEXT: procedure(mode: GLenum); stdcall = nil; - -function Load_GL_EXT_blend_minmax: Boolean; - -//***** GL_EXT_blend_subtract *****// -const - GL_FUNC_SUBTRACT_EXT = $800A; - GL_FUNC_REVERSE_SUBTRACT_EXT = $800B; - -function Load_GL_EXT_blend_subtract: Boolean; - -//***** GL_EXT_clip_volume_hint *****// -const - GL_CLIP_VOLUME_CLIPPING_HINT_EXT = $80F0; - -function Load_GL_EXT_clip_volume_hint: Boolean; - -//***** GL_EXT_color_subtable *****// -var - glColorSubTableEXT: procedure(target: GLenum; start: GLsizei; count: GLsizei; format: GLenum; _type: GLenum; const data: PGLvoid); stdcall = nil; - glCopyColorSubTableEXT: procedure(target: GLenum; start: GLsizei; x: GLint; y: GLint; width: GLsizei); stdcall = nil; - -function Load_GL_EXT_color_subtable: Boolean; - -//***** GL_EXT_compiled_vertex_array *****// -const - GL_ARRAY_ELEMENT_LOCK_FIRST_EXT = $81A8; - GL_ARRAY_ELEMENT_LOCK_COUNT_EXT = $81A9; -var - glLockArraysEXT: procedure(first: GLint; count: GLsizei); stdcall = nil; - glUnlockArraysEXT: procedure(); stdcall = nil; - -function Load_GL_EXT_compiled_vertex_array: Boolean; - -//***** GL_EXT_convolution *****// -const - GL_CONVOLUTION_1D_EXT = $8010; - GL_CONVOLUTION_2D_EXT = $8011; - GL_SEPARABLE_2D_EXT = $8012; - GL_CONVOLUTION_BORDER_MODE_EXT = $8013; - GL_CONVOLUTION_FILTER_SCALE_EXT = $8014; - GL_CONVOLUTION_FILTER_BIAS_EXT = $8015; - GL_REDUCE_EXT = $8016; - GL_CONVOLUTION_FORMAT_EXT = $8017; - GL_CONVOLUTION_WIDTH_EXT = $8018; - GL_CONVOLUTION_HEIGHT_EXT = $8019; - GL_MAX_CONVOLUTION_WIDTH_EXT = $801A; - GL_MAX_CONVOLUTION_HEIGHT_EXT = $801B; - GL_POST_CONVOLUTION_RED_SCALE_EXT = $801C; - GL_POST_CONVOLUTION_GREEN_SCALE_EXT = $801D; - GL_POST_CONVOLUTION_BLUE_SCALE_EXT = $801E; - GL_POST_CONVOLUTION_ALPHA_SCALE_EXT = $801F; - GL_POST_CONVOLUTION_RED_BIAS_EXT = $8020; - GL_POST_CONVOLUTION_GREEN_BIAS_EXT = $8021; - GL_POST_CONVOLUTION_BLUE_BIAS_EXT = $8022; - GL_POST_CONVOLUTION_ALPHA_BIAS_EXT = $8023; -var - glConvolutionFilter1DEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); stdcall = nil; - glConvolutionFilter2DEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const image: PGLvoid); stdcall = nil; - glCopyConvolutionFilter1DEXT: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); stdcall = nil; - glCopyConvolutionFilter2DEXT: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei; height: GLsizei); stdcall = nil; - glGetConvolutionFilterEXT: procedure(target: GLenum; format: GLenum; _type: GLenum; image: PGLvoid); stdcall = nil; - glSeparableFilter2DEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const row: PGLvoid; const column: PGLvoid); stdcall = nil; - glGetSeparableFilterEXT: procedure(target: GLenum; format: GLenum; _type: GLenum; row: PGLvoid; column: PGLvoid; span: PGLvoid); stdcall = nil; - glConvolutionParameteriEXT: procedure(target: GLenum; pname: GLenum; param: GLint); stdcall = nil; - glConvolutionParameterivEXT: procedure(target: GLenum; pname: GLenum; const params: PGLint); stdcall = nil; - glConvolutionParameterfEXT: procedure(target: GLenum; pname: GLenum; param: GLfloat); stdcall = nil; - glConvolutionParameterfvEXT: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); stdcall = nil; - glGetConvolutionParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetConvolutionParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - -function Load_GL_EXT_convolution: Boolean; - -//***** GL_EXT_histogram *****// -const - GL_HISTOGRAM_EXT = $8024; - GL_PROXY_HISTOGRAM_EXT = $8025; - GL_HISTOGRAM_WIDTH_EXT = $8026; - GL_HISTOGRAM_FORMAT_EXT = $8027; - GL_HISTOGRAM_RED_SIZE_EXT = $8028; - GL_HISTOGRAM_GREEN_SIZE_EXT = $8029; - GL_HISTOGRAM_BLUE_SIZE_EXT = $802A; - GL_HISTOGRAM_ALPHA_SIZE_EXT = $802B; - GL_HISTOGRAM_LUMINANCE_SIZE_EXT = $802C; - GL_HISTOGRAM_SINK_EXT = $802D; - GL_MINMAX_EXT = $802E; - GL_MINMAX_FORMAT_EXT = $802F; - GL_MINMAX_SINK_EXT = $8030; -var - glHistogramEXT: procedure(target: GLenum; width: GLsizei; internalformat: GLenum; sink: GLboolean); stdcall = nil; - glResetHistogramEXT: procedure(target: GLenum); stdcall = nil; - glGetHistogramEXT: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); stdcall = nil; - glGetHistogramParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetHistogramParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glMinmaxEXT: procedure(target: GLenum; internalformat: GLenum; sink: GLboolean); stdcall = nil; - glResetMinmaxEXT: procedure(target: GLenum); stdcall = nil; - glGetMinmaxEXT: procedure(target: GLenum; reset: GLboolean; format: GLenum; _type: GLenum; values: PGLvoid); stdcall = nil; - glGetMinmaxParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetMinmaxParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - -function Load_GL_EXT_histogram: Boolean; - -//***** GL_EXT_multi_draw_arrays *****// -var - glMultiDrawArraysEXT: procedure(mode: GLenum; first: PGLint; count: PGLsizei; primcount: GLsizei); stdcall = nil; - glMultiDrawElementsEXT: procedure(mode: GLenum; count: PGLsizei; _type: GLenum; const indices: PGLvoid; primcount: GLsizei); stdcall = nil; - -function Load_GL_EXT_multi_draw_arrays: Boolean; - -//***** GL_EXT_packed_pixels *****// -const - GL_UNSIGNED_BYTE_3_3_2_EXT = $8032; - GL_UNSIGNED_SHORT_4_4_4_4_EXT = $8033; - GL_UNSIGNED_SHORT_5_5_5_1_EXT = $8034; - GL_UNSIGNED_INT_8_8_8_8_EXT = $8035; - GL_UNSIGNED_INT_10_10_10_2_EXT = $8036; - -function Load_GL_EXT_packed_pixels: Boolean; - -//***** GL_EXT_paletted_texture *****// -const - GL_COLOR_INDEX1_EXT = $80E2; - GL_COLOR_INDEX2_EXT = $80E3; - GL_COLOR_INDEX4_EXT = $80E4; - GL_COLOR_INDEX8_EXT = $80E5; - GL_COLOR_INDEX12_EXT = $80E6; - GL_COLOR_INDEX16_EXT = $80E7; - GL_COLOR_TABLE_FORMAT_EXT = $80D8; - GL_COLOR_TABLE_WIDTH_EXT = $80D9; - GL_COLOR_TABLE_RED_SIZE_EXT = $80DA; - GL_COLOR_TABLE_GREEN_SIZE_EXT = $80DB; - GL_COLOR_TABLE_BLUE_SIZE_EXT = $80DC; - GL_COLOR_TABLE_ALPHA_SIZE_EXT = $80DD; - GL_COLOR_TABLE_LUMINANCE_SIZE_EXT = $80DE; - GL_COLOR_TABLE_INTENSITY_SIZE_EXT = $80DF; - GL_TEXTURE_INDEX_SIZE_EXT = $80ED; - GL_TEXTURE_1D = $0DE0; - GL_TEXTURE_2D = $0DE1; - GL_TEXTURE_3D_EXT = $806F; - // GL_TEXTURE_CUBE_MAP_ARB { already defined } - GL_PROXY_TEXTURE_1D = $8063; - GL_PROXY_TEXTURE_2D = $8064; - GL_PROXY_TEXTURE_3D_EXT = $8070; - // GL_PROXY_TEXTURE_CUBE_MAP_ARB { already defined } - // GL_TEXTURE_1D { already defined } - // GL_TEXTURE_2D { already defined } - // GL_TEXTURE_3D_EXT { already defined } - // GL_TEXTURE_CUBE_MAP_ARB { already defined } -var - glColorTableEXT: procedure(target: GLenum; internalFormat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const data: PGLvoid); stdcall = nil; - // glColorSubTableEXT { already defined } - glGetColorTableEXT: procedure(target: GLenum; format: GLenum; _type: GLenum; data: PGLvoid); stdcall = nil; - glGetColorTableParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetColorTableParameterfvEXT: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - -function Load_GL_EXT_paletted_texture: Boolean; - -//***** GL_EXT_point_parameters *****// -const - GL_POINT_SIZE_MIN_EXT = $8126; - GL_POINT_SIZE_MAX_EXT = $8127; - GL_POINT_FADE_THRESHOLD_SIZE_EXT = $8128; - GL_DISTANCE_ATTENUATION_EXT = $8129; -var - glPointParameterfEXT: procedure(pname: GLenum; param: GLfloat); stdcall = nil; - glPointParameterfvEXT: procedure(pname: GLenum; params: PGLfloat); stdcall = nil; - -function Load_GL_EXT_point_parameters: Boolean; - -//***** GL_EXT_polygon_offset *****// -const - GL_POLYGON_OFFSET_EXT = $8037; - GL_POLYGON_OFFSET_FACTOR_EXT = $8038; - GL_POLYGON_OFFSET_BIAS_EXT = $8039; -var - glPolygonOffsetEXT: procedure(factor: GLfloat; bias: GLfloat); stdcall = nil; - -function Load_GL_EXT_polygon_offset: Boolean; - -//***** GL_EXT_separate_specular_color *****// -const - GL_LIGHT_MODEL_COLOR_CONTROL_EXT = $81F8; - GL_SINGLE_COLOR_EXT = $81F9; - GL_SEPARATE_SPECULAR_COLOR_EXT = $81FA; - -function Load_GL_EXT_separate_specular_color: Boolean; - -//***** GL_EXT_shadow_funcs *****// - -function Load_GL_EXT_shadow_funcs: Boolean; - -//***** GL_EXT_shared_texture_palette *****// -const - GL_SHARED_TEXTURE_PALETTE_EXT = $81FB; - -function Load_GL_EXT_shared_texture_palette: Boolean; - -//***** GL_EXT_stencil_two_side *****// -const - GL_STENCIL_TEST_TWO_SIDE_EXT = $8910; - GL_ACTIVE_STENCIL_FACE_EXT = $8911; -var - glActiveStencilFaceEXT: procedure(face: GLenum); stdcall = nil; - -function Load_GL_EXT_stencil_two_side: Boolean; - -//***** GL_EXT_stencil_wrap *****// -const - GL_INCR_WRAP_EXT = $8507; - GL_DECR_WRAP_EXT = $8508; - -function Load_GL_EXT_stencil_wrap: Boolean; - -//***** GL_EXT_subtexture *****// -var - glTexSubImage1DEXT: procedure(target: GLenum; level: GLint; xoffset: GLint; width: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); stdcall = nil; - glTexSubImage2DEXT: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); stdcall = nil; - glTexSubImage3DEXT: procedure(target: GLenum; level: GLint; xoffset: GLint; yoffset: GLint; zoffset: GLint; width: GLsizei; height: GLsizei; depth: GLsizei; format: GLenum; _type: GLenum; const pixels: PGLvoid); stdcall = nil; - -function Load_GL_EXT_subtexture: Boolean; - -//***** GL_EXT_texture3D *****// -const - GL_PACK_SKIP_IMAGES_EXT = $806B; - GL_PACK_IMAGE_HEIGHT_EXT = $806C; - GL_UNPACK_SKIP_IMAGES_EXT = $806D; - GL_UNPACK_IMAGE_HEIGHT_EXT = $806E; - // GL_TEXTURE_3D_EXT { already defined } - // GL_PROXY_TEXTURE_3D_EXT { already defined } - GL_TEXTURE_DEPTH_EXT = $8071; - GL_TEXTURE_WRAP_R_EXT = $8072; - GL_MAX_3D_TEXTURE_SIZE_EXT = $8073; -var - glTexImage3DEXT: procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; depth: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); stdcall = nil; - -function Load_GL_EXT_texture3D: Boolean; - -//***** GL_EXT_texture_compression_s3tc *****// -const - GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0; - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1; - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2; - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3; - -function Load_GL_EXT_texture_compression_s3tc: Boolean; - -//***** GL_EXT_texture_env_add *****// - -function Load_GL_EXT_texture_env_add: Boolean; - -//***** GL_EXT_texture_env_combine *****// -const - GL_COMBINE_EXT = $8570; - GL_COMBINE_RGB_EXT = $8571; - GL_COMBINE_ALPHA_EXT = $8572; - GL_SOURCE0_RGB_EXT = $8580; - GL_SOURCE1_RGB_EXT = $8581; - GL_SOURCE2_RGB_EXT = $8582; - GL_SOURCE0_ALPHA_EXT = $8588; - GL_SOURCE1_ALPHA_EXT = $8589; - GL_SOURCE2_ALPHA_EXT = $858A; - GL_OPERAND0_RGB_EXT = $8590; - GL_OPERAND1_RGB_EXT = $8591; - GL_OPERAND2_RGB_EXT = $8592; - GL_OPERAND0_ALPHA_EXT = $8598; - GL_OPERAND1_ALPHA_EXT = $8599; - GL_OPERAND2_ALPHA_EXT = $859A; - GL_RGB_SCALE_EXT = $8573; - GL_ADD_SIGNED_EXT = $8574; - GL_INTERPOLATE_EXT = $8575; - GL_CONSTANT_EXT = $8576; - GL_PRIMARY_COLOR_EXT = $8577; - GL_PREVIOUS_EXT = $8578; - -function Load_GL_EXT_texture_env_combine: Boolean; - -//***** GL_EXT_texture_env_dot3 *****// -const - GL_DOT3_RGB_EXT = $8740; - GL_DOT3_RGBA_EXT = $8741; - -function Load_GL_EXT_texture_env_dot3: Boolean; - -//***** GL_EXT_texture_filter_anisotropic *****// -const - GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE; - GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF; - -function Load_GL_EXT_texture_filter_anisotropic: Boolean; - -//***** GL_EXT_texture_lod_bias *****// -const - GL_TEXTURE_FILTER_CONTROL_EXT = $8500; - GL_TEXTURE_LOD_BIAS_EXT = $8501; - GL_MAX_TEXTURE_LOD_BIAS_EXT = $84FD; - -function Load_GL_EXT_texture_lod_bias: Boolean; - -//***** GL_EXT_texture_object *****// -const - GL_TEXTURE_PRIORITY_EXT = $8066; - GL_TEXTURE_RESIDENT_EXT = $8067; - GL_TEXTURE_1D_BINDING_EXT = $8068; - GL_TEXTURE_2D_BINDING_EXT = $8069; - GL_TEXTURE_3D_BINDING_EXT = $806A; -var - glGenTexturesEXT: procedure(n: GLsizei; textures: PGLuint); stdcall = nil; - glDeleteTexturesEXT: procedure(n: GLsizei; const textures: PGLuint); stdcall = nil; - glBindTextureEXT: procedure(target: GLenum; texture: GLuint); stdcall = nil; - glPrioritizeTexturesEXT: procedure(n: GLsizei; const textures: PGLuint; const priorities: PGLclampf); stdcall = nil; - glAreTexturesResidentEXT: function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; stdcall = nil; - glIsTextureEXT: function(texture: GLuint): GLboolean; stdcall = nil; - -function Load_GL_EXT_texture_object: Boolean; - -//***** GL_EXT_vertex_array *****// -const - GL_VERTEX_ARRAY_EXT = $8074; - GL_NORMAL_ARRAY_EXT = $8075; - GL_COLOR_ARRAY_EXT = $8076; - GL_INDEX_ARRAY_EXT = $8077; - GL_TEXTURE_COORD_ARRAY_EXT = $8078; - GL_EDGE_FLAG_ARRAY_EXT = $8079; - GL_DOUBLE_EXT = $140A; - GL_VERTEX_ARRAY_SIZE_EXT = $807A; - GL_VERTEX_ARRAY_TYPE_EXT = $807B; - GL_VERTEX_ARRAY_STRIDE_EXT = $807C; - GL_VERTEX_ARRAY_COUNT_EXT = $807D; - GL_NORMAL_ARRAY_TYPE_EXT = $807E; - GL_NORMAL_ARRAY_STRIDE_EXT = $807F; - GL_NORMAL_ARRAY_COUNT_EXT = $8080; - GL_COLOR_ARRAY_SIZE_EXT = $8081; - GL_COLOR_ARRAY_TYPE_EXT = $8082; - GL_COLOR_ARRAY_STRIDE_EXT = $8083; - GL_COLOR_ARRAY_COUNT_EXT = $8084; - GL_INDEX_ARRAY_TYPE_EXT = $8085; - GL_INDEX_ARRAY_STRIDE_EXT = $8086; - GL_INDEX_ARRAY_COUNT_EXT = $8087; - GL_TEXTURE_COORD_ARRAY_SIZE_EXT = $8088; - GL_TEXTURE_COORD_ARRAY_TYPE_EXT = $8089; - GL_TEXTURE_COORD_ARRAY_STRIDE_EXT = $808A; - GL_TEXTURE_COORD_ARRAY_COUNT_EXT = $808B; - GL_EDGE_FLAG_ARRAY_STRIDE_EXT = $808C; - GL_EDGE_FLAG_ARRAY_COUNT_EXT = $808D; - GL_VERTEX_ARRAY_POINTER_EXT = $808E; - GL_NORMAL_ARRAY_POINTER_EXT = $808F; - GL_COLOR_ARRAY_POINTER_EXT = $8090; - GL_INDEX_ARRAY_POINTER_EXT = $8091; - GL_TEXTURE_COORD_ARRAY_POINTER_EXT = $8092; - GL_EDGE_FLAG_ARRAY_POINTER_EXT = $8093; -var - glArrayElementEXT: procedure(i: GLint); stdcall = nil; - glDrawArraysEXT: procedure(mode: GLenum; first: GLint; count: GLsizei); stdcall = nil; - glVertexPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); stdcall = nil; - glNormalPointerEXT: procedure(_type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); stdcall = nil; - glColorPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); stdcall = nil; - glIndexPointerEXT: procedure(_type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); stdcall = nil; - glTexCoordPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; count: GLsizei; const pointer: PGLvoid); stdcall = nil; - glEdgeFlagPointerEXT: procedure(stride: GLsizei; count: GLsizei; const pointer: PGLboolean); stdcall = nil; - glGetPointervEXT: procedure(pname: GLenum; params: PGLvoid); stdcall = nil; - -function Load_GL_EXT_vertex_array: Boolean; - -//***** GL_EXT_vertex_shader *****// -const - GL_VERTEX_SHADER_EXT = $8780; - GL_VARIANT_VALUE_EXT = $87E4; - GL_VARIANT_DATATYPE_EXT = $87E5; - GL_VARIANT_ARRAY_STRIDE_EXT = $87E6; - GL_VARIANT_ARRAY_TYPE_EXT = $87E7; - GL_VARIANT_ARRAY_EXT = $87E8; - GL_VARIANT_ARRAY_POINTER_EXT = $87E9; - GL_INVARIANT_VALUE_EXT = $87EA; - GL_INVARIANT_DATATYPE_EXT = $87EB; - GL_LOCAL_CONSTANT_VALUE_EXT = $87EC; - GL_LOCAL_CONSTANT_DATATYPE_EXT = $87ED; - GL_OP_INDEX_EXT = $8782; - GL_OP_NEGATE_EXT = $8783; - GL_OP_DOT3_EXT = $8784; - GL_OP_DOT4_EXT = $8785; - GL_OP_MUL_EXT = $8786; - GL_OP_ADD_EXT = $8787; - GL_OP_MADD_EXT = $8788; - GL_OP_FRAC_EXT = $8789; - GL_OP_MAX_EXT = $878A; - GL_OP_MIN_EXT = $878B; - GL_OP_SET_GE_EXT = $878C; - GL_OP_SET_LT_EXT = $878D; - GL_OP_CLAMP_EXT = $878E; - GL_OP_FLOOR_EXT = $878F; - GL_OP_ROUND_EXT = $8790; - GL_OP_EXP_BASE_2_EXT = $8791; - GL_OP_LOG_BASE_2_EXT = $8792; - GL_OP_POWER_EXT = $8793; - GL_OP_RECIP_EXT = $8794; - GL_OP_RECIP_SQRT_EXT = $8795; - GL_OP_SUB_EXT = $8796; - GL_OP_CROSS_PRODUCT_EXT = $8797; - GL_OP_MULTIPLY_MATRIX_EXT = $8798; - GL_OP_MOV_EXT = $8799; - GL_OUTPUT_VERTEX_EXT = $879A; - GL_OUTPUT_COLOR0_EXT = $879B; - GL_OUTPUT_COLOR1_EXT = $879C; - GL_OUTPUT_TEXTURE_COORD0_EXT = $879D; - GL_OUTPUT_TEXTURE_COORD1_EXT = $879E; - GL_OUTPUT_TEXTURE_COORD2_EXT = $879F; - GL_OUTPUT_TEXTURE_COORD3_EXT = $87A0; - GL_OUTPUT_TEXTURE_COORD4_EXT = $87A1; - GL_OUTPUT_TEXTURE_COORD5_EXT = $87A2; - GL_OUTPUT_TEXTURE_COORD6_EXT = $87A3; - GL_OUTPUT_TEXTURE_COORD7_EXT = $87A4; - GL_OUTPUT_TEXTURE_COORD8_EXT = $87A5; - GL_OUTPUT_TEXTURE_COORD9_EXT = $87A6; - GL_OUTPUT_TEXTURE_COORD10_EXT = $87A7; - GL_OUTPUT_TEXTURE_COORD11_EXT = $87A8; - GL_OUTPUT_TEXTURE_COORD12_EXT = $87A9; - GL_OUTPUT_TEXTURE_COORD13_EXT = $87AA; - GL_OUTPUT_TEXTURE_COORD14_EXT = $87AB; - GL_OUTPUT_TEXTURE_COORD15_EXT = $87AC; - GL_OUTPUT_TEXTURE_COORD16_EXT = $87AD; - GL_OUTPUT_TEXTURE_COORD17_EXT = $87AE; - GL_OUTPUT_TEXTURE_COORD18_EXT = $87AF; - GL_OUTPUT_TEXTURE_COORD19_EXT = $87B0; - GL_OUTPUT_TEXTURE_COORD20_EXT = $87B1; - GL_OUTPUT_TEXTURE_COORD21_EXT = $87B2; - GL_OUTPUT_TEXTURE_COORD22_EXT = $87B3; - GL_OUTPUT_TEXTURE_COORD23_EXT = $87B4; - GL_OUTPUT_TEXTURE_COORD24_EXT = $87B5; - GL_OUTPUT_TEXTURE_COORD25_EXT = $87B6; - GL_OUTPUT_TEXTURE_COORD26_EXT = $87B7; - GL_OUTPUT_TEXTURE_COORD27_EXT = $87B8; - GL_OUTPUT_TEXTURE_COORD28_EXT = $87B9; - GL_OUTPUT_TEXTURE_COORD29_EXT = $87BA; - GL_OUTPUT_TEXTURE_COORD30_EXT = $87BB; - GL_OUTPUT_TEXTURE_COORD31_EXT = $87BC; - GL_OUTPUT_FOG_EXT = $87BD; - GL_SCALAR_EXT = $87BE; - GL_VECTOR_EXT = $87BF; - GL_MATRIX_EXT = $87C0; - GL_VARIANT_EXT = $87C1; - GL_INVARIANT_EXT = $87C2; - GL_LOCAL_CONSTANT_EXT = $87C3; - GL_LOCAL_EXT = $87C4; - GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT = $87C5; - GL_MAX_VERTEX_SHADER_VARIANTS_EXT = $87C6; - GL_MAX_VERTEX_SHADER_INVARIANTS_EXT = $87C7; - GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87C8; - GL_MAX_VERTEX_SHADER_LOCALS_EXT = $87C9; - GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT = $87CA; - GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT = $87CB; - GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87CC; - GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT = $87CD; - GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT = $87CE; - GL_VERTEX_SHADER_INSTRUCTIONS_EXT = $87CF; - GL_VERTEX_SHADER_VARIANTS_EXT = $87D0; - GL_VERTEX_SHADER_INVARIANTS_EXT = $87D1; - GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT = $87D2; - GL_VERTEX_SHADER_LOCALS_EXT = $87D3; - GL_VERTEX_SHADER_BINDING_EXT = $8781; - GL_VERTEX_SHADER_OPTIMIZED_EXT = $87D4; - GL_X_EXT = $87D5; - GL_Y_EXT = $87D6; - GL_Z_EXT = $87D7; - GL_W_EXT = $87D8; - GL_NEGATIVE_X_EXT = $87D9; - GL_NEGATIVE_Y_EXT = $87DA; - GL_NEGATIVE_Z_EXT = $87DB; - GL_NEGATIVE_W_EXT = $87DC; - GL_ZERO_EXT = $87DD; - GL_ONE_EXT = $87DE; - GL_NEGATIVE_ONE_EXT = $87DF; - GL_NORMALIZED_RANGE_EXT = $87E0; - GL_FULL_RANGE_EXT = $87E1; - GL_CURRENT_VERTEX_EXT = $87E2; - GL_MVP_MATRIX_EXT = $87E3; -var - glBeginVertexShaderEXT: procedure(); stdcall = nil; - glEndVertexShaderEXT: procedure(); stdcall = nil; - glBindVertexShaderEXT: procedure(id: GLuint); stdcall = nil; - glGenVertexShadersEXT: function(range: GLuint): GLuint; stdcall = nil; - glDeleteVertexShaderEXT: procedure(id: GLuint); stdcall = nil; - glShaderOp1EXT: procedure(op: GLenum; res: GLuint; arg1: GLuint); stdcall = nil; - glShaderOp2EXT: procedure(op: GLenum; res: GLuint; arg1: GLuint; arg2: GLuint); stdcall = nil; - glShaderOp3EXT: procedure(op: GLenum; res: GLuint; arg1: GLuint; arg2: GLuint; arg3: GLuint); stdcall = nil; - glSwizzleEXT: procedure(res: GLuint; _in: GLuint; outX: GLenum; outY: GLenum; outZ: GLenum; outW: GLenum); stdcall = nil; - glWriteMaskEXT: procedure(res: GLuint; _in: GLuint; outX: GLenum; outY: GLenum; outZ: GLenum; outW: GLenum); stdcall = nil; - glInsertComponentEXT: procedure(res: GLuint; src: GLuint; num: GLuint); stdcall = nil; - glExtractComponentEXT: procedure(res: GLuint; src: GLuint; num: GLuint); stdcall = nil; - glGenSymbolsEXT: function(datatype: GLenum; storagetype: GLenum; range: GLenum; components: GLuint): GLuint; stdcall = nil; - glSetInvariantEXT: procedure(id: GLuint; _type: GLenum; addr: PGLvoid); stdcall = nil; - glSetLocalConstantEXT: procedure(id: GLuint; _type: GLenum; addr: PGLvoid); stdcall = nil; - glVariantbvEXT: procedure(id: GLuint; addr: PGLbyte); stdcall = nil; - glVariantsvEXT: procedure(id: GLuint; addr: PGLshort); stdcall = nil; - glVariantivEXT: procedure(id: GLuint; addr: PGLint); stdcall = nil; - glVariantfvEXT: procedure(id: GLuint; addr: PGLfloat); stdcall = nil; - glVariantdvEXT: procedure(id: GLuint; addr: PGLdouble); stdcall = nil; - glVariantubvEXT: procedure(id: GLuint; addr: PGLubyte); stdcall = nil; - glVariantusvEXT: procedure(id: GLuint; addr: PGLushort); stdcall = nil; - glVariantuivEXT: procedure(id: GLuint; addr: PGLuint); stdcall = nil; - glVariantPointerEXT: procedure(id: GLuint; _type: GLenum; stride: GLuint; addr: PGLvoid); stdcall = nil; - glEnableVariantClientStateEXT: procedure(id: GLuint); stdcall = nil; - glDisableVariantClientStateEXT: procedure(id: GLuint); stdcall = nil; - glBindLightParameterEXT: function(light: GLenum; value: GLenum): GLuint; stdcall = nil; - glBindMaterialParameterEXT: function(face: GLenum; value: GLenum): GLuint; stdcall = nil; - glBindTexGenParameterEXT: function(_unit: GLenum; coord: GLenum; value: GLenum): GLuint; stdcall = nil; - glBindTextureUnitParameterEXT: function(_unit: GLenum; value: GLenum): GLuint; stdcall = nil; - glBindParameterEXT: function(value: GLenum): GLuint; stdcall = nil; - glIsVariantEnabledEXT: function(id: GLuint; cap: GLenum): GLboolean; stdcall = nil; - glGetVariantBooleanvEXT: procedure(id: GLuint; value: GLenum; data: PGLboolean); stdcall = nil; - glGetVariantIntegervEXT: procedure(id: GLuint; value: GLenum; data: PGLint); stdcall = nil; - glGetVariantFloatvEXT: procedure(id: GLuint; value: GLenum; data: PGLfloat); stdcall = nil; - glGetVariantPointervEXT: procedure(id: GLuint; value: GLenum; data: PGLvoid); stdcall = nil; - glGetInvariantBooleanvEXT: procedure(id: GLuint; value: GLenum; data: PGLboolean); stdcall = nil; - glGetInvariantIntegervEXT: procedure(id: GLuint; value: GLenum; data: PGLint); stdcall = nil; - glGetInvariantFloatvEXT: procedure(id: GLuint; value: GLenum; data: PGLfloat); stdcall = nil; - glGetLocalConstantBooleanvEXT: procedure(id: GLuint; value: GLenum; data: PGLboolean); stdcall = nil; - glGetLocalConstantIntegervEXT: procedure(id: GLuint; value: GLenum; data: PGLint); stdcall = nil; - glGetLocalConstantFloatvEXT: procedure(id: GLuint; value: GLenum; data: PGLfloat); stdcall = nil; - -function Load_GL_EXT_vertex_shader: Boolean; - -//***** GL_EXT_vertex_weighting *****// -const - GL_VERTEX_WEIGHTING_EXT = $8509; - GL_MODELVIEW0_EXT = $1700; - GL_MODELVIEW1_EXT = $850A; - GL_MODELVIEW0_MATRIX_EXT = $0BA6; - GL_MODELVIEW1_MATRIX_EXT = $8506; - GL_CURRENT_VERTEX_WEIGHT_EXT = $850B; - GL_VERTEX_WEIGHT_ARRAY_EXT = $850C; - GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT = $850D; - GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT = $850E; - GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT = $850F; - GL_MODELVIEW0_STACK_DEPTH_EXT = $0BA3; - GL_MODELVIEW1_STACK_DEPTH_EXT = $8502; - GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT = $8510; -var - glVertexWeightfEXT: procedure(weight: GLfloat); stdcall = nil; - glVertexWeightfvEXT: procedure(weight: PGLfloat); stdcall = nil; - glVertexWeightPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); stdcall = nil; - -function Load_GL_EXT_vertex_weighting: Boolean; - -//***** GL_HP_occlusion_test *****// -const - GL_OCCLUSION_TEST_HP = $8165; - GL_OCCLUSION_TEST_RESULT_HP = $8166; - -function Load_GL_HP_occlusion_test: Boolean; - -//***** GL_NV_blend_square *****// - -function Load_GL_NV_blend_square: Boolean; - -//***** GL_NV_copy_depth_to_color *****// -const - GL_DEPTH_STENCIL_TO_RGBA_NV = $886E; - GL_DEPTH_STENCIL_TO_BGRA_NV = $886F; - -function Load_GL_NV_copy_depth_to_color: Boolean; - -//***** GL_NV_depth_clamp *****// -const - GL_DEPTH_CLAMP_NV = $864F; - -function Load_GL_NV_depth_clamp: Boolean; - -//***** GL_NV_evaluators *****// -const - GL_EVAL_2D_NV = $86C0; - GL_EVAL_TRIANGULAR_2D_NV = $86C1; - GL_MAP_TESSELLATION_NV = $86C2; - GL_MAP_ATTRIB_U_ORDER_NV = $86C3; - GL_MAP_ATTRIB_V_ORDER_NV = $86C4; - GL_EVAL_FRACTIONAL_TESSELLATION_NV = $86C5; - GL_EVAL_VERTEX_ATTRIB0_NV = $86C6; - GL_EVAL_VERTEX_ATTRIB1_NV = $86C7; - GL_EVAL_VERTEX_ATTRIB2_NV = $86C8; - GL_EVAL_VERTEX_ATTRIB3_NV = $86C9; - GL_EVAL_VERTEX_ATTRIB4_NV = $86CA; - GL_EVAL_VERTEX_ATTRIB5_NV = $86CB; - GL_EVAL_VERTEX_ATTRIB6_NV = $86CC; - GL_EVAL_VERTEX_ATTRIB7_NV = $86CD; - GL_EVAL_VERTEX_ATTRIB8_NV = $86CE; - GL_EVAL_VERTEX_ATTRIB9_NV = $86CF; - GL_EVAL_VERTEX_ATTRIB10_NV = $86D0; - GL_EVAL_VERTEX_ATTRIB11_NV = $86D1; - GL_EVAL_VERTEX_ATTRIB12_NV = $86D2; - GL_EVAL_VERTEX_ATTRIB13_NV = $86D3; - GL_EVAL_VERTEX_ATTRIB14_NV = $86D4; - GL_EVAL_VERTEX_ATTRIB15_NV = $86D5; - GL_MAX_MAP_TESSELLATION_NV = $86D6; - GL_MAX_RATIONAL_EVAL_ORDER_NV = $86D7; -var - glMapControlPointsNV: procedure(target: GLenum; index: GLuint; _type: GLenum; ustride: GLsizei; vstride: GLsizei; uorder: GLint; vorder: GLint; _packed: GLboolean; const points: PGLvoid); stdcall = nil; - glMapParameterivNV: procedure(target: GLenum; pname: GLenum; const params: PGLint); stdcall = nil; - glMapParameterfvNV: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); stdcall = nil; - glGetMapControlPointsNV: procedure(target: GLenum; index: GLuint; _type: GLenum; ustride: GLsizei; vstride: GLsizei; _packed: GLboolean; points: PGLvoid); stdcall = nil; - glGetMapParameterivNV: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetMapParameterfvNV: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetMapAttribParameterivNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetMapAttribParameterfvNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glEvalMapsNV: procedure(target: GLenum; mode: GLenum); stdcall = nil; - -function Load_GL_NV_evaluators: Boolean; - -//***** GL_NV_fence *****// -const - GL_ALL_COMPLETED_NV = $84F2; - GL_FENCE_STATUS_NV = $84F3; - GL_FENCE_CONDITION_NV = $84F4; -var - glGenFencesNV: procedure(n: GLsizei; fences: PGLuint); stdcall = nil; - glDeleteFencesNV: procedure(n: GLsizei; const fences: PGLuint); stdcall = nil; - glSetFenceNV: procedure(fence: GLuint; condition: GLenum); stdcall = nil; - glTestFenceNV: function(fence: GLuint): GLboolean; stdcall = nil; - glFinishFenceNV: procedure(fence: GLuint); stdcall = nil; - glIsFenceNV: function(fence: GLuint): GLboolean; stdcall = nil; - glGetFenceivNV: procedure(fence: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - -function Load_GL_NV_fence: Boolean; - -//***** GL_NV_fog_distance *****// -const - GL_FOG_DISTANCE_MODE_NV = $855A; - GL_EYE_RADIAL_NV = $855B; - GL_EYE_PLANE_ABSOLUTE_NV = $855C; - -function Load_GL_NV_fog_distance: Boolean; - -//***** GL_NV_light_max_exponent *****// -const - GL_MAX_SHININESS_NV = $8504; - GL_MAX_SPOT_EXPONENT_NV = $8505; - -function Load_GL_NV_light_max_exponent: Boolean; - -//***** GL_NV_multisample_filter_hint *****// -const - GL_MULTISAMPLE_FILTER_HINT_NV = $8534; - -function Load_GL_NV_multisample_filter_hint: Boolean; - -//***** GL_NV_occlusion_query *****// - // GL_OCCLUSION_TEST_HP { already defined } - // GL_OCCLUSION_TEST_RESULT_HP { already defined } -const - GL_PIXEL_COUNTER_BITS_NV = $8864; - GL_CURRENT_OCCLUSION_QUERY_ID_NV = $8865; - GL_PIXEL_COUNT_NV = $8866; - GL_PIXEL_COUNT_AVAILABLE_NV = $8867; -var - glGenOcclusionQueriesNV: procedure(n: GLsizei; ids: PGLuint); stdcall = nil; - glDeleteOcclusionQueriesNV: procedure(n: GLsizei; const ids: PGLuint); stdcall = nil; - glIsOcclusionQueryNV: function(id: GLuint): GLboolean; stdcall = nil; - glBeginOcclusionQueryNV: procedure(id: GLuint); stdcall = nil; - glEndOcclusionQueryNV: procedure(); stdcall = nil; - glGetOcclusionQueryivNV: procedure(id: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetOcclusionQueryuivNV: procedure(id: GLuint; pname: GLenum; params: PGLuint); stdcall = nil; - -function Load_GL_NV_occlusion_query: Boolean; - -//***** GL_NV_packed_depth_stencil *****// -const - GL_DEPTH_STENCIL_NV = $84F9; - GL_UNSIGNED_INT_24_8_NV = $84FA; - -function Load_GL_NV_packed_depth_stencil: Boolean; - -//***** GL_NV_point_sprite *****// -const - GL_POINT_SPRITE_NV = $8861; - GL_COORD_REPLACE_NV = $8862; - GL_POINT_SPRITE_R_MODE_NV = $8863; -var - glPointParameteriNV: procedure(pname: GLenum; param: GLint); stdcall = nil; - glPointParameterivNV: procedure(pname: GLenum; const params: PGLint); stdcall = nil; - -function Load_GL_NV_point_sprite: Boolean; - -//***** GL_NV_register_combiners *****// -const - GL_REGISTER_COMBINERS_NV = $8522; - GL_COMBINER0_NV = $8550; - GL_COMBINER1_NV = $8551; - GL_COMBINER2_NV = $8552; - GL_COMBINER3_NV = $8553; - GL_COMBINER4_NV = $8554; - GL_COMBINER5_NV = $8555; - GL_COMBINER6_NV = $8556; - GL_COMBINER7_NV = $8557; - GL_VARIABLE_A_NV = $8523; - GL_VARIABLE_B_NV = $8524; - GL_VARIABLE_C_NV = $8525; - GL_VARIABLE_D_NV = $8526; - GL_VARIABLE_E_NV = $8527; - GL_VARIABLE_F_NV = $8528; - GL_VARIABLE_G_NV = $8529; - GL_CONSTANT_COLOR0_NV = $852A; - GL_CONSTANT_COLOR1_NV = $852B; - GL_PRIMARY_COLOR_NV = $852C; - GL_SECONDARY_COLOR_NV = $852D; - GL_SPARE0_NV = $852E; - GL_SPARE1_NV = $852F; - GL_UNSIGNED_IDENTITY_NV = $8536; - GL_UNSIGNED_INVERT_NV = $8537; - GL_EXPAND_NORMAL_NV = $8538; - GL_EXPAND_NEGATE_NV = $8539; - GL_HALF_BIAS_NORMAL_NV = $853A; - GL_HALF_BIAS_NEGATE_NV = $853B; - GL_SIGNED_IDENTITY_NV = $853C; - GL_SIGNED_NEGATE_NV = $853D; - GL_E_TIMES_F_NV = $8531; - GL_SPARE0_PLUS_SECONDARY_COLOR_NV = $8532; - GL_SCALE_BY_TWO_NV = $853E; - GL_SCALE_BY_FOUR_NV = $853F; - GL_SCALE_BY_ONE_HALF_NV = $8540; - GL_BIAS_BY_NEGATIVE_ONE_HALF_NV = $8541; - GL_DISCARD_NV = $8530; - GL_COMBINER_INPUT_NV = $8542; - GL_COMBINER_MAPPING_NV = $8543; - GL_COMBINER_COMPONENT_USAGE_NV = $8544; - GL_COMBINER_AB_DOT_PRODUCT_NV = $8545; - GL_COMBINER_CD_DOT_PRODUCT_NV = $8546; - GL_COMBINER_MUX_SUM_NV = $8547; - GL_COMBINER_SCALE_NV = $8548; - GL_COMBINER_BIAS_NV = $8549; - GL_COMBINER_AB_OUTPUT_NV = $854A; - GL_COMBINER_CD_OUTPUT_NV = $854B; - GL_COMBINER_SUM_OUTPUT_NV = $854C; - GL_NUM_GENERAL_COMBINERS_NV = $854E; - GL_COLOR_SUM_CLAMP_NV = $854F; - GL_MAX_GENERAL_COMBINERS_NV = $854D; -var - glCombinerParameterfvNV: procedure(pname: GLenum; const params: PGLfloat); stdcall = nil; - glCombinerParameterivNV: procedure(pname: GLenum; const params: PGLint); stdcall = nil; - glCombinerParameterfNV: procedure(pname: GLenum; param: GLfloat); stdcall = nil; - glCombinerParameteriNV: procedure(pname: GLenum; param: GLint); stdcall = nil; - glCombinerInputNV: procedure(stage: GLenum; portion: GLenum; variable: GLenum; input: GLenum; mapping: GLenum; componentUsage: GLenum); stdcall = nil; - glCombinerOutputNV: procedure(stage: GLenum; portion: GLenum; abOutput: GLenum; cdOutput: GLenum; sumOutput: GLenum; scale: GLenum; bias: GLenum; abDotProduct: GLboolean; cdDotProduct: GLboolean; muxSum: GLboolean); stdcall = nil; - glFinalCombinerInputNV: procedure(variable: GLenum; input: GLenum; mapping: GLenum; componentUsage: GLenum); stdcall = nil; - glGetCombinerInputParameterfvNV: procedure(stage: GLenum; portion: GLenum; variable: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetCombinerInputParameterivNV: procedure(stage: GLenum; portion: GLenum; variable: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetCombinerOutputParameterfvNV: procedure(stage: GLenum; portion: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetCombinerOutputParameterivNV: procedure(stage: GLenum; portion: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetFinalCombinerInputParameterfvNV: procedure(variable: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetFinalCombinerInputParameterivNV: procedure(variable: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - -function Load_GL_NV_register_combiners: Boolean; - -//***** GL_NV_register_combiners2 *****// -const - GL_PER_STAGE_CONSTANTS_NV = $8535; -var - glCombinerStageParameterfvNV: procedure(stage: GLenum; pname: GLenum; const params: PGLfloat); stdcall = nil; - glGetCombinerStageParameterfvNV: procedure(stage: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - -function Load_GL_NV_register_combiners2: Boolean; - -//***** GL_NV_texgen_emboss *****// -const - GL_EMBOSS_MAP_NV = $855F; - GL_EMBOSS_LIGHT_NV = $855D; - GL_EMBOSS_CONSTANT_NV = $855E; - -function Load_GL_NV_texgen_emboss: Boolean; - -//***** GL_NV_texgen_reflection *****// -const - GL_NORMAL_MAP_NV = $8511; - GL_REFLECTION_MAP_NV = $8512; - -function Load_GL_NV_texgen_reflection: Boolean; - -//***** GL_NV_texture_compression_vtc *****// - // GL_COMPRESSED_RGB_S3TC_DXT1_EXT { already defined } - // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT { already defined } - // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT { already defined } - // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT { already defined } - -function Load_GL_NV_texture_compression_vtc: Boolean; - -//***** GL_NV_texture_env_combine4 *****// -const - GL_COMBINE4_NV = $8503; - GL_SOURCE3_RGB_NV = $8583; - GL_SOURCE3_ALPHA_NV = $858B; - GL_OPERAND3_RGB_NV = $8593; - GL_OPERAND3_ALPHA_NV = $859B; - -function Load_GL_NV_texture_env_combine4: Boolean; - -//***** GL_NV_texture_rectangle *****// -const - GL_TEXTURE_RECTANGLE_NV = $84F5; - GL_TEXTURE_BINDING_RECTANGLE_NV = $84F6; - GL_PROXY_TEXTURE_RECTANGLE_NV = $84F7; - GL_MAX_RECTANGLE_TEXTURE_SIZE_NV = $84F8; - -function Load_GL_NV_texture_rectangle: Boolean; - -//***** GL_NV_texture_shader *****// -const - GL_TEXTURE_SHADER_NV = $86DE; - GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV = $86D9; - GL_SHADER_OPERATION_NV = $86DF; - GL_CULL_MODES_NV = $86E0; - GL_OFFSET_TEXTURE_MATRIX_NV = $86E1; - GL_OFFSET_TEXTURE_SCALE_NV = $86E2; - GL_OFFSET_TEXTURE_BIAS_NV = $86E3; - GL_PREVIOUS_TEXTURE_INPUT_NV = $86E4; - GL_CONST_EYE_NV = $86E5; - GL_SHADER_CONSISTENT_NV = $86DD; - GL_PASS_THROUGH_NV = $86E6; - GL_CULL_FRAGMENT_NV = $86E7; - GL_OFFSET_TEXTURE_2D_NV = $86E8; - GL_OFFSET_TEXTURE_RECTANGLE_NV = $864C; - GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV = $864D; - GL_DEPENDENT_AR_TEXTURE_2D_NV = $86E9; - GL_DEPENDENT_GB_TEXTURE_2D_NV = $86EA; - GL_DOT_PRODUCT_NV = $86EC; - GL_DOT_PRODUCT_DEPTH_REPLACE_NV = $86ED; - GL_DOT_PRODUCT_TEXTURE_2D_NV = $86EE; - GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV = $864E; - GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV = $86F0; - GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV = $86F1; - GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV = $86F2; - GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV = $86F3; - GL_HILO_NV = $86F4; - GL_DSDT_NV = $86F5; - GL_DSDT_MAG_NV = $86F6; - GL_DSDT_MAG_VIB_NV = $86F7; - GL_UNSIGNED_INT_S8_S8_8_8_NV = $86DA; - GL_UNSIGNED_INT_8_8_S8_S8_REV_NV = $86DB; - GL_SIGNED_RGBA_NV = $86FB; - GL_SIGNED_RGBA8_NV = $86FC; - GL_SIGNED_RGB_NV = $86FE; - GL_SIGNED_RGB8_NV = $86FF; - GL_SIGNED_LUMINANCE_NV = $8701; - GL_SIGNED_LUMINANCE8_NV = $8702; - GL_SIGNED_LUMINANCE_ALPHA_NV = $8703; - GL_SIGNED_LUMINANCE8_ALPHA8_NV = $8704; - GL_SIGNED_ALPHA_NV = $8705; - GL_SIGNED_ALPHA8_NV = $8706; - GL_SIGNED_INTENSITY_NV = $8707; - GL_SIGNED_INTENSITY8_NV = $8708; - GL_SIGNED_RGB_UNSIGNED_ALPHA_NV = $870C; - GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV = $870D; - GL_HILO16_NV = $86F8; - GL_SIGNED_HILO_NV = $86F9; - GL_SIGNED_HILO16_NV = $86FA; - GL_DSDT8_NV = $8709; - GL_DSDT8_MAG8_NV = $870A; - GL_DSDT_MAG_INTENSITY_NV = $86DC; - GL_DSDT8_MAG8_INTENSITY8_NV = $870B; - GL_HI_SCALE_NV = $870E; - GL_LO_SCALE_NV = $870F; - GL_DS_SCALE_NV = $8710; - GL_DT_SCALE_NV = $8711; - GL_MAGNITUDE_SCALE_NV = $8712; - GL_VIBRANCE_SCALE_NV = $8713; - GL_HI_BIAS_NV = $8714; - GL_LO_BIAS_NV = $8715; - GL_DS_BIAS_NV = $8716; - GL_DT_BIAS_NV = $8717; - GL_MAGNITUDE_BIAS_NV = $8718; - GL_VIBRANCE_BIAS_NV = $8719; - GL_TEXTURE_BORDER_VALUES_NV = $871A; - GL_TEXTURE_HI_SIZE_NV = $871B; - GL_TEXTURE_LO_SIZE_NV = $871C; - GL_TEXTURE_DS_SIZE_NV = $871D; - GL_TEXTURE_DT_SIZE_NV = $871E; - GL_TEXTURE_MAG_SIZE_NV = $871F; - -function Load_GL_NV_texture_shader: Boolean; - -//***** GL_NV_texture_shader2 *****// -const - GL_DOT_PRODUCT_TEXTURE_3D_NV = $86EF; - // GL_HILO_NV { already defined } - // GL_DSDT_NV { already defined } - // GL_DSDT_MAG_NV { already defined } - // GL_DSDT_MAG_VIB_NV { already defined } - // GL_UNSIGNED_INT_S8_S8_8_8_NV { already defined } - // GL_UNSIGNED_INT_8_8_S8_S8_REV_NV { already defined } - // GL_SIGNED_RGBA_NV { already defined } - // GL_SIGNED_RGBA8_NV { already defined } - // GL_SIGNED_RGB_NV { already defined } - // GL_SIGNED_RGB8_NV { already defined } - // GL_SIGNED_LUMINANCE_NV { already defined } - // GL_SIGNED_LUMINANCE8_NV { already defined } - // GL_SIGNED_LUMINANCE_ALPHA_NV { already defined } - // GL_SIGNED_LUMINANCE8_ALPHA8_NV { already defined } - // GL_SIGNED_ALPHA_NV { already defined } - // GL_SIGNED_ALPHA8_NV { already defined } - // GL_SIGNED_INTENSITY_NV { already defined } - // GL_SIGNED_INTENSITY8_NV { already defined } - // GL_SIGNED_RGB_UNSIGNED_ALPHA_NV { already defined } - // GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV { already defined } - // GL_HILO16_NV { already defined } - // GL_SIGNED_HILO_NV { already defined } - // GL_SIGNED_HILO16_NV { already defined } - // GL_DSDT8_NV { already defined } - // GL_DSDT8_MAG8_NV { already defined } - // GL_DSDT_MAG_INTENSITY_NV { already defined } - // GL_DSDT8_MAG8_INTENSITY8_NV { already defined } - -function Load_GL_NV_texture_shader2: Boolean; - -//***** GL_NV_texture_shader3 *****// -const - GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV = $8850; - GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV = $8851; - GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV = $8852; - GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV = $8853; - GL_OFFSET_HILO_TEXTURE_2D_NV = $8854; - GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV = $8855; - GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV = $8856; - GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV = $8857; - GL_DEPENDENT_HILO_TEXTURE_2D_NV = $8858; - GL_DEPENDENT_RGB_TEXTURE_3D_NV = $8859; - GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV = $885A; - GL_DOT_PRODUCT_PASS_THROUGH_NV = $885B; - GL_DOT_PRODUCT_TEXTURE_1D_NV = $885C; - GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV = $885D; - GL_HILO8_NV = $885E; - GL_SIGNED_HILO8_NV = $885F; - GL_FORCE_BLUE_TO_ONE_NV = $8860; - -function Load_GL_NV_texture_shader3: Boolean; - -//***** GL_NV_vertex_array_range *****// -const - GL_VERTEX_ARRAY_RANGE_NV = $851D; - GL_VERTEX_ARRAY_RANGE_LENGTH_NV = $851E; - GL_VERTEX_ARRAY_RANGE_VALID_NV = $851F; - GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV = $8520; - GL_VERTEX_ARRAY_RANGE_POINTER_NV = $8521; -var - glVertexArrayRangeNV: procedure(length: GLsizei; pointer: PGLvoid); stdcall = nil; - glFlushVertexArrayRangeNV: procedure(); stdcall = nil; - wglAllocateMemoryNV: function(size: GLsizei; readFrequency: GLfloat; writeFrequency: GLfloat; priority: GLfloat): PGLvoid; stdcall = nil; - wglFreeMemoryNV: procedure(pointer: PGLvoid); stdcall = nil; - -function Load_GL_NV_vertex_array_range: Boolean; - -//***** GL_NV_vertex_array_range2 *****// -const - GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV = $8533; - -function Load_GL_NV_vertex_array_range2: Boolean; - -//***** GL_NV_vertex_program *****// -const - GL_VERTEX_PROGRAM_NV = $8620; - GL_VERTEX_PROGRAM_POINT_SIZE_NV = $8642; - GL_VERTEX_PROGRAM_TWO_SIDE_NV = $8643; - GL_VERTEX_STATE_PROGRAM_NV = $8621; - GL_ATTRIB_ARRAY_SIZE_NV = $8623; - GL_ATTRIB_ARRAY_STRIDE_NV = $8624; - GL_ATTRIB_ARRAY_TYPE_NV = $8625; - GL_CURRENT_ATTRIB_NV = $8626; - GL_PROGRAM_PARAMETER_NV = $8644; - GL_ATTRIB_ARRAY_POINTER_NV = $8645; - GL_PROGRAM_TARGET_NV = $8646; - GL_PROGRAM_LENGTH_NV = $8627; - GL_PROGRAM_RESIDENT_NV = $8647; - GL_PROGRAM_STRING_NV = $8628; - GL_TRACK_MATRIX_NV = $8648; - GL_TRACK_MATRIX_TRANSFORM_NV = $8649; - GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV = $862E; - GL_MAX_TRACK_MATRICES_NV = $862F; - GL_CURRENT_MATRIX_STACK_DEPTH_NV = $8640; - GL_CURRENT_MATRIX_NV = $8641; - GL_VERTEX_PROGRAM_BINDING_NV = $864A; - GL_PROGRAM_ERROR_POSITION_NV = $864B; - GL_MODELVIEW_PROJECTION_NV = $8629; - GL_MATRIX0_NV = $8630; - GL_MATRIX1_NV = $8631; - GL_MATRIX2_NV = $8632; - GL_MATRIX3_NV = $8633; - GL_MATRIX4_NV = $8634; - GL_MATRIX5_NV = $8635; - GL_MATRIX6_NV = $8636; - GL_MATRIX7_NV = $8637; - GL_IDENTITY_NV = $862A; - GL_INVERSE_NV = $862B; - GL_TRANSPOSE_NV = $862C; - GL_INVERSE_TRANSPOSE_NV = $862D; - GL_VERTEX_ATTRIB_ARRAY0_NV = $8650; - GL_VERTEX_ATTRIB_ARRAY1_NV = $8651; - GL_VERTEX_ATTRIB_ARRAY2_NV = $8652; - GL_VERTEX_ATTRIB_ARRAY3_NV = $8653; - GL_VERTEX_ATTRIB_ARRAY4_NV = $8654; - GL_VERTEX_ATTRIB_ARRAY5_NV = $8655; - GL_VERTEX_ATTRIB_ARRAY6_NV = $8656; - GL_VERTEX_ATTRIB_ARRAY7_NV = $8657; - GL_VERTEX_ATTRIB_ARRAY8_NV = $8658; - GL_VERTEX_ATTRIB_ARRAY9_NV = $8659; - GL_VERTEX_ATTRIB_ARRAY10_NV = $865A; - GL_VERTEX_ATTRIB_ARRAY11_NV = $865B; - GL_VERTEX_ATTRIB_ARRAY12_NV = $865C; - GL_VERTEX_ATTRIB_ARRAY13_NV = $865D; - GL_VERTEX_ATTRIB_ARRAY14_NV = $865E; - GL_VERTEX_ATTRIB_ARRAY15_NV = $865F; - GL_MAP1_VERTEX_ATTRIB0_4_NV = $8660; - GL_MAP1_VERTEX_ATTRIB1_4_NV = $8661; - GL_MAP1_VERTEX_ATTRIB2_4_NV = $8662; - GL_MAP1_VERTEX_ATTRIB3_4_NV = $8663; - GL_MAP1_VERTEX_ATTRIB4_4_NV = $8664; - GL_MAP1_VERTEX_ATTRIB5_4_NV = $8665; - GL_MAP1_VERTEX_ATTRIB6_4_NV = $8666; - GL_MAP1_VERTEX_ATTRIB7_4_NV = $8667; - GL_MAP1_VERTEX_ATTRIB8_4_NV = $8668; - GL_MAP1_VERTEX_ATTRIB9_4_NV = $8669; - GL_MAP1_VERTEX_ATTRIB10_4_NV = $866A; - GL_MAP1_VERTEX_ATTRIB11_4_NV = $866B; - GL_MAP1_VERTEX_ATTRIB12_4_NV = $866C; - GL_MAP1_VERTEX_ATTRIB13_4_NV = $866D; - GL_MAP1_VERTEX_ATTRIB14_4_NV = $866E; - GL_MAP1_VERTEX_ATTRIB15_4_NV = $866F; - GL_MAP2_VERTEX_ATTRIB0_4_NV = $8670; - GL_MAP2_VERTEX_ATTRIB1_4_NV = $8671; - GL_MAP2_VERTEX_ATTRIB2_4_NV = $8672; - GL_MAP2_VERTEX_ATTRIB3_4_NV = $8673; - GL_MAP2_VERTEX_ATTRIB4_4_NV = $8674; - GL_MAP2_VERTEX_ATTRIB5_4_NV = $8675; - GL_MAP2_VERTEX_ATTRIB6_4_NV = $8676; - GL_MAP2_VERTEX_ATTRIB7_4_NV = $8677; - GL_MAP2_VERTEX_ATTRIB8_4_NV = $8678; - GL_MAP2_VERTEX_ATTRIB9_4_NV = $8679; - GL_MAP2_VERTEX_ATTRIB10_4_NV = $867A; - GL_MAP2_VERTEX_ATTRIB11_4_NV = $867B; - GL_MAP2_VERTEX_ATTRIB12_4_NV = $867C; - GL_MAP2_VERTEX_ATTRIB13_4_NV = $867D; - GL_MAP2_VERTEX_ATTRIB14_4_NV = $867E; - GL_MAP2_VERTEX_ATTRIB15_4_NV = $867F; -var - glBindProgramNV: procedure(target: GLenum; id: GLuint); stdcall = nil; - glDeleteProgramsNV: procedure(n: GLsizei; const ids: PGLuint); stdcall = nil; - glExecuteProgramNV: procedure(target: GLenum; id: GLuint; const params: PGLfloat); stdcall = nil; - glGenProgramsNV: procedure(n: GLsizei; ids: PGLuint); stdcall = nil; - glAreProgramsResidentNV: function(n: GLsizei; const ids: PGLuint; residences: PGLboolean): GLboolean; stdcall = nil; - glRequestResidentProgramsNV: procedure(n: GLsizei; ids: PGLuint); stdcall = nil; - glGetProgramParameterfvNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetProgramParameterdvNV: procedure(target: GLenum; index: GLuint; pname: GLenum; params: PGLdouble); stdcall = nil; - glGetProgramivNV: procedure(id: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetProgramStringNV: procedure(id: GLuint; pname: GLenum; _program: PGLubyte); stdcall = nil; - glGetTrackMatrixivNV: procedure(target: GLenum; address: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetVertexAttribdvNV: procedure(index: GLuint; pname: GLenum; params: PGLdouble); stdcall = nil; - glGetVertexAttribfvNV: procedure(index: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetVertexAttribivNV: procedure(index: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetVertexAttribPointervNV: procedure(index: GLuint; pname: GLenum; pointer: PGLvoid); stdcall = nil; - glIsProgramNV: function(id: GLuint): GLboolean; stdcall = nil; - glLoadProgramNV: procedure(target: GLenum; id: GLuint; len: GLsizei; const _program: PGLubyte); stdcall = nil; - glProgramParameter4fNV: procedure(target: GLenum; index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glProgramParameter4fvNV: procedure(target: GLenum; index: GLuint; const params: PGLfloat); stdcall = nil; - glProgramParameters4dvNV: procedure(target: GLenum; index: GLuint; num: GLuint; const params: PGLdouble); stdcall = nil; - glProgramParameters4fvNV: procedure(target: GLenum; index: GLuint; num: GLuint; const params: PGLfloat); stdcall = nil; - glTrackMatrixNV: procedure(target: GLenum; address: GLuint; matrix: GLenum; transform: GLenum); stdcall = nil; - glVertexAttribPointerNV: procedure(index: GLuint; size: GLint; _type: GLenum; stride: GLsizei; const pointer: PGLvoid); stdcall = nil; - glVertexAttrib1sNV: procedure(index: GLuint; x: GLshort); stdcall = nil; - glVertexAttrib1fNV: procedure(index: GLuint; x: GLfloat); stdcall = nil; - glVertexAttrib1dNV: procedure(index: GLuint; x: GLdouble); stdcall = nil; - glVertexAttrib2sNV: procedure(index: GLuint; x: GLshort; y: GLshort); stdcall = nil; - glVertexAttrib2fNV: procedure(index: GLuint; x: GLfloat; y: GLfloat); stdcall = nil; - glVertexAttrib2dNV: procedure(index: GLuint; x: GLdouble; y: GLdouble); stdcall = nil; - glVertexAttrib3sNV: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort); stdcall = nil; - glVertexAttrib3fNV: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glVertexAttrib3dNV: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble); stdcall = nil; - glVertexAttrib4sNV: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort; w: GLshort); stdcall = nil; - glVertexAttrib4fNV: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glVertexAttrib4dNV: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); stdcall = nil; - glVertexAttrib4ubNV: procedure(index: GLuint; x: GLubyte; y: GLubyte; z: GLubyte; w: GLubyte); stdcall = nil; - glVertexAttrib1svNV: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib1fvNV: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib1dvNV: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib2svNV: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib2fvNV: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib2dvNV: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib3svNV: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib3fvNV: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib3dvNV: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib4svNV: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib4fvNV: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib4dvNV: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib4ubvNV: procedure(index: GLuint; const v: PGLubyte); stdcall = nil; - glVertexAttribs1svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); stdcall = nil; - glVertexAttribs1fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); stdcall = nil; - glVertexAttribs1dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); stdcall = nil; - glVertexAttribs2svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); stdcall = nil; - glVertexAttribs2fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); stdcall = nil; - glVertexAttribs2dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); stdcall = nil; - glVertexAttribs3svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); stdcall = nil; - glVertexAttribs3fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); stdcall = nil; - glVertexAttribs3dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); stdcall = nil; - glVertexAttribs4svNV: procedure(index: GLuint; n: GLsizei; const v: PGLshort); stdcall = nil; - glVertexAttribs4fvNV: procedure(index: GLuint; n: GLsizei; const v: PGLfloat); stdcall = nil; - glVertexAttribs4dvNV: procedure(index: GLuint; n: GLsizei; const v: PGLdouble); stdcall = nil; - glVertexAttribs4ubvNV: procedure(index: GLuint; n: GLsizei; const v: PGLubyte); stdcall = nil; - -function Load_GL_NV_vertex_program: Boolean; - -//***** GL_NV_vertex_program1_1 *****// - -function Load_GL_NV_vertex_program1_1: Boolean; - -//***** GL_ATI_element_array *****// -const - GL_ELEMENT_ARRAY_ATI = $8768; - GL_ELEMENT_ARRAY_TYPE_ATI = $8769; - GL_ELEMENT_ARRAY_POINTER_ATI = $876A; -var - glElementPointerATI: procedure(_type: GLenum; const pointer: PGLvoid); stdcall = nil; - glDrawElementArrayATI: procedure(mode: GLenum; count: GLsizei); stdcall = nil; - glDrawRangeElementArrayATI: procedure(mode: GLenum; start: GLuint; _end: GLuint; count: GLsizei); stdcall = nil; - -function Load_GL_ATI_element_array: Boolean; - -//***** GL_ATI_envmap_bumpmap *****// -const - GL_BUMP_ROT_MATRIX_ATI = $8775; - GL_BUMP_ROT_MATRIX_SIZE_ATI = $8776; - GL_BUMP_NUM_TEX_UNITS_ATI = $8777; - GL_BUMP_TEX_UNITS_ATI = $8778; - GL_DUDV_ATI = $8779; - GL_DU8DV8_ATI = $877A; - GL_BUMP_ENVMAP_ATI = $877B; - GL_BUMP_TARGET_ATI = $877C; -var - glTexBumpParameterivATI: procedure(pname: GLenum; param: PGLint); stdcall = nil; - glTexBumpParameterfvATI: procedure(pname: GLenum; param: PGLfloat); stdcall = nil; - glGetTexBumpParameterivATI: procedure(pname: GLenum; param: PGLint); stdcall = nil; - glGetTexBumpParameterfvATI: procedure(pname: GLenum; param: PGLfloat); stdcall = nil; - -function Load_GL_ATI_envmap_bumpmap: Boolean; - -//***** GL_ATI_fragment_shader *****// -const - GL_FRAGMENT_SHADER_ATI = $8920; - GL_REG_0_ATI = $8921; - GL_REG_1_ATI = $8922; - GL_REG_2_ATI = $8923; - GL_REG_3_ATI = $8924; - GL_REG_4_ATI = $8925; - GL_REG_5_ATI = $8926; - GL_CON_0_ATI = $8941; - GL_CON_1_ATI = $8942; - GL_CON_2_ATI = $8943; - GL_CON_3_ATI = $8944; - GL_CON_4_ATI = $8945; - GL_CON_5_ATI = $8946; - GL_CON_6_ATI = $8947; - GL_CON_7_ATI = $8948; - GL_MOV_ATI = $8961; - GL_ADD_ATI = $8963; - GL_MUL_ATI = $8964; - GL_SUB_ATI = $8965; - GL_DOT3_ATI = $8966; - GL_DOT4_ATI = $8967; - GL_MAD_ATI = $8968; - GL_LERP_ATI = $8969; - GL_CND_ATI = $896A; - GL_CND0_ATI = $896B; - GL_DOT2_ADD_ATI = $896C; - GL_SECONDARY_INTERPOLATOR_ATI = $896D; - GL_SWIZZLE_STR_ATI = $8976; - GL_SWIZZLE_STQ_ATI = $8977; - GL_SWIZZLE_STR_DR_ATI = $8978; - GL_SWIZZLE_STQ_DQ_ATI = $8979; - GL_RED_BIT_ATI = $0001; - GL_GREEN_BIT_ATI = $0002; - GL_BLUE_BIT_ATI = $0004; - GL_2X_BIT_ATI = $0001; - GL_4X_BIT_ATI = $0002; - GL_8X_BIT_ATI = $0004; - GL_HALF_BIT_ATI = $0008; - GL_QUARTER_BIT_ATI = $0010; - GL_EIGHTH_BIT_ATI = $0020; - GL_SATURATE_BIT_ATI = $0040; - // GL_2X_BIT_ATI { already defined } - GL_COMP_BIT_ATI = $0002; - GL_NEGATE_BIT_ATI = $0004; - GL_BIAS_BIT_ATI = $0008; -var - glGenFragmentShadersATI: function(range: GLuint): GLuint; stdcall = nil; - glBindFragmentShaderATI: procedure(id: GLuint); stdcall = nil; - glDeleteFragmentShaderATI: procedure(id: GLuint); stdcall = nil; - glBeginFragmentShaderATI: procedure(); stdcall = nil; - glEndFragmentShaderATI: procedure(); stdcall = nil; - glPassTexCoordATI: procedure(dst: GLuint; coord: GLuint; swizzle: GLenum); stdcall = nil; - glSampleMapATI: procedure(dst: GLuint; interp: GLuint; swizzle: GLenum); stdcall = nil; - glColorFragmentOp1ATI: procedure(op: GLenum; dst: GLuint; dstMask: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint); stdcall = nil; - glColorFragmentOp2ATI: procedure(op: GLenum; dst: GLuint; dstMask: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint); stdcall = nil; - glColorFragmentOp3ATI: procedure(op: GLenum; dst: GLuint; dstMask: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint; arg3: GLuint; arg3Rep: GLuint; arg3Mod: GLuint); stdcall = nil; - glAlphaFragmentOp1ATI: procedure(op: GLenum; dst: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint); stdcall = nil; - glAlphaFragmentOp2ATI: procedure(op: GLenum; dst: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint); stdcall = nil; - glAlphaFragmentOp3ATI: procedure(op: GLenum; dst: GLuint; dstMod: GLuint; arg1: GLuint; arg1Rep: GLuint; arg1Mod: GLuint; arg2: GLuint; arg2Rep: GLuint; arg2Mod: GLuint; arg3: GLuint; arg3Rep: GLuint; arg3Mod: GLuint); stdcall = nil; - glSetFragmentShaderConstantATI: procedure(dst: GLuint; const value: PGLfloat); stdcall = nil; - -function Load_GL_ATI_fragment_shader: Boolean; - -//***** GL_ATI_pn_triangles *****// -const - GL_PN_TRIANGLES_ATI = $87F0; - GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI = $87F1; - GL_PN_TRIANGLES_POINT_MODE_ATI = $87F2; - GL_PN_TRIANGLES_NORMAL_MODE_ATI = $87F3; - GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI = $87F4; - GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI = $87F5; - GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI = $87F6; - GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI = $87F7; - GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI = $87F8; -var - glPNTrianglesiATI: procedure(pname: GLenum; param: GLint); stdcall = nil; - glPNTrianglesfATI: procedure(pname: GLenum; param: GLfloat); stdcall = nil; - -function Load_GL_ATI_pn_triangles: Boolean; - -//***** GL_ATI_texture_mirror_once *****// -const - GL_MIRROR_CLAMP_ATI = $8742; - GL_MIRROR_CLAMP_TO_EDGE_ATI = $8743; - -function Load_GL_ATI_texture_mirror_once: Boolean; - -//***** GL_ATI_vertex_array_object *****// -const - GL_STATIC_ATI = $8760; - GL_DYNAMIC_ATI = $8761; - GL_PRESERVE_ATI = $8762; - GL_DISCARD_ATI = $8763; - GL_OBJECT_BUFFER_SIZE_ATI = $8764; - GL_OBJECT_BUFFER_USAGE_ATI = $8765; - GL_ARRAY_OBJECT_BUFFER_ATI = $8766; - GL_ARRAY_OBJECT_OFFSET_ATI = $8767; -var - glNewObjectBufferATI: function(size: GLsizei; const pointer: PGLvoid; usage: GLenum): GLuint; stdcall = nil; - glIsObjectBufferATI: function(buffer: GLuint): GLboolean; stdcall = nil; - glUpdateObjectBufferATI: procedure(buffer: GLuint; offset: GLuint; size: GLsizei; const pointer: PGLvoid; preserve: GLenum); stdcall = nil; - glGetObjectBufferfvATI: procedure(buffer: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetObjectBufferivATI: procedure(buffer: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glDeleteObjectBufferATI: procedure(buffer: GLuint); stdcall = nil; - glArrayObjectATI: procedure(_array: GLenum; size: GLint; _type: GLenum; stride: GLsizei; buffer: GLuint; offset: GLuint); stdcall = nil; - glGetArrayObjectfvATI: procedure(_array: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetArrayObjectivATI: procedure(_array: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glVariantArrayObjectATI: procedure(id: GLuint; _type: GLenum; stride: GLsizei; buffer: GLuint; offset: GLuint); stdcall = nil; - glGetVariantArrayObjectfvATI: procedure(id: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetVariantArrayObjectivATI: procedure(id: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - -function Load_GL_ATI_vertex_array_object: Boolean; - -//***** GL_ATI_vertex_streams *****// -const - GL_MAX_VERTEX_STREAMS_ATI = $876B; - GL_VERTEX_STREAM0_ATI = $876C; - GL_VERTEX_STREAM1_ATI = $876D; - GL_VERTEX_STREAM2_ATI = $876E; - GL_VERTEX_STREAM3_ATI = $876F; - GL_VERTEX_STREAM4_ATI = $8770; - GL_VERTEX_STREAM5_ATI = $8771; - GL_VERTEX_STREAM6_ATI = $8772; - GL_VERTEX_STREAM7_ATI = $8773; - GL_VERTEX_SOURCE_ATI = $8774; -var - glVertexStream1s: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream1i: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream1f: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream1d: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glVertexStream1sv: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream1iv: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream1fv: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream1dv: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glVertexStream2s: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream2i: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream2f: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream2d: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glVertexStream2sv: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream2iv: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream2fv: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream2dv: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glVertexStream3s: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream3i: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream3f: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream3d: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glVertexStream3sv: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream3iv: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream3fv: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream3dv: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glVertexStream4s: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream4i: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream4f: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream4d: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glVertexStream4sv: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glVertexStream4iv: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glVertexStream4fv: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glVertexStream4dv: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glNormalStream3b: procedure(stream: GLenum; coords: GLbyte); stdcall = nil; - glNormalStream3s: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glNormalStream3i: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glNormalStream3f: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glNormalStream3d: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glNormalStream3bv: procedure(stream: GLenum; coords: GLbyte); stdcall = nil; - glNormalStream3sv: procedure(stream: GLenum; coords: GLshort); stdcall = nil; - glNormalStream3iv: procedure(stream: GLenum; coords: GLint); stdcall = nil; - glNormalStream3fv: procedure(stream: GLenum; coords: GLfloat); stdcall = nil; - glNormalStream3dv: procedure(stream: GLenum; coords: GLdouble); stdcall = nil; - glClientActiveVertexStream: procedure(stream: GLenum); stdcall = nil; - glVertexBlendEnvi: procedure(pname: GLenum; param: GLint); stdcall = nil; - glVertexBlendEnvf: procedure(pname: GLenum; param: GLfloat); stdcall = nil; - -function Load_GL_ATI_vertex_streams: Boolean; - -//***** WGL_I3D_image_buffer *****// -const - WGL_IMAGE_BUFFER_MIN_ACCESS_I3D = $0001; - WGL_IMAGE_BUFFER_LOCK_I3D = $0002; -var - wglCreateImageBufferI3D: function(hDC: HDC; dwSize: DWORD; uFlags: UINT): PGLvoid; stdcall = nil; - wglDestroyImageBufferI3D: function(hDC: HDC; pAddress: PGLvoid): BOOL; stdcall = nil; - wglAssociateImageBufferEventsI3D: function(hdc: HDC; pEvent: PHandle; pAddress: PGLvoid; pSize: PDWORD; count: UINT): BOOL; stdcall = nil; - wglReleaseImageBufferEventsI3D: function(hdc: HDC; pAddress: PGLvoid; count: UINT): BOOL; stdcall = nil; - -function Load_WGL_I3D_image_buffer: Boolean; - -//***** WGL_I3D_swap_frame_lock *****// -var - wglEnableFrameLockI3D: function(): BOOL; stdcall = nil; - wglDisableFrameLockI3D: function(): BOOL; stdcall = nil; - wglIsEnabledFrameLockI3D: function(pFlag: PBOOL): BOOL; stdcall = nil; - wglQueryFrameLockMasterI3D: function(pFlag: PBOOL): BOOL; stdcall = nil; - -function Load_WGL_I3D_swap_frame_lock: Boolean; - -//***** WGL_I3D_swap_frame_usage *****// -var - wglGetFrameUsageI3D: function(pUsage: PGLfloat): BOOL; stdcall = nil; - wglBeginFrameTrackingI3D: function(): BOOL; stdcall = nil; - wglEndFrameTrackingI3D: function(): BOOL; stdcall = nil; - wglQueryFrameTrackingI3D: function(pFrameCount: PDWORD; pMissedFrames: PDWORD; pLastMissedUsage: PGLfloat): BOOL; stdcall = nil; - -function Load_WGL_I3D_swap_frame_usage: Boolean; - -//***** GL_3DFX_texture_compression_FXT1 *****// -const - GL_COMPRESSED_RGB_FXT1_3DFX = $86B0; - GL_COMPRESSED_RGBA_FXT1_3DFX = $86B1; - -function Load_GL_3DFX_texture_compression_FXT1: Boolean; - -//***** GL_IBM_cull_vertex *****// -const - GL_CULL_VERTEX_IBM = $1928A; - -function Load_GL_IBM_cull_vertex: Boolean; - -//***** GL_IBM_multimode_draw_arrays *****// -var - glMultiModeDrawArraysIBM: procedure(mode: PGLenum; first: PGLint; count: PGLsizei; primcount: GLsizei; modestride: GLint); stdcall = nil; - glMultiModeDrawElementsIBM: procedure(mode: PGLenum; count: PGLsizei; _type: GLenum; const indices: PGLvoid; primcount: GLsizei; modestride: GLint); stdcall = nil; - -function Load_GL_IBM_multimode_draw_arrays: Boolean; - -//***** GL_IBM_raster_pos_clip *****// -const - GL_RASTER_POSITION_UNCLIPPED_IBM = $19262; - -function Load_GL_IBM_raster_pos_clip: Boolean; - -//***** GL_IBM_texture_mirrored_repeat *****// -const - GL_MIRRORED_REPEAT_IBM = $8370; - -function Load_GL_IBM_texture_mirrored_repeat: Boolean; - -//***** GL_IBM_vertex_array_lists *****// -const - GL_VERTEX_ARRAY_LIST_IBM = $1929E; - GL_NORMAL_ARRAY_LIST_IBM = $1929F; - GL_COLOR_ARRAY_LIST_IBM = $192A0; - GL_INDEX_ARRAY_LIST_IBM = $192A1; - GL_TEXTURE_COORD_ARRAY_LIST_IBM = $192A2; - GL_EDGE_FLAG_ARRAY_LIST_IBM = $192A3; - GL_FOG_COORDINATE_ARRAY_LIST_IBM = $192A4; - GL_SECONDARY_COLOR_ARRAY_LIST_IBM = $192A5; - GL_VERTEX_ARRAY_LIST_STRIDE_IBM = $192A8; - GL_NORMAL_ARRAY_LIST_STRIDE_IBM = $192A9; - GL_COLOR_ARRAY_LIST_STRIDE_IBM = $192AA; - GL_INDEX_ARRAY_LIST_STRIDE_IBM = $192AB; - GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM = $192AC; - GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM = $192AD; - GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM = $192AE; - GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM = $192AF; -var - glColorPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); stdcall = nil; - glSecondaryColorPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); stdcall = nil; - glEdgeFlagPointerListIBM: procedure(stride: GLint; const pointer: PGLboolean; ptrstride: GLint); stdcall = nil; - glFogCoordPointerListIBM: procedure(_type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); stdcall = nil; - glNormalPointerListIBM: procedure(_type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); stdcall = nil; - glTexCoordPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); stdcall = nil; - glVertexPointerListIBM: procedure(size: GLint; _type: GLenum; stride: GLint; const pointer: PGLvoid; ptrstride: GLint); stdcall = nil; - -function Load_GL_IBM_vertex_array_lists: Boolean; - -//***** GL_MESA_resize_buffers *****// -var - glResizeBuffersMESA: procedure(); stdcall = nil; - -function Load_GL_MESA_resize_buffers: Boolean; - -//***** GL_MESA_window_pos *****// -var - glWindowPos2dMESA: procedure(x: GLdouble; y: GLdouble); stdcall = nil; - glWindowPos2fMESA: procedure(x: GLfloat; y: GLfloat); stdcall = nil; - glWindowPos2iMESA: procedure(x: GLint; y: GLint); stdcall = nil; - glWindowPos2sMESA: procedure(x: GLshort; y: GLshort); stdcall = nil; - glWindowPos2ivMESA: procedure(const p: PGLint); stdcall = nil; - glWindowPos2svMESA: procedure(const p: PGLshort); stdcall = nil; - glWindowPos2fvMESA: procedure(const p: PGLfloat); stdcall = nil; - glWindowPos2dvMESA: procedure(const p: PGLdouble); stdcall = nil; - glWindowPos3iMESA: procedure(x: GLint; y: GLint; z: GLint); stdcall = nil; - glWindowPos3sMESA: procedure(x: GLshort; y: GLshort; z: GLshort); stdcall = nil; - glWindowPos3fMESA: procedure(x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glWindowPos3dMESA: procedure(x: GLdouble; y: GLdouble; z: GLdouble); stdcall = nil; - glWindowPos3ivMESA: procedure(const p: PGLint); stdcall = nil; - glWindowPos3svMESA: procedure(const p: PGLshort); stdcall = nil; - glWindowPos3fvMESA: procedure(const p: PGLfloat); stdcall = nil; - glWindowPos3dvMESA: procedure(const p: PGLdouble); stdcall = nil; - glWindowPos4iMESA: procedure(x: GLint; y: GLint; z: GLint; w: GLint); stdcall = nil; - glWindowPos4sMESA: procedure(x: GLshort; y: GLshort; z: GLshort; w: GLshort); stdcall = nil; - glWindowPos4fMESA: procedure(x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glWindowPos4dMESA: procedure(x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); stdcall = nil; - glWindowPos4ivMESA: procedure(const p: PGLint); stdcall = nil; - glWindowPos4svMESA: procedure(const p: PGLshort); stdcall = nil; - glWindowPos4fvMESA: procedure(const p: PGLfloat); stdcall = nil; - glWindowPos4dvMESA: procedure(const p: PGLdouble); stdcall = nil; - -function Load_GL_MESA_window_pos: Boolean; - -//***** GL_OML_interlace *****// -const - GL_INTERLACE_OML = $8980; - GL_INTERLACE_READ_OML = $8981; - -function Load_GL_OML_interlace: Boolean; - -//***** GL_OML_resample *****// -const - GL_PACK_RESAMPLE_OML = $8984; - GL_UNPACK_RESAMPLE_OML = $8985; - GL_RESAMPLE_REPLICATE_OML = $8986; - GL_RESAMPLE_ZERO_FILL_OML = $8987; - GL_RESAMPLE_AVERAGE_OML = $8988; - GL_RESAMPLE_DECIMATE_OML = $8989; - // GL_RESAMPLE_AVERAGE_OML { already defined } - -function Load_GL_OML_resample: Boolean; - -//***** GL_OML_subsample *****// -const - GL_FORMAT_SUBSAMPLE_24_24_OML = $8982; - GL_FORMAT_SUBSAMPLE_244_244_OML = $8983; - -function Load_GL_OML_subsample: Boolean; - -//***** GL_SGIS_generate_mipmap *****// -const - GL_GENERATE_MIPMAP_SGIS = $8191; - GL_GENERATE_MIPMAP_HINT_SGIS = $8192; - -function Load_GL_SGIS_generate_mipmap: Boolean; - -//***** GL_SGIS_multisample *****// -const - GLX_SAMPLE_BUFFERS_SGIS = $186A0; - GLX_SAMPLES_SGIS = $186A1; - GL_MULTISAMPLE_SGIS = $809D; - GL_SAMPLE_ALPHA_TO_MASK_SGIS = $809E; - GL_SAMPLE_ALPHA_TO_ONE_SGIS = $809F; - GL_SAMPLE_MASK_SGIS = $80A0; - GL_MULTISAMPLE_BIT_EXT = $20000000; - GL_1PASS_SGIS = $80A1; - GL_2PASS_0_SGIS = $80A2; - GL_2PASS_1_SGIS = $80A3; - GL_4PASS_0_SGIS = $80A4; - GL_4PASS_1_SGIS = $80A5; - GL_4PASS_2_SGIS = $80A6; - GL_4PASS_3_SGIS = $80A7; - GL_SAMPLE_BUFFERS_SGIS = $80A8; - GL_SAMPLES_SGIS = $80A9; - GL_SAMPLE_MASK_VALUE_SGIS = $80AA; - GL_SAMPLE_MASK_INVERT_SGIS = $80AB; - GL_SAMPLE_PATTERN_SGIS = $80AC; -var - glSampleMaskSGIS: procedure(value: GLclampf; invert: GLboolean); stdcall = nil; - glSamplePatternSGIS: procedure(pattern: GLenum); stdcall = nil; - -function Load_GL_SGIS_multisample: Boolean; - -//***** GL_SGIS_pixel_texture *****// -const - GL_PIXEL_TEXTURE_SGIS = $8353; - GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS = $8354; - GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS = $8355; - GL_PIXEL_GROUP_COLOR_SGIS = $8356; -var - glPixelTexGenParameteriSGIS: procedure(pname: GLenum; param: GLint); stdcall = nil; - glPixelTexGenParameterfSGIS: procedure(pname: GLenum; param: GLfloat); stdcall = nil; - glGetPixelTexGenParameterivSGIS: procedure(pname: GLenum; params: GLint); stdcall = nil; - glGetPixelTexGenParameterfvSGIS: procedure(pname: GLenum; params: GLfloat); stdcall = nil; - -function Load_GL_SGIS_pixel_texture: Boolean; - -//***** GL_SGIS_texture_border_clamp *****// - // GL_CLAMP_TO_BORDER_SGIS { already defined } - -function Load_GL_SGIS_texture_border_clamp: Boolean; - -//***** GL_SGIS_texture_color_mask *****// -const - GL_TEXTURE_COLOR_WRITEMASK_SGIS = $81EF; -var - glTextureColorMaskSGIS: procedure(r: GLboolean; g: GLboolean; b: GLboolean; a: GLboolean); stdcall = nil; - -function Load_GL_SGIS_texture_color_mask: Boolean; - -//***** GL_SGIS_texture_edge_clamp *****// -const - GL_CLAMP_TO_EDGE_SGIS = $812F; - -function Load_GL_SGIS_texture_edge_clamp: Boolean; - -//***** GL_SGIS_texture_lod *****// -const - GL_TEXTURE_MIN_LOD_SGIS = $813A; - GL_TEXTURE_MAX_LOD_SGIS = $813B; - GL_TEXTURE_BASE_LEVEL_SGIS = $813C; - GL_TEXTURE_MAX_LEVEL_SGIS = $813D; - -function Load_GL_SGIS_texture_lod: Boolean; - -//***** GL_SGIS_depth_texture *****// -const - GL_DEPTH_COMPONENT16_SGIX = $81A5; - GL_DEPTH_COMPONENT24_SGIX = $81A6; - GL_DEPTH_COMPONENT32_SGIX = $81A7; - -function Load_GL_SGIS_depth_texture: Boolean; - -//***** GL_SGIX_fog_offset *****// -const - GL_FOG_OFFSET_SGIX = $8198; - GL_FOG_OFFSET_VALUE_SGIX = $8199; - -function Load_GL_SGIX_fog_offset: Boolean; - -//***** GL_SGIX_interlace *****// -const - GL_INTERLACE_SGIX = $8094; - -function Load_GL_SGIX_interlace: Boolean; - -//***** GL_SGIX_shadow_ambient *****// -const - GL_SHADOW_AMBIENT_SGIX = $80BF; - -function Load_GL_SGIX_shadow_ambient: Boolean; - -//***** GL_SGI_color_matrix *****// -const - GL_COLOR_MATRIX_SGI = $80B1; - GL_COLOR_MATRIX_STACK_DEPTH_SGI = $80B2; - GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI = $80B3; - GL_POST_COLOR_MATRIX_RED_SCALE_SGI = $80B4; - GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI = $80B5; - GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI = $80B6; - GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI = $80B7; - GL_POST_COLOR_MATRIX_RED_BIAS_SGI = $80B8; - GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI = $80B9; - GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI = $80BA; - GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI = $80BB; - -function Load_GL_SGI_color_matrix: Boolean; - -//***** GL_SGI_color_table *****// -const - GL_COLOR_TABLE_SGI = $80D0; - GL_POST_CONVOLUTION_COLOR_TABLE_SGI = $80D1; - GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI = $80D2; - GL_PROXY_COLOR_TABLE_SGI = $80D3; - GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI = $80D4; - GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI = $80D5; - GL_COLOR_TABLE_SCALE_SGI = $80D6; - GL_COLOR_TABLE_BIAS_SGI = $80D7; - GL_COLOR_TABLE_FORMAT_SGI = $80D8; - GL_COLOR_TABLE_WIDTH_SGI = $80D9; - GL_COLOR_TABLE_RED_SIZE_SGI = $80DA; - GL_COLOR_TABLE_GREEN_SIZE_SGI = $80DB; - GL_COLOR_TABLE_BLUE_SIZE_SGI = $80DC; - GL_COLOR_TABLE_ALPHA_SIZE_SGI = $80DD; - GL_COLOR_TABLE_LUMINANCE_SIZE_SGI = $80DE; - GL_COLOR_TABLE_INTENSITY_SIZE_SGI = $80DF; -var - glColorTableSGI: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; format: GLenum; _type: GLenum; const table: PGLvoid); stdcall = nil; - glCopyColorTableSGI: procedure(target: GLenum; internalformat: GLenum; x: GLint; y: GLint; width: GLsizei); stdcall = nil; - glColorTableParameterivSGI: procedure(target: GLenum; pname: GLenum; const params: PGLint); stdcall = nil; - glColorTableParameterfvSGI: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); stdcall = nil; - glGetColorTableSGI: procedure(target: GLenum; format: GLenum; _type: GLenum; table: PGLvoid); stdcall = nil; - glGetColorTableParameterivSGI: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetColorTableParameterfvSGI: procedure(target: GLenum; pname: GLenum; params: PGLfloat); stdcall = nil; - -function Load_GL_SGI_color_table: Boolean; - -//***** GL_SGI_texture_color_table *****// -const - GL_TEXTURE_COLOR_TABLE_SGI = $80BC; - GL_PROXY_TEXTURE_COLOR_TABLE_SGI = $80BD; - -function Load_GL_SGI_texture_color_table: Boolean; - -//***** GL_SUN_vertex *****// -var - glColor4ubVertex2fSUN: procedure(r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat); stdcall = nil; - glColor4ubVertex2fvSUN: procedure(const c: PGLubyte; const v: PGLfloat); stdcall = nil; - glColor4ubVertex3fSUN: procedure(r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glColor4ubVertex3fvSUN: procedure(const c: PGLubyte; const v: PGLfloat); stdcall = nil; - glColor3fVertex3fSUN: procedure(r: GLfloat; g: GLfloat; b: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glColor3fVertex3fvSUN: procedure(const c: PGLfloat; const v: PGLfloat); stdcall = nil; - glNormal3fVertex3fSUN: procedure(nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glNormal3fVertex3fvSUN: procedure(const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glColor4fNormal3fVertex3fSUN: procedure(r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glColor4fNormal3fVertex3fvSUN: procedure(const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glTexCoord2fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glTexCoord2fVertex3fvSUN: procedure(const tc: PGLfloat; const v: PGLfloat); stdcall = nil; - glTexCoord4fVertex4fSUN: procedure(s: GLfloat; t: GLfloat; p: GLfloat; q: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glTexCoord4fVertex4fvSUN: procedure(const tc: PGLfloat; const v: PGLfloat); stdcall = nil; - glTexCoord2fColor4ubVertex3fSUN: procedure(s: GLfloat; t: GLfloat; r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glTexCoord2fColor4ubVertex3fvSUN: procedure(const tc: PGLfloat; const c: PGLubyte; const v: PGLfloat); stdcall = nil; - glTexCoord2fColor3fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glTexCoord2fColor3fVertex3fvSUN: procedure(const tc: PGLfloat; const c: PGLfloat; const v: PGLfloat); stdcall = nil; - glTexCoord2fNormal3fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glTexCoord2fNormal3fVertex3fvSUN: procedure(const tc: PGLfloat; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glTexCoord2fColor4fNormal3fVertex3fSUN: procedure(s: GLfloat; t: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glTexCoord2fColor4fNormal3fVertex3fvSUN: procedure(const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glTexCoord4fColor4fNormal3fVertex4fSUN: procedure(s: GLfloat; t: GLfloat; p: GLfloat; q: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glTexCoord4fColor4fNormal3fVertex4fvSUN: procedure(const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiVertex3fSUN: procedure(rc: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiVertex3fvSUN: procedure(const rc: PGLuint; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiColor4ubVertex3fSUN: procedure(rc: GLuint; r: GLubyte; g: GLubyte; b: GLubyte; a: GLubyte; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiColor4ubVertex3fvSUN: procedure(const rc: PGLuint; const c: PGLubyte; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiColor3fVertex3fSUN: procedure(rc: GLuint; r: GLfloat; g: GLfloat; b: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiColor3fVertex3fvSUN: procedure(const rc: PGLuint; const c: PGLfloat; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiNormal3fVertex3fSUN: procedure(rc: GLuint; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiColor4fNormal3fVertex3fSUN: procedure(rc: GLuint; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiColor4fNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiTexCoord2fVertex3fSUN: procedure(rc: GLuint; s: GLfloat; t: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiTexCoord2fVertex3fvSUN: procedure(const rc: PGLuint; const tc: PGLfloat; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN: procedure(rc: GLuint; s: GLfloat; t: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const tc: PGLfloat; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN: procedure(rc: GLuint; s: GLfloat; t: GLfloat; r: GLfloat; g: GLfloat; b: GLfloat; a: GLfloat; nx: GLfloat; ny: GLfloat; nz: GLfloat; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN: procedure(const rc: PGLuint; const tc: PGLfloat; const c: PGLfloat; const n: PGLfloat; const v: PGLfloat); stdcall = nil; - -function Load_GL_SUN_vertex: Boolean; - -//***** GL_ARB_fragment_program *****// -const - GL_FRAGMENT_PROGRAM_ARB = $8804; - // GL_PROGRAM_FORMAT_ASCII_ARB { already defined } - // GL_PROGRAM_LENGTH_ARB { already defined } - // GL_PROGRAM_FORMAT_ARB { already defined } - // GL_PROGRAM_BINDING_ARB { already defined } - // GL_PROGRAM_INSTRUCTIONS_ARB { already defined } - // GL_MAX_PROGRAM_INSTRUCTIONS_ARB { already defined } - // GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB { already defined } - // GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB { already defined } - // GL_PROGRAM_TEMPORARIES_ARB { already defined } - // GL_MAX_PROGRAM_TEMPORARIES_ARB { already defined } - // GL_PROGRAM_NATIVE_TEMPORARIES_ARB { already defined } - // GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB { already defined } - // GL_PROGRAM_PARAMETERS_ARB { already defined } - // GL_MAX_PROGRAM_PARAMETERS_ARB { already defined } - // GL_PROGRAM_NATIVE_PARAMETERS_ARB { already defined } - // GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB { already defined } - // GL_PROGRAM_ATTRIBS_ARB { already defined } - // GL_MAX_PROGRAM_ATTRIBS_ARB { already defined } - // GL_PROGRAM_NATIVE_ATTRIBS_ARB { already defined } - // GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB { already defined } - // GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB { already defined } - // GL_MAX_PROGRAM_ENV_PARAMETERS_ARB { already defined } - // GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB { already defined } - GL_PROGRAM_ALU_INSTRUCTIONS_ARB = $8805; - GL_PROGRAM_TEX_INSTRUCTIONS_ARB = $8806; - GL_PROGRAM_TEX_INDIRECTIONS_ARB = $8807; - GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = $8808; - GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = $8809; - GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = $880A; - GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB = $880B; - GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB = $880C; - GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB = $880D; - GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB = $880E; - GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB = $880F; - GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB = $8810; - // GL_PROGRAM_STRING_ARB { already defined } - // GL_PROGRAM_ERROR_POSITION_ARB { already defined } - // GL_CURRENT_MATRIX_ARB { already defined } - // GL_TRANSPOSE_CURRENT_MATRIX_ARB { already defined } - // GL_CURRENT_MATRIX_STACK_DEPTH_ARB { already defined } - // GL_MAX_PROGRAM_MATRICES_ARB { already defined } - // GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB { already defined } - GL_MAX_TEXTURE_COORDS_ARB = $8871; - GL_MAX_TEXTURE_IMAGE_UNITS_ARB = $8872; - // GL_PROGRAM_ERROR_STRING_ARB { already defined } - // GL_MATRIX0_ARB { already defined } - // GL_MATRIX1_ARB { already defined } - // GL_MATRIX2_ARB { already defined } - // GL_MATRIX3_ARB { already defined } - // GL_MATRIX4_ARB { already defined } - // GL_MATRIX5_ARB { already defined } - // GL_MATRIX6_ARB { already defined } - // GL_MATRIX7_ARB { already defined } - // GL_MATRIX8_ARB { already defined } - // GL_MATRIX9_ARB { already defined } - // GL_MATRIX10_ARB { already defined } - // GL_MATRIX11_ARB { already defined } - // GL_MATRIX12_ARB { already defined } - // GL_MATRIX13_ARB { already defined } - // GL_MATRIX14_ARB { already defined } - // GL_MATRIX15_ARB { already defined } - // GL_MATRIX16_ARB { already defined } - // GL_MATRIX17_ARB { already defined } - // GL_MATRIX18_ARB { already defined } - // GL_MATRIX19_ARB { already defined } - // GL_MATRIX20_ARB { already defined } - // GL_MATRIX21_ARB { already defined } - // GL_MATRIX22_ARB { already defined } - // GL_MATRIX23_ARB { already defined } - // GL_MATRIX24_ARB { already defined } - // GL_MATRIX25_ARB { already defined } - // GL_MATRIX26_ARB { already defined } - // GL_MATRIX27_ARB { already defined } - // GL_MATRIX28_ARB { already defined } - // GL_MATRIX29_ARB { already defined } - // GL_MATRIX30_ARB { already defined } - // GL_MATRIX31_ARB { already defined } - // glProgramStringARB { already defined } - // glBindProgramARB { already defined } - // glDeleteProgramsARB { already defined } - // glGenProgramsARB { already defined } - // glProgramEnvParameter4dARB { already defined } - // glProgramEnvParameter4dvARB { already defined } - // glProgramEnvParameter4fARB { already defined } - // glProgramEnvParameter4fvARB { already defined } - // glProgramLocalParameter4dARB { already defined } - // glProgramLocalParameter4dvARB { already defined } - // glProgramLocalParameter4fARB { already defined } - // glProgramLocalParameter4fvARB { already defined } - // glGetProgramEnvParameterdvARB { already defined } - // glGetProgramEnvParameterfvARB { already defined } - // glGetProgramLocalParameterdvARB { already defined } - // glGetProgramLocalParameterfvARB { already defined } - // glGetProgramivARB { already defined } - // glGetProgramStringARB { already defined } - // glIsProgramARB { already defined } - -function Load_GL_ARB_fragment_program: Boolean; - -//***** GL_ATI_text_fragment_shader *****// -const - GL_TEXT_FRAGMENT_SHADER_ATI = $8200; - -function Load_GL_ATI_text_fragment_shader: Boolean; - -//***** GL_APPLE_client_storage *****// -const - GL_UNPACK_CLIENT_STORAGE_APPLE = $85B2; - -function Load_GL_APPLE_client_storage: Boolean; - -//***** GL_APPLE_element_array *****// -const - GL_ELEMENT_ARRAY_APPLE = $8768; - GL_ELEMENT_ARRAY_TYPE_APPLE = $8769; - GL_ELEMENT_ARRAY_POINTER_APPLE = $876A; -var - glElementPointerAPPLE: procedure(_type: GLenum; const pointer: PGLvoid); stdcall = nil; - glDrawElementArrayAPPLE: procedure(mode: GLenum; first: GLint; count: GLsizei); stdcall = nil; - glDrawRangeElementArrayAPPLE: procedure(mode: GLenum; start: GLuint; _end: GLuint; first: GLint; count: GLsizei); stdcall = nil; - glMultiDrawElementArrayAPPLE: procedure(mode: GLenum; const first: PGLint; const count: PGLsizei; primcount: GLsizei); stdcall = nil; - glMultiDrawRangeElementArrayAPPLE: procedure(mode: GLenum; start: GLuint; _end: GLuint; const first: PGLint; const count: PGLsizei; primcount: GLsizei); stdcall = nil; - -function Load_GL_APPLE_element_array: Boolean; - -//***** GL_APPLE_fence *****// -const - GL_DRAW_PIXELS_APPLE = $8A0A; - GL_FENCE_APPLE = $8A0B; -var - glGenFencesAPPLE: procedure(n: GLsizei; fences: PGLuint); stdcall = nil; - glDeleteFencesAPPLE: procedure(n: GLsizei; const fences: PGLuint); stdcall = nil; - glSetFenceAPPLE: procedure(fence: GLuint); stdcall = nil; - glIsFenceAPPLE: function(fence: GLuint): GLboolean; stdcall = nil; - glTestFenceAPPLE: function(fence: GLuint): GLboolean; stdcall = nil; - glFinishFenceAPPLE: procedure(fence: GLuint); stdcall = nil; - glTestObjectAPPLE: function(_object: GLenum; name: GLuint): GLboolean; stdcall = nil; - glFinishObjectAPPLE: procedure(_object: GLenum; name: GLint); stdcall = nil; - -function Load_GL_APPLE_fence: Boolean; - -//***** GL_APPLE_vertex_array_object *****// -const - GL_VERTEX_ARRAY_BINDING_APPLE = $85B5; -var - glBindVertexArrayAPPLE: procedure(_array: GLuint); stdcall = nil; - glDeleteVertexArraysAPPLE: procedure(n: GLsizei; const arrays: PGLuint); stdcall = nil; - glGenVertexArraysAPPLE: procedure(n: GLsizei; const arrays: PGLuint); stdcall = nil; - glIsVertexArrayAPPLE: function(_array: GLuint): GLboolean; stdcall = nil; - -function Load_GL_APPLE_vertex_array_object: Boolean; - -//***** GL_APPLE_vertex_array_range *****// -const - GL_VERTEX_ARRAY_RANGE_APPLE = $851D; - GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE = $851E; - GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_APPLE = $8520; - GL_VERTEX_ARRAY_RANGE_POINTER_APPLE = $8521; - GL_VERTEX_ARRAY_STORAGE_HINT_APPLE = $851F; - GL_STORAGE_CACHED_APPLE = $85BE; - GL_STORAGE_SHARED_APPLE = $85BF; -var - glVertexArrayRangeAPPLE: procedure(length: GLsizei; pointer: PGLvoid); stdcall = nil; - glFlushVertexArrayRangeAPPLE: procedure(length: GLsizei; pointer: PGLvoid); stdcall = nil; - glVertexArrayParameteriAPPLE: procedure(pname: GLenum; param: GLint); stdcall = nil; - -function Load_GL_APPLE_vertex_array_range: Boolean; - -//***** WGL_ARB_pixel_format *****// -const - WGL_NUMBER_PIXEL_FORMATS_ARB = $2000; - WGL_DRAW_TO_WINDOW_ARB = $2001; - WGL_DRAW_TO_BITMAP_ARB = $2002; - WGL_ACCELERATION_ARB = $2003; - WGL_NEED_PALETTE_ARB = $2004; - WGL_NEED_SYSTEM_PALETTE_ARB = $2005; - WGL_SWAP_LAYER_BUFFERS_ARB = $2006; - WGL_SWAP_METHOD_ARB = $2007; - WGL_NUMBER_OVERLAYS_ARB = $2008; - WGL_NUMBER_UNDERLAYS_ARB = $2009; - WGL_TRANSPARENT_ARB = $200A; - WGL_TRANSPARENT_RED_VALUE_ARB = $2037; - WGL_TRANSPARENT_GREEN_VALUE_ARB = $2038; - WGL_TRANSPARENT_BLUE_VALUE_ARB = $2039; - WGL_TRANSPARENT_ALPHA_VALUE_ARB = $203A; - WGL_TRANSPARENT_INDEX_VALUE_ARB = $203B; - WGL_SHARE_DEPTH_ARB = $200C; - WGL_SHARE_STENCIL_ARB = $200D; - WGL_SHARE_ACCUM_ARB = $200E; - WGL_SUPPORT_GDI_ARB = $200F; - WGL_SUPPORT_OPENGL_ARB = $2010; - WGL_DOUBLE_BUFFER_ARB = $2011; - WGL_STEREO_ARB = $2012; - WGL_PIXEL_TYPE_ARB = $2013; - WGL_COLOR_BITS_ARB = $2014; - WGL_RED_BITS_ARB = $2015; - WGL_RED_SHIFT_ARB = $2016; - WGL_GREEN_BITS_ARB = $2017; - WGL_GREEN_SHIFT_ARB = $2018; - WGL_BLUE_BITS_ARB = $2019; - WGL_BLUE_SHIFT_ARB = $201A; - WGL_ALPHA_BITS_ARB = $201B; - WGL_ALPHA_SHIFT_ARB = $201C; - WGL_ACCUM_BITS_ARB = $201D; - WGL_ACCUM_RED_BITS_ARB = $201E; - WGL_ACCUM_GREEN_BITS_ARB = $201F; - WGL_ACCUM_BLUE_BITS_ARB = $2020; - WGL_ACCUM_ALPHA_BITS_ARB = $2021; - WGL_DEPTH_BITS_ARB = $2022; - WGL_STENCIL_BITS_ARB = $2023; - WGL_AUX_BUFFERS_ARB = $2024; - WGL_NO_ACCELERATION_ARB = $2025; - WGL_GENERIC_ACCELERATION_ARB = $2026; - WGL_FULL_ACCELERATION_ARB = $2027; - WGL_SWAP_EXCHANGE_ARB = $2028; - WGL_SWAP_COPY_ARB = $2029; - WGL_SWAP_UNDEFINED_ARB = $202A; - WGL_TYPE_RGBA_ARB = $202B; - WGL_TYPE_COLORINDEX_ARB = $202C; -var - wglGetPixelFormatAttribivARB: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; const piAttributes: PGLint; piValues: PGLint): BOOL; stdcall = nil; - wglGetPixelFormatAttribfvARB: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; const piAttributes: PGLint; pfValues: PGLfloat): BOOL; stdcall = nil; - wglChoosePixelFormatARB: function(hdc: HDC; const piAttribIList: PGLint; const pfAttribFList: PGLfloat; nMaxFormats: GLuint; piFormats: PGLint; nNumFormats: PGLuint): BOOL; stdcall = nil; - -function Load_WGL_ARB_pixel_format: Boolean; - -//***** WGL_ARB_make_current_read *****// -const - WGL_ERROR_INVALID_PIXEL_TYPE_ARB = $2043; - WGL_ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB = $2054; -var - wglMakeContextCurrentARB: function(hDrawDC: HDC; hReadDC: HDC; hglrc: HGLRC): BOOL; stdcall = nil; - wglGetCurrentReadDCARB: function(): HDC; stdcall = nil; - -function Load_WGL_ARB_make_current_read: Boolean; - -//***** WGL_ARB_pbuffer *****// -const - WGL_DRAW_TO_PBUFFER_ARB = $202D; - // WGL_DRAW_TO_PBUFFER_ARB { already defined } - WGL_MAX_PBUFFER_PIXELS_ARB = $202E; - WGL_MAX_PBUFFER_WIDTH_ARB = $202F; - WGL_MAX_PBUFFER_HEIGHT_ARB = $2030; - WGL_PBUFFER_LARGEST_ARB = $2033; - WGL_PBUFFER_WIDTH_ARB = $2034; - WGL_PBUFFER_HEIGHT_ARB = $2035; - WGL_PBUFFER_LOST_ARB = $2036; -var - wglCreatePbufferARB: function(hDC: HDC; iPixelFormat: GLint; iWidth: GLint; iHeight: GLint; const piAttribList: PGLint): THandle; stdcall = nil; - wglGetPbufferDCARB: function(hPbuffer: THandle): HDC; stdcall = nil; - wglReleasePbufferDCARB: function(hPbuffer: THandle; hDC: HDC): GLint; stdcall = nil; - wglDestroyPbufferARB: function(hPbuffer: THandle): BOOL; stdcall = nil; - wglQueryPbufferARB: function(hPbuffer: THandle; iAttribute: GLint; piValue: PGLint): BOOL; stdcall = nil; - -function Load_WGL_ARB_pbuffer: Boolean; - -//***** WGL_EXT_swap_control *****// -var - wglSwapIntervalEXT: function(interval: GLint): BOOL; stdcall = nil; - wglGetSwapIntervalEXT: function(): GLint; stdcall = nil; - -function Load_WGL_EXT_swap_control: Boolean; - -//***** WGL_ARB_render_texture *****// -const - WGL_BIND_TO_TEXTURE_RGB_ARB = $2070; - WGL_BIND_TO_TEXTURE_RGBA_ARB = $2071; - WGL_TEXTURE_FORMAT_ARB = $2072; - WGL_TEXTURE_TARGET_ARB = $2073; - WGL_MIPMAP_TEXTURE_ARB = $2074; - WGL_TEXTURE_RGB_ARB = $2075; - WGL_TEXTURE_RGBA_ARB = $2076; - WGL_NO_TEXTURE_ARB = $2077; - WGL_TEXTURE_CUBE_MAP_ARB = $2078; - WGL_TEXTURE_1D_ARB = $2079; - WGL_TEXTURE_2D_ARB = $207A; - // WGL_NO_TEXTURE_ARB { already defined } - WGL_MIPMAP_LEVEL_ARB = $207B; - WGL_CUBE_MAP_FACE_ARB = $207C; - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB = $207D; - WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB = $207E; - WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB = $207F; - WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB = $2080; - WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB = $2081; - WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB = $2082; - WGL_FRONT_LEFT_ARB = $2083; - WGL_FRONT_RIGHT_ARB = $2084; - WGL_BACK_LEFT_ARB = $2085; - WGL_BACK_RIGHT_ARB = $2086; - WGL_AUX0_ARB = $2087; - WGL_AUX1_ARB = $2088; - WGL_AUX2_ARB = $2089; - WGL_AUX3_ARB = $208A; - WGL_AUX4_ARB = $208B; - WGL_AUX5_ARB = $208C; - WGL_AUX6_ARB = $208D; - WGL_AUX7_ARB = $208E; - WGL_AUX8_ARB = $208F; - WGL_AUX9_ARB = $2090; -var - wglBindTexImageARB: function(hPbuffer: THandle; iBuffer: GLint): BOOL; stdcall = nil; - wglReleaseTexImageARB: function(hPbuffer: THandle; iBuffer: GLint): BOOL; stdcall = nil; - wglSetPbufferAttribARB: function(hPbuffer: THandle; const piAttribList: PGLint): BOOL; stdcall = nil; - -function Load_WGL_ARB_render_texture: Boolean; - -//***** WGL_EXT_extensions_string *****// -var - wglGetExtensionsStringEXT: function(): Pchar; stdcall = nil; - -function Load_WGL_EXT_extensions_string: Boolean; - -//***** WGL_EXT_make_current_read *****// -var - wglMakeContextCurrentEXT: function(hDrawDC: HDC; hReadDC: HDC; hglrc: HGLRC): BOOL; stdcall = nil; - wglGetCurrentReadDCEXT: function(): HDC; stdcall = nil; - -function Load_WGL_EXT_make_current_read: Boolean; - -//***** WGL_EXT_pbuffer *****// -const - WGL_DRAW_TO_PBUFFER_EXT = $202D; - WGL_MAX_PBUFFER_PIXELS_EXT = $202E; - WGL_MAX_PBUFFER_WIDTH_EXT = $202F; - WGL_MAX_PBUFFER_HEIGHT_EXT = $2030; - WGL_OPTIMAL_PBUFFER_WIDTH_EXT = $2031; - WGL_OPTIMAL_PBUFFER_HEIGHT_EXT = $2032; - WGL_PBUFFER_LARGEST_EXT = $2033; - WGL_PBUFFER_WIDTH_EXT = $2034; - WGL_PBUFFER_HEIGHT_EXT = $2035; -var - wglCreatePbufferEXT: function(hDC: HDC; iPixelFormat: GLint; iWidth: GLint; iHeight: GLint; const piAttribList: PGLint): THandle; stdcall = nil; - wglGetPbufferDCEXT: function(hPbuffer: THandle): HDC; stdcall = nil; - wglReleasePbufferDCEXT: function(hPbuffer: THandle; hDC: HDC): GLint; stdcall = nil; - wglDestroyPbufferEXT: function(hPbuffer: THandle): BOOL; stdcall = nil; - wglQueryPbufferEXT: function(hPbuffer: THandle; iAttribute: GLint; piValue: PGLint): BOOL; stdcall = nil; - -function Load_WGL_EXT_pbuffer: Boolean; - -//***** WGL_EXT_pixel_format *****// -const - WGL_NUMBER_PIXEL_FORMATS_EXT = $2000; - WGL_DRAW_TO_WINDOW_EXT = $2001; - WGL_DRAW_TO_BITMAP_EXT = $2002; - WGL_ACCELERATION_EXT = $2003; - WGL_NEED_PALETTE_EXT = $2004; - WGL_NEED_SYSTEM_PALETTE_EXT = $2005; - WGL_SWAP_LAYER_BUFFERS_EXT = $2006; - WGL_SWAP_METHOD_EXT = $2007; - WGL_NUMBER_OVERLAYS_EXT = $2008; - WGL_NUMBER_UNDERLAYS_EXT = $2009; - WGL_TRANSPARENT_EXT = $200A; - WGL_TRANSPARENT_VALUE_EXT = $200B; - WGL_SHARE_DEPTH_EXT = $200C; - WGL_SHARE_STENCIL_EXT = $200D; - WGL_SHARE_ACCUM_EXT = $200E; - WGL_SUPPORT_GDI_EXT = $200F; - WGL_SUPPORT_OPENGL_EXT = $2010; - WGL_DOUBLE_BUFFER_EXT = $2011; - WGL_STEREO_EXT = $2012; - WGL_PIXEL_TYPE_EXT = $2013; - WGL_COLOR_BITS_EXT = $2014; - WGL_RED_BITS_EXT = $2015; - WGL_RED_SHIFT_EXT = $2016; - WGL_GREEN_BITS_EXT = $2017; - WGL_GREEN_SHIFT_EXT = $2018; - WGL_BLUE_BITS_EXT = $2019; - WGL_BLUE_SHIFT_EXT = $201A; - WGL_ALPHA_BITS_EXT = $201B; - WGL_ALPHA_SHIFT_EXT = $201C; - WGL_ACCUM_BITS_EXT = $201D; - WGL_ACCUM_RED_BITS_EXT = $201E; - WGL_ACCUM_GREEN_BITS_EXT = $201F; - WGL_ACCUM_BLUE_BITS_EXT = $2020; - WGL_ACCUM_ALPHA_BITS_EXT = $2021; - WGL_DEPTH_BITS_EXT = $2022; - WGL_STENCIL_BITS_EXT = $2023; - WGL_AUX_BUFFERS_EXT = $2024; - WGL_NO_ACCELERATION_EXT = $2025; - WGL_GENERIC_ACCELERATION_EXT = $2026; - WGL_FULL_ACCELERATION_EXT = $2027; - WGL_SWAP_EXCHANGE_EXT = $2028; - WGL_SWAP_COPY_EXT = $2029; - WGL_SWAP_UNDEFINED_EXT = $202A; - WGL_TYPE_RGBA_EXT = $202B; - WGL_TYPE_COLORINDEX_EXT = $202C; -var - wglGetPixelFormatAttribivEXT: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; piAttributes: PGLint; piValues: PGLint): BOOL; stdcall = nil; - wglGetPixelFormatAttribfvEXT: function(hdc: HDC; iPixelFormat: GLint; iLayerPlane: GLint; nAttributes: GLuint; piAttributes: PGLint; pfValues: PGLfloat): BOOL; stdcall = nil; - wglChoosePixelFormatEXT: function(hdc: HDC; const piAttribIList: PGLint; const pfAttribFList: PGLfloat; nMaxFormats: GLuint; piFormats: PGLint; nNumFormats: PGLuint): BOOL; stdcall = nil; - -function Load_WGL_EXT_pixel_format: Boolean; - -//***** WGL_I3D_digital_video_control *****// -const - WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D = $2050; - WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D = $2051; - WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D = $2052; - WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D = $2053; -var - wglGetDigitalVideoParametersI3D: function(hDC: HDC; iAttribute: GLint; piValue: PGLint): BOOL; stdcall = nil; - wglSetDigitalVideoParametersI3D: function(hDC: HDC; iAttribute: GLint; const piValue: PGLint): BOOL; stdcall = nil; - -function Load_WGL_I3D_digital_video_control: Boolean; - -//***** WGL_I3D_gamma *****// -const - WGL_GAMMA_TABLE_SIZE_I3D = $204E; - WGL_GAMMA_EXCLUDE_DESKTOP_I3D = $204F; - // WGL_GAMMA_EXCLUDE_DESKTOP_I3D { already defined } -var - wglGetGammaTableParametersI3D: function(hDC: HDC; iAttribute: GLint; piValue: PGLint): BOOL; stdcall = nil; - wglSetGammaTableParametersI3D: function(hDC: HDC; iAttribute: GLint; const piValue: PGLint): BOOL; stdcall = nil; - wglGetGammaTableI3D: function(hDC: HDC; iEntries: GLint; puRed: PGLUSHORT; puGreen: PGLUSHORT; puBlue: PGLUSHORT): BOOL; stdcall = nil; - wglSetGammaTableI3D: function(hDC: HDC; iEntries: GLint; const puRed: PGLUSHORT; const puGreen: PGLUSHORT; const puBlue: PGLUSHORT): BOOL; stdcall = nil; - -function Load_WGL_I3D_gamma: Boolean; - -//***** WGL_I3D_genlock *****// -const - WGL_GENLOCK_SOURCE_MULTIVIEW_I3D = $2044; - WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D = $2045; - WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D = $2046; - WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D = $2047; - WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D = $2048; - WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D = $2049; - WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D = $204A; - WGL_GENLOCK_SOURCE_EDGE_RISING_I3D = $204B; - WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D = $204C; -var - wglEnableGenlockI3D: function(hDC: HDC): BOOL; stdcall = nil; - wglDisableGenlockI3D: function(hDC: HDC): BOOL; stdcall = nil; - wglIsEnabledGenlockI3D: function(hDC: HDC; pFlag: PBOOL): BOOL; stdcall = nil; - wglGenlockSourceI3D: function(hDC: HDC; uSource: GLUINT): BOOL; stdcall = nil; - wglGetGenlockSourceI3D: function(hDC: HDC; uSource: PGLUINT): BOOL; stdcall = nil; - wglGenlockSourceEdgeI3D: function(hDC: HDC; uEdge: GLUINT): BOOL; stdcall = nil; - wglGetGenlockSourceEdgeI3D: function(hDC: HDC; uEdge: PGLUINT): BOOL; stdcall = nil; - wglGenlockSampleRateI3D: function(hDC: HDC; uRate: GLUINT): BOOL; stdcall = nil; - wglGetGenlockSampleRateI3D: function(hDC: HDC; uRate: PGLUINT): BOOL; stdcall = nil; - wglGenlockSourceDelayI3D: function(hDC: HDC; uDelay: GLUINT): BOOL; stdcall = nil; - wglGetGenlockSourceDelayI3D: function(hDC: HDC; uDelay: PGLUINT): BOOL; stdcall = nil; - wglQueryGenlockMaxSourceDelayI3D: function(hDC: HDC; uMaxLineDelay: PGLUINT; uMaxPixelDelay: PGLUINT): BOOL; stdcall = nil; - -function Load_WGL_I3D_genlock: Boolean; - -//***** GL_ARB_matrix_palette *****// -const - GL_MATRIX_PALETTE_ARB = $8840; - GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB = $8841; - GL_MAX_PALETTE_MATRICES_ARB = $8842; - GL_CURRENT_PALETTE_MATRIX_ARB = $8843; - GL_MATRIX_INDEX_ARRAY_ARB = $8844; - GL_CURRENT_MATRIX_INDEX_ARB = $8845; - GL_MATRIX_INDEX_ARRAY_SIZE_ARB = $8846; - GL_MATRIX_INDEX_ARRAY_TYPE_ARB = $8847; - GL_MATRIX_INDEX_ARRAY_STRIDE_ARB = $8848; - GL_MATRIX_INDEX_ARRAY_POINTER_ARB = $8849; -var - glCurrentPaletteMatrixARB: procedure(index: GLint); stdcall = nil; - glMatrixIndexubvARB: procedure(size: GLint; indices: PGLubyte); stdcall = nil; - glMatrixIndexusvARB: procedure(size: GLint; indices: PGLushort); stdcall = nil; - glMatrixIndexuivARB: procedure(size: GLint; indices: PGLuint); stdcall = nil; - glMatrixIndexPointerARB: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); stdcall = nil; - -function Load_GL_ARB_matrix_palette: Boolean; - -//***** GL_NV_element_array *****// -const - GL_ELEMENT_ARRAY_TYPE_NV = $8769; - GL_ELEMENT_ARRAY_POINTER_NV = $876A; -var - glElementPointerNV: procedure(_type: GLenum; const pointer: PGLvoid); stdcall = nil; - glDrawElementArrayNV: procedure(mode: GLenum; first: GLint; count: GLsizei); stdcall = nil; - glDrawRangeElementArrayNV: procedure(mode: GLenum; start: GLuint; _end: GLuint; first: GLint; count: GLsizei); stdcall = nil; - glMultiDrawElementArrayNV: procedure(mode: GLenum; const first: PGLint; const count: PGLsizei; primcount: GLsizei); stdcall = nil; - glMultiDrawRangeElementArrayNV: procedure(mode: GLenum; start: GLuint; _end: GLuint; const first: PGLint; const count: PGLsizei; primcount: GLsizei); stdcall = nil; - -function Load_GL_NV_element_array: Boolean; - -//***** GL_NV_float_buffer *****// -const - GL_FLOAT_R_NV = $8880; - GL_FLOAT_RG_NV = $8881; - GL_FLOAT_RGB_NV = $8882; - GL_FLOAT_RGBA_NV = $8883; - GL_FLOAT_R16_NV = $8884; - GL_FLOAT_R32_NV = $8885; - GL_FLOAT_RG16_NV = $8886; - GL_FLOAT_RG32_NV = $8887; - GL_FLOAT_RGB16_NV = $8888; - GL_FLOAT_RGB32_NV = $8889; - GL_FLOAT_RGBA16_NV = $888A; - GL_FLOAT_RGBA32_NV = $888B; - GL_TEXTURE_FLOAT_COMPONENTS_NV = $888C; - GL_FLOAT_CLEAR_COLOR_VALUE_NV = $888D; - GL_FLOAT_RGBA_MODE_NV = $888E; - WGL_FLOAT_COMPONENTS_NV = $20B0; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV = $20B1; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV = $20B2; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV = $20B3; - WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV = $20B4; - WGL_TEXTURE_FLOAT_R_NV = $20B5; - WGL_TEXTURE_FLOAT_RG_NV = $20B6; - WGL_TEXTURE_FLOAT_RGB_NV = $20B7; - WGL_TEXTURE_FLOAT_RGBA_NV = $20B8; - -function Load_GL_NV_float_buffer: Boolean; - -//***** GL_NV_fragment_program *****// -const - GL_FRAGMENT_PROGRAM_NV = $8870; - GL_MAX_TEXTURE_COORDS_NV = $8871; - GL_MAX_TEXTURE_IMAGE_UNITS_NV = $8872; - GL_FRAGMENT_PROGRAM_BINDING_NV = $8873; - GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV = $8868; - GL_PROGRAM_ERROR_STRING_NV = $8874; -var - glProgramNamedParameter4fNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glProgramNamedParameter4dNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); stdcall = nil; - glGetProgramNamedParameterfvNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; params: PGLfloat); stdcall = nil; - glGetProgramNamedParameterdvNV: procedure(id: GLuint; len: GLsizei; const name: PGLubyte; params: PGLdouble); stdcall = nil; - // glProgramLocalParameter4dARB { already defined } - // glProgramLocalParameter4dvARB { already defined } - // glProgramLocalParameter4fARB { already defined } - // glProgramLocalParameter4fvARB { already defined } - // glGetProgramLocalParameterdvARB { already defined } - // glGetProgramLocalParameterfvARB { already defined } - -function Load_GL_NV_fragment_program: Boolean; - -//***** GL_NV_primitive_restart *****// -const - GL_PRIMITIVE_RESTART_NV = $8558; - GL_PRIMITIVE_RESTART_INDEX_NV = $8559; -var - glPrimitiveRestartNV: procedure(); stdcall = nil; - glPrimitiveRestartIndexNV: procedure(index: GLuint); stdcall = nil; - -function Load_GL_NV_primitive_restart: Boolean; - -//***** GL_NV_vertex_program2 *****// - -function Load_GL_NV_vertex_program2: Boolean; - -//***** WGL_NV_render_texture_rectangle *****// -const - WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV = $20A0; - WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV = $20A1; - WGL_TEXTURE_RECTANGLE_NV = $20A2; - -function Load_WGL_NV_render_texture_rectangle: Boolean; - -//***** GL_NV_pixel_data_range *****// -const - GL_WRITE_PIXEL_DATA_RANGE_NV = $8878; - GL_READ_PIXEL_DATA_RANGE_NV = $8879; - GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV = $887A; - GL_READ_PIXEL_DATA_RANGE_LENGTH_NV = $887B; - GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV = $887C; - GL_READ_PIXEL_DATA_RANGE_POINTER_NV = $887D; -var - glPixelDataRangeNV: procedure(target: GLenum; length: GLsizei; pointer: PGLvoid); stdcall = nil; - glFlushPixelDataRangeNV: procedure(target: GLenum); stdcall = nil; - // wglAllocateMemoryNV { already defined } - // wglFreeMemoryNV { already defined } - -function Load_GL_NV_pixel_data_range: Boolean; - -//***** GL_EXT_texture_rectangle *****// -const - GL_TEXTURE_RECTANGLE_EXT = $84F5; - GL_TEXTURE_BINDING_RECTANGLE_EXT = $84F6; - GL_PROXY_TEXTURE_RECTANGLE_EXT = $84F7; - GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT = $84F8; - -function Load_GL_EXT_texture_rectangle: Boolean; - -//***** GL_S3_s3tc *****// -const - GL_RGB_S3TC = $83A0; - GL_RGB4_S3TC = $83A1; - GL_RGBA_S3TC = $83A2; - GL_RGBA4_S3TC = $83A3; - -function Load_GL_S3_s3tc: Boolean; - -//***** GL_ATI_draw_buffers *****// -const - GL_MAX_DRAW_BUFFERS_ATI = $8824; - GL_DRAW_BUFFER0_ATI = $8825; - GL_DRAW_BUFFER1_ATI = $8826; - GL_DRAW_BUFFER2_ATI = $8827; - GL_DRAW_BUFFER3_ATI = $8828; - GL_DRAW_BUFFER4_ATI = $8829; - GL_DRAW_BUFFER5_ATI = $882A; - GL_DRAW_BUFFER6_ATI = $882B; - GL_DRAW_BUFFER7_ATI = $882C; - GL_DRAW_BUFFER8_ATI = $882D; - GL_DRAW_BUFFER9_ATI = $882E; - GL_DRAW_BUFFER10_ATI = $882F; - GL_DRAW_BUFFER11_ATI = $8830; - GL_DRAW_BUFFER12_ATI = $8831; - GL_DRAW_BUFFER13_ATI = $8832; - GL_DRAW_BUFFER14_ATI = $8833; - GL_DRAW_BUFFER15_ATI = $8834; -var - glDrawBuffersATI: procedure(n: GLsizei; const bufs: PGLenum); stdcall = nil; - -function Load_GL_ATI_draw_buffers: Boolean; - -//***** WGL_ATI_pixel_format_float *****// -const - WGL_RGBA_FLOAT_MODE_ATI = $8820; - WGL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI = $8835; - WGL_TYPE_RGBA_FLOAT_ATI = $21A0; - -function Load_WGL_ATI_pixel_format_float: Boolean; - -//***** GL_ATI_texture_env_combine3 *****// -const - GL_MODULATE_ADD_ATI = $8744; - GL_MODULATE_SIGNED_ADD_ATI = $8745; - GL_MODULATE_SUBTRACT_ATI = $8746; - -function Load_GL_ATI_texture_env_combine3: Boolean; - -//***** GL_ATI_texture_float *****// -const - GL_RGBA_FLOAT32_ATI = $8814; - GL_RGB_FLOAT32_ATI = $8815; - GL_ALPHA_FLOAT32_ATI = $8816; - GL_INTENSITY_FLOAT32_ATI = $8817; - GL_LUMINANCE_FLOAT32_ATI = $8818; - GL_LUMINANCE_ALPHA_FLOAT32_ATI = $8819; - GL_RGBA_FLOAT16_ATI = $881A; - GL_RGB_FLOAT16_ATI = $881B; - GL_ALPHA_FLOAT16_ATI = $881C; - GL_INTENSITY_FLOAT16_ATI = $881D; - GL_LUMINANCE_FLOAT16_ATI = $881E; - GL_LUMINANCE_ALPHA_FLOAT16_ATI = $881F; - -function Load_GL_ATI_texture_float: Boolean; - -//***** GL_NV_texture_expand_normal *****// -const - GL_TEXTURE_UNSIGNED_REMAP_MODE_NV = $888F; - -function Load_GL_NV_texture_expand_normal: Boolean; - -//***** GL_NV_half_float *****// -const - GL_HALF_FLOAT_NV = $140B; -var - glVertex2hNV: procedure(x: GLushort; y: GLushort); stdcall = nil; - glVertex2hvNV: procedure(const v: PGLushort); stdcall = nil; - glVertex3hNV: procedure(x: GLushort; y: GLushort; z: GLushort); stdcall = nil; - glVertex3hvNV: procedure(const v: PGLushort); stdcall = nil; - glVertex4hNV: procedure(x: GLushort; y: GLushort; z: GLushort; w: GLushort); stdcall = nil; - glVertex4hvNV: procedure(const v: PGLushort); stdcall = nil; - glNormal3hNV: procedure(nx: GLushort; ny: GLushort; nz: GLushort); stdcall = nil; - glNormal3hvNV: procedure(const v: PGLushort); stdcall = nil; - glColor3hNV: procedure(red: GLushort; green: GLushort; blue: GLushort); stdcall = nil; - glColor3hvNV: procedure(const v: PGLushort); stdcall = nil; - glColor4hNV: procedure(red: GLushort; green: GLushort; blue: GLushort; alpha: GLushort); stdcall = nil; - glColor4hvNV: procedure(const v: PGLushort); stdcall = nil; - glTexCoord1hNV: procedure(s: GLushort); stdcall = nil; - glTexCoord1hvNV: procedure(const v: PGLushort); stdcall = nil; - glTexCoord2hNV: procedure(s: GLushort; t: GLushort); stdcall = nil; - glTexCoord2hvNV: procedure(const v: PGLushort); stdcall = nil; - glTexCoord3hNV: procedure(s: GLushort; t: GLushort; r: GLushort); stdcall = nil; - glTexCoord3hvNV: procedure(const v: PGLushort); stdcall = nil; - glTexCoord4hNV: procedure(s: GLushort; t: GLushort; r: GLushort; q: GLushort); stdcall = nil; - glTexCoord4hvNV: procedure(const v: PGLushort); stdcall = nil; - glMultiTexCoord1hNV: procedure(target: GLenum; s: GLushort); stdcall = nil; - glMultiTexCoord1hvNV: procedure(target: GLenum; const v: PGLushort); stdcall = nil; - glMultiTexCoord2hNV: procedure(target: GLenum; s: GLushort; t: GLushort); stdcall = nil; - glMultiTexCoord2hvNV: procedure(target: GLenum; const v: PGLushort); stdcall = nil; - glMultiTexCoord3hNV: procedure(target: GLenum; s: GLushort; t: GLushort; r: GLushort); stdcall = nil; - glMultiTexCoord3hvNV: procedure(target: GLenum; const v: PGLushort); stdcall = nil; - glMultiTexCoord4hNV: procedure(target: GLenum; s: GLushort; t: GLushort; r: GLushort; q: GLushort); stdcall = nil; - glMultiTexCoord4hvNV: procedure(target: GLenum; const v: PGLushort); stdcall = nil; - glFogCoordhNV: procedure(fog: GLushort); stdcall = nil; - glFogCoordhvNV: procedure(const fog: PGLushort); stdcall = nil; - glSecondaryColor3hNV: procedure(red: GLushort; green: GLushort; blue: GLushort); stdcall = nil; - glSecondaryColor3hvNV: procedure(const v: PGLushort); stdcall = nil; - glVertexWeighthNV: procedure(weight: GLushort); stdcall = nil; - glVertexWeighthvNV: procedure(const weight: PGLushort); stdcall = nil; - glVertexAttrib1hNV: procedure(index: GLuint; x: GLushort); stdcall = nil; - glVertexAttrib1hvNV: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttrib2hNV: procedure(index: GLuint; x: GLushort; y: GLushort); stdcall = nil; - glVertexAttrib2hvNV: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttrib3hNV: procedure(index: GLuint; x: GLushort; y: GLushort; z: GLushort); stdcall = nil; - glVertexAttrib3hvNV: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttrib4hNV: procedure(index: GLuint; x: GLushort; y: GLushort; z: GLushort; w: GLushort); stdcall = nil; - glVertexAttrib4hvNV: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttribs1hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); stdcall = nil; - glVertexAttribs2hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); stdcall = nil; - glVertexAttribs3hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); stdcall = nil; - glVertexAttribs4hvNV: procedure(index: GLuint; n: GLsizei; const v: PGLushort); stdcall = nil; - -function Load_GL_NV_half_float: Boolean; - -//***** GL_ATI_map_object_buffer *****// -var - glMapObjectBufferATI: function(buffer: GLuint): PGLvoid; stdcall = nil; - glUnmapObjectBufferATI: procedure(buffer: GLuint); stdcall = nil; - -function Load_GL_ATI_map_object_buffer: Boolean; - -//***** GL_ATI_separate_stencil *****// -const - GL_KEEP = $1E00; - GL_ZERO = $0000; - GL_REPLACE = $1E01; - GL_INCR = $1E02; - GL_DECR = $1E03; - GL_INVERT = $150A; - GL_NEVER = $0200; - GL_LESS = $0201; - GL_LEQUAL = $0203; - GL_GREATER = $0204; - GL_GEQUAL = $0206; - GL_EQUAL = $0202; - GL_NOTEQUAL = $0205; - GL_ALWAYS = $0207; - GL_FRONT = $0404; - GL_BACK = $0405; - GL_FRONT_AND_BACK = $0408; - GL_STENCIL_BACK_FUNC_ATI = $8800; - GL_STENCIL_BACK_FAIL_ATI = $8801; - GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI = $8802; - GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI = $8803; -var - glStencilOpSeparateATI: procedure(face: GLenum; sfail: GLenum; dpfail: GLenum; dppass: GLenum); stdcall = nil; - glStencilFuncSeparateATI: procedure(frontfunc: GLenum; backfunc: GLenum; ref: GLint; mask: GLuint); stdcall = nil; - -function Load_GL_ATI_separate_stencil: Boolean; - -//***** GL_ATI_vertex_attrib_array_object *****// -var - glVertexAttribArrayObjectATI: procedure(index: GLuint; size: GLint; _type: GLenum; normalized: GLboolean; stride: GLsizei; buffer: GLuint; offset: GLuint); stdcall = nil; - glGetVertexAttribArrayObjectfvATI: procedure(index: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetVertexAttribArrayObjectivATI: procedure(index: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - -function Load_GL_ATI_vertex_attrib_array_object: Boolean; - -//***** GL_ARB_vertex_buffer_object *****// -const - GL_ARRAY_BUFFER_ARB = $8892; - GL_ELEMENT_ARRAY_BUFFER_ARB = $8893; - GL_ARRAY_BUFFER_BINDING_ARB = $8894; - GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB = $8895; - GL_VERTEX_ARRAY_BUFFER_BINDING_ARB = $8896; - GL_NORMAL_ARRAY_BUFFER_BINDING_ARB = $8897; - GL_COLOR_ARRAY_BUFFER_BINDING_ARB = $8898; - GL_INDEX_ARRAY_BUFFER_BINDING_ARB = $8899; - GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB = $889A; - GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB = $889B; - GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB = $889C; - GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB = $889D; - GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB = $889E; - GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB = $889F; - GL_STREAM_DRAW_ARB = $88E0; - GL_STREAM_READ_ARB = $88E1; - GL_STREAM_COPY_ARB = $88E2; - GL_STATIC_DRAW_ARB = $88E4; - GL_STATIC_READ_ARB = $88E5; - GL_STATIC_COPY_ARB = $88E6; - GL_DYNAMIC_DRAW_ARB = $88E8; - GL_DYNAMIC_READ_ARB = $88E9; - GL_DYNAMIC_COPY_ARB = $88EA; - GL_READ_ONLY_ARB = $88B8; - GL_WRITE_ONLY_ARB = $88B9; - GL_READ_WRITE_ARB = $88BA; - GL_BUFFER_SIZE_ARB = $8764; - GL_BUFFER_USAGE_ARB = $8765; - GL_BUFFER_ACCESS_ARB = $88BB; - GL_BUFFER_MAPPED_ARB = $88BC; - GL_BUFFER_MAP_POINTER_ARB = $88BD; -var - glBindBufferARB: procedure(target: GLenum; buffer: GLuint); stdcall = nil; - glDeleteBuffersARB: procedure(n: GLsizei; const buffers: PGLuint); stdcall = nil; - glGenBuffersARB: procedure(n: GLsizei; buffers: PGLuint); stdcall = nil; - glIsBufferARB: function(buffer: GLuint): GLboolean; stdcall = nil; - glBufferDataARB: procedure(target: GLenum; size: GLsizeiptrARB; const data: PGLvoid; usage: GLenum); stdcall = nil; - glBufferSubDataARB: procedure(target: GLenum; offset: GLintptrARB; size: GLsizeiptrARB; const data: PGLvoid); stdcall = nil; - glGetBufferSubDataARB: procedure(target: GLenum; offset: GLintptrARB; size: GLsizeiptrARB; data: PGLvoid); stdcall = nil; - glMapBufferARB: function(target: GLenum; access: GLenum): PGLvoid; stdcall = nil; - glUnmapBufferARB: function(target: GLenum): GLboolean; stdcall = nil; - glGetBufferParameterivARB: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetBufferPointervARB: procedure(target: GLenum; pname: GLenum; params: PGLvoid); stdcall = nil; - -function Load_GL_ARB_vertex_buffer_object: Boolean; - -//***** GL_ARB_occlusion_query *****// -const - GL_SAMPLES_PASSED_ARB = $8914; - GL_QUERY_COUNTER_BITS_ARB = $8864; - GL_CURRENT_QUERY_ARB = $8865; - GL_QUERY_RESULT_ARB = $8866; - GL_QUERY_RESULT_AVAILABLE_ARB = $8867; -var - glGenQueriesARB: procedure(n: GLsizei; ids: PGLuint); stdcall = nil; - glDeleteQueriesARB: procedure(n: GLsizei; const ids: PGLuint); stdcall = nil; - glIsQueryARB: function(id: GLuint): GLboolean; stdcall = nil; - glBeginQueryARB: procedure(target: GLenum; id: GLuint); stdcall = nil; - glEndQueryARB: procedure(target: GLenum); stdcall = nil; - glGetQueryivARB: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetQueryObjectivARB: procedure(id: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetQueryObjectuivARB: procedure(id: GLuint; pname: GLenum; params: PGLuint); stdcall = nil; - -function Load_GL_ARB_occlusion_query: Boolean; - -//***** GL_ARB_shader_objects *****// -const - GL_PROGRAM_OBJECT_ARB = $8B40; - GL_OBJECT_TYPE_ARB = $8B4E; - GL_OBJECT_SUBTYPE_ARB = $8B4F; - GL_OBJECT_DELETE_STATUS_ARB = $8B80; - GL_OBJECT_COMPILE_STATUS_ARB = $8B81; - GL_OBJECT_LINK_STATUS_ARB = $8B82; - GL_OBJECT_VALIDATE_STATUS_ARB = $8B83; - GL_OBJECT_INFO_LOG_LENGTH_ARB = $8B84; - GL_OBJECT_ATTACHED_OBJECTS_ARB = $8B85; - GL_OBJECT_ACTIVE_UNIFORMS_ARB = $8B86; - GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB = $8B87; - GL_OBJECT_SHADER_SOURCE_LENGTH_ARB = $8B88; - GL_SHADER_OBJECT_ARB = $8B48; - GL_FLOAT = $1406; - GL_FLOAT_VEC2_ARB = $8B50; - GL_FLOAT_VEC3_ARB = $8B51; - GL_FLOAT_VEC4_ARB = $8B52; - GL_INT = $1404; - GL_INT_VEC2_ARB = $8B53; - GL_INT_VEC3_ARB = $8B54; - GL_INT_VEC4_ARB = $8B55; - GL_BOOL_ARB = $8B56; - GL_BOOL_VEC2_ARB = $8B57; - GL_BOOL_VEC3_ARB = $8B58; - GL_BOOL_VEC4_ARB = $8B59; - GL_FLOAT_MAT2_ARB = $8B5A; - GL_FLOAT_MAT3_ARB = $8B5B; - GL_FLOAT_MAT4_ARB = $8B5C; -var - glDeleteObjectARB: procedure(obj: GLhandleARB); stdcall = nil; - glGetHandleARB: function(pname: GLenum): GLhandleARB; stdcall = nil; - glDetachObjectARB: procedure(containerObj: GLhandleARB; attachedObj: GLhandleARB); stdcall = nil; - glCreateShaderObjectARB: function(shaderType: GLenum): GLhandleARB; stdcall = nil; - glShaderSourceARB: procedure(shaderObj: GLhandleARB; count: GLsizei; const _string: PGLvoid; const length: PGLint); stdcall = nil; - glCompileShaderARB: procedure(shaderObj: GLhandleARB); stdcall = nil; - glCreateProgramObjectARB: function(): GLhandleARB; stdcall = nil; - glAttachObjectARB: procedure(containerObj: GLhandleARB; obj: GLhandleARB); stdcall = nil; - glLinkProgramARB: procedure(programObj: GLhandleARB); stdcall = nil; - glUseProgramObjectARB: procedure(programObj: GLhandleARB); stdcall = nil; - glValidateProgramARB: procedure(programObj: GLhandleARB); stdcall = nil; - glUniform1fARB: procedure(location: GLint; v0: GLfloat); stdcall = nil; - glUniform2fARB: procedure(location: GLint; v0: GLfloat; v1: GLfloat); stdcall = nil; - glUniform3fARB: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat); stdcall = nil; - glUniform4fARB: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat; v3: GLfloat); stdcall = nil; - glUniform1iARB: procedure(location: GLint; v0: GLint); stdcall = nil; - glUniform2iARB: procedure(location: GLint; v0: GLint; v1: GLint); stdcall = nil; - glUniform3iARB: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint); stdcall = nil; - glUniform4iARB: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint; v3: GLint); stdcall = nil; - glUniform1fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); stdcall = nil; - glUniform2fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); stdcall = nil; - glUniform3fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); stdcall = nil; - glUniform4fvARB: procedure(location: GLint; count: GLsizei; value: PGLfloat); stdcall = nil; - glUniform1ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); stdcall = nil; - glUniform2ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); stdcall = nil; - glUniform3ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); stdcall = nil; - glUniform4ivARB: procedure(location: GLint; count: GLsizei; value: PGLint); stdcall = nil; - glUniformMatrix2fvARB: procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); stdcall = nil; - glUniformMatrix3fvARB: procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); stdcall = nil; - glUniformMatrix4fvARB: procedure(location: GLint; count: GLsizei; transpose: GLboolean; value: PGLfloat); stdcall = nil; - glGetObjectParameterfvARB: procedure(obj: GLhandleARB; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetObjectParameterivARB: procedure(obj: GLhandleARB; pname: GLenum; params: PGLint); stdcall = nil; - glGetInfoLogARB: procedure(obj: GLhandleARB; maxLength: GLsizei; length: PGLsizei; infoLog: PGLcharARB); stdcall = nil; - glGetAttachedObjectsARB: procedure(containerObj: GLhandleARB; maxCount: GLsizei; count: PGLsizei; obj: PGLhandleARB); stdcall = nil; - glGetUniformLocationARB: function(programObj: GLhandleARB; const name: PGLcharARB): GLint; stdcall = nil; - glGetActiveUniformARB: procedure(programObj: GLhandleARB; index: GLuint; maxLength: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLcharARB); stdcall = nil; - glGetUniformfvARB: procedure(programObj: GLhandleARB; location: GLint; params: PGLfloat); stdcall = nil; - glGetUniformivARB: procedure(programObj: GLhandleARB; location: GLint; params: PGLint); stdcall = nil; - glGetShaderSourceARB: procedure(obj: GLhandleARB; maxLength: GLsizei; length: PGLsizei; source: PGLcharARB); stdcall = nil; - -function Load_GL_ARB_shader_objects: Boolean; - -//***** GL_ARB_vertex_shader *****// -const - GL_VERTEX_SHADER_ARB = $8B31; - GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB = $8B4A; - GL_MAX_VARYING_FLOATS_ARB = $8B4B; - // GL_MAX_VERTEX_ATTRIBS_ARB { already defined } - // GL_MAX_TEXTURE_IMAGE_UNITS_ARB { already defined } - GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB = $8B4C; - GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB = $8B4D; - // GL_MAX_TEXTURE_COORDS_ARB { already defined } - // GL_VERTEX_PROGRAM_POINT_SIZE_ARB { already defined } - // GL_VERTEX_PROGRAM_TWO_SIDE_ARB { already defined } - // GL_OBJECT_TYPE_ARB { already defined } - // GL_OBJECT_SUBTYPE_ARB { already defined } - GL_OBJECT_ACTIVE_ATTRIBUTES_ARB = $8B89; - GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB = $8B8A; - // GL_SHADER_OBJECT_ARB { already defined } - // GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB { already defined } - // GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB { already defined } - // GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB { already defined } - // GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB { already defined } - // GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB { already defined } - // GL_CURRENT_VERTEX_ATTRIB_ARB { already defined } - // GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB { already defined } - // GL_FLOAT { already defined } - // GL_FLOAT_VEC2_ARB { already defined } - // GL_FLOAT_VEC3_ARB { already defined } - // GL_FLOAT_VEC4_ARB { already defined } - // GL_FLOAT_MAT2_ARB { already defined } - // GL_FLOAT_MAT3_ARB { already defined } - // GL_FLOAT_MAT4_ARB { already defined } - // glVertexAttrib1fARB { already defined } - // glVertexAttrib1sARB { already defined } - // glVertexAttrib1dARB { already defined } - // glVertexAttrib2fARB { already defined } - // glVertexAttrib2sARB { already defined } - // glVertexAttrib2dARB { already defined } - // glVertexAttrib3fARB { already defined } - // glVertexAttrib3sARB { already defined } - // glVertexAttrib3dARB { already defined } - // glVertexAttrib4fARB { already defined } - // glVertexAttrib4sARB { already defined } - // glVertexAttrib4dARB { already defined } - // glVertexAttrib4NubARB { already defined } - // glVertexAttrib1fvARB { already defined } - // glVertexAttrib1svARB { already defined } - // glVertexAttrib1dvARB { already defined } - // glVertexAttrib2fvARB { already defined } - // glVertexAttrib2svARB { already defined } - // glVertexAttrib2dvARB { already defined } - // glVertexAttrib3fvARB { already defined } - // glVertexAttrib3svARB { already defined } - // glVertexAttrib3dvARB { already defined } - // glVertexAttrib4fvARB { already defined } - // glVertexAttrib4svARB { already defined } - // glVertexAttrib4dvARB { already defined } - // glVertexAttrib4ivARB { already defined } - // glVertexAttrib4bvARB { already defined } - // glVertexAttrib4ubvARB { already defined } - // glVertexAttrib4usvARB { already defined } - // glVertexAttrib4uivARB { already defined } - // glVertexAttrib4NbvARB { already defined } - // glVertexAttrib4NsvARB { already defined } - // glVertexAttrib4NivARB { already defined } - // glVertexAttrib4NubvARB { already defined } - // glVertexAttrib4NusvARB { already defined } - // glVertexAttrib4NuivARB { already defined } - // glVertexAttribPointerARB { already defined } - // glEnableVertexAttribArrayARB { already defined } - // glDisableVertexAttribArrayARB { already defined } -var - glBindAttribLocationARB: procedure(programObj: GLhandleARB; index: GLuint; const name: PGLcharARB); stdcall = nil; - glGetActiveAttribARB: procedure(programObj: GLhandleARB; index: GLuint; maxLength: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLcharARB); stdcall = nil; - glGetAttribLocationARB: function(programObj: GLhandleARB; const name: PGLcharARB): GLint; stdcall = nil; - // glGetVertexAttribdvARB { already defined } - // glGetVertexAttribfvARB { already defined } - // glGetVertexAttribivARB { already defined } - // glGetVertexAttribPointervARB { already defined } - -function Load_GL_ARB_vertex_shader: Boolean; - -//***** GL_ARB_fragment_shader *****// -const - GL_FRAGMENT_SHADER_ARB = $8B30; - GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB = $8B49; - // GL_MAX_TEXTURE_COORDS_ARB { already defined } - // GL_MAX_TEXTURE_IMAGE_UNITS_ARB { already defined } - // GL_OBJECT_TYPE_ARB { already defined } - // GL_OBJECT_SUBTYPE_ARB { already defined } - // GL_SHADER_OBJECT_ARB { already defined } - -function Load_GL_ARB_fragment_shader: Boolean; - -//***** GL_ARB_shading_language_100 *****// -const - GL_SHADING_LANGUAGE_VERSION_ARB = $8B8C; - -function Load_GL_ARB_shading_language_100: Boolean; - -//***** GL_ARB_texture_non_power_of_two *****// - -function Load_GL_ARB_texture_non_power_of_two: Boolean; - -//***** GL_ARB_point_sprite *****// -const - GL_POINT_SPRITE_ARB = $8861; - GL_COORD_REPLACE_ARB = $8862; - -function Load_GL_ARB_point_sprite: Boolean; - -//***** GL_EXT_depth_bounds_test *****// -const - GL_DEPTH_BOUNDS_TEST_EXT = $8890; - GL_DEPTH_BOUNDS_EXT = $8891; -var - glDepthBoundsEXT: procedure(zmin: GLclampd; zmax: GLclampd); stdcall = nil; - -function Load_GL_EXT_depth_bounds_test: Boolean; - -//***** GL_EXT_secondary_color *****// -const - GL_COLOR_SUM_EXT = $8458; - GL_CURRENT_SECONDARY_COLOR_EXT = $8459; - GL_SECONDARY_COLOR_ARRAY_SIZE_EXT = $845A; - GL_SECONDARY_COLOR_ARRAY_TYPE_EXT = $845B; - GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT = $845C; - GL_SECONDARY_COLOR_ARRAY_POINTER_EXT = $845D; - GL_SECONDARY_COLOR_ARRAY_EXT = $845E; -var - glSecondaryColor3bEXT: procedure(r: GLbyte; g: GLbyte; b: GLbyte); stdcall = nil; - glSecondaryColor3sEXT: procedure(r: GLshort; g: GLshort; b: GLshort); stdcall = nil; - glSecondaryColor3iEXT: procedure(r: GLint; g: GLint; b: GLint); stdcall = nil; - glSecondaryColor3fEXT: procedure(r: GLfloat; g: GLfloat; b: GLfloat); stdcall = nil; - glSecondaryColor3dEXT: procedure(r: GLdouble; g: GLdouble; b: GLdouble); stdcall = nil; - glSecondaryColor3ubEXT: procedure(r: GLubyte; g: GLubyte; b: GLubyte); stdcall = nil; - glSecondaryColor3usEXT: procedure(r: GLushort; g: GLushort; b: GLushort); stdcall = nil; - glSecondaryColor3uiEXT: procedure(r: GLuint; g: GLuint; b: GLuint); stdcall = nil; - glSecondaryColor3bvEXT: procedure(components: PGLbyte); stdcall = nil; - glSecondaryColor3svEXT: procedure(components: PGLshort); stdcall = nil; - glSecondaryColor3ivEXT: procedure(components: PGLint); stdcall = nil; - glSecondaryColor3fvEXT: procedure(components: PGLfloat); stdcall = nil; - glSecondaryColor3dvEXT: procedure(components: PGLdouble); stdcall = nil; - glSecondaryColor3ubvEXT: procedure(components: PGLubyte); stdcall = nil; - glSecondaryColor3usvEXT: procedure(components: PGLushort); stdcall = nil; - glSecondaryColor3uivEXT: procedure(components: PGLuint); stdcall = nil; - glSecondaryColorPointerEXT: procedure(size: GLint; _type: GLenum; stride: GLsizei; pointer: PGLvoid); stdcall = nil; - -function Load_GL_EXT_secondary_color: Boolean; - -//***** GL_EXT_texture_mirror_clamp *****// -const - GL_MIRROR_CLAMP_EXT = $8742; - GL_MIRROR_CLAMP_TO_EDGE_EXT = $8743; - GL_MIRROR_CLAMP_TO_BORDER_EXT = $8912; - -function Load_GL_EXT_texture_mirror_clamp: Boolean; - -//***** GL_EXT_blend_equation_separate *****// -const - GL_BLEND_EQUATION_RGB_EXT = $8009; - GL_BLEND_EQUATION_ALPHA_EXT = $883D; -var - glBlendEquationSeparateEXT: procedure(modeRGB: GLenum; modeAlpha: GLenum); stdcall = nil; - -function Load_GL_EXT_blend_equation_separate: Boolean; - -//***** GL_MESA_pack_invert *****// -const - GL_PACK_INVERT_MESA = $8758; - -function Load_GL_MESA_pack_invert: Boolean; - -//***** GL_MESA_ycbcr_texture *****// -const - GL_YCBCR_MESA = $8757; - GL_UNSIGNED_SHORT_8_8_MESA = $85BA; - GL_UNSIGNED_SHORT_8_8_REV_MESA = $85BB; - -function Load_GL_MESA_ycbcr_texture: Boolean; - -//***** GL_ARB_fragment_program_shadow *****// - -function Load_GL_ARB_fragment_program_shadow: Boolean; - -//***** GL_EXT_fog_coord *****// -const - GL_FOG_COORDINATE_SOURCE_EXT = $8450; - GL_FOG_COORDINATE_EXT = $8451; - GL_FRAGMENT_DEPTH_EXT = $8452; - GL_CURRENT_FOG_COORDINATE_EXT = $8453; - GL_FOG_COORDINATE_ARRAY_TYPE_EXT = $8454; - GL_FOG_COORDINATE_ARRAY_STRIDE_EXT = $8455; - GL_FOG_COORDINATE_ARRAY_POINTER_EXT = $8456; - GL_FOG_COORDINATE_ARRAY_EXT = $8457; -var - glFogCoordfEXT: procedure(coord: GLfloat); stdcall = nil; - glFogCoorddEXT: procedure(coord: GLdouble); stdcall = nil; - glFogCoordfvEXT: procedure(coord: PGLfloat); stdcall = nil; - glFogCoorddvEXT: procedure(coord: PGLdouble); stdcall = nil; - glFogCoordPointerEXT: procedure(_type: GLenum; stride: GLsizei; pointer: PGLvoid); stdcall = nil; - -function Load_GL_EXT_fog_coord: Boolean; - -//***** GL_NV_fragment_program_option *****// - -function Load_GL_NV_fragment_program_option: Boolean; - -//***** GL_EXT_pixel_buffer_object *****// -const - GL_PIXEL_PACK_BUFFER_EXT = $88EB; - GL_PIXEL_UNPACK_BUFFER_EXT = $88EC; - GL_PIXEL_PACK_BUFFER_BINDING_EXT = $88ED; - GL_PIXEL_UNPACK_BUFFER_BINDING_EXT = $88EF; - -function Load_GL_EXT_pixel_buffer_object: Boolean; - -//***** GL_NV_fragment_program2 *****// -const - GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV = $88F4; - GL_MAX_PROGRAM_CALL_DEPTH_NV = $88F5; - GL_MAX_PROGRAM_IF_DEPTH_NV = $88F6; - GL_MAX_PROGRAM_LOOP_DEPTH_NV = $88F7; - GL_MAX_PROGRAM_LOOP_COUNT_NV = $88F8; - -function Load_GL_NV_fragment_program2: Boolean; - -//***** GL_NV_vertex_program2_option *****// - // GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV { already defined } - // GL_MAX_PROGRAM_CALL_DEPTH_NV { already defined } - -function Load_GL_NV_vertex_program2_option: Boolean; - -//***** GL_NV_vertex_program3 *****// - // GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB { already defined } - -function Load_GL_NV_vertex_program3: Boolean; - -//***** GL_ARB_draw_buffers *****// -const - GL_MAX_DRAW_BUFFERS_ARB = $8824; - GL_DRAW_BUFFER0_ARB = $8825; - GL_DRAW_BUFFER1_ARB = $8826; - GL_DRAW_BUFFER2_ARB = $8827; - GL_DRAW_BUFFER3_ARB = $8828; - GL_DRAW_BUFFER4_ARB = $8829; - GL_DRAW_BUFFER5_ARB = $882A; - GL_DRAW_BUFFER6_ARB = $882B; - GL_DRAW_BUFFER7_ARB = $882C; - GL_DRAW_BUFFER8_ARB = $882D; - GL_DRAW_BUFFER9_ARB = $882E; - GL_DRAW_BUFFER10_ARB = $882F; - GL_DRAW_BUFFER11_ARB = $8830; - GL_DRAW_BUFFER12_ARB = $8831; - GL_DRAW_BUFFER13_ARB = $8832; - GL_DRAW_BUFFER14_ARB = $8833; - GL_DRAW_BUFFER15_ARB = $8834; -var - glDrawBuffersARB: procedure(n: GLsizei; const bufs: PGLenum); stdcall = nil; - -function Load_GL_ARB_draw_buffers: Boolean; - -//***** GL_ARB_texture_rectangle *****// -const - GL_TEXTURE_RECTANGLE_ARB = $84F5; - GL_TEXTURE_BINDING_RECTANGLE_ARB = $84F6; - GL_PROXY_TEXTURE_RECTANGLE_ARB = $84F7; - GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB = $84F8; - -function Load_GL_ARB_texture_rectangle: Boolean; - -//***** GL_ARB_color_buffer_float *****// -const - GL_RGBA_FLOAT_MODE_ARB = $8820; - GL_CLAMP_VERTEX_COLOR_ARB = $891A; - GL_CLAMP_FRAGMENT_COLOR_ARB = $891B; - GL_CLAMP_READ_COLOR_ARB = $891C; - GL_FIXED_ONLY_ARB = $891D; - WGL_TYPE_RGBA_FLOAT_ARB = $21A0; -var - glClampColorARB: procedure(target: GLenum; clamp: GLenum); stdcall = nil; - -function Load_GL_ARB_color_buffer_float: Boolean; - -//***** GL_ARB_half_float_pixel *****// -const - GL_HALF_FLOAT_ARB = $140B; - -function Load_GL_ARB_half_float_pixel: Boolean; - -//***** GL_ARB_texture_float *****// -const - GL_TEXTURE_RED_TYPE_ARB = $8C10; - GL_TEXTURE_GREEN_TYPE_ARB = $8C11; - GL_TEXTURE_BLUE_TYPE_ARB = $8C12; - GL_TEXTURE_ALPHA_TYPE_ARB = $8C13; - GL_TEXTURE_LUMINANCE_TYPE_ARB = $8C14; - GL_TEXTURE_INTENSITY_TYPE_ARB = $8C15; - GL_TEXTURE_DEPTH_TYPE_ARB = $8C16; - GL_UNSIGNED_NORMALIZED_ARB = $8C17; - GL_RGBA32F_ARB = $8814; - GL_RGB32F_ARB = $8815; - GL_ALPHA32F_ARB = $8816; - GL_INTENSITY32F_ARB = $8817; - GL_LUMINANCE32F_ARB = $8818; - GL_LUMINANCE_ALPHA32F_ARB = $8819; - GL_RGBA16F_ARB = $881A; - GL_RGB16F_ARB = $881B; - GL_ALPHA16F_ARB = $881C; - GL_INTENSITY16F_ARB = $881D; - GL_LUMINANCE16F_ARB = $881E; - GL_LUMINANCE_ALPHA16F_ARB = $881F; - -function Load_GL_ARB_texture_float: Boolean; - -//***** GL_EXT_texture_compression_dxt1 *****// - // GL_COMPRESSED_RGB_S3TC_DXT1_EXT { already defined } - // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT { already defined } - -function Load_GL_EXT_texture_compression_dxt1: Boolean; - -//***** GL_ARB_pixel_buffer_object *****// -const - GL_PIXEL_PACK_BUFFER_ARB = $88EB; - GL_PIXEL_UNPACK_BUFFER_ARB = $88EC; - GL_PIXEL_PACK_BUFFER_BINDING_ARB = $88ED; - GL_PIXEL_UNPACK_BUFFER_BINDING_ARB = $88EF; - -function Load_GL_ARB_pixel_buffer_object: Boolean; - -//***** GL_EXT_framebuffer_object *****// -const - GL_FRAMEBUFFER_EXT = $8D40; - GL_RENDERBUFFER_EXT = $8D41; - GL_STENCIL_INDEX_EXT = $8D45; - GL_STENCIL_INDEX1_EXT = $8D46; - GL_STENCIL_INDEX4_EXT = $8D47; - GL_STENCIL_INDEX8_EXT = $8D48; - GL_STENCIL_INDEX16_EXT = $8D49; - GL_RENDERBUFFER_WIDTH_EXT = $8D42; - GL_RENDERBUFFER_HEIGHT_EXT = $8D43; - GL_RENDERBUFFER_INTERNAL_FORMAT_EXT = $8D44; - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT = $8CD0; - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT = $8CD1; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT = $8CD2; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT = $8CD3; - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT = $8CD4; - GL_COLOR_ATTACHMENT0_EXT = $8CE0; - GL_COLOR_ATTACHMENT1_EXT = $8CE1; - GL_COLOR_ATTACHMENT2_EXT = $8CE2; - GL_COLOR_ATTACHMENT3_EXT = $8CE3; - GL_COLOR_ATTACHMENT4_EXT = $8CE4; - GL_COLOR_ATTACHMENT5_EXT = $8CE5; - GL_COLOR_ATTACHMENT6_EXT = $8CE6; - GL_COLOR_ATTACHMENT7_EXT = $8CE7; - GL_COLOR_ATTACHMENT8_EXT = $8CE8; - GL_COLOR_ATTACHMENT9_EXT = $8CE9; - GL_COLOR_ATTACHMENT10_EXT = $8CEA; - GL_COLOR_ATTACHMENT11_EXT = $8CEB; - GL_COLOR_ATTACHMENT12_EXT = $8CEC; - GL_COLOR_ATTACHMENT13_EXT = $8CED; - GL_COLOR_ATTACHMENT14_EXT = $8CEE; - GL_COLOR_ATTACHMENT15_EXT = $8CEF; - GL_DEPTH_ATTACHMENT_EXT = $8D00; - GL_STENCIL_ATTACHMENT_EXT = $8D20; - GL_FRAMEBUFFER_COMPLETE_EXT = $8CD5; - GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT = $8CD6; - GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT = $8CD7; - GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT = $8CD8; - GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT = $8CD9; - GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT = $8CDA; - GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT = $8CDB; - GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT = $8CDC; - GL_FRAMEBUFFER_UNSUPPORTED_EXT = $8CDD; - GL_FRAMEBUFFER_STATUS_ERROR_EXT = $8CDE; - GL_FRAMEBUFFER_BINDING_EXT = $8CA6; - GL_RENDERBUFFER_BINDING_EXT = $8CA7; - GL_MAX_COLOR_ATTACHMENTS_EXT = $8CDF; - GL_MAX_RENDERBUFFER_SIZE_EXT = $84E8; - GL_INVALID_FRAMEBUFFER_OPERATION_EXT = $0506; -var - glIsRenderbufferEXT: function(renderbuffer: GLuint): GLboolean; stdcall = nil; - glBindRenderbufferEXT: procedure(target: GLenum; renderbuffer: GLuint); stdcall = nil; - glDeleteRenderbuffersEXT: procedure(n: GLsizei; const renderbuffers: PGLuint); stdcall = nil; - glGenRenderbuffersEXT: procedure(n: GLsizei; renderbuffers: PGLuint); stdcall = nil; - glRenderbufferStorageEXT: procedure(target: GLenum; internalformat: GLenum; width: GLsizei; height: GLsizei); stdcall = nil; - glGetRenderbufferParameterivEXT: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glIsFramebufferEXT: function(framebuffer: GLuint): GLboolean; stdcall = nil; - glBindFramebufferEXT: procedure(target: GLenum; framebuffer: GLuint); stdcall = nil; - glDeleteFramebuffersEXT: procedure(n: GLsizei; const framebuffers: PGLuint); stdcall = nil; - glGenFramebuffersEXT: procedure(n: GLsizei; framebuffers: PGLuint); stdcall = nil; - glCheckFramebufferStatusEXT: function(target: GLenum): GLenum; stdcall = nil; - glFramebufferTexture1DEXT: procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); stdcall = nil; - glFramebufferTexture2DEXT: procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint); stdcall = nil; - glFramebufferTexture3DEXT: procedure(target: GLenum; attachment: GLenum; textarget: GLenum; texture: GLuint; level: GLint; zoffset: GLint); stdcall = nil; - glFramebufferRenderbufferEXT: procedure(target: GLenum; attachment: GLenum; renderbuffertarget: GLenum; renderbuffer: GLuint); stdcall = nil; - glGetFramebufferAttachmentParameterivEXT: procedure(target: GLenum; attachment: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGenerateMipmapEXT: procedure(target: GLenum); stdcall = nil; - -function Load_GL_EXT_framebuffer_object: Boolean; - -//***** GL_version_1_4 *****// -const - GL_BLEND_DST_RGB = $80C8; - GL_BLEND_SRC_RGB = $80C9; - GL_BLEND_DST_ALPHA = $80CA; - GL_BLEND_SRC_ALPHA = $80CB; - GL_POINT_SIZE_MIN = $8126; - GL_POINT_SIZE_MAX = $8127; - GL_POINT_FADE_THRESHOLD_SIZE = $8128; - GL_POINT_DISTANCE_ATTENUATION = $8129; - GL_GENERATE_MIPMAP = $8191; - GL_GENERATE_MIPMAP_HINT = $8192; - GL_DEPTH_COMPONENT16 = $81A5; - GL_DEPTH_COMPONENT24 = $81A6; - GL_DEPTH_COMPONENT32 = $81A7; - GL_MIRRORED_REPEAT = $8370; - GL_FOG_COORDINATE_SOURCE = $8450; - GL_FOG_COORDINATE = $8451; - GL_FRAGMENT_DEPTH = $8452; - GL_CURRENT_FOG_COORDINATE = $8453; - GL_FOG_COORDINATE_ARRAY_TYPE = $8454; - GL_FOG_COORDINATE_ARRAY_STRIDE = $8455; - GL_FOG_COORDINATE_ARRAY_POINTER = $8456; - GL_FOG_COORDINATE_ARRAY = $8457; - GL_COLOR_SUM = $8458; - GL_CURRENT_SECONDARY_COLOR = $8459; - GL_SECONDARY_COLOR_ARRAY_SIZE = $845A; - GL_SECONDARY_COLOR_ARRAY_TYPE = $845B; - GL_SECONDARY_COLOR_ARRAY_STRIDE = $845C; - GL_SECONDARY_COLOR_ARRAY_POINTER = $845D; - GL_SECONDARY_COLOR_ARRAY = $845E; - GL_MAX_TEXTURE_LOD_BIAS = $84FD; - GL_TEXTURE_FILTER_CONTROL = $8500; - GL_TEXTURE_LOD_BIAS = $8501; - GL_INCR_WRAP = $8507; - GL_DECR_WRAP = $8508; - GL_TEXTURE_DEPTH_SIZE = $884A; - GL_DEPTH_TEXTURE_MODE = $884B; - GL_TEXTURE_COMPARE_MODE = $884C; - GL_TEXTURE_COMPARE_FUNC = $884D; - GL_COMPARE_R_TO_TEXTURE = $884E; -var - glBlendFuncSeparate: procedure(sfactorRGB: GLenum; dfactorRGB: GLenum; sfactorAlpha: GLenum; dfactorAlpha: GLenum); stdcall = nil; - glFogCoordf: procedure(coord: GLfloat); stdcall = nil; - glFogCoordfv: procedure(const coord: PGLfloat); stdcall = nil; - glFogCoordd: procedure(coord: GLdouble); stdcall = nil; - glFogCoorddv: procedure(const coord: PGLdouble); stdcall = nil; - glFogCoordPointer: procedure(_type: GLenum; stride: GLsizei; const pointer: PGLvoid); stdcall = nil; - glMultiDrawArrays: procedure(mode: GLenum; first: PGLint; count: PGLsizei; primcount: GLsizei); stdcall = nil; - glMultiDrawElements: procedure(mode: GLenum; const count: PGLsizei; _type: GLenum; const indices: PGLvoid; primcount: GLsizei); stdcall = nil; - glPointParameterf: procedure(pname: GLenum; param: GLfloat); stdcall = nil; - glPointParameterfv: procedure(pname: GLenum; const params: PGLfloat); stdcall = nil; - glPointParameteri: procedure(pname: GLenum; param: GLint); stdcall = nil; - glPointParameteriv: procedure(pname: GLenum; const params: PGLint); stdcall = nil; - glSecondaryColor3b: procedure(red: GLbyte; green: GLbyte; blue: GLbyte); stdcall = nil; - glSecondaryColor3bv: procedure(const v: PGLbyte); stdcall = nil; - glSecondaryColor3d: procedure(red: GLdouble; green: GLdouble; blue: GLdouble); stdcall = nil; - glSecondaryColor3dv: procedure(const v: PGLdouble); stdcall = nil; - glSecondaryColor3f: procedure(red: GLfloat; green: GLfloat; blue: GLfloat); stdcall = nil; - glSecondaryColor3fv: procedure(const v: PGLfloat); stdcall = nil; - glSecondaryColor3i: procedure(red: GLint; green: GLint; blue: GLint); stdcall = nil; - glSecondaryColor3iv: procedure(const v: PGLint); stdcall = nil; - glSecondaryColor3s: procedure(red: GLshort; green: GLshort; blue: GLshort); stdcall = nil; - glSecondaryColor3sv: procedure(const v: PGLshort); stdcall = nil; - glSecondaryColor3ub: procedure(red: GLubyte; green: GLubyte; blue: GLubyte); stdcall = nil; - glSecondaryColor3ubv: procedure(const v: PGLubyte); stdcall = nil; - glSecondaryColor3ui: procedure(red: GLuint; green: GLuint; blue: GLuint); stdcall = nil; - glSecondaryColor3uiv: procedure(const v: PGLuint); stdcall = nil; - glSecondaryColor3us: procedure(red: GLushort; green: GLushort; blue: GLushort); stdcall = nil; - glSecondaryColor3usv: procedure(const v: PGLushort); stdcall = nil; - glSecondaryColorPointer: procedure(size: GLint; _type: GLenum; stride: GLsizei; const pointer: PGLvoid); stdcall = nil; - glWindowPos2d: procedure(x: GLdouble; y: GLdouble); stdcall = nil; - glWindowPos2dv: procedure(const v: PGLdouble); stdcall = nil; - glWindowPos2f: procedure(x: GLfloat; y: GLfloat); stdcall = nil; - glWindowPos2fv: procedure(const v: PGLfloat); stdcall = nil; - glWindowPos2i: procedure(x: GLint; y: GLint); stdcall = nil; - glWindowPos2iv: procedure(const v: PGLint); stdcall = nil; - glWindowPos2s: procedure(x: GLshort; y: GLshort); stdcall = nil; - glWindowPos2sv: procedure(const v: PGLshort); stdcall = nil; - glWindowPos3d: procedure(x: GLdouble; y: GLdouble; z: GLdouble); stdcall = nil; - glWindowPos3dv: procedure(const v: PGLdouble); stdcall = nil; - glWindowPos3f: procedure(x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glWindowPos3fv: procedure(const v: PGLfloat); stdcall = nil; - glWindowPos3i: procedure(x: GLint; y: GLint; z: GLint); stdcall = nil; - glWindowPos3iv: procedure(const v: PGLint); stdcall = nil; - glWindowPos3s: procedure(x: GLshort; y: GLshort; z: GLshort); stdcall = nil; - glWindowPos3sv: procedure(const v: PGLshort); stdcall = nil; - -function Load_GL_version_1_4: Boolean; - -//***** GL_version_1_5 *****// -const - GL_BUFFER_SIZE = $8764; - GL_BUFFER_USAGE = $8765; - GL_QUERY_COUNTER_BITS = $8864; - GL_CURRENT_QUERY = $8865; - GL_QUERY_RESULT = $8866; - GL_QUERY_RESULT_AVAILABLE = $8867; - GL_ARRAY_BUFFER = $8892; - GL_ELEMENT_ARRAY_BUFFER = $8893; - GL_ARRAY_BUFFER_BINDING = $8894; - GL_ELEMENT_ARRAY_BUFFER_BINDING = $8895; - GL_VERTEX_ARRAY_BUFFER_BINDING = $8896; - GL_NORMAL_ARRAY_BUFFER_BINDING = $8897; - GL_COLOR_ARRAY_BUFFER_BINDING = $8898; - GL_INDEX_ARRAY_BUFFER_BINDING = $8899; - GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING = $889A; - GL_EDGE_FLAG_ARRAY_BUFFER_BINDING = $889B; - GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING = $889C; - GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING = $889D; - GL_WEIGHT_ARRAY_BUFFER_BINDING = $889E; - GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = $889F; - GL_READ_ONLY = $88B8; - GL_WRITE_ONLY = $88B9; - GL_READ_WRITE = $88BA; - GL_BUFFER_ACCESS = $88BB; - GL_BUFFER_MAPPED = $88BC; - GL_BUFFER_MAP_POINTER = $88BD; - GL_STREAM_DRAW = $88E0; - GL_STREAM_READ = $88E1; - GL_STREAM_COPY = $88E2; - GL_STATIC_DRAW = $88E4; - GL_STATIC_READ = $88E5; - GL_STATIC_COPY = $88E6; - GL_DYNAMIC_DRAW = $88E8; - GL_DYNAMIC_READ = $88E9; - GL_DYNAMIC_COPY = $88EA; - GL_SAMPLES_PASSED = $8914; - GL_FOG_COORD_SRC = $8450; - GL_FOG_COORD = $8451; - GL_CURRENT_FOG_COORD = $8453; - GL_FOG_COORD_ARRAY_TYPE = $8454; - GL_FOG_COORD_ARRAY_STRIDE = $8455; - GL_FOG_COORD_ARRAY_POINTER = $8456; - GL_FOG_COORD_ARRAY = $8457; - GL_FOG_COORD_ARRAY_BUFFER_BINDING = $889D; - GL_SRC0_RGB = $8580; - GL_SRC1_RGB = $8581; - GL_SRC2_RGB = $8582; - GL_SRC0_ALPHA = $8588; - GL_SRC1_ALPHA = $8589; - GL_SRC2_ALPHA = $858A; -var - glGenQueries: procedure(n: GLsizei; ids: PGLuint); stdcall = nil; - glDeleteQueries: procedure(n: GLsizei; const ids: PGLuint); stdcall = nil; - glIsQuery: function(id: GLuint): GLboolean; stdcall = nil; - glBeginQuery: procedure(target: GLenum; id: GLuint); stdcall = nil; - glEndQuery: procedure(target: GLenum); stdcall = nil; - glGetQueryiv: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetQueryObjectiv: procedure(id: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetQueryObjectuiv: procedure(id: GLuint; pname: GLenum; params: PGLuint); stdcall = nil; - glBindBuffer: procedure(target: GLenum; buffer: GLuint); stdcall = nil; - glDeleteBuffers: procedure(n: GLsizei; const buffers: PGLuint); stdcall = nil; - glGenBuffers: procedure(n: GLsizei; buffers: PGLuint); stdcall = nil; - glIsBuffer: function(buffer: GLuint): GLboolean; stdcall = nil; - glBufferData: procedure(target: GLenum; size: GLsizeiptr; const data: PGLvoid; usage: GLenum); stdcall = nil; - glBufferSubData: procedure(target: GLenum; offset: GLintptr; size: GLsizeiptr; const data: PGLvoid); stdcall = nil; - glGetBufferSubData: procedure(target: GLenum; offset: GLintptr; size: GLsizeiptr; data: PGLvoid); stdcall = nil; - glMapBuffer: function(target: GLenum; access: GLenum): PGLvoid; stdcall = nil; - glUnmapBuffer: function(target: GLenum): GLboolean; stdcall = nil; - glGetBufferParameteriv: procedure(target: GLenum; pname: GLenum; params: PGLint); stdcall = nil; - glGetBufferPointerv: procedure(target: GLenum; pname: GLenum; params: PGLvoid); stdcall = nil; - -function Load_GL_version_1_5: Boolean; - -//***** GL_version_2_0 *****// -const - GL_BLEND_EQUATION_RGB = $8009; - GL_VERTEX_ATTRIB_ARRAY_ENABLED = $8622; - GL_VERTEX_ATTRIB_ARRAY_SIZE = $8623; - GL_VERTEX_ATTRIB_ARRAY_STRIDE = $8624; - GL_VERTEX_ATTRIB_ARRAY_TYPE = $8625; - GL_CURRENT_VERTEX_ATTRIB = $8626; - GL_VERTEX_PROGRAM_POINT_SIZE = $8642; - GL_VERTEX_PROGRAM_TWO_SIDE = $8643; - GL_VERTEX_ATTRIB_ARRAY_POINTER = $8645; - GL_STENCIL_BACK_FUNC = $8800; - GL_STENCIL_BACK_FAIL = $8801; - GL_STENCIL_BACK_PASS_DEPTH_FAIL = $8802; - GL_STENCIL_BACK_PASS_DEPTH_PASS = $8803; - GL_MAX_DRAW_BUFFERS = $8824; - GL_DRAW_BUFFER0 = $8825; - GL_DRAW_BUFFER1 = $8826; - GL_DRAW_BUFFER2 = $8827; - GL_DRAW_BUFFER3 = $8828; - GL_DRAW_BUFFER4 = $8829; - GL_DRAW_BUFFER5 = $882A; - GL_DRAW_BUFFER6 = $882B; - GL_DRAW_BUFFER7 = $882C; - GL_DRAW_BUFFER8 = $882D; - GL_DRAW_BUFFER9 = $882E; - GL_DRAW_BUFFER10 = $882F; - GL_DRAW_BUFFER11 = $8830; - GL_DRAW_BUFFER12 = $8831; - GL_DRAW_BUFFER13 = $8832; - GL_DRAW_BUFFER14 = $8833; - GL_DRAW_BUFFER15 = $8834; - GL_BLEND_EQUATION_ALPHA = $883D; - GL_POINT_SPRITE = $8861; - GL_COORD_REPLACE = $8862; - GL_MAX_VERTEX_ATTRIBS = $8869; - GL_VERTEX_ATTRIB_ARRAY_NORMALIZED = $886A; - GL_MAX_TEXTURE_COORDS = $8871; - GL_MAX_TEXTURE_IMAGE_UNITS = $8872; - GL_FRAGMENT_SHADER = $8B30; - GL_VERTEX_SHADER = $8B31; - GL_MAX_FRAGMENT_UNIFORM_COMPONENTS = $8B49; - GL_MAX_VERTEX_UNIFORM_COMPONENTS = $8B4A; - GL_MAX_VARYING_FLOATS = $8B4B; - GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = $8B4C; - GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = $8B4D; - GL_SHADER_TYPE = $8B4F; - GL_FLOAT_VEC2 = $8B50; - GL_FLOAT_VEC3 = $8B51; - GL_FLOAT_VEC4 = $8B52; - GL_INT_VEC2 = $8B53; - GL_INT_VEC3 = $8B54; - GL_INT_VEC4 = $8B55; - GL_BOOL = $8B56; - GL_BOOL_VEC2 = $8B57; - GL_BOOL_VEC3 = $8B58; - GL_BOOL_VEC4 = $8B59; - GL_FLOAT_MAT2 = $8B5A; - GL_FLOAT_MAT3 = $8B5B; - GL_FLOAT_MAT4 = $8B5C; - GL_SAMPLER_1D = $8B5D; - GL_SAMPLER_2D = $8B5E; - GL_SAMPLER_3D = $8B5F; - GL_SAMPLER_CUBE = $8B60; - GL_SAMPLER_1D_SHADOW = $8B61; - GL_SAMPLER_2D_SHADOW = $8B62; - GL_DELETE_STATUS = $8B80; - GL_COMPILE_STATUS = $8B81; - GL_LINK_STATUS = $8B82; - GL_VALIDATE_STATUS = $8B83; - GL_INFO_LOG_LENGTH = $8B84; - GL_ATTACHED_SHADERS = $8B85; - GL_ACTIVE_UNIFORMS = $8B86; - GL_ACTIVE_UNIFORM_MAX_LENGTH = $8B87; - GL_SHADER_SOURCE_LENGTH = $8B88; - GL_ACTIVE_ATTRIBUTES = $8B89; - GL_ACTIVE_ATTRIBUTE_MAX_LENGTH = $8B8A; - GL_FRAGMENT_SHADER_DERIVATIVE_HINT = $8B8B; - GL_SHADING_LANGUAGE_VERSION = $8B8C; - GL_CURRENT_PROGRAM = $8B8D; - GL_POINT_SPRITE_COORD_ORIGIN = $8CA0; - GL_LOWER_LEFT = $8CA1; - GL_UPPER_LEFT = $8CA2; - GL_STENCIL_BACK_REF = $8CA3; - GL_STENCIL_BACK_VALUE_MASK = $8CA4; - GL_STENCIL_BACK_WRITEMASK = $8CA5; -var - glBlendEquationSeparate: procedure(modeRGB: GLenum; modeAlpha: GLenum); stdcall = nil; - glDrawBuffers: procedure(n: GLsizei; const bufs: PGLenum); stdcall = nil; - glStencilOpSeparate: procedure(face: GLenum; sfail: GLenum; dpfail: GLenum; dppass: GLenum); stdcall = nil; - glStencilFuncSeparate: procedure(frontfunc: GLenum; backfunc: GLenum; ref: GLint; mask: GLuint); stdcall = nil; - glStencilMaskSeparate: procedure(face: GLenum; mask: GLuint); stdcall = nil; - glAttachShader: procedure(_program: GLuint; shader: GLuint); stdcall = nil; - glBindAttribLocation: procedure(_program: GLuint; index: GLuint; const name: PGLchar); stdcall = nil; - glCompileShader: procedure(shader: GLuint); stdcall = nil; - glCreateProgram: function(): GLuint; stdcall = nil; - glCreateShader: function(_type: GLenum): GLuint; stdcall = nil; - glDeleteProgram: procedure(_program: GLuint); stdcall = nil; - glDeleteShader: procedure(shader: GLuint); stdcall = nil; - glDetachShader: procedure(_program: GLuint; shader: GLuint); stdcall = nil; - glDisableVertexAttribArray: procedure(index: GLuint); stdcall = nil; - glEnableVertexAttribArray: procedure(index: GLuint); stdcall = nil; - glGetActiveAttrib: procedure(_program: GLuint; index: GLuint; bufSize: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLchar); stdcall = nil; - glGetActiveUniform: procedure(_program: GLuint; index: GLuint; bufSize: GLsizei; length: PGLsizei; size: PGLint; _type: PGLenum; name: PGLchar); stdcall = nil; - glGetAttachedShaders: procedure(_program: GLuint; maxCount: GLsizei; count: PGLsizei; obj: PGLuint); stdcall = nil; - glGetAttribLocation: function(_program: GLuint; const name: PGLchar): GLint; stdcall = nil; - glGetProgramiv: procedure(_program: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetProgramInfoLog: procedure(_program: GLuint; bufSize: GLsizei; length: PGLsizei; infoLog: PGLchar); stdcall = nil; - glGetShaderiv: procedure(shader: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetShaderInfoLog: procedure(shader: GLuint; bufSize: GLsizei; length: PGLsizei; infoLog: PGLchar); stdcall = nil; - glGetShaderSource: procedure(shader: GLuint; bufSize: GLsizei; length: PGLsizei; source: PGLchar); stdcall = nil; - glGetUniformLocation: function(_program: GLuint; const name: PGLchar): GLint; stdcall = nil; - glGetUniformfv: procedure(_program: GLuint; location: GLint; params: PGLfloat); stdcall = nil; - glGetUniformiv: procedure(_program: GLuint; location: GLint; params: PGLint); stdcall = nil; - glGetVertexAttribdv: procedure(index: GLuint; pname: GLenum; params: PGLdouble); stdcall = nil; - glGetVertexAttribfv: procedure(index: GLuint; pname: GLenum; params: PGLfloat); stdcall = nil; - glGetVertexAttribiv: procedure(index: GLuint; pname: GLenum; params: PGLint); stdcall = nil; - glGetVertexAttribPointerv: procedure(index: GLuint; pname: GLenum; pointer: PGLvoid); stdcall = nil; - glIsProgram: function(_program: GLuint): GLboolean; stdcall = nil; - glIsShader: function(shader: GLuint): GLboolean; stdcall = nil; - glLinkProgram: procedure(_program: GLuint); stdcall = nil; - glShaderSource: procedure(shader: GLuint; count: GLsizei; const _string: PGLchar; const length: PGLint); stdcall = nil; - glUseProgram: procedure(_program: GLuint); stdcall = nil; - glUniform1f: procedure(location: GLint; v0: GLfloat); stdcall = nil; - glUniform2f: procedure(location: GLint; v0: GLfloat; v1: GLfloat); stdcall = nil; - glUniform3f: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat); stdcall = nil; - glUniform4f: procedure(location: GLint; v0: GLfloat; v1: GLfloat; v2: GLfloat; v3: GLfloat); stdcall = nil; - glUniform1i: procedure(location: GLint; v0: GLint); stdcall = nil; - glUniform2i: procedure(location: GLint; v0: GLint; v1: GLint); stdcall = nil; - glUniform3i: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint); stdcall = nil; - glUniform4i: procedure(location: GLint; v0: GLint; v1: GLint; v2: GLint; v3: GLint); stdcall = nil; - glUniform1fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); stdcall = nil; - glUniform2fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); stdcall = nil; - glUniform3fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); stdcall = nil; - glUniform4fv: procedure(location: GLint; count: GLsizei; const value: PGLfloat); stdcall = nil; - glUniform1iv: procedure(location: GLint; count: GLsizei; const value: PGLint); stdcall = nil; - glUniform2iv: procedure(location: GLint; count: GLsizei; const value: PGLint); stdcall = nil; - glUniform3iv: procedure(location: GLint; count: GLsizei; const value: PGLint); stdcall = nil; - glUniform4iv: procedure(location: GLint; count: GLsizei; const value: PGLint); stdcall = nil; - glUniformMatrix2fv: procedure(location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); stdcall = nil; - glUniformMatrix3fv: procedure(location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); stdcall = nil; - glUniformMatrix4fv: procedure(location: GLint; count: GLsizei; transpose: GLboolean; const value: PGLfloat); stdcall = nil; - glValidateProgram: procedure(_program: GLuint); stdcall = nil; - glVertexAttrib1d: procedure(index: GLuint; x: GLdouble); stdcall = nil; - glVertexAttrib1dv: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib1f: procedure(index: GLuint; x: GLfloat); stdcall = nil; - glVertexAttrib1fv: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib1s: procedure(index: GLuint; x: GLshort); stdcall = nil; - glVertexAttrib1sv: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib2d: procedure(index: GLuint; x: GLdouble; y: GLdouble); stdcall = nil; - glVertexAttrib2dv: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib2f: procedure(index: GLuint; x: GLfloat; y: GLfloat); stdcall = nil; - glVertexAttrib2fv: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib2s: procedure(index: GLuint; x: GLshort; y: GLshort); stdcall = nil; - glVertexAttrib2sv: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib3d: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble); stdcall = nil; - glVertexAttrib3dv: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib3f: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat); stdcall = nil; - glVertexAttrib3fv: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib3s: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort); stdcall = nil; - glVertexAttrib3sv: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib4Nbv: procedure(index: GLuint; const v: PGLbyte); stdcall = nil; - glVertexAttrib4Niv: procedure(index: GLuint; const v: PGLint); stdcall = nil; - glVertexAttrib4Nsv: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib4Nub: procedure(index: GLuint; x: GLubyte; y: GLubyte; z: GLubyte; w: GLubyte); stdcall = nil; - glVertexAttrib4Nubv: procedure(index: GLuint; const v: PGLubyte); stdcall = nil; - glVertexAttrib4Nuiv: procedure(index: GLuint; const v: PGLuint); stdcall = nil; - glVertexAttrib4Nusv: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttrib4bv: procedure(index: GLuint; const v: PGLbyte); stdcall = nil; - glVertexAttrib4d: procedure(index: GLuint; x: GLdouble; y: GLdouble; z: GLdouble; w: GLdouble); stdcall = nil; - glVertexAttrib4dv: procedure(index: GLuint; const v: PGLdouble); stdcall = nil; - glVertexAttrib4f: procedure(index: GLuint; x: GLfloat; y: GLfloat; z: GLfloat; w: GLfloat); stdcall = nil; - glVertexAttrib4fv: procedure(index: GLuint; const v: PGLfloat); stdcall = nil; - glVertexAttrib4iv: procedure(index: GLuint; const v: PGLint); stdcall = nil; - glVertexAttrib4s: procedure(index: GLuint; x: GLshort; y: GLshort; z: GLshort; w: GLshort); stdcall = nil; - glVertexAttrib4sv: procedure(index: GLuint; const v: PGLshort); stdcall = nil; - glVertexAttrib4ubv: procedure(index: GLuint; const v: PGLubyte); stdcall = nil; - glVertexAttrib4uiv: procedure(index: GLuint; const v: PGLuint); stdcall = nil; - glVertexAttrib4usv: procedure(index: GLuint; const v: PGLushort); stdcall = nil; - glVertexAttribPointer: procedure(index: GLuint; size: GLint; _type: GLenum; normalized: GLboolean; stride: GLsizei; const pointer: PGLvoid); stdcall = nil; - -function Load_GL_version_2_0: Boolean; - -implementation - -function glext_ExtensionSupported(const extension: String; const searchIn: String): Boolean; -var - extensions: PChar; - start: PChar; - where, terminator: PChar; -begin - - if (Pos(' ', extension) <> 0) or (extension = '') then - begin - Result := FALSE; - Exit; - end; - - if searchIn = '' then extensions := PChar(glGetString(GL_EXTENSIONS)) - else extensions := PChar(searchIn); - start := extensions; - while TRUE do - begin - where := StrPos(start, PChar(extension)); - if where = nil then Break; - terminator := Pointer(Integer(where) + Length(extension)); - if (where = start) or (PChar(Integer(where) - 1)^ = ' ') then - begin - if (terminator^ = ' ') or (terminator^ = #0) then - begin - Result := TRUE; - Exit; - end; - end; - start := terminator; - end; - Result := FALSE; - -end; - -function Load_GL_version_1_2: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - glDrawRangeElements := wglGetProcAddress('glDrawRangeElements'); - if not Assigned(glDrawRangeElements) then Exit; - glTexImage3D := wglGetProcAddress('glTexImage3D'); - if not Assigned(glTexImage3D) then Exit; - glTexSubImage3D := wglGetProcAddress('glTexSubImage3D'); - if not Assigned(glTexSubImage3D) then Exit; - glCopyTexSubImage3D := wglGetProcAddress('glCopyTexSubImage3D'); - if not Assigned(glCopyTexSubImage3D) then Exit; - Result := TRUE; - -end; - -function Load_GL_ARB_imaging: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_imaging', extstring) then - begin - glColorTable := wglGetProcAddress('glColorTable'); - if not Assigned(glColorTable) then Exit; - glColorTableParameterfv := wglGetProcAddress('glColorTableParameterfv'); - if not Assigned(glColorTableParameterfv) then Exit; - glColorTableParameteriv := wglGetProcAddress('glColorTableParameteriv'); - if not Assigned(glColorTableParameteriv) then Exit; - glCopyColorTable := wglGetProcAddress('glCopyColorTable'); - if not Assigned(glCopyColorTable) then Exit; - glGetColorTable := wglGetProcAddress('glGetColorTable'); - if not Assigned(glGetColorTable) then Exit; - glGetColorTableParameterfv := wglGetProcAddress('glGetColorTableParameterfv'); - if not Assigned(glGetColorTableParameterfv) then Exit; - glGetColorTableParameteriv := wglGetProcAddress('glGetColorTableParameteriv'); - if not Assigned(glGetColorTableParameteriv) then Exit; - glColorSubTable := wglGetProcAddress('glColorSubTable'); - if not Assigned(glColorSubTable) then Exit; - glCopyColorSubTable := wglGetProcAddress('glCopyColorSubTable'); - if not Assigned(glCopyColorSubTable) then Exit; - glConvolutionFilter1D := wglGetProcAddress('glConvolutionFilter1D'); - if not Assigned(glConvolutionFilter1D) then Exit; - glConvolutionFilter2D := wglGetProcAddress('glConvolutionFilter2D'); - if not Assigned(glConvolutionFilter2D) then Exit; - glConvolutionParameterf := wglGetProcAddress('glConvolutionParameterf'); - if not Assigned(glConvolutionParameterf) then Exit; - glConvolutionParameterfv := wglGetProcAddress('glConvolutionParameterfv'); - if not Assigned(glConvolutionParameterfv) then Exit; - glConvolutionParameteri := wglGetProcAddress('glConvolutionParameteri'); - if not Assigned(glConvolutionParameteri) then Exit; - glConvolutionParameteriv := wglGetProcAddress('glConvolutionParameteriv'); - if not Assigned(glConvolutionParameteriv) then Exit; - glCopyConvolutionFilter1D := wglGetProcAddress('glCopyConvolutionFilter1D'); - if not Assigned(glCopyConvolutionFilter1D) then Exit; - glCopyConvolutionFilter2D := wglGetProcAddress('glCopyConvolutionFilter2D'); - if not Assigned(glCopyConvolutionFilter2D) then Exit; - glGetConvolutionFilter := wglGetProcAddress('glGetConvolutionFilter'); - if not Assigned(glGetConvolutionFilter) then Exit; - glGetConvolutionParameterfv := wglGetProcAddress('glGetConvolutionParameterfv'); - if not Assigned(glGetConvolutionParameterfv) then Exit; - glGetConvolutionParameteriv := wglGetProcAddress('glGetConvolutionParameteriv'); - if not Assigned(glGetConvolutionParameteriv) then Exit; - glGetSeparableFilter := wglGetProcAddress('glGetSeparableFilter'); - if not Assigned(glGetSeparableFilter) then Exit; - glSeparableFilter2D := wglGetProcAddress('glSeparableFilter2D'); - if not Assigned(glSeparableFilter2D) then Exit; - glGetHistogram := wglGetProcAddress('glGetHistogram'); - if not Assigned(glGetHistogram) then Exit; - glGetHistogramParameterfv := wglGetProcAddress('glGetHistogramParameterfv'); - if not Assigned(glGetHistogramParameterfv) then Exit; - glGetHistogramParameteriv := wglGetProcAddress('glGetHistogramParameteriv'); - if not Assigned(glGetHistogramParameteriv) then Exit; - glGetMinmax := wglGetProcAddress('glGetMinmax'); - if not Assigned(glGetMinmax) then Exit; - glGetMinmaxParameterfv := wglGetProcAddress('glGetMinmaxParameterfv'); - if not Assigned(glGetMinmaxParameterfv) then Exit; - glGetMinmaxParameteriv := wglGetProcAddress('glGetMinmaxParameteriv'); - if not Assigned(glGetMinmaxParameteriv) then Exit; - glHistogram := wglGetProcAddress('glHistogram'); - if not Assigned(glHistogram) then Exit; - glMinmax := wglGetProcAddress('glMinmax'); - if not Assigned(glMinmax) then Exit; - glResetHistogram := wglGetProcAddress('glResetHistogram'); - if not Assigned(glResetHistogram) then Exit; - glResetMinmax := wglGetProcAddress('glResetMinmax'); - if not Assigned(glResetMinmax) then Exit; - glBlendEquation := wglGetProcAddress('glBlendEquation'); - if not Assigned(glBlendEquation) then Exit; - glBlendColor := wglGetProcAddress('glBlendColor'); - if not Assigned(glBlendColor) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_version_1_3: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - glActiveTexture := wglGetProcAddress('glActiveTexture'); - if not Assigned(glActiveTexture) then Exit; - glClientActiveTexture := wglGetProcAddress('glClientActiveTexture'); - if not Assigned(glClientActiveTexture) then Exit; - glMultiTexCoord1d := wglGetProcAddress('glMultiTexCoord1d'); - if not Assigned(glMultiTexCoord1d) then Exit; - glMultiTexCoord1dv := wglGetProcAddress('glMultiTexCoord1dv'); - if not Assigned(glMultiTexCoord1dv) then Exit; - glMultiTexCoord1f := wglGetProcAddress('glMultiTexCoord1f'); - if not Assigned(glMultiTexCoord1f) then Exit; - glMultiTexCoord1fv := wglGetProcAddress('glMultiTexCoord1fv'); - if not Assigned(glMultiTexCoord1fv) then Exit; - glMultiTexCoord1i := wglGetProcAddress('glMultiTexCoord1i'); - if not Assigned(glMultiTexCoord1i) then Exit; - glMultiTexCoord1iv := wglGetProcAddress('glMultiTexCoord1iv'); - if not Assigned(glMultiTexCoord1iv) then Exit; - glMultiTexCoord1s := wglGetProcAddress('glMultiTexCoord1s'); - if not Assigned(glMultiTexCoord1s) then Exit; - glMultiTexCoord1sv := wglGetProcAddress('glMultiTexCoord1sv'); - if not Assigned(glMultiTexCoord1sv) then Exit; - glMultiTexCoord2d := wglGetProcAddress('glMultiTexCoord2d'); - if not Assigned(glMultiTexCoord2d) then Exit; - glMultiTexCoord2dv := wglGetProcAddress('glMultiTexCoord2dv'); - if not Assigned(glMultiTexCoord2dv) then Exit; - glMultiTexCoord2f := wglGetProcAddress('glMultiTexCoord2f'); - if not Assigned(glMultiTexCoord2f) then Exit; - glMultiTexCoord2fv := wglGetProcAddress('glMultiTexCoord2fv'); - if not Assigned(glMultiTexCoord2fv) then Exit; - glMultiTexCoord2i := wglGetProcAddress('glMultiTexCoord2i'); - if not Assigned(glMultiTexCoord2i) then Exit; - glMultiTexCoord2iv := wglGetProcAddress('glMultiTexCoord2iv'); - if not Assigned(glMultiTexCoord2iv) then Exit; - glMultiTexCoord2s := wglGetProcAddress('glMultiTexCoord2s'); - if not Assigned(glMultiTexCoord2s) then Exit; - glMultiTexCoord2sv := wglGetProcAddress('glMultiTexCoord2sv'); - if not Assigned(glMultiTexCoord2sv) then Exit; - glMultiTexCoord3d := wglGetProcAddress('glMultiTexCoord3d'); - if not Assigned(glMultiTexCoord3d) then Exit; - glMultiTexCoord3dv := wglGetProcAddress('glMultiTexCoord3dv'); - if not Assigned(glMultiTexCoord3dv) then Exit; - glMultiTexCoord3f := wglGetProcAddress('glMultiTexCoord3f'); - if not Assigned(glMultiTexCoord3f) then Exit; - glMultiTexCoord3fv := wglGetProcAddress('glMultiTexCoord3fv'); - if not Assigned(glMultiTexCoord3fv) then Exit; - glMultiTexCoord3i := wglGetProcAddress('glMultiTexCoord3i'); - if not Assigned(glMultiTexCoord3i) then Exit; - glMultiTexCoord3iv := wglGetProcAddress('glMultiTexCoord3iv'); - if not Assigned(glMultiTexCoord3iv) then Exit; - glMultiTexCoord3s := wglGetProcAddress('glMultiTexCoord3s'); - if not Assigned(glMultiTexCoord3s) then Exit; - glMultiTexCoord3sv := wglGetProcAddress('glMultiTexCoord3sv'); - if not Assigned(glMultiTexCoord3sv) then Exit; - glMultiTexCoord4d := wglGetProcAddress('glMultiTexCoord4d'); - if not Assigned(glMultiTexCoord4d) then Exit; - glMultiTexCoord4dv := wglGetProcAddress('glMultiTexCoord4dv'); - if not Assigned(glMultiTexCoord4dv) then Exit; - glMultiTexCoord4f := wglGetProcAddress('glMultiTexCoord4f'); - if not Assigned(glMultiTexCoord4f) then Exit; - glMultiTexCoord4fv := wglGetProcAddress('glMultiTexCoord4fv'); - if not Assigned(glMultiTexCoord4fv) then Exit; - glMultiTexCoord4i := wglGetProcAddress('glMultiTexCoord4i'); - if not Assigned(glMultiTexCoord4i) then Exit; - glMultiTexCoord4iv := wglGetProcAddress('glMultiTexCoord4iv'); - if not Assigned(glMultiTexCoord4iv) then Exit; - glMultiTexCoord4s := wglGetProcAddress('glMultiTexCoord4s'); - if not Assigned(glMultiTexCoord4s) then Exit; - glMultiTexCoord4sv := wglGetProcAddress('glMultiTexCoord4sv'); - if not Assigned(glMultiTexCoord4sv) then Exit; - glLoadTransposeMatrixf := wglGetProcAddress('glLoadTransposeMatrixf'); - if not Assigned(glLoadTransposeMatrixf) then Exit; - glLoadTransposeMatrixd := wglGetProcAddress('glLoadTransposeMatrixd'); - if not Assigned(glLoadTransposeMatrixd) then Exit; - glMultTransposeMatrixf := wglGetProcAddress('glMultTransposeMatrixf'); - if not Assigned(glMultTransposeMatrixf) then Exit; - glMultTransposeMatrixd := wglGetProcAddress('glMultTransposeMatrixd'); - if not Assigned(glMultTransposeMatrixd) then Exit; - glSampleCoverage := wglGetProcAddress('glSampleCoverage'); - if not Assigned(glSampleCoverage) then Exit; - glCompressedTexImage3D := wglGetProcAddress('glCompressedTexImage3D'); - if not Assigned(glCompressedTexImage3D) then Exit; - glCompressedTexImage2D := wglGetProcAddress('glCompressedTexImage2D'); - if not Assigned(glCompressedTexImage2D) then Exit; - glCompressedTexImage1D := wglGetProcAddress('glCompressedTexImage1D'); - if not Assigned(glCompressedTexImage1D) then Exit; - glCompressedTexSubImage3D := wglGetProcAddress('glCompressedTexSubImage3D'); - if not Assigned(glCompressedTexSubImage3D) then Exit; - glCompressedTexSubImage2D := wglGetProcAddress('glCompressedTexSubImage2D'); - if not Assigned(glCompressedTexSubImage2D) then Exit; - glCompressedTexSubImage1D := wglGetProcAddress('glCompressedTexSubImage1D'); - if not Assigned(glCompressedTexSubImage1D) then Exit; - glGetCompressedTexImage := wglGetProcAddress('glGetCompressedTexImage'); - if not Assigned(glGetCompressedTexImage) then Exit; - Result := TRUE; - -end; - -function Load_GL_ARB_multitexture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_multitexture', extstring) then - begin - glActiveTextureARB := wglGetProcAddress('glActiveTextureARB'); - if not Assigned(glActiveTextureARB) then Exit; - glClientActiveTextureARB := wglGetProcAddress('glClientActiveTextureARB'); - if not Assigned(glClientActiveTextureARB) then Exit; - glMultiTexCoord1dARB := wglGetProcAddress('glMultiTexCoord1dARB'); - if not Assigned(glMultiTexCoord1dARB) then Exit; - glMultiTexCoord1dvARB := wglGetProcAddress('glMultiTexCoord1dvARB'); - if not Assigned(glMultiTexCoord1dvARB) then Exit; - glMultiTexCoord1fARB := wglGetProcAddress('glMultiTexCoord1fARB'); - if not Assigned(glMultiTexCoord1fARB) then Exit; - glMultiTexCoord1fvARB := wglGetProcAddress('glMultiTexCoord1fvARB'); - if not Assigned(glMultiTexCoord1fvARB) then Exit; - glMultiTexCoord1iARB := wglGetProcAddress('glMultiTexCoord1iARB'); - if not Assigned(glMultiTexCoord1iARB) then Exit; - glMultiTexCoord1ivARB := wglGetProcAddress('glMultiTexCoord1ivARB'); - if not Assigned(glMultiTexCoord1ivARB) then Exit; - glMultiTexCoord1sARB := wglGetProcAddress('glMultiTexCoord1sARB'); - if not Assigned(glMultiTexCoord1sARB) then Exit; - glMultiTexCoord1svARB := wglGetProcAddress('glMultiTexCoord1svARB'); - if not Assigned(glMultiTexCoord1svARB) then Exit; - glMultiTexCoord2dARB := wglGetProcAddress('glMultiTexCoord2dARB'); - if not Assigned(glMultiTexCoord2dARB) then Exit; - glMultiTexCoord2dvARB := wglGetProcAddress('glMultiTexCoord2dvARB'); - if not Assigned(glMultiTexCoord2dvARB) then Exit; - glMultiTexCoord2fARB := wglGetProcAddress('glMultiTexCoord2fARB'); - if not Assigned(glMultiTexCoord2fARB) then Exit; - glMultiTexCoord2fvARB := wglGetProcAddress('glMultiTexCoord2fvARB'); - if not Assigned(glMultiTexCoord2fvARB) then Exit; - glMultiTexCoord2iARB := wglGetProcAddress('glMultiTexCoord2iARB'); - if not Assigned(glMultiTexCoord2iARB) then Exit; - glMultiTexCoord2ivARB := wglGetProcAddress('glMultiTexCoord2ivARB'); - if not Assigned(glMultiTexCoord2ivARB) then Exit; - glMultiTexCoord2sARB := wglGetProcAddress('glMultiTexCoord2sARB'); - if not Assigned(glMultiTexCoord2sARB) then Exit; - glMultiTexCoord2svARB := wglGetProcAddress('glMultiTexCoord2svARB'); - if not Assigned(glMultiTexCoord2svARB) then Exit; - glMultiTexCoord3dARB := wglGetProcAddress('glMultiTexCoord3dARB'); - if not Assigned(glMultiTexCoord3dARB) then Exit; - glMultiTexCoord3dvARB := wglGetProcAddress('glMultiTexCoord3dvARB'); - if not Assigned(glMultiTexCoord3dvARB) then Exit; - glMultiTexCoord3fARB := wglGetProcAddress('glMultiTexCoord3fARB'); - if not Assigned(glMultiTexCoord3fARB) then Exit; - glMultiTexCoord3fvARB := wglGetProcAddress('glMultiTexCoord3fvARB'); - if not Assigned(glMultiTexCoord3fvARB) then Exit; - glMultiTexCoord3iARB := wglGetProcAddress('glMultiTexCoord3iARB'); - if not Assigned(glMultiTexCoord3iARB) then Exit; - glMultiTexCoord3ivARB := wglGetProcAddress('glMultiTexCoord3ivARB'); - if not Assigned(glMultiTexCoord3ivARB) then Exit; - glMultiTexCoord3sARB := wglGetProcAddress('glMultiTexCoord3sARB'); - if not Assigned(glMultiTexCoord3sARB) then Exit; - glMultiTexCoord3svARB := wglGetProcAddress('glMultiTexCoord3svARB'); - if not Assigned(glMultiTexCoord3svARB) then Exit; - glMultiTexCoord4dARB := wglGetProcAddress('glMultiTexCoord4dARB'); - if not Assigned(glMultiTexCoord4dARB) then Exit; - glMultiTexCoord4dvARB := wglGetProcAddress('glMultiTexCoord4dvARB'); - if not Assigned(glMultiTexCoord4dvARB) then Exit; - glMultiTexCoord4fARB := wglGetProcAddress('glMultiTexCoord4fARB'); - if not Assigned(glMultiTexCoord4fARB) then Exit; - glMultiTexCoord4fvARB := wglGetProcAddress('glMultiTexCoord4fvARB'); - if not Assigned(glMultiTexCoord4fvARB) then Exit; - glMultiTexCoord4iARB := wglGetProcAddress('glMultiTexCoord4iARB'); - if not Assigned(glMultiTexCoord4iARB) then Exit; - glMultiTexCoord4ivARB := wglGetProcAddress('glMultiTexCoord4ivARB'); - if not Assigned(glMultiTexCoord4ivARB) then Exit; - glMultiTexCoord4sARB := wglGetProcAddress('glMultiTexCoord4sARB'); - if not Assigned(glMultiTexCoord4sARB) then Exit; - glMultiTexCoord4svARB := wglGetProcAddress('glMultiTexCoord4svARB'); - if not Assigned(glMultiTexCoord4svARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_transpose_matrix: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_transpose_matrix', extstring) then - begin - glLoadTransposeMatrixfARB := wglGetProcAddress('glLoadTransposeMatrixfARB'); - if not Assigned(glLoadTransposeMatrixfARB) then Exit; - glLoadTransposeMatrixdARB := wglGetProcAddress('glLoadTransposeMatrixdARB'); - if not Assigned(glLoadTransposeMatrixdARB) then Exit; - glMultTransposeMatrixfARB := wglGetProcAddress('glMultTransposeMatrixfARB'); - if not Assigned(glMultTransposeMatrixfARB) then Exit; - glMultTransposeMatrixdARB := wglGetProcAddress('glMultTransposeMatrixdARB'); - if not Assigned(glMultTransposeMatrixdARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_multisample: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_multisample', extstring) then - begin - glSampleCoverageARB := wglGetProcAddress('glSampleCoverageARB'); - if not Assigned(glSampleCoverageARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_env_add: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_env_add', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_WGL_ARB_extensions_string: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_ARB_extensions_string', extstring) then - begin - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_ARB_buffer_region: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_ARB_buffer_region', extstring) then - begin - wglCreateBufferRegionARB := wglGetProcAddress('wglCreateBufferRegionARB'); - if not Assigned(wglCreateBufferRegionARB) then Exit; - wglDeleteBufferRegionARB := wglGetProcAddress('wglDeleteBufferRegionARB'); - if not Assigned(wglDeleteBufferRegionARB) then Exit; - wglSaveBufferRegionARB := wglGetProcAddress('wglSaveBufferRegionARB'); - if not Assigned(wglSaveBufferRegionARB) then Exit; - wglRestoreBufferRegionARB := wglGetProcAddress('wglRestoreBufferRegionARB'); - if not Assigned(wglRestoreBufferRegionARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_cube_map: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_cube_map', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_depth_texture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_depth_texture', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_point_parameters: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_point_parameters', extstring) then - begin - glPointParameterfARB := wglGetProcAddress('glPointParameterfARB'); - if not Assigned(glPointParameterfARB) then Exit; - glPointParameterfvARB := wglGetProcAddress('glPointParameterfvARB'); - if not Assigned(glPointParameterfvARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_shadow: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_shadow', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_shadow_ambient: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_shadow_ambient', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_border_clamp: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_border_clamp', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_compression: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_compression', extstring) then - begin - glCompressedTexImage3DARB := wglGetProcAddress('glCompressedTexImage3DARB'); - if not Assigned(glCompressedTexImage3DARB) then Exit; - glCompressedTexImage2DARB := wglGetProcAddress('glCompressedTexImage2DARB'); - if not Assigned(glCompressedTexImage2DARB) then Exit; - glCompressedTexImage1DARB := wglGetProcAddress('glCompressedTexImage1DARB'); - if not Assigned(glCompressedTexImage1DARB) then Exit; - glCompressedTexSubImage3DARB := wglGetProcAddress('glCompressedTexSubImage3DARB'); - if not Assigned(glCompressedTexSubImage3DARB) then Exit; - glCompressedTexSubImage2DARB := wglGetProcAddress('glCompressedTexSubImage2DARB'); - if not Assigned(glCompressedTexSubImage2DARB) then Exit; - glCompressedTexSubImage1DARB := wglGetProcAddress('glCompressedTexSubImage1DARB'); - if not Assigned(glCompressedTexSubImage1DARB) then Exit; - glGetCompressedTexImageARB := wglGetProcAddress('glGetCompressedTexImageARB'); - if not Assigned(glGetCompressedTexImageARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_env_combine: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_env_combine', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_env_crossbar: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_env_crossbar', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_env_dot3: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_env_dot3', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_mirrored_repeat: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_mirrored_repeat', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_vertex_blend: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_vertex_blend', extstring) then - begin - glWeightbvARB := wglGetProcAddress('glWeightbvARB'); - if not Assigned(glWeightbvARB) then Exit; - glWeightsvARB := wglGetProcAddress('glWeightsvARB'); - if not Assigned(glWeightsvARB) then Exit; - glWeightivARB := wglGetProcAddress('glWeightivARB'); - if not Assigned(glWeightivARB) then Exit; - glWeightfvARB := wglGetProcAddress('glWeightfvARB'); - if not Assigned(glWeightfvARB) then Exit; - glWeightdvARB := wglGetProcAddress('glWeightdvARB'); - if not Assigned(glWeightdvARB) then Exit; - glWeightvARB := wglGetProcAddress('glWeightvARB'); - if not Assigned(glWeightvARB) then Exit; - glWeightubvARB := wglGetProcAddress('glWeightubvARB'); - if not Assigned(glWeightubvARB) then Exit; - glWeightusvARB := wglGetProcAddress('glWeightusvARB'); - if not Assigned(glWeightusvARB) then Exit; - glWeightuivARB := wglGetProcAddress('glWeightuivARB'); - if not Assigned(glWeightuivARB) then Exit; - glWeightPointerARB := wglGetProcAddress('glWeightPointerARB'); - if not Assigned(glWeightPointerARB) then Exit; - glVertexBlendARB := wglGetProcAddress('glVertexBlendARB'); - if not Assigned(glVertexBlendARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_vertex_program: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_vertex_program', extstring) then - begin - glVertexAttrib1sARB := wglGetProcAddress('glVertexAttrib1sARB'); - if not Assigned(glVertexAttrib1sARB) then Exit; - glVertexAttrib1fARB := wglGetProcAddress('glVertexAttrib1fARB'); - if not Assigned(glVertexAttrib1fARB) then Exit; - glVertexAttrib1dARB := wglGetProcAddress('glVertexAttrib1dARB'); - if not Assigned(glVertexAttrib1dARB) then Exit; - glVertexAttrib2sARB := wglGetProcAddress('glVertexAttrib2sARB'); - if not Assigned(glVertexAttrib2sARB) then Exit; - glVertexAttrib2fARB := wglGetProcAddress('glVertexAttrib2fARB'); - if not Assigned(glVertexAttrib2fARB) then Exit; - glVertexAttrib2dARB := wglGetProcAddress('glVertexAttrib2dARB'); - if not Assigned(glVertexAttrib2dARB) then Exit; - glVertexAttrib3sARB := wglGetProcAddress('glVertexAttrib3sARB'); - if not Assigned(glVertexAttrib3sARB) then Exit; - glVertexAttrib3fARB := wglGetProcAddress('glVertexAttrib3fARB'); - if not Assigned(glVertexAttrib3fARB) then Exit; - glVertexAttrib3dARB := wglGetProcAddress('glVertexAttrib3dARB'); - if not Assigned(glVertexAttrib3dARB) then Exit; - glVertexAttrib4sARB := wglGetProcAddress('glVertexAttrib4sARB'); - if not Assigned(glVertexAttrib4sARB) then Exit; - glVertexAttrib4fARB := wglGetProcAddress('glVertexAttrib4fARB'); - if not Assigned(glVertexAttrib4fARB) then Exit; - glVertexAttrib4dARB := wglGetProcAddress('glVertexAttrib4dARB'); - if not Assigned(glVertexAttrib4dARB) then Exit; - glVertexAttrib4NubARB := wglGetProcAddress('glVertexAttrib4NubARB'); - if not Assigned(glVertexAttrib4NubARB) then Exit; - glVertexAttrib1svARB := wglGetProcAddress('glVertexAttrib1svARB'); - if not Assigned(glVertexAttrib1svARB) then Exit; - glVertexAttrib1fvARB := wglGetProcAddress('glVertexAttrib1fvARB'); - if not Assigned(glVertexAttrib1fvARB) then Exit; - glVertexAttrib1dvARB := wglGetProcAddress('glVertexAttrib1dvARB'); - if not Assigned(glVertexAttrib1dvARB) then Exit; - glVertexAttrib2svARB := wglGetProcAddress('glVertexAttrib2svARB'); - if not Assigned(glVertexAttrib2svARB) then Exit; - glVertexAttrib2fvARB := wglGetProcAddress('glVertexAttrib2fvARB'); - if not Assigned(glVertexAttrib2fvARB) then Exit; - glVertexAttrib2dvARB := wglGetProcAddress('glVertexAttrib2dvARB'); - if not Assigned(glVertexAttrib2dvARB) then Exit; - glVertexAttrib3svARB := wglGetProcAddress('glVertexAttrib3svARB'); - if not Assigned(glVertexAttrib3svARB) then Exit; - glVertexAttrib3fvARB := wglGetProcAddress('glVertexAttrib3fvARB'); - if not Assigned(glVertexAttrib3fvARB) then Exit; - glVertexAttrib3dvARB := wglGetProcAddress('glVertexAttrib3dvARB'); - if not Assigned(glVertexAttrib3dvARB) then Exit; - glVertexAttrib4bvARB := wglGetProcAddress('glVertexAttrib4bvARB'); - if not Assigned(glVertexAttrib4bvARB) then Exit; - glVertexAttrib4svARB := wglGetProcAddress('glVertexAttrib4svARB'); - if not Assigned(glVertexAttrib4svARB) then Exit; - glVertexAttrib4ivARB := wglGetProcAddress('glVertexAttrib4ivARB'); - if not Assigned(glVertexAttrib4ivARB) then Exit; - glVertexAttrib4ubvARB := wglGetProcAddress('glVertexAttrib4ubvARB'); - if not Assigned(glVertexAttrib4ubvARB) then Exit; - glVertexAttrib4usvARB := wglGetProcAddress('glVertexAttrib4usvARB'); - if not Assigned(glVertexAttrib4usvARB) then Exit; - glVertexAttrib4uivARB := wglGetProcAddress('glVertexAttrib4uivARB'); - if not Assigned(glVertexAttrib4uivARB) then Exit; - glVertexAttrib4fvARB := wglGetProcAddress('glVertexAttrib4fvARB'); - if not Assigned(glVertexAttrib4fvARB) then Exit; - glVertexAttrib4dvARB := wglGetProcAddress('glVertexAttrib4dvARB'); - if not Assigned(glVertexAttrib4dvARB) then Exit; - glVertexAttrib4NbvARB := wglGetProcAddress('glVertexAttrib4NbvARB'); - if not Assigned(glVertexAttrib4NbvARB) then Exit; - glVertexAttrib4NsvARB := wglGetProcAddress('glVertexAttrib4NsvARB'); - if not Assigned(glVertexAttrib4NsvARB) then Exit; - glVertexAttrib4NivARB := wglGetProcAddress('glVertexAttrib4NivARB'); - if not Assigned(glVertexAttrib4NivARB) then Exit; - glVertexAttrib4NubvARB := wglGetProcAddress('glVertexAttrib4NubvARB'); - if not Assigned(glVertexAttrib4NubvARB) then Exit; - glVertexAttrib4NusvARB := wglGetProcAddress('glVertexAttrib4NusvARB'); - if not Assigned(glVertexAttrib4NusvARB) then Exit; - glVertexAttrib4NuivARB := wglGetProcAddress('glVertexAttrib4NuivARB'); - if not Assigned(glVertexAttrib4NuivARB) then Exit; - glVertexAttribPointerARB := wglGetProcAddress('glVertexAttribPointerARB'); - if not Assigned(glVertexAttribPointerARB) then Exit; - glEnableVertexAttribArrayARB := wglGetProcAddress('glEnableVertexAttribArrayARB'); - if not Assigned(glEnableVertexAttribArrayARB) then Exit; - glDisableVertexAttribArrayARB := wglGetProcAddress('glDisableVertexAttribArrayARB'); - if not Assigned(glDisableVertexAttribArrayARB) then Exit; - glProgramStringARB := wglGetProcAddress('glProgramStringARB'); - if not Assigned(glProgramStringARB) then Exit; - glBindProgramARB := wglGetProcAddress('glBindProgramARB'); - if not Assigned(glBindProgramARB) then Exit; - glDeleteProgramsARB := wglGetProcAddress('glDeleteProgramsARB'); - if not Assigned(glDeleteProgramsARB) then Exit; - glGenProgramsARB := wglGetProcAddress('glGenProgramsARB'); - if not Assigned(glGenProgramsARB) then Exit; - glProgramEnvParameter4dARB := wglGetProcAddress('glProgramEnvParameter4dARB'); - if not Assigned(glProgramEnvParameter4dARB) then Exit; - glProgramEnvParameter4dvARB := wglGetProcAddress('glProgramEnvParameter4dvARB'); - if not Assigned(glProgramEnvParameter4dvARB) then Exit; - glProgramEnvParameter4fARB := wglGetProcAddress('glProgramEnvParameter4fARB'); - if not Assigned(glProgramEnvParameter4fARB) then Exit; - glProgramEnvParameter4fvARB := wglGetProcAddress('glProgramEnvParameter4fvARB'); - if not Assigned(glProgramEnvParameter4fvARB) then Exit; - glProgramLocalParameter4dARB := wglGetProcAddress('glProgramLocalParameter4dARB'); - if not Assigned(glProgramLocalParameter4dARB) then Exit; - glProgramLocalParameter4dvARB := wglGetProcAddress('glProgramLocalParameter4dvARB'); - if not Assigned(glProgramLocalParameter4dvARB) then Exit; - glProgramLocalParameter4fARB := wglGetProcAddress('glProgramLocalParameter4fARB'); - if not Assigned(glProgramLocalParameter4fARB) then Exit; - glProgramLocalParameter4fvARB := wglGetProcAddress('glProgramLocalParameter4fvARB'); - if not Assigned(glProgramLocalParameter4fvARB) then Exit; - glGetProgramEnvParameterdvARB := wglGetProcAddress('glGetProgramEnvParameterdvARB'); - if not Assigned(glGetProgramEnvParameterdvARB) then Exit; - glGetProgramEnvParameterfvARB := wglGetProcAddress('glGetProgramEnvParameterfvARB'); - if not Assigned(glGetProgramEnvParameterfvARB) then Exit; - glGetProgramLocalParameterdvARB := wglGetProcAddress('glGetProgramLocalParameterdvARB'); - if not Assigned(glGetProgramLocalParameterdvARB) then Exit; - glGetProgramLocalParameterfvARB := wglGetProcAddress('glGetProgramLocalParameterfvARB'); - if not Assigned(glGetProgramLocalParameterfvARB) then Exit; - glGetProgramivARB := wglGetProcAddress('glGetProgramivARB'); - if not Assigned(glGetProgramivARB) then Exit; - glGetProgramStringARB := wglGetProcAddress('glGetProgramStringARB'); - if not Assigned(glGetProgramStringARB) then Exit; - glGetVertexAttribdvARB := wglGetProcAddress('glGetVertexAttribdvARB'); - if not Assigned(glGetVertexAttribdvARB) then Exit; - glGetVertexAttribfvARB := wglGetProcAddress('glGetVertexAttribfvARB'); - if not Assigned(glGetVertexAttribfvARB) then Exit; - glGetVertexAttribivARB := wglGetProcAddress('glGetVertexAttribivARB'); - if not Assigned(glGetVertexAttribivARB) then Exit; - glGetVertexAttribPointervARB := wglGetProcAddress('glGetVertexAttribPointervARB'); - if not Assigned(glGetVertexAttribPointervARB) then Exit; - glIsProgramARB := wglGetProcAddress('glIsProgramARB'); - if not Assigned(glIsProgramARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_window_pos: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_window_pos', extstring) then - begin - glWindowPos2dARB := wglGetProcAddress('glWindowPos2dARB'); - if not Assigned(glWindowPos2dARB) then Exit; - glWindowPos2fARB := wglGetProcAddress('glWindowPos2fARB'); - if not Assigned(glWindowPos2fARB) then Exit; - glWindowPos2iARB := wglGetProcAddress('glWindowPos2iARB'); - if not Assigned(glWindowPos2iARB) then Exit; - glWindowPos2sARB := wglGetProcAddress('glWindowPos2sARB'); - if not Assigned(glWindowPos2sARB) then Exit; - glWindowPos2dvARB := wglGetProcAddress('glWindowPos2dvARB'); - if not Assigned(glWindowPos2dvARB) then Exit; - glWindowPos2fvARB := wglGetProcAddress('glWindowPos2fvARB'); - if not Assigned(glWindowPos2fvARB) then Exit; - glWindowPos2ivARB := wglGetProcAddress('glWindowPos2ivARB'); - if not Assigned(glWindowPos2ivARB) then Exit; - glWindowPos2svARB := wglGetProcAddress('glWindowPos2svARB'); - if not Assigned(glWindowPos2svARB) then Exit; - glWindowPos3dARB := wglGetProcAddress('glWindowPos3dARB'); - if not Assigned(glWindowPos3dARB) then Exit; - glWindowPos3fARB := wglGetProcAddress('glWindowPos3fARB'); - if not Assigned(glWindowPos3fARB) then Exit; - glWindowPos3iARB := wglGetProcAddress('glWindowPos3iARB'); - if not Assigned(glWindowPos3iARB) then Exit; - glWindowPos3sARB := wglGetProcAddress('glWindowPos3sARB'); - if not Assigned(glWindowPos3sARB) then Exit; - glWindowPos3dvARB := wglGetProcAddress('glWindowPos3dvARB'); - if not Assigned(glWindowPos3dvARB) then Exit; - glWindowPos3fvARB := wglGetProcAddress('glWindowPos3fvARB'); - if not Assigned(glWindowPos3fvARB) then Exit; - glWindowPos3ivARB := wglGetProcAddress('glWindowPos3ivARB'); - if not Assigned(glWindowPos3ivARB) then Exit; - glWindowPos3svARB := wglGetProcAddress('glWindowPos3svARB'); - if not Assigned(glWindowPos3svARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_422_pixels: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_422_pixels', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_abgr: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_abgr', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_bgra: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_bgra', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_blend_color: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_blend_color', extstring) then - begin - glBlendColorEXT := wglGetProcAddress('glBlendColorEXT'); - if not Assigned(glBlendColorEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_blend_func_separate: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_blend_func_separate', extstring) then - begin - glBlendFuncSeparateEXT := wglGetProcAddress('glBlendFuncSeparateEXT'); - if not Assigned(glBlendFuncSeparateEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_blend_logic_op: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_blend_logic_op', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_blend_minmax: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_blend_minmax', extstring) then - begin - glBlendEquationEXT := wglGetProcAddress('glBlendEquationEXT'); - if not Assigned(glBlendEquationEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_blend_subtract: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_blend_subtract', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_clip_volume_hint: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_clip_volume_hint', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_color_subtable: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_color_subtable', extstring) then - begin - glColorSubTableEXT := wglGetProcAddress('glColorSubTableEXT'); - if not Assigned(glColorSubTableEXT) then Exit; - glCopyColorSubTableEXT := wglGetProcAddress('glCopyColorSubTableEXT'); - if not Assigned(glCopyColorSubTableEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_compiled_vertex_array: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_compiled_vertex_array', extstring) then - begin - glLockArraysEXT := wglGetProcAddress('glLockArraysEXT'); - if not Assigned(glLockArraysEXT) then Exit; - glUnlockArraysEXT := wglGetProcAddress('glUnlockArraysEXT'); - if not Assigned(glUnlockArraysEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_convolution: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_convolution', extstring) then - begin - glConvolutionFilter1DEXT := wglGetProcAddress('glConvolutionFilter1DEXT'); - if not Assigned(glConvolutionFilter1DEXT) then Exit; - glConvolutionFilter2DEXT := wglGetProcAddress('glConvolutionFilter2DEXT'); - if not Assigned(glConvolutionFilter2DEXT) then Exit; - glCopyConvolutionFilter1DEXT := wglGetProcAddress('glCopyConvolutionFilter1DEXT'); - if not Assigned(glCopyConvolutionFilter1DEXT) then Exit; - glCopyConvolutionFilter2DEXT := wglGetProcAddress('glCopyConvolutionFilter2DEXT'); - if not Assigned(glCopyConvolutionFilter2DEXT) then Exit; - glGetConvolutionFilterEXT := wglGetProcAddress('glGetConvolutionFilterEXT'); - if not Assigned(glGetConvolutionFilterEXT) then Exit; - glSeparableFilter2DEXT := wglGetProcAddress('glSeparableFilter2DEXT'); - if not Assigned(glSeparableFilter2DEXT) then Exit; - glGetSeparableFilterEXT := wglGetProcAddress('glGetSeparableFilterEXT'); - if not Assigned(glGetSeparableFilterEXT) then Exit; - glConvolutionParameteriEXT := wglGetProcAddress('glConvolutionParameteriEXT'); - if not Assigned(glConvolutionParameteriEXT) then Exit; - glConvolutionParameterivEXT := wglGetProcAddress('glConvolutionParameterivEXT'); - if not Assigned(glConvolutionParameterivEXT) then Exit; - glConvolutionParameterfEXT := wglGetProcAddress('glConvolutionParameterfEXT'); - if not Assigned(glConvolutionParameterfEXT) then Exit; - glConvolutionParameterfvEXT := wglGetProcAddress('glConvolutionParameterfvEXT'); - if not Assigned(glConvolutionParameterfvEXT) then Exit; - glGetConvolutionParameterivEXT := wglGetProcAddress('glGetConvolutionParameterivEXT'); - if not Assigned(glGetConvolutionParameterivEXT) then Exit; - glGetConvolutionParameterfvEXT := wglGetProcAddress('glGetConvolutionParameterfvEXT'); - if not Assigned(glGetConvolutionParameterfvEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_histogram: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_histogram', extstring) then - begin - glHistogramEXT := wglGetProcAddress('glHistogramEXT'); - if not Assigned(glHistogramEXT) then Exit; - glResetHistogramEXT := wglGetProcAddress('glResetHistogramEXT'); - if not Assigned(glResetHistogramEXT) then Exit; - glGetHistogramEXT := wglGetProcAddress('glGetHistogramEXT'); - if not Assigned(glGetHistogramEXT) then Exit; - glGetHistogramParameterivEXT := wglGetProcAddress('glGetHistogramParameterivEXT'); - if not Assigned(glGetHistogramParameterivEXT) then Exit; - glGetHistogramParameterfvEXT := wglGetProcAddress('glGetHistogramParameterfvEXT'); - if not Assigned(glGetHistogramParameterfvEXT) then Exit; - glMinmaxEXT := wglGetProcAddress('glMinmaxEXT'); - if not Assigned(glMinmaxEXT) then Exit; - glResetMinmaxEXT := wglGetProcAddress('glResetMinmaxEXT'); - if not Assigned(glResetMinmaxEXT) then Exit; - glGetMinmaxEXT := wglGetProcAddress('glGetMinmaxEXT'); - if not Assigned(glGetMinmaxEXT) then Exit; - glGetMinmaxParameterivEXT := wglGetProcAddress('glGetMinmaxParameterivEXT'); - if not Assigned(glGetMinmaxParameterivEXT) then Exit; - glGetMinmaxParameterfvEXT := wglGetProcAddress('glGetMinmaxParameterfvEXT'); - if not Assigned(glGetMinmaxParameterfvEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_multi_draw_arrays: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_multi_draw_arrays', extstring) then - begin - glMultiDrawArraysEXT := wglGetProcAddress('glMultiDrawArraysEXT'); - if not Assigned(glMultiDrawArraysEXT) then Exit; - glMultiDrawElementsEXT := wglGetProcAddress('glMultiDrawElementsEXT'); - if not Assigned(glMultiDrawElementsEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_packed_pixels: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_packed_pixels', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_paletted_texture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_paletted_texture', extstring) then - begin - glColorTableEXT := wglGetProcAddress('glColorTableEXT'); - if not Assigned(glColorTableEXT) then Exit; - glColorSubTableEXT := wglGetProcAddress('glColorSubTableEXT'); - if not Assigned(glColorSubTableEXT) then Exit; - glGetColorTableEXT := wglGetProcAddress('glGetColorTableEXT'); - if not Assigned(glGetColorTableEXT) then Exit; - glGetColorTableParameterivEXT := wglGetProcAddress('glGetColorTableParameterivEXT'); - if not Assigned(glGetColorTableParameterivEXT) then Exit; - glGetColorTableParameterfvEXT := wglGetProcAddress('glGetColorTableParameterfvEXT'); - if not Assigned(glGetColorTableParameterfvEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_point_parameters: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_point_parameters', extstring) then - begin - glPointParameterfEXT := wglGetProcAddress('glPointParameterfEXT'); - if not Assigned(glPointParameterfEXT) then Exit; - glPointParameterfvEXT := wglGetProcAddress('glPointParameterfvEXT'); - if not Assigned(glPointParameterfvEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_polygon_offset: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_polygon_offset', extstring) then - begin - glPolygonOffsetEXT := wglGetProcAddress('glPolygonOffsetEXT'); - if not Assigned(glPolygonOffsetEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_separate_specular_color: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_separate_specular_color', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_shadow_funcs: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_shadow_funcs', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_shared_texture_palette: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_shared_texture_palette', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_stencil_two_side: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_stencil_two_side', extstring) then - begin - glActiveStencilFaceEXT := wglGetProcAddress('glActiveStencilFaceEXT'); - if not Assigned(glActiveStencilFaceEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_stencil_wrap: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_stencil_wrap', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_subtexture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_subtexture', extstring) then - begin - glTexSubImage1DEXT := wglGetProcAddress('glTexSubImage1DEXT'); - if not Assigned(glTexSubImage1DEXT) then Exit; - glTexSubImage2DEXT := wglGetProcAddress('glTexSubImage2DEXT'); - if not Assigned(glTexSubImage2DEXT) then Exit; - glTexSubImage3DEXT := wglGetProcAddress('glTexSubImage3DEXT'); - if not Assigned(glTexSubImage3DEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture3D: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture3D', extstring) then - begin - glTexImage3DEXT := wglGetProcAddress('glTexImage3DEXT'); - if not Assigned(glTexImage3DEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_compression_s3tc: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_compression_s3tc', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_env_add: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_env_add', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_env_combine: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_env_combine', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_env_dot3: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_env_dot3', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_filter_anisotropic: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_filter_anisotropic', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_lod_bias: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_lod_bias', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_object', extstring) then - begin - glGenTexturesEXT := wglGetProcAddress('glGenTexturesEXT'); - if not Assigned(glGenTexturesEXT) then Exit; - glDeleteTexturesEXT := wglGetProcAddress('glDeleteTexturesEXT'); - if not Assigned(glDeleteTexturesEXT) then Exit; - glBindTextureEXT := wglGetProcAddress('glBindTextureEXT'); - if not Assigned(glBindTextureEXT) then Exit; - glPrioritizeTexturesEXT := wglGetProcAddress('glPrioritizeTexturesEXT'); - if not Assigned(glPrioritizeTexturesEXT) then Exit; - glAreTexturesResidentEXT := wglGetProcAddress('glAreTexturesResidentEXT'); - if not Assigned(glAreTexturesResidentEXT) then Exit; - glIsTextureEXT := wglGetProcAddress('glIsTextureEXT'); - if not Assigned(glIsTextureEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_vertex_array: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_vertex_array', extstring) then - begin - glArrayElementEXT := wglGetProcAddress('glArrayElementEXT'); - if not Assigned(glArrayElementEXT) then Exit; - glDrawArraysEXT := wglGetProcAddress('glDrawArraysEXT'); - if not Assigned(glDrawArraysEXT) then Exit; - glVertexPointerEXT := wglGetProcAddress('glVertexPointerEXT'); - if not Assigned(glVertexPointerEXT) then Exit; - glNormalPointerEXT := wglGetProcAddress('glNormalPointerEXT'); - if not Assigned(glNormalPointerEXT) then Exit; - glColorPointerEXT := wglGetProcAddress('glColorPointerEXT'); - if not Assigned(glColorPointerEXT) then Exit; - glIndexPointerEXT := wglGetProcAddress('glIndexPointerEXT'); - if not Assigned(glIndexPointerEXT) then Exit; - glTexCoordPointerEXT := wglGetProcAddress('glTexCoordPointerEXT'); - if not Assigned(glTexCoordPointerEXT) then Exit; - glEdgeFlagPointerEXT := wglGetProcAddress('glEdgeFlagPointerEXT'); - if not Assigned(glEdgeFlagPointerEXT) then Exit; - glGetPointervEXT := wglGetProcAddress('glGetPointervEXT'); - if not Assigned(glGetPointervEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_vertex_shader: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_vertex_shader', extstring) then - begin - glBeginVertexShaderEXT := wglGetProcAddress('glBeginVertexShaderEXT'); - if not Assigned(glBeginVertexShaderEXT) then Exit; - glEndVertexShaderEXT := wglGetProcAddress('glEndVertexShaderEXT'); - if not Assigned(glEndVertexShaderEXT) then Exit; - glBindVertexShaderEXT := wglGetProcAddress('glBindVertexShaderEXT'); - if not Assigned(glBindVertexShaderEXT) then Exit; - glGenVertexShadersEXT := wglGetProcAddress('glGenVertexShadersEXT'); - if not Assigned(glGenVertexShadersEXT) then Exit; - glDeleteVertexShaderEXT := wglGetProcAddress('glDeleteVertexShaderEXT'); - if not Assigned(glDeleteVertexShaderEXT) then Exit; - glShaderOp1EXT := wglGetProcAddress('glShaderOp1EXT'); - if not Assigned(glShaderOp1EXT) then Exit; - glShaderOp2EXT := wglGetProcAddress('glShaderOp2EXT'); - if not Assigned(glShaderOp2EXT) then Exit; - glShaderOp3EXT := wglGetProcAddress('glShaderOp3EXT'); - if not Assigned(glShaderOp3EXT) then Exit; - glSwizzleEXT := wglGetProcAddress('glSwizzleEXT'); - if not Assigned(glSwizzleEXT) then Exit; - glWriteMaskEXT := wglGetProcAddress('glWriteMaskEXT'); - if not Assigned(glWriteMaskEXT) then Exit; - glInsertComponentEXT := wglGetProcAddress('glInsertComponentEXT'); - if not Assigned(glInsertComponentEXT) then Exit; - glExtractComponentEXT := wglGetProcAddress('glExtractComponentEXT'); - if not Assigned(glExtractComponentEXT) then Exit; - glGenSymbolsEXT := wglGetProcAddress('glGenSymbolsEXT'); - if not Assigned(glGenSymbolsEXT) then Exit; - glSetInvariantEXT := wglGetProcAddress('glSetInvariantEXT'); - if not Assigned(glSetInvariantEXT) then Exit; - glSetLocalConstantEXT := wglGetProcAddress('glSetLocalConstantEXT'); - if not Assigned(glSetLocalConstantEXT) then Exit; - glVariantbvEXT := wglGetProcAddress('glVariantbvEXT'); - if not Assigned(glVariantbvEXT) then Exit; - glVariantsvEXT := wglGetProcAddress('glVariantsvEXT'); - if not Assigned(glVariantsvEXT) then Exit; - glVariantivEXT := wglGetProcAddress('glVariantivEXT'); - if not Assigned(glVariantivEXT) then Exit; - glVariantfvEXT := wglGetProcAddress('glVariantfvEXT'); - if not Assigned(glVariantfvEXT) then Exit; - glVariantdvEXT := wglGetProcAddress('glVariantdvEXT'); - if not Assigned(glVariantdvEXT) then Exit; - glVariantubvEXT := wglGetProcAddress('glVariantubvEXT'); - if not Assigned(glVariantubvEXT) then Exit; - glVariantusvEXT := wglGetProcAddress('glVariantusvEXT'); - if not Assigned(glVariantusvEXT) then Exit; - glVariantuivEXT := wglGetProcAddress('glVariantuivEXT'); - if not Assigned(glVariantuivEXT) then Exit; - glVariantPointerEXT := wglGetProcAddress('glVariantPointerEXT'); - if not Assigned(glVariantPointerEXT) then Exit; - glEnableVariantClientStateEXT := wglGetProcAddress('glEnableVariantClientStateEXT'); - if not Assigned(glEnableVariantClientStateEXT) then Exit; - glDisableVariantClientStateEXT := wglGetProcAddress('glDisableVariantClientStateEXT'); - if not Assigned(glDisableVariantClientStateEXT) then Exit; - glBindLightParameterEXT := wglGetProcAddress('glBindLightParameterEXT'); - if not Assigned(glBindLightParameterEXT) then Exit; - glBindMaterialParameterEXT := wglGetProcAddress('glBindMaterialParameterEXT'); - if not Assigned(glBindMaterialParameterEXT) then Exit; - glBindTexGenParameterEXT := wglGetProcAddress('glBindTexGenParameterEXT'); - if not Assigned(glBindTexGenParameterEXT) then Exit; - glBindTextureUnitParameterEXT := wglGetProcAddress('glBindTextureUnitParameterEXT'); - if not Assigned(glBindTextureUnitParameterEXT) then Exit; - glBindParameterEXT := wglGetProcAddress('glBindParameterEXT'); - if not Assigned(glBindParameterEXT) then Exit; - glIsVariantEnabledEXT := wglGetProcAddress('glIsVariantEnabledEXT'); - if not Assigned(glIsVariantEnabledEXT) then Exit; - glGetVariantBooleanvEXT := wglGetProcAddress('glGetVariantBooleanvEXT'); - if not Assigned(glGetVariantBooleanvEXT) then Exit; - glGetVariantIntegervEXT := wglGetProcAddress('glGetVariantIntegervEXT'); - if not Assigned(glGetVariantIntegervEXT) then Exit; - glGetVariantFloatvEXT := wglGetProcAddress('glGetVariantFloatvEXT'); - if not Assigned(glGetVariantFloatvEXT) then Exit; - glGetVariantPointervEXT := wglGetProcAddress('glGetVariantPointervEXT'); - if not Assigned(glGetVariantPointervEXT) then Exit; - glGetInvariantBooleanvEXT := wglGetProcAddress('glGetInvariantBooleanvEXT'); - if not Assigned(glGetInvariantBooleanvEXT) then Exit; - glGetInvariantIntegervEXT := wglGetProcAddress('glGetInvariantIntegervEXT'); - if not Assigned(glGetInvariantIntegervEXT) then Exit; - glGetInvariantFloatvEXT := wglGetProcAddress('glGetInvariantFloatvEXT'); - if not Assigned(glGetInvariantFloatvEXT) then Exit; - glGetLocalConstantBooleanvEXT := wglGetProcAddress('glGetLocalConstantBooleanvEXT'); - if not Assigned(glGetLocalConstantBooleanvEXT) then Exit; - glGetLocalConstantIntegervEXT := wglGetProcAddress('glGetLocalConstantIntegervEXT'); - if not Assigned(glGetLocalConstantIntegervEXT) then Exit; - glGetLocalConstantFloatvEXT := wglGetProcAddress('glGetLocalConstantFloatvEXT'); - if not Assigned(glGetLocalConstantFloatvEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_vertex_weighting: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_vertex_weighting', extstring) then - begin - glVertexWeightfEXT := wglGetProcAddress('glVertexWeightfEXT'); - if not Assigned(glVertexWeightfEXT) then Exit; - glVertexWeightfvEXT := wglGetProcAddress('glVertexWeightfvEXT'); - if not Assigned(glVertexWeightfvEXT) then Exit; - glVertexWeightPointerEXT := wglGetProcAddress('glVertexWeightPointerEXT'); - if not Assigned(glVertexWeightPointerEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_HP_occlusion_test: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_HP_occlusion_test', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_blend_square: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_blend_square', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_copy_depth_to_color: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_copy_depth_to_color', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_depth_clamp: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_depth_clamp', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_evaluators: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_evaluators', extstring) then - begin - glMapControlPointsNV := wglGetProcAddress('glMapControlPointsNV'); - if not Assigned(glMapControlPointsNV) then Exit; - glMapParameterivNV := wglGetProcAddress('glMapParameterivNV'); - if not Assigned(glMapParameterivNV) then Exit; - glMapParameterfvNV := wglGetProcAddress('glMapParameterfvNV'); - if not Assigned(glMapParameterfvNV) then Exit; - glGetMapControlPointsNV := wglGetProcAddress('glGetMapControlPointsNV'); - if not Assigned(glGetMapControlPointsNV) then Exit; - glGetMapParameterivNV := wglGetProcAddress('glGetMapParameterivNV'); - if not Assigned(glGetMapParameterivNV) then Exit; - glGetMapParameterfvNV := wglGetProcAddress('glGetMapParameterfvNV'); - if not Assigned(glGetMapParameterfvNV) then Exit; - glGetMapAttribParameterivNV := wglGetProcAddress('glGetMapAttribParameterivNV'); - if not Assigned(glGetMapAttribParameterivNV) then Exit; - glGetMapAttribParameterfvNV := wglGetProcAddress('glGetMapAttribParameterfvNV'); - if not Assigned(glGetMapAttribParameterfvNV) then Exit; - glEvalMapsNV := wglGetProcAddress('glEvalMapsNV'); - if not Assigned(glEvalMapsNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_fence: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_fence', extstring) then - begin - glGenFencesNV := wglGetProcAddress('glGenFencesNV'); - if not Assigned(glGenFencesNV) then Exit; - glDeleteFencesNV := wglGetProcAddress('glDeleteFencesNV'); - if not Assigned(glDeleteFencesNV) then Exit; - glSetFenceNV := wglGetProcAddress('glSetFenceNV'); - if not Assigned(glSetFenceNV) then Exit; - glTestFenceNV := wglGetProcAddress('glTestFenceNV'); - if not Assigned(glTestFenceNV) then Exit; - glFinishFenceNV := wglGetProcAddress('glFinishFenceNV'); - if not Assigned(glFinishFenceNV) then Exit; - glIsFenceNV := wglGetProcAddress('glIsFenceNV'); - if not Assigned(glIsFenceNV) then Exit; - glGetFenceivNV := wglGetProcAddress('glGetFenceivNV'); - if not Assigned(glGetFenceivNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_fog_distance: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_fog_distance', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_light_max_exponent: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_light_max_exponent', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_multisample_filter_hint: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_multisample_filter_hint', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_occlusion_query: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_occlusion_query', extstring) then - begin - glGenOcclusionQueriesNV := wglGetProcAddress('glGenOcclusionQueriesNV'); - if not Assigned(glGenOcclusionQueriesNV) then Exit; - glDeleteOcclusionQueriesNV := wglGetProcAddress('glDeleteOcclusionQueriesNV'); - if not Assigned(glDeleteOcclusionQueriesNV) then Exit; - glIsOcclusionQueryNV := wglGetProcAddress('glIsOcclusionQueryNV'); - if not Assigned(glIsOcclusionQueryNV) then Exit; - glBeginOcclusionQueryNV := wglGetProcAddress('glBeginOcclusionQueryNV'); - if not Assigned(glBeginOcclusionQueryNV) then Exit; - glEndOcclusionQueryNV := wglGetProcAddress('glEndOcclusionQueryNV'); - if not Assigned(glEndOcclusionQueryNV) then Exit; - glGetOcclusionQueryivNV := wglGetProcAddress('glGetOcclusionQueryivNV'); - if not Assigned(glGetOcclusionQueryivNV) then Exit; - glGetOcclusionQueryuivNV := wglGetProcAddress('glGetOcclusionQueryuivNV'); - if not Assigned(glGetOcclusionQueryuivNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_packed_depth_stencil: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_packed_depth_stencil', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_point_sprite: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_point_sprite', extstring) then - begin - glPointParameteriNV := wglGetProcAddress('glPointParameteriNV'); - if not Assigned(glPointParameteriNV) then Exit; - glPointParameterivNV := wglGetProcAddress('glPointParameterivNV'); - if not Assigned(glPointParameterivNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_register_combiners: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_register_combiners', extstring) then - begin - glCombinerParameterfvNV := wglGetProcAddress('glCombinerParameterfvNV'); - if not Assigned(glCombinerParameterfvNV) then Exit; - glCombinerParameterivNV := wglGetProcAddress('glCombinerParameterivNV'); - if not Assigned(glCombinerParameterivNV) then Exit; - glCombinerParameterfNV := wglGetProcAddress('glCombinerParameterfNV'); - if not Assigned(glCombinerParameterfNV) then Exit; - glCombinerParameteriNV := wglGetProcAddress('glCombinerParameteriNV'); - if not Assigned(glCombinerParameteriNV) then Exit; - glCombinerInputNV := wglGetProcAddress('glCombinerInputNV'); - if not Assigned(glCombinerInputNV) then Exit; - glCombinerOutputNV := wglGetProcAddress('glCombinerOutputNV'); - if not Assigned(glCombinerOutputNV) then Exit; - glFinalCombinerInputNV := wglGetProcAddress('glFinalCombinerInputNV'); - if not Assigned(glFinalCombinerInputNV) then Exit; - glGetCombinerInputParameterfvNV := wglGetProcAddress('glGetCombinerInputParameterfvNV'); - if not Assigned(glGetCombinerInputParameterfvNV) then Exit; - glGetCombinerInputParameterivNV := wglGetProcAddress('glGetCombinerInputParameterivNV'); - if not Assigned(glGetCombinerInputParameterivNV) then Exit; - glGetCombinerOutputParameterfvNV := wglGetProcAddress('glGetCombinerOutputParameterfvNV'); - if not Assigned(glGetCombinerOutputParameterfvNV) then Exit; - glGetCombinerOutputParameterivNV := wglGetProcAddress('glGetCombinerOutputParameterivNV'); - if not Assigned(glGetCombinerOutputParameterivNV) then Exit; - glGetFinalCombinerInputParameterfvNV := wglGetProcAddress('glGetFinalCombinerInputParameterfvNV'); - if not Assigned(glGetFinalCombinerInputParameterfvNV) then Exit; - glGetFinalCombinerInputParameterivNV := wglGetProcAddress('glGetFinalCombinerInputParameterivNV'); - if not Assigned(glGetFinalCombinerInputParameterivNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_register_combiners2: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_register_combiners2', extstring) then - begin - glCombinerStageParameterfvNV := wglGetProcAddress('glCombinerStageParameterfvNV'); - if not Assigned(glCombinerStageParameterfvNV) then Exit; - glGetCombinerStageParameterfvNV := wglGetProcAddress('glGetCombinerStageParameterfvNV'); - if not Assigned(glGetCombinerStageParameterfvNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_texgen_emboss: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texgen_emboss', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texgen_reflection: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texgen_reflection', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texture_compression_vtc: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texture_compression_vtc', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texture_env_combine4: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texture_env_combine4', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texture_rectangle: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texture_rectangle', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texture_shader: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texture_shader', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texture_shader2: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texture_shader2', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texture_shader3: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texture_shader3', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_vertex_array_range: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_vertex_array_range', extstring) then - begin - glVertexArrayRangeNV := wglGetProcAddress('glVertexArrayRangeNV'); - if not Assigned(glVertexArrayRangeNV) then Exit; - glFlushVertexArrayRangeNV := wglGetProcAddress('glFlushVertexArrayRangeNV'); - if not Assigned(glFlushVertexArrayRangeNV) then Exit; - wglAllocateMemoryNV := wglGetProcAddress('wglAllocateMemoryNV'); - if not Assigned(wglAllocateMemoryNV) then Exit; - wglFreeMemoryNV := wglGetProcAddress('wglFreeMemoryNV'); - if not Assigned(wglFreeMemoryNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_vertex_array_range2: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_vertex_array_range2', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_vertex_program: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_vertex_program', extstring) then - begin - glBindProgramNV := wglGetProcAddress('glBindProgramNV'); - if not Assigned(glBindProgramNV) then Exit; - glDeleteProgramsNV := wglGetProcAddress('glDeleteProgramsNV'); - if not Assigned(glDeleteProgramsNV) then Exit; - glExecuteProgramNV := wglGetProcAddress('glExecuteProgramNV'); - if not Assigned(glExecuteProgramNV) then Exit; - glGenProgramsNV := wglGetProcAddress('glGenProgramsNV'); - if not Assigned(glGenProgramsNV) then Exit; - glAreProgramsResidentNV := wglGetProcAddress('glAreProgramsResidentNV'); - if not Assigned(glAreProgramsResidentNV) then Exit; - glRequestResidentProgramsNV := wglGetProcAddress('glRequestResidentProgramsNV'); - if not Assigned(glRequestResidentProgramsNV) then Exit; - glGetProgramParameterfvNV := wglGetProcAddress('glGetProgramParameterfvNV'); - if not Assigned(glGetProgramParameterfvNV) then Exit; - glGetProgramParameterdvNV := wglGetProcAddress('glGetProgramParameterdvNV'); - if not Assigned(glGetProgramParameterdvNV) then Exit; - glGetProgramivNV := wglGetProcAddress('glGetProgramivNV'); - if not Assigned(glGetProgramivNV) then Exit; - glGetProgramStringNV := wglGetProcAddress('glGetProgramStringNV'); - if not Assigned(glGetProgramStringNV) then Exit; - glGetTrackMatrixivNV := wglGetProcAddress('glGetTrackMatrixivNV'); - if not Assigned(glGetTrackMatrixivNV) then Exit; - glGetVertexAttribdvNV := wglGetProcAddress('glGetVertexAttribdvNV'); - if not Assigned(glGetVertexAttribdvNV) then Exit; - glGetVertexAttribfvNV := wglGetProcAddress('glGetVertexAttribfvNV'); - if not Assigned(glGetVertexAttribfvNV) then Exit; - glGetVertexAttribivNV := wglGetProcAddress('glGetVertexAttribivNV'); - if not Assigned(glGetVertexAttribivNV) then Exit; - glGetVertexAttribPointervNV := wglGetProcAddress('glGetVertexAttribPointervNV'); - if not Assigned(glGetVertexAttribPointervNV) then Exit; - glIsProgramNV := wglGetProcAddress('glIsProgramNV'); - if not Assigned(glIsProgramNV) then Exit; - glLoadProgramNV := wglGetProcAddress('glLoadProgramNV'); - if not Assigned(glLoadProgramNV) then Exit; - glProgramParameter4fNV := wglGetProcAddress('glProgramParameter4fNV'); - if not Assigned(glProgramParameter4fNV) then Exit; - glProgramParameter4fvNV := wglGetProcAddress('glProgramParameter4fvNV'); - if not Assigned(glProgramParameter4fvNV) then Exit; - glProgramParameters4dvNV := wglGetProcAddress('glProgramParameters4dvNV'); - if not Assigned(glProgramParameters4dvNV) then Exit; - glProgramParameters4fvNV := wglGetProcAddress('glProgramParameters4fvNV'); - if not Assigned(glProgramParameters4fvNV) then Exit; - glTrackMatrixNV := wglGetProcAddress('glTrackMatrixNV'); - if not Assigned(glTrackMatrixNV) then Exit; - glVertexAttribPointerNV := wglGetProcAddress('glVertexAttribPointerNV'); - if not Assigned(glVertexAttribPointerNV) then Exit; - glVertexAttrib1sNV := wglGetProcAddress('glVertexAttrib1sNV'); - if not Assigned(glVertexAttrib1sNV) then Exit; - glVertexAttrib1fNV := wglGetProcAddress('glVertexAttrib1fNV'); - if not Assigned(glVertexAttrib1fNV) then Exit; - glVertexAttrib1dNV := wglGetProcAddress('glVertexAttrib1dNV'); - if not Assigned(glVertexAttrib1dNV) then Exit; - glVertexAttrib2sNV := wglGetProcAddress('glVertexAttrib2sNV'); - if not Assigned(glVertexAttrib2sNV) then Exit; - glVertexAttrib2fNV := wglGetProcAddress('glVertexAttrib2fNV'); - if not Assigned(glVertexAttrib2fNV) then Exit; - glVertexAttrib2dNV := wglGetProcAddress('glVertexAttrib2dNV'); - if not Assigned(glVertexAttrib2dNV) then Exit; - glVertexAttrib3sNV := wglGetProcAddress('glVertexAttrib3sNV'); - if not Assigned(glVertexAttrib3sNV) then Exit; - glVertexAttrib3fNV := wglGetProcAddress('glVertexAttrib3fNV'); - if not Assigned(glVertexAttrib3fNV) then Exit; - glVertexAttrib3dNV := wglGetProcAddress('glVertexAttrib3dNV'); - if not Assigned(glVertexAttrib3dNV) then Exit; - glVertexAttrib4sNV := wglGetProcAddress('glVertexAttrib4sNV'); - if not Assigned(glVertexAttrib4sNV) then Exit; - glVertexAttrib4fNV := wglGetProcAddress('glVertexAttrib4fNV'); - if not Assigned(glVertexAttrib4fNV) then Exit; - glVertexAttrib4dNV := wglGetProcAddress('glVertexAttrib4dNV'); - if not Assigned(glVertexAttrib4dNV) then Exit; - glVertexAttrib4ubNV := wglGetProcAddress('glVertexAttrib4ubNV'); - if not Assigned(glVertexAttrib4ubNV) then Exit; - glVertexAttrib1svNV := wglGetProcAddress('glVertexAttrib1svNV'); - if not Assigned(glVertexAttrib1svNV) then Exit; - glVertexAttrib1fvNV := wglGetProcAddress('glVertexAttrib1fvNV'); - if not Assigned(glVertexAttrib1fvNV) then Exit; - glVertexAttrib1dvNV := wglGetProcAddress('glVertexAttrib1dvNV'); - if not Assigned(glVertexAttrib1dvNV) then Exit; - glVertexAttrib2svNV := wglGetProcAddress('glVertexAttrib2svNV'); - if not Assigned(glVertexAttrib2svNV) then Exit; - glVertexAttrib2fvNV := wglGetProcAddress('glVertexAttrib2fvNV'); - if not Assigned(glVertexAttrib2fvNV) then Exit; - glVertexAttrib2dvNV := wglGetProcAddress('glVertexAttrib2dvNV'); - if not Assigned(glVertexAttrib2dvNV) then Exit; - glVertexAttrib3svNV := wglGetProcAddress('glVertexAttrib3svNV'); - if not Assigned(glVertexAttrib3svNV) then Exit; - glVertexAttrib3fvNV := wglGetProcAddress('glVertexAttrib3fvNV'); - if not Assigned(glVertexAttrib3fvNV) then Exit; - glVertexAttrib3dvNV := wglGetProcAddress('glVertexAttrib3dvNV'); - if not Assigned(glVertexAttrib3dvNV) then Exit; - glVertexAttrib4svNV := wglGetProcAddress('glVertexAttrib4svNV'); - if not Assigned(glVertexAttrib4svNV) then Exit; - glVertexAttrib4fvNV := wglGetProcAddress('glVertexAttrib4fvNV'); - if not Assigned(glVertexAttrib4fvNV) then Exit; - glVertexAttrib4dvNV := wglGetProcAddress('glVertexAttrib4dvNV'); - if not Assigned(glVertexAttrib4dvNV) then Exit; - glVertexAttrib4ubvNV := wglGetProcAddress('glVertexAttrib4ubvNV'); - if not Assigned(glVertexAttrib4ubvNV) then Exit; - glVertexAttribs1svNV := wglGetProcAddress('glVertexAttribs1svNV'); - if not Assigned(glVertexAttribs1svNV) then Exit; - glVertexAttribs1fvNV := wglGetProcAddress('glVertexAttribs1fvNV'); - if not Assigned(glVertexAttribs1fvNV) then Exit; - glVertexAttribs1dvNV := wglGetProcAddress('glVertexAttribs1dvNV'); - if not Assigned(glVertexAttribs1dvNV) then Exit; - glVertexAttribs2svNV := wglGetProcAddress('glVertexAttribs2svNV'); - if not Assigned(glVertexAttribs2svNV) then Exit; - glVertexAttribs2fvNV := wglGetProcAddress('glVertexAttribs2fvNV'); - if not Assigned(glVertexAttribs2fvNV) then Exit; - glVertexAttribs2dvNV := wglGetProcAddress('glVertexAttribs2dvNV'); - if not Assigned(glVertexAttribs2dvNV) then Exit; - glVertexAttribs3svNV := wglGetProcAddress('glVertexAttribs3svNV'); - if not Assigned(glVertexAttribs3svNV) then Exit; - glVertexAttribs3fvNV := wglGetProcAddress('glVertexAttribs3fvNV'); - if not Assigned(glVertexAttribs3fvNV) then Exit; - glVertexAttribs3dvNV := wglGetProcAddress('glVertexAttribs3dvNV'); - if not Assigned(glVertexAttribs3dvNV) then Exit; - glVertexAttribs4svNV := wglGetProcAddress('glVertexAttribs4svNV'); - if not Assigned(glVertexAttribs4svNV) then Exit; - glVertexAttribs4fvNV := wglGetProcAddress('glVertexAttribs4fvNV'); - if not Assigned(glVertexAttribs4fvNV) then Exit; - glVertexAttribs4dvNV := wglGetProcAddress('glVertexAttribs4dvNV'); - if not Assigned(glVertexAttribs4dvNV) then Exit; - glVertexAttribs4ubvNV := wglGetProcAddress('glVertexAttribs4ubvNV'); - if not Assigned(glVertexAttribs4ubvNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_vertex_program1_1: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_vertex_program1_1', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ATI_element_array: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_element_array', extstring) then - begin - glElementPointerATI := wglGetProcAddress('glElementPointerATI'); - if not Assigned(glElementPointerATI) then Exit; - glDrawElementArrayATI := wglGetProcAddress('glDrawElementArrayATI'); - if not Assigned(glDrawElementArrayATI) then Exit; - glDrawRangeElementArrayATI := wglGetProcAddress('glDrawRangeElementArrayATI'); - if not Assigned(glDrawRangeElementArrayATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_envmap_bumpmap: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_envmap_bumpmap', extstring) then - begin - glTexBumpParameterivATI := wglGetProcAddress('glTexBumpParameterivATI'); - if not Assigned(glTexBumpParameterivATI) then Exit; - glTexBumpParameterfvATI := wglGetProcAddress('glTexBumpParameterfvATI'); - if not Assigned(glTexBumpParameterfvATI) then Exit; - glGetTexBumpParameterivATI := wglGetProcAddress('glGetTexBumpParameterivATI'); - if not Assigned(glGetTexBumpParameterivATI) then Exit; - glGetTexBumpParameterfvATI := wglGetProcAddress('glGetTexBumpParameterfvATI'); - if not Assigned(glGetTexBumpParameterfvATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_fragment_shader: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_fragment_shader', extstring) then - begin - glGenFragmentShadersATI := wglGetProcAddress('glGenFragmentShadersATI'); - if not Assigned(glGenFragmentShadersATI) then Exit; - glBindFragmentShaderATI := wglGetProcAddress('glBindFragmentShaderATI'); - if not Assigned(glBindFragmentShaderATI) then Exit; - glDeleteFragmentShaderATI := wglGetProcAddress('glDeleteFragmentShaderATI'); - if not Assigned(glDeleteFragmentShaderATI) then Exit; - glBeginFragmentShaderATI := wglGetProcAddress('glBeginFragmentShaderATI'); - if not Assigned(glBeginFragmentShaderATI) then Exit; - glEndFragmentShaderATI := wglGetProcAddress('glEndFragmentShaderATI'); - if not Assigned(glEndFragmentShaderATI) then Exit; - glPassTexCoordATI := wglGetProcAddress('glPassTexCoordATI'); - if not Assigned(glPassTexCoordATI) then Exit; - glSampleMapATI := wglGetProcAddress('glSampleMapATI'); - if not Assigned(glSampleMapATI) then Exit; - glColorFragmentOp1ATI := wglGetProcAddress('glColorFragmentOp1ATI'); - if not Assigned(glColorFragmentOp1ATI) then Exit; - glColorFragmentOp2ATI := wglGetProcAddress('glColorFragmentOp2ATI'); - if not Assigned(glColorFragmentOp2ATI) then Exit; - glColorFragmentOp3ATI := wglGetProcAddress('glColorFragmentOp3ATI'); - if not Assigned(glColorFragmentOp3ATI) then Exit; - glAlphaFragmentOp1ATI := wglGetProcAddress('glAlphaFragmentOp1ATI'); - if not Assigned(glAlphaFragmentOp1ATI) then Exit; - glAlphaFragmentOp2ATI := wglGetProcAddress('glAlphaFragmentOp2ATI'); - if not Assigned(glAlphaFragmentOp2ATI) then Exit; - glAlphaFragmentOp3ATI := wglGetProcAddress('glAlphaFragmentOp3ATI'); - if not Assigned(glAlphaFragmentOp3ATI) then Exit; - glSetFragmentShaderConstantATI := wglGetProcAddress('glSetFragmentShaderConstantATI'); - if not Assigned(glSetFragmentShaderConstantATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_pn_triangles: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_pn_triangles', extstring) then - begin - glPNTrianglesiATI := wglGetProcAddress('glPNTrianglesiATI'); - if not Assigned(glPNTrianglesiATI) then Exit; - glPNTrianglesfATI := wglGetProcAddress('glPNTrianglesfATI'); - if not Assigned(glPNTrianglesfATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_texture_mirror_once: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_texture_mirror_once', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ATI_vertex_array_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_vertex_array_object', extstring) then - begin - glNewObjectBufferATI := wglGetProcAddress('glNewObjectBufferATI'); - if not Assigned(glNewObjectBufferATI) then Exit; - glIsObjectBufferATI := wglGetProcAddress('glIsObjectBufferATI'); - if not Assigned(glIsObjectBufferATI) then Exit; - glUpdateObjectBufferATI := wglGetProcAddress('glUpdateObjectBufferATI'); - if not Assigned(glUpdateObjectBufferATI) then Exit; - glGetObjectBufferfvATI := wglGetProcAddress('glGetObjectBufferfvATI'); - if not Assigned(glGetObjectBufferfvATI) then Exit; - glGetObjectBufferivATI := wglGetProcAddress('glGetObjectBufferivATI'); - if not Assigned(glGetObjectBufferivATI) then Exit; - glDeleteObjectBufferATI := wglGetProcAddress('glDeleteObjectBufferATI'); - if not Assigned(glDeleteObjectBufferATI) then Exit; - glArrayObjectATI := wglGetProcAddress('glArrayObjectATI'); - if not Assigned(glArrayObjectATI) then Exit; - glGetArrayObjectfvATI := wglGetProcAddress('glGetArrayObjectfvATI'); - if not Assigned(glGetArrayObjectfvATI) then Exit; - glGetArrayObjectivATI := wglGetProcAddress('glGetArrayObjectivATI'); - if not Assigned(glGetArrayObjectivATI) then Exit; - glVariantArrayObjectATI := wglGetProcAddress('glVariantArrayObjectATI'); - if not Assigned(glVariantArrayObjectATI) then Exit; - glGetVariantArrayObjectfvATI := wglGetProcAddress('glGetVariantArrayObjectfvATI'); - if not Assigned(glGetVariantArrayObjectfvATI) then Exit; - glGetVariantArrayObjectivATI := wglGetProcAddress('glGetVariantArrayObjectivATI'); - if not Assigned(glGetVariantArrayObjectivATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_vertex_streams: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_vertex_streams', extstring) then - begin - glVertexStream1s := wglGetProcAddress('glVertexStream1s'); - if not Assigned(glVertexStream1s) then Exit; - glVertexStream1i := wglGetProcAddress('glVertexStream1i'); - if not Assigned(glVertexStream1i) then Exit; - glVertexStream1f := wglGetProcAddress('glVertexStream1f'); - if not Assigned(glVertexStream1f) then Exit; - glVertexStream1d := wglGetProcAddress('glVertexStream1d'); - if not Assigned(glVertexStream1d) then Exit; - glVertexStream1sv := wglGetProcAddress('glVertexStream1sv'); - if not Assigned(glVertexStream1sv) then Exit; - glVertexStream1iv := wglGetProcAddress('glVertexStream1iv'); - if not Assigned(glVertexStream1iv) then Exit; - glVertexStream1fv := wglGetProcAddress('glVertexStream1fv'); - if not Assigned(glVertexStream1fv) then Exit; - glVertexStream1dv := wglGetProcAddress('glVertexStream1dv'); - if not Assigned(glVertexStream1dv) then Exit; - glVertexStream2s := wglGetProcAddress('glVertexStream2s'); - if not Assigned(glVertexStream2s) then Exit; - glVertexStream2i := wglGetProcAddress('glVertexStream2i'); - if not Assigned(glVertexStream2i) then Exit; - glVertexStream2f := wglGetProcAddress('glVertexStream2f'); - if not Assigned(glVertexStream2f) then Exit; - glVertexStream2d := wglGetProcAddress('glVertexStream2d'); - if not Assigned(glVertexStream2d) then Exit; - glVertexStream2sv := wglGetProcAddress('glVertexStream2sv'); - if not Assigned(glVertexStream2sv) then Exit; - glVertexStream2iv := wglGetProcAddress('glVertexStream2iv'); - if not Assigned(glVertexStream2iv) then Exit; - glVertexStream2fv := wglGetProcAddress('glVertexStream2fv'); - if not Assigned(glVertexStream2fv) then Exit; - glVertexStream2dv := wglGetProcAddress('glVertexStream2dv'); - if not Assigned(glVertexStream2dv) then Exit; - glVertexStream3s := wglGetProcAddress('glVertexStream3s'); - if not Assigned(glVertexStream3s) then Exit; - glVertexStream3i := wglGetProcAddress('glVertexStream3i'); - if not Assigned(glVertexStream3i) then Exit; - glVertexStream3f := wglGetProcAddress('glVertexStream3f'); - if not Assigned(glVertexStream3f) then Exit; - glVertexStream3d := wglGetProcAddress('glVertexStream3d'); - if not Assigned(glVertexStream3d) then Exit; - glVertexStream3sv := wglGetProcAddress('glVertexStream3sv'); - if not Assigned(glVertexStream3sv) then Exit; - glVertexStream3iv := wglGetProcAddress('glVertexStream3iv'); - if not Assigned(glVertexStream3iv) then Exit; - glVertexStream3fv := wglGetProcAddress('glVertexStream3fv'); - if not Assigned(glVertexStream3fv) then Exit; - glVertexStream3dv := wglGetProcAddress('glVertexStream3dv'); - if not Assigned(glVertexStream3dv) then Exit; - glVertexStream4s := wglGetProcAddress('glVertexStream4s'); - if not Assigned(glVertexStream4s) then Exit; - glVertexStream4i := wglGetProcAddress('glVertexStream4i'); - if not Assigned(glVertexStream4i) then Exit; - glVertexStream4f := wglGetProcAddress('glVertexStream4f'); - if not Assigned(glVertexStream4f) then Exit; - glVertexStream4d := wglGetProcAddress('glVertexStream4d'); - if not Assigned(glVertexStream4d) then Exit; - glVertexStream4sv := wglGetProcAddress('glVertexStream4sv'); - if not Assigned(glVertexStream4sv) then Exit; - glVertexStream4iv := wglGetProcAddress('glVertexStream4iv'); - if not Assigned(glVertexStream4iv) then Exit; - glVertexStream4fv := wglGetProcAddress('glVertexStream4fv'); - if not Assigned(glVertexStream4fv) then Exit; - glVertexStream4dv := wglGetProcAddress('glVertexStream4dv'); - if not Assigned(glVertexStream4dv) then Exit; - glNormalStream3b := wglGetProcAddress('glNormalStream3b'); - if not Assigned(glNormalStream3b) then Exit; - glNormalStream3s := wglGetProcAddress('glNormalStream3s'); - if not Assigned(glNormalStream3s) then Exit; - glNormalStream3i := wglGetProcAddress('glNormalStream3i'); - if not Assigned(glNormalStream3i) then Exit; - glNormalStream3f := wglGetProcAddress('glNormalStream3f'); - if not Assigned(glNormalStream3f) then Exit; - glNormalStream3d := wglGetProcAddress('glNormalStream3d'); - if not Assigned(glNormalStream3d) then Exit; - glNormalStream3bv := wglGetProcAddress('glNormalStream3bv'); - if not Assigned(glNormalStream3bv) then Exit; - glNormalStream3sv := wglGetProcAddress('glNormalStream3sv'); - if not Assigned(glNormalStream3sv) then Exit; - glNormalStream3iv := wglGetProcAddress('glNormalStream3iv'); - if not Assigned(glNormalStream3iv) then Exit; - glNormalStream3fv := wglGetProcAddress('glNormalStream3fv'); - if not Assigned(glNormalStream3fv) then Exit; - glNormalStream3dv := wglGetProcAddress('glNormalStream3dv'); - if not Assigned(glNormalStream3dv) then Exit; - glClientActiveVertexStream := wglGetProcAddress('glClientActiveVertexStream'); - if not Assigned(glClientActiveVertexStream) then Exit; - glVertexBlendEnvi := wglGetProcAddress('glVertexBlendEnvi'); - if not Assigned(glVertexBlendEnvi) then Exit; - glVertexBlendEnvf := wglGetProcAddress('glVertexBlendEnvf'); - if not Assigned(glVertexBlendEnvf) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_I3D_image_buffer: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_I3D_image_buffer', extstring) then - begin - wglCreateImageBufferI3D := wglGetProcAddress('wglCreateImageBufferI3D'); - if not Assigned(wglCreateImageBufferI3D) then Exit; - wglDestroyImageBufferI3D := wglGetProcAddress('wglDestroyImageBufferI3D'); - if not Assigned(wglDestroyImageBufferI3D) then Exit; - wglAssociateImageBufferEventsI3D := wglGetProcAddress('wglAssociateImageBufferEventsI3D'); - if not Assigned(wglAssociateImageBufferEventsI3D) then Exit; - wglReleaseImageBufferEventsI3D := wglGetProcAddress('wglReleaseImageBufferEventsI3D'); - if not Assigned(wglReleaseImageBufferEventsI3D) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_I3D_swap_frame_lock: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_I3D_swap_frame_lock', extstring) then - begin - wglEnableFrameLockI3D := wglGetProcAddress('wglEnableFrameLockI3D'); - if not Assigned(wglEnableFrameLockI3D) then Exit; - wglDisableFrameLockI3D := wglGetProcAddress('wglDisableFrameLockI3D'); - if not Assigned(wglDisableFrameLockI3D) then Exit; - wglIsEnabledFrameLockI3D := wglGetProcAddress('wglIsEnabledFrameLockI3D'); - if not Assigned(wglIsEnabledFrameLockI3D) then Exit; - wglQueryFrameLockMasterI3D := wglGetProcAddress('wglQueryFrameLockMasterI3D'); - if not Assigned(wglQueryFrameLockMasterI3D) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_I3D_swap_frame_usage: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_I3D_swap_frame_usage', extstring) then - begin - wglGetFrameUsageI3D := wglGetProcAddress('wglGetFrameUsageI3D'); - if not Assigned(wglGetFrameUsageI3D) then Exit; - wglBeginFrameTrackingI3D := wglGetProcAddress('wglBeginFrameTrackingI3D'); - if not Assigned(wglBeginFrameTrackingI3D) then Exit; - wglEndFrameTrackingI3D := wglGetProcAddress('wglEndFrameTrackingI3D'); - if not Assigned(wglEndFrameTrackingI3D) then Exit; - wglQueryFrameTrackingI3D := wglGetProcAddress('wglQueryFrameTrackingI3D'); - if not Assigned(wglQueryFrameTrackingI3D) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_3DFX_texture_compression_FXT1: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_3DFX_texture_compression_FXT1', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_IBM_cull_vertex: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_IBM_cull_vertex', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_IBM_multimode_draw_arrays: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_IBM_multimode_draw_arrays', extstring) then - begin - glMultiModeDrawArraysIBM := wglGetProcAddress('glMultiModeDrawArraysIBM'); - if not Assigned(glMultiModeDrawArraysIBM) then Exit; - glMultiModeDrawElementsIBM := wglGetProcAddress('glMultiModeDrawElementsIBM'); - if not Assigned(glMultiModeDrawElementsIBM) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_IBM_raster_pos_clip: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_IBM_raster_pos_clip', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_IBM_texture_mirrored_repeat: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_IBM_texture_mirrored_repeat', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_IBM_vertex_array_lists: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_IBM_vertex_array_lists', extstring) then - begin - glColorPointerListIBM := wglGetProcAddress('glColorPointerListIBM'); - if not Assigned(glColorPointerListIBM) then Exit; - glSecondaryColorPointerListIBM := wglGetProcAddress('glSecondaryColorPointerListIBM'); - if not Assigned(glSecondaryColorPointerListIBM) then Exit; - glEdgeFlagPointerListIBM := wglGetProcAddress('glEdgeFlagPointerListIBM'); - if not Assigned(glEdgeFlagPointerListIBM) then Exit; - glFogCoordPointerListIBM := wglGetProcAddress('glFogCoordPointerListIBM'); - if not Assigned(glFogCoordPointerListIBM) then Exit; - glNormalPointerListIBM := wglGetProcAddress('glNormalPointerListIBM'); - if not Assigned(glNormalPointerListIBM) then Exit; - glTexCoordPointerListIBM := wglGetProcAddress('glTexCoordPointerListIBM'); - if not Assigned(glTexCoordPointerListIBM) then Exit; - glVertexPointerListIBM := wglGetProcAddress('glVertexPointerListIBM'); - if not Assigned(glVertexPointerListIBM) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_MESA_resize_buffers: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_MESA_resize_buffers', extstring) then - begin - glResizeBuffersMESA := wglGetProcAddress('glResizeBuffersMESA'); - if not Assigned(glResizeBuffersMESA) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_MESA_window_pos: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_MESA_window_pos', extstring) then - begin - glWindowPos2dMESA := wglGetProcAddress('glWindowPos2dMESA'); - if not Assigned(glWindowPos2dMESA) then Exit; - glWindowPos2fMESA := wglGetProcAddress('glWindowPos2fMESA'); - if not Assigned(glWindowPos2fMESA) then Exit; - glWindowPos2iMESA := wglGetProcAddress('glWindowPos2iMESA'); - if not Assigned(glWindowPos2iMESA) then Exit; - glWindowPos2sMESA := wglGetProcAddress('glWindowPos2sMESA'); - if not Assigned(glWindowPos2sMESA) then Exit; - glWindowPos2ivMESA := wglGetProcAddress('glWindowPos2ivMESA'); - if not Assigned(glWindowPos2ivMESA) then Exit; - glWindowPos2svMESA := wglGetProcAddress('glWindowPos2svMESA'); - if not Assigned(glWindowPos2svMESA) then Exit; - glWindowPos2fvMESA := wglGetProcAddress('glWindowPos2fvMESA'); - if not Assigned(glWindowPos2fvMESA) then Exit; - glWindowPos2dvMESA := wglGetProcAddress('glWindowPos2dvMESA'); - if not Assigned(glWindowPos2dvMESA) then Exit; - glWindowPos3iMESA := wglGetProcAddress('glWindowPos3iMESA'); - if not Assigned(glWindowPos3iMESA) then Exit; - glWindowPos3sMESA := wglGetProcAddress('glWindowPos3sMESA'); - if not Assigned(glWindowPos3sMESA) then Exit; - glWindowPos3fMESA := wglGetProcAddress('glWindowPos3fMESA'); - if not Assigned(glWindowPos3fMESA) then Exit; - glWindowPos3dMESA := wglGetProcAddress('glWindowPos3dMESA'); - if not Assigned(glWindowPos3dMESA) then Exit; - glWindowPos3ivMESA := wglGetProcAddress('glWindowPos3ivMESA'); - if not Assigned(glWindowPos3ivMESA) then Exit; - glWindowPos3svMESA := wglGetProcAddress('glWindowPos3svMESA'); - if not Assigned(glWindowPos3svMESA) then Exit; - glWindowPos3fvMESA := wglGetProcAddress('glWindowPos3fvMESA'); - if not Assigned(glWindowPos3fvMESA) then Exit; - glWindowPos3dvMESA := wglGetProcAddress('glWindowPos3dvMESA'); - if not Assigned(glWindowPos3dvMESA) then Exit; - glWindowPos4iMESA := wglGetProcAddress('glWindowPos4iMESA'); - if not Assigned(glWindowPos4iMESA) then Exit; - glWindowPos4sMESA := wglGetProcAddress('glWindowPos4sMESA'); - if not Assigned(glWindowPos4sMESA) then Exit; - glWindowPos4fMESA := wglGetProcAddress('glWindowPos4fMESA'); - if not Assigned(glWindowPos4fMESA) then Exit; - glWindowPos4dMESA := wglGetProcAddress('glWindowPos4dMESA'); - if not Assigned(glWindowPos4dMESA) then Exit; - glWindowPos4ivMESA := wglGetProcAddress('glWindowPos4ivMESA'); - if not Assigned(glWindowPos4ivMESA) then Exit; - glWindowPos4svMESA := wglGetProcAddress('glWindowPos4svMESA'); - if not Assigned(glWindowPos4svMESA) then Exit; - glWindowPos4fvMESA := wglGetProcAddress('glWindowPos4fvMESA'); - if not Assigned(glWindowPos4fvMESA) then Exit; - glWindowPos4dvMESA := wglGetProcAddress('glWindowPos4dvMESA'); - if not Assigned(glWindowPos4dvMESA) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_OML_interlace: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_OML_interlace', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_OML_resample: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_OML_resample', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_OML_subsample: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_OML_subsample', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_generate_mipmap: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_generate_mipmap', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_multisample: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_multisample', extstring) then - begin - glSampleMaskSGIS := wglGetProcAddress('glSampleMaskSGIS'); - if not Assigned(glSampleMaskSGIS) then Exit; - glSamplePatternSGIS := wglGetProcAddress('glSamplePatternSGIS'); - if not Assigned(glSamplePatternSGIS) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_pixel_texture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_pixel_texture', extstring) then - begin - glPixelTexGenParameteriSGIS := wglGetProcAddress('glPixelTexGenParameteriSGIS'); - if not Assigned(glPixelTexGenParameteriSGIS) then Exit; - glPixelTexGenParameterfSGIS := wglGetProcAddress('glPixelTexGenParameterfSGIS'); - if not Assigned(glPixelTexGenParameterfSGIS) then Exit; - glGetPixelTexGenParameterivSGIS := wglGetProcAddress('glGetPixelTexGenParameterivSGIS'); - if not Assigned(glGetPixelTexGenParameterivSGIS) then Exit; - glGetPixelTexGenParameterfvSGIS := wglGetProcAddress('glGetPixelTexGenParameterfvSGIS'); - if not Assigned(glGetPixelTexGenParameterfvSGIS) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_texture_border_clamp: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_texture_border_clamp', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_texture_color_mask: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_texture_color_mask', extstring) then - begin - glTextureColorMaskSGIS := wglGetProcAddress('glTextureColorMaskSGIS'); - if not Assigned(glTextureColorMaskSGIS) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_texture_edge_clamp: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_texture_edge_clamp', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_texture_lod: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_texture_lod', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIS_depth_texture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIS_depth_texture', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIX_fog_offset: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIX_fog_offset', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIX_interlace: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIX_interlace', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGIX_shadow_ambient: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGIX_shadow_ambient', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGI_color_matrix: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGI_color_matrix', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SGI_color_table: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGI_color_table', extstring) then - begin - glColorTableSGI := wglGetProcAddress('glColorTableSGI'); - if not Assigned(glColorTableSGI) then Exit; - glCopyColorTableSGI := wglGetProcAddress('glCopyColorTableSGI'); - if not Assigned(glCopyColorTableSGI) then Exit; - glColorTableParameterivSGI := wglGetProcAddress('glColorTableParameterivSGI'); - if not Assigned(glColorTableParameterivSGI) then Exit; - glColorTableParameterfvSGI := wglGetProcAddress('glColorTableParameterfvSGI'); - if not Assigned(glColorTableParameterfvSGI) then Exit; - glGetColorTableSGI := wglGetProcAddress('glGetColorTableSGI'); - if not Assigned(glGetColorTableSGI) then Exit; - glGetColorTableParameterivSGI := wglGetProcAddress('glGetColorTableParameterivSGI'); - if not Assigned(glGetColorTableParameterivSGI) then Exit; - glGetColorTableParameterfvSGI := wglGetProcAddress('glGetColorTableParameterfvSGI'); - if not Assigned(glGetColorTableParameterfvSGI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_SGI_texture_color_table: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SGI_texture_color_table', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_SUN_vertex: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_SUN_vertex', extstring) then - begin - glColor4ubVertex2fSUN := wglGetProcAddress('glColor4ubVertex2fSUN'); - if not Assigned(glColor4ubVertex2fSUN) then Exit; - glColor4ubVertex2fvSUN := wglGetProcAddress('glColor4ubVertex2fvSUN'); - if not Assigned(glColor4ubVertex2fvSUN) then Exit; - glColor4ubVertex3fSUN := wglGetProcAddress('glColor4ubVertex3fSUN'); - if not Assigned(glColor4ubVertex3fSUN) then Exit; - glColor4ubVertex3fvSUN := wglGetProcAddress('glColor4ubVertex3fvSUN'); - if not Assigned(glColor4ubVertex3fvSUN) then Exit; - glColor3fVertex3fSUN := wglGetProcAddress('glColor3fVertex3fSUN'); - if not Assigned(glColor3fVertex3fSUN) then Exit; - glColor3fVertex3fvSUN := wglGetProcAddress('glColor3fVertex3fvSUN'); - if not Assigned(glColor3fVertex3fvSUN) then Exit; - glNormal3fVertex3fSUN := wglGetProcAddress('glNormal3fVertex3fSUN'); - if not Assigned(glNormal3fVertex3fSUN) then Exit; - glNormal3fVertex3fvSUN := wglGetProcAddress('glNormal3fVertex3fvSUN'); - if not Assigned(glNormal3fVertex3fvSUN) then Exit; - glColor4fNormal3fVertex3fSUN := wglGetProcAddress('glColor4fNormal3fVertex3fSUN'); - if not Assigned(glColor4fNormal3fVertex3fSUN) then Exit; - glColor4fNormal3fVertex3fvSUN := wglGetProcAddress('glColor4fNormal3fVertex3fvSUN'); - if not Assigned(glColor4fNormal3fVertex3fvSUN) then Exit; - glTexCoord2fVertex3fSUN := wglGetProcAddress('glTexCoord2fVertex3fSUN'); - if not Assigned(glTexCoord2fVertex3fSUN) then Exit; - glTexCoord2fVertex3fvSUN := wglGetProcAddress('glTexCoord2fVertex3fvSUN'); - if not Assigned(glTexCoord2fVertex3fvSUN) then Exit; - glTexCoord4fVertex4fSUN := wglGetProcAddress('glTexCoord4fVertex4fSUN'); - if not Assigned(glTexCoord4fVertex4fSUN) then Exit; - glTexCoord4fVertex4fvSUN := wglGetProcAddress('glTexCoord4fVertex4fvSUN'); - if not Assigned(glTexCoord4fVertex4fvSUN) then Exit; - glTexCoord2fColor4ubVertex3fSUN := wglGetProcAddress('glTexCoord2fColor4ubVertex3fSUN'); - if not Assigned(glTexCoord2fColor4ubVertex3fSUN) then Exit; - glTexCoord2fColor4ubVertex3fvSUN := wglGetProcAddress('glTexCoord2fColor4ubVertex3fvSUN'); - if not Assigned(glTexCoord2fColor4ubVertex3fvSUN) then Exit; - glTexCoord2fColor3fVertex3fSUN := wglGetProcAddress('glTexCoord2fColor3fVertex3fSUN'); - if not Assigned(glTexCoord2fColor3fVertex3fSUN) then Exit; - glTexCoord2fColor3fVertex3fvSUN := wglGetProcAddress('glTexCoord2fColor3fVertex3fvSUN'); - if not Assigned(glTexCoord2fColor3fVertex3fvSUN) then Exit; - glTexCoord2fNormal3fVertex3fSUN := wglGetProcAddress('glTexCoord2fNormal3fVertex3fSUN'); - if not Assigned(glTexCoord2fNormal3fVertex3fSUN) then Exit; - glTexCoord2fNormal3fVertex3fvSUN := wglGetProcAddress('glTexCoord2fNormal3fVertex3fvSUN'); - if not Assigned(glTexCoord2fNormal3fVertex3fvSUN) then Exit; - glTexCoord2fColor4fNormal3fVertex3fSUN := wglGetProcAddress('glTexCoord2fColor4fNormal3fVertex3fSUN'); - if not Assigned(glTexCoord2fColor4fNormal3fVertex3fSUN) then Exit; - glTexCoord2fColor4fNormal3fVertex3fvSUN := wglGetProcAddress('glTexCoord2fColor4fNormal3fVertex3fvSUN'); - if not Assigned(glTexCoord2fColor4fNormal3fVertex3fvSUN) then Exit; - glTexCoord4fColor4fNormal3fVertex4fSUN := wglGetProcAddress('glTexCoord4fColor4fNormal3fVertex4fSUN'); - if not Assigned(glTexCoord4fColor4fNormal3fVertex4fSUN) then Exit; - glTexCoord4fColor4fNormal3fVertex4fvSUN := wglGetProcAddress('glTexCoord4fColor4fNormal3fVertex4fvSUN'); - if not Assigned(glTexCoord4fColor4fNormal3fVertex4fvSUN) then Exit; - glReplacementCodeuiVertex3fSUN := wglGetProcAddress('glReplacementCodeuiVertex3fSUN'); - if not Assigned(glReplacementCodeuiVertex3fSUN) then Exit; - glReplacementCodeuiVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiVertex3fvSUN'); - if not Assigned(glReplacementCodeuiVertex3fvSUN) then Exit; - glReplacementCodeuiColor4ubVertex3fSUN := wglGetProcAddress('glReplacementCodeuiColor4ubVertex3fSUN'); - if not Assigned(glReplacementCodeuiColor4ubVertex3fSUN) then Exit; - glReplacementCodeuiColor4ubVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiColor4ubVertex3fvSUN'); - if not Assigned(glReplacementCodeuiColor4ubVertex3fvSUN) then Exit; - glReplacementCodeuiColor3fVertex3fSUN := wglGetProcAddress('glReplacementCodeuiColor3fVertex3fSUN'); - if not Assigned(glReplacementCodeuiColor3fVertex3fSUN) then Exit; - glReplacementCodeuiColor3fVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiColor3fVertex3fvSUN'); - if not Assigned(glReplacementCodeuiColor3fVertex3fvSUN) then Exit; - glReplacementCodeuiNormal3fVertex3fSUN := wglGetProcAddress('glReplacementCodeuiNormal3fVertex3fSUN'); - if not Assigned(glReplacementCodeuiNormal3fVertex3fSUN) then Exit; - glReplacementCodeuiNormal3fVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiNormal3fVertex3fvSUN'); - if not Assigned(glReplacementCodeuiNormal3fVertex3fvSUN) then Exit; - glReplacementCodeuiColor4fNormal3fVertex3fSUN := wglGetProcAddress('glReplacementCodeuiColor4fNormal3fVertex3fSUN'); - if not Assigned(glReplacementCodeuiColor4fNormal3fVertex3fSUN) then Exit; - glReplacementCodeuiColor4fNormal3fVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiColor4fNormal3fVertex3fvSUN'); - if not Assigned(glReplacementCodeuiColor4fNormal3fVertex3fvSUN) then Exit; - glReplacementCodeuiTexCoord2fVertex3fSUN := wglGetProcAddress('glReplacementCodeuiTexCoord2fVertex3fSUN'); - if not Assigned(glReplacementCodeuiTexCoord2fVertex3fSUN) then Exit; - glReplacementCodeuiTexCoord2fVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiTexCoord2fVertex3fvSUN'); - if not Assigned(glReplacementCodeuiTexCoord2fVertex3fvSUN) then Exit; - glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN := wglGetProcAddress('glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN'); - if not Assigned(glReplacementCodeuiTexCoord2fNormal3fVertex3fSUN) then Exit; - glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN'); - if not Assigned(glReplacementCodeuiTexCoord2fNormal3fVertex3fvSUN) then Exit; - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN := wglGetProcAddress('glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN'); - if not Assigned(glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fSUN) then Exit; - glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN := wglGetProcAddress('glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN'); - if not Assigned(glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_fragment_program: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_fragment_program', extstring) then - begin - glProgramStringARB := wglGetProcAddress('glProgramStringARB'); - if not Assigned(glProgramStringARB) then Exit; - glBindProgramARB := wglGetProcAddress('glBindProgramARB'); - if not Assigned(glBindProgramARB) then Exit; - glDeleteProgramsARB := wglGetProcAddress('glDeleteProgramsARB'); - if not Assigned(glDeleteProgramsARB) then Exit; - glGenProgramsARB := wglGetProcAddress('glGenProgramsARB'); - if not Assigned(glGenProgramsARB) then Exit; - glProgramEnvParameter4dARB := wglGetProcAddress('glProgramEnvParameter4dARB'); - if not Assigned(glProgramEnvParameter4dARB) then Exit; - glProgramEnvParameter4dvARB := wglGetProcAddress('glProgramEnvParameter4dvARB'); - if not Assigned(glProgramEnvParameter4dvARB) then Exit; - glProgramEnvParameter4fARB := wglGetProcAddress('glProgramEnvParameter4fARB'); - if not Assigned(glProgramEnvParameter4fARB) then Exit; - glProgramEnvParameter4fvARB := wglGetProcAddress('glProgramEnvParameter4fvARB'); - if not Assigned(glProgramEnvParameter4fvARB) then Exit; - glProgramLocalParameter4dARB := wglGetProcAddress('glProgramLocalParameter4dARB'); - if not Assigned(glProgramLocalParameter4dARB) then Exit; - glProgramLocalParameter4dvARB := wglGetProcAddress('glProgramLocalParameter4dvARB'); - if not Assigned(glProgramLocalParameter4dvARB) then Exit; - glProgramLocalParameter4fARB := wglGetProcAddress('glProgramLocalParameter4fARB'); - if not Assigned(glProgramLocalParameter4fARB) then Exit; - glProgramLocalParameter4fvARB := wglGetProcAddress('glProgramLocalParameter4fvARB'); - if not Assigned(glProgramLocalParameter4fvARB) then Exit; - glGetProgramEnvParameterdvARB := wglGetProcAddress('glGetProgramEnvParameterdvARB'); - if not Assigned(glGetProgramEnvParameterdvARB) then Exit; - glGetProgramEnvParameterfvARB := wglGetProcAddress('glGetProgramEnvParameterfvARB'); - if not Assigned(glGetProgramEnvParameterfvARB) then Exit; - glGetProgramLocalParameterdvARB := wglGetProcAddress('glGetProgramLocalParameterdvARB'); - if not Assigned(glGetProgramLocalParameterdvARB) then Exit; - glGetProgramLocalParameterfvARB := wglGetProcAddress('glGetProgramLocalParameterfvARB'); - if not Assigned(glGetProgramLocalParameterfvARB) then Exit; - glGetProgramivARB := wglGetProcAddress('glGetProgramivARB'); - if not Assigned(glGetProgramivARB) then Exit; - glGetProgramStringARB := wglGetProcAddress('glGetProgramStringARB'); - if not Assigned(glGetProgramStringARB) then Exit; - glIsProgramARB := wglGetProcAddress('glIsProgramARB'); - if not Assigned(glIsProgramARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_text_fragment_shader: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_text_fragment_shader', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_APPLE_client_storage: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_APPLE_client_storage', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_APPLE_element_array: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_APPLE_element_array', extstring) then - begin - glElementPointerAPPLE := wglGetProcAddress('glElementPointerAPPLE'); - if not Assigned(glElementPointerAPPLE) then Exit; - glDrawElementArrayAPPLE := wglGetProcAddress('glDrawElementArrayAPPLE'); - if not Assigned(glDrawElementArrayAPPLE) then Exit; - glDrawRangeElementArrayAPPLE := wglGetProcAddress('glDrawRangeElementArrayAPPLE'); - if not Assigned(glDrawRangeElementArrayAPPLE) then Exit; - glMultiDrawElementArrayAPPLE := wglGetProcAddress('glMultiDrawElementArrayAPPLE'); - if not Assigned(glMultiDrawElementArrayAPPLE) then Exit; - glMultiDrawRangeElementArrayAPPLE := wglGetProcAddress('glMultiDrawRangeElementArrayAPPLE'); - if not Assigned(glMultiDrawRangeElementArrayAPPLE) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_APPLE_fence: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_APPLE_fence', extstring) then - begin - glGenFencesAPPLE := wglGetProcAddress('glGenFencesAPPLE'); - if not Assigned(glGenFencesAPPLE) then Exit; - glDeleteFencesAPPLE := wglGetProcAddress('glDeleteFencesAPPLE'); - if not Assigned(glDeleteFencesAPPLE) then Exit; - glSetFenceAPPLE := wglGetProcAddress('glSetFenceAPPLE'); - if not Assigned(glSetFenceAPPLE) then Exit; - glIsFenceAPPLE := wglGetProcAddress('glIsFenceAPPLE'); - if not Assigned(glIsFenceAPPLE) then Exit; - glTestFenceAPPLE := wglGetProcAddress('glTestFenceAPPLE'); - if not Assigned(glTestFenceAPPLE) then Exit; - glFinishFenceAPPLE := wglGetProcAddress('glFinishFenceAPPLE'); - if not Assigned(glFinishFenceAPPLE) then Exit; - glTestObjectAPPLE := wglGetProcAddress('glTestObjectAPPLE'); - if not Assigned(glTestObjectAPPLE) then Exit; - glFinishObjectAPPLE := wglGetProcAddress('glFinishObjectAPPLE'); - if not Assigned(glFinishObjectAPPLE) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_APPLE_vertex_array_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_APPLE_vertex_array_object', extstring) then - begin - glBindVertexArrayAPPLE := wglGetProcAddress('glBindVertexArrayAPPLE'); - if not Assigned(glBindVertexArrayAPPLE) then Exit; - glDeleteVertexArraysAPPLE := wglGetProcAddress('glDeleteVertexArraysAPPLE'); - if not Assigned(glDeleteVertexArraysAPPLE) then Exit; - glGenVertexArraysAPPLE := wglGetProcAddress('glGenVertexArraysAPPLE'); - if not Assigned(glGenVertexArraysAPPLE) then Exit; - glIsVertexArrayAPPLE := wglGetProcAddress('glIsVertexArrayAPPLE'); - if not Assigned(glIsVertexArrayAPPLE) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_APPLE_vertex_array_range: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_APPLE_vertex_array_range', extstring) then - begin - glVertexArrayRangeAPPLE := wglGetProcAddress('glVertexArrayRangeAPPLE'); - if not Assigned(glVertexArrayRangeAPPLE) then Exit; - glFlushVertexArrayRangeAPPLE := wglGetProcAddress('glFlushVertexArrayRangeAPPLE'); - if not Assigned(glFlushVertexArrayRangeAPPLE) then Exit; - glVertexArrayParameteriAPPLE := wglGetProcAddress('glVertexArrayParameteriAPPLE'); - if not Assigned(glVertexArrayParameteriAPPLE) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_ARB_pixel_format: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_ARB_pixel_format', extstring) then - begin - wglGetPixelFormatAttribivARB := wglGetProcAddress('wglGetPixelFormatAttribivARB'); - if not Assigned(wglGetPixelFormatAttribivARB) then Exit; - wglGetPixelFormatAttribfvARB := wglGetProcAddress('wglGetPixelFormatAttribfvARB'); - if not Assigned(wglGetPixelFormatAttribfvARB) then Exit; - wglChoosePixelFormatARB := wglGetProcAddress('wglChoosePixelFormatARB'); - if not Assigned(wglChoosePixelFormatARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_ARB_make_current_read: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_ARB_make_current_read', extstring) then - begin - wglMakeContextCurrentARB := wglGetProcAddress('wglMakeContextCurrentARB'); - if not Assigned(wglMakeContextCurrentARB) then Exit; - wglGetCurrentReadDCARB := wglGetProcAddress('wglGetCurrentReadDCARB'); - if not Assigned(wglGetCurrentReadDCARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_ARB_pbuffer: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_ARB_pbuffer', extstring) then - begin - wglCreatePbufferARB := wglGetProcAddress('wglCreatePbufferARB'); - if not Assigned(wglCreatePbufferARB) then Exit; - wglGetPbufferDCARB := wglGetProcAddress('wglGetPbufferDCARB'); - if not Assigned(wglGetPbufferDCARB) then Exit; - wglReleasePbufferDCARB := wglGetProcAddress('wglReleasePbufferDCARB'); - if not Assigned(wglReleasePbufferDCARB) then Exit; - wglDestroyPbufferARB := wglGetProcAddress('wglDestroyPbufferARB'); - if not Assigned(wglDestroyPbufferARB) then Exit; - wglQueryPbufferARB := wglGetProcAddress('wglQueryPbufferARB'); - if not Assigned(wglQueryPbufferARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_EXT_swap_control: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_EXT_swap_control', extstring) then - begin - wglSwapIntervalEXT := wglGetProcAddress('wglSwapIntervalEXT'); - if not Assigned(wglSwapIntervalEXT) then Exit; - wglGetSwapIntervalEXT := wglGetProcAddress('wglGetSwapIntervalEXT'); - if not Assigned(wglGetSwapIntervalEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_ARB_render_texture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_ARB_render_texture', extstring) then - begin - wglBindTexImageARB := wglGetProcAddress('wglBindTexImageARB'); - if not Assigned(wglBindTexImageARB) then Exit; - wglReleaseTexImageARB := wglGetProcAddress('wglReleaseTexImageARB'); - if not Assigned(wglReleaseTexImageARB) then Exit; - wglSetPbufferAttribARB := wglGetProcAddress('wglSetPbufferAttribARB'); - if not Assigned(wglSetPbufferAttribARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_EXT_extensions_string: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_EXT_extensions_string', extstring) then - begin - wglGetExtensionsStringEXT := wglGetProcAddress('wglGetExtensionsStringEXT'); - if not Assigned(wglGetExtensionsStringEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_EXT_make_current_read: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_EXT_make_current_read', extstring) then - begin - wglMakeContextCurrentEXT := wglGetProcAddress('wglMakeContextCurrentEXT'); - if not Assigned(wglMakeContextCurrentEXT) then Exit; - wglGetCurrentReadDCEXT := wglGetProcAddress('wglGetCurrentReadDCEXT'); - if not Assigned(wglGetCurrentReadDCEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_EXT_pbuffer: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_EXT_pbuffer', extstring) then - begin - wglCreatePbufferEXT := wglGetProcAddress('wglCreatePbufferEXT'); - if not Assigned(wglCreatePbufferEXT) then Exit; - wglGetPbufferDCEXT := wglGetProcAddress('wglGetPbufferDCEXT'); - if not Assigned(wglGetPbufferDCEXT) then Exit; - wglReleasePbufferDCEXT := wglGetProcAddress('wglReleasePbufferDCEXT'); - if not Assigned(wglReleasePbufferDCEXT) then Exit; - wglDestroyPbufferEXT := wglGetProcAddress('wglDestroyPbufferEXT'); - if not Assigned(wglDestroyPbufferEXT) then Exit; - wglQueryPbufferEXT := wglGetProcAddress('wglQueryPbufferEXT'); - if not Assigned(wglQueryPbufferEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_EXT_pixel_format: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_EXT_pixel_format', extstring) then - begin - wglGetPixelFormatAttribivEXT := wglGetProcAddress('wglGetPixelFormatAttribivEXT'); - if not Assigned(wglGetPixelFormatAttribivEXT) then Exit; - wglGetPixelFormatAttribfvEXT := wglGetProcAddress('wglGetPixelFormatAttribfvEXT'); - if not Assigned(wglGetPixelFormatAttribfvEXT) then Exit; - wglChoosePixelFormatEXT := wglGetProcAddress('wglChoosePixelFormatEXT'); - if not Assigned(wglChoosePixelFormatEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_I3D_digital_video_control: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_I3D_digital_video_control', extstring) then - begin - wglGetDigitalVideoParametersI3D := wglGetProcAddress('wglGetDigitalVideoParametersI3D'); - if not Assigned(wglGetDigitalVideoParametersI3D) then Exit; - wglSetDigitalVideoParametersI3D := wglGetProcAddress('wglSetDigitalVideoParametersI3D'); - if not Assigned(wglSetDigitalVideoParametersI3D) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_I3D_gamma: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_I3D_gamma', extstring) then - begin - wglGetGammaTableParametersI3D := wglGetProcAddress('wglGetGammaTableParametersI3D'); - if not Assigned(wglGetGammaTableParametersI3D) then Exit; - wglSetGammaTableParametersI3D := wglGetProcAddress('wglSetGammaTableParametersI3D'); - if not Assigned(wglSetGammaTableParametersI3D) then Exit; - wglGetGammaTableI3D := wglGetProcAddress('wglGetGammaTableI3D'); - if not Assigned(wglGetGammaTableI3D) then Exit; - wglSetGammaTableI3D := wglGetProcAddress('wglSetGammaTableI3D'); - if not Assigned(wglSetGammaTableI3D) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_I3D_genlock: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_I3D_genlock', extstring) then - begin - wglEnableGenlockI3D := wglGetProcAddress('wglEnableGenlockI3D'); - if not Assigned(wglEnableGenlockI3D) then Exit; - wglDisableGenlockI3D := wglGetProcAddress('wglDisableGenlockI3D'); - if not Assigned(wglDisableGenlockI3D) then Exit; - wglIsEnabledGenlockI3D := wglGetProcAddress('wglIsEnabledGenlockI3D'); - if not Assigned(wglIsEnabledGenlockI3D) then Exit; - wglGenlockSourceI3D := wglGetProcAddress('wglGenlockSourceI3D'); - if not Assigned(wglGenlockSourceI3D) then Exit; - wglGetGenlockSourceI3D := wglGetProcAddress('wglGetGenlockSourceI3D'); - if not Assigned(wglGetGenlockSourceI3D) then Exit; - wglGenlockSourceEdgeI3D := wglGetProcAddress('wglGenlockSourceEdgeI3D'); - if not Assigned(wglGenlockSourceEdgeI3D) then Exit; - wglGetGenlockSourceEdgeI3D := wglGetProcAddress('wglGetGenlockSourceEdgeI3D'); - if not Assigned(wglGetGenlockSourceEdgeI3D) then Exit; - wglGenlockSampleRateI3D := wglGetProcAddress('wglGenlockSampleRateI3D'); - if not Assigned(wglGenlockSampleRateI3D) then Exit; - wglGetGenlockSampleRateI3D := wglGetProcAddress('wglGetGenlockSampleRateI3D'); - if not Assigned(wglGetGenlockSampleRateI3D) then Exit; - wglGenlockSourceDelayI3D := wglGetProcAddress('wglGenlockSourceDelayI3D'); - if not Assigned(wglGenlockSourceDelayI3D) then Exit; - wglGetGenlockSourceDelayI3D := wglGetProcAddress('wglGetGenlockSourceDelayI3D'); - if not Assigned(wglGetGenlockSourceDelayI3D) then Exit; - wglQueryGenlockMaxSourceDelayI3D := wglGetProcAddress('wglQueryGenlockMaxSourceDelayI3D'); - if not Assigned(wglQueryGenlockMaxSourceDelayI3D) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_matrix_palette: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_matrix_palette', extstring) then - begin - glCurrentPaletteMatrixARB := wglGetProcAddress('glCurrentPaletteMatrixARB'); - if not Assigned(glCurrentPaletteMatrixARB) then Exit; - glMatrixIndexubvARB := wglGetProcAddress('glMatrixIndexubvARB'); - if not Assigned(glMatrixIndexubvARB) then Exit; - glMatrixIndexusvARB := wglGetProcAddress('glMatrixIndexusvARB'); - if not Assigned(glMatrixIndexusvARB) then Exit; - glMatrixIndexuivARB := wglGetProcAddress('glMatrixIndexuivARB'); - if not Assigned(glMatrixIndexuivARB) then Exit; - glMatrixIndexPointerARB := wglGetProcAddress('glMatrixIndexPointerARB'); - if not Assigned(glMatrixIndexPointerARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_element_array: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_element_array', extstring) then - begin - glElementPointerNV := wglGetProcAddress('glElementPointerNV'); - if not Assigned(glElementPointerNV) then Exit; - glDrawElementArrayNV := wglGetProcAddress('glDrawElementArrayNV'); - if not Assigned(glDrawElementArrayNV) then Exit; - glDrawRangeElementArrayNV := wglGetProcAddress('glDrawRangeElementArrayNV'); - if not Assigned(glDrawRangeElementArrayNV) then Exit; - glMultiDrawElementArrayNV := wglGetProcAddress('glMultiDrawElementArrayNV'); - if not Assigned(glMultiDrawElementArrayNV) then Exit; - glMultiDrawRangeElementArrayNV := wglGetProcAddress('glMultiDrawRangeElementArrayNV'); - if not Assigned(glMultiDrawRangeElementArrayNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_float_buffer: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_float_buffer', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_fragment_program: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_fragment_program', extstring) then - begin - glProgramNamedParameter4fNV := wglGetProcAddress('glProgramNamedParameter4fNV'); - if not Assigned(glProgramNamedParameter4fNV) then Exit; - glProgramNamedParameter4dNV := wglGetProcAddress('glProgramNamedParameter4dNV'); - if not Assigned(glProgramNamedParameter4dNV) then Exit; - glGetProgramNamedParameterfvNV := wglGetProcAddress('glGetProgramNamedParameterfvNV'); - if not Assigned(glGetProgramNamedParameterfvNV) then Exit; - glGetProgramNamedParameterdvNV := wglGetProcAddress('glGetProgramNamedParameterdvNV'); - if not Assigned(glGetProgramNamedParameterdvNV) then Exit; - glProgramLocalParameter4dARB := wglGetProcAddress('glProgramLocalParameter4dARB'); - if not Assigned(glProgramLocalParameter4dARB) then Exit; - glProgramLocalParameter4dvARB := wglGetProcAddress('glProgramLocalParameter4dvARB'); - if not Assigned(glProgramLocalParameter4dvARB) then Exit; - glProgramLocalParameter4fARB := wglGetProcAddress('glProgramLocalParameter4fARB'); - if not Assigned(glProgramLocalParameter4fARB) then Exit; - glProgramLocalParameter4fvARB := wglGetProcAddress('glProgramLocalParameter4fvARB'); - if not Assigned(glProgramLocalParameter4fvARB) then Exit; - glGetProgramLocalParameterdvARB := wglGetProcAddress('glGetProgramLocalParameterdvARB'); - if not Assigned(glGetProgramLocalParameterdvARB) then Exit; - glGetProgramLocalParameterfvARB := wglGetProcAddress('glGetProgramLocalParameterfvARB'); - if not Assigned(glGetProgramLocalParameterfvARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_primitive_restart: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_primitive_restart', extstring) then - begin - glPrimitiveRestartNV := wglGetProcAddress('glPrimitiveRestartNV'); - if not Assigned(glPrimitiveRestartNV) then Exit; - glPrimitiveRestartIndexNV := wglGetProcAddress('glPrimitiveRestartIndexNV'); - if not Assigned(glPrimitiveRestartIndexNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_vertex_program2: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_vertex_program2', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_WGL_NV_render_texture_rectangle: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_NV_render_texture_rectangle', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_pixel_data_range: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_pixel_data_range', extstring) then - begin - glPixelDataRangeNV := wglGetProcAddress('glPixelDataRangeNV'); - if not Assigned(glPixelDataRangeNV) then Exit; - glFlushPixelDataRangeNV := wglGetProcAddress('glFlushPixelDataRangeNV'); - if not Assigned(glFlushPixelDataRangeNV) then Exit; - wglAllocateMemoryNV := wglGetProcAddress('wglAllocateMemoryNV'); - if not Assigned(wglAllocateMemoryNV) then Exit; - wglFreeMemoryNV := wglGetProcAddress('wglFreeMemoryNV'); - if not Assigned(wglFreeMemoryNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_rectangle: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_rectangle', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_S3_s3tc: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_S3_s3tc', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ATI_draw_buffers: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_draw_buffers', extstring) then - begin - glDrawBuffersATI := wglGetProcAddress('glDrawBuffersATI'); - if not Assigned(glDrawBuffersATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_WGL_ATI_pixel_format_float: Boolean; -var - extstring: String; -begin - - Result := FALSE; - wglGetExtensionsStringARB := wglGetProcAddress('wglGetExtensionsStringARB'); - if not Assigned(wglGetExtensionsStringARB) then Exit; - extstring := String(PChar(wglGetExtensionsStringARB(wglGetCurrentDC))); - - if glext_ExtensionSupported('WGL_ATI_pixel_format_float', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ATI_texture_env_combine3: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_texture_env_combine3', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ATI_texture_float: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_texture_float', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_texture_expand_normal: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_texture_expand_normal', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_half_float: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_half_float', extstring) then - begin - glVertex2hNV := wglGetProcAddress('glVertex2hNV'); - if not Assigned(glVertex2hNV) then Exit; - glVertex2hvNV := wglGetProcAddress('glVertex2hvNV'); - if not Assigned(glVertex2hvNV) then Exit; - glVertex3hNV := wglGetProcAddress('glVertex3hNV'); - if not Assigned(glVertex3hNV) then Exit; - glVertex3hvNV := wglGetProcAddress('glVertex3hvNV'); - if not Assigned(glVertex3hvNV) then Exit; - glVertex4hNV := wglGetProcAddress('glVertex4hNV'); - if not Assigned(glVertex4hNV) then Exit; - glVertex4hvNV := wglGetProcAddress('glVertex4hvNV'); - if not Assigned(glVertex4hvNV) then Exit; - glNormal3hNV := wglGetProcAddress('glNormal3hNV'); - if not Assigned(glNormal3hNV) then Exit; - glNormal3hvNV := wglGetProcAddress('glNormal3hvNV'); - if not Assigned(glNormal3hvNV) then Exit; - glColor3hNV := wglGetProcAddress('glColor3hNV'); - if not Assigned(glColor3hNV) then Exit; - glColor3hvNV := wglGetProcAddress('glColor3hvNV'); - if not Assigned(glColor3hvNV) then Exit; - glColor4hNV := wglGetProcAddress('glColor4hNV'); - if not Assigned(glColor4hNV) then Exit; - glColor4hvNV := wglGetProcAddress('glColor4hvNV'); - if not Assigned(glColor4hvNV) then Exit; - glTexCoord1hNV := wglGetProcAddress('glTexCoord1hNV'); - if not Assigned(glTexCoord1hNV) then Exit; - glTexCoord1hvNV := wglGetProcAddress('glTexCoord1hvNV'); - if not Assigned(glTexCoord1hvNV) then Exit; - glTexCoord2hNV := wglGetProcAddress('glTexCoord2hNV'); - if not Assigned(glTexCoord2hNV) then Exit; - glTexCoord2hvNV := wglGetProcAddress('glTexCoord2hvNV'); - if not Assigned(glTexCoord2hvNV) then Exit; - glTexCoord3hNV := wglGetProcAddress('glTexCoord3hNV'); - if not Assigned(glTexCoord3hNV) then Exit; - glTexCoord3hvNV := wglGetProcAddress('glTexCoord3hvNV'); - if not Assigned(glTexCoord3hvNV) then Exit; - glTexCoord4hNV := wglGetProcAddress('glTexCoord4hNV'); - if not Assigned(glTexCoord4hNV) then Exit; - glTexCoord4hvNV := wglGetProcAddress('glTexCoord4hvNV'); - if not Assigned(glTexCoord4hvNV) then Exit; - glMultiTexCoord1hNV := wglGetProcAddress('glMultiTexCoord1hNV'); - if not Assigned(glMultiTexCoord1hNV) then Exit; - glMultiTexCoord1hvNV := wglGetProcAddress('glMultiTexCoord1hvNV'); - if not Assigned(glMultiTexCoord1hvNV) then Exit; - glMultiTexCoord2hNV := wglGetProcAddress('glMultiTexCoord2hNV'); - if not Assigned(glMultiTexCoord2hNV) then Exit; - glMultiTexCoord2hvNV := wglGetProcAddress('glMultiTexCoord2hvNV'); - if not Assigned(glMultiTexCoord2hvNV) then Exit; - glMultiTexCoord3hNV := wglGetProcAddress('glMultiTexCoord3hNV'); - if not Assigned(glMultiTexCoord3hNV) then Exit; - glMultiTexCoord3hvNV := wglGetProcAddress('glMultiTexCoord3hvNV'); - if not Assigned(glMultiTexCoord3hvNV) then Exit; - glMultiTexCoord4hNV := wglGetProcAddress('glMultiTexCoord4hNV'); - if not Assigned(glMultiTexCoord4hNV) then Exit; - glMultiTexCoord4hvNV := wglGetProcAddress('glMultiTexCoord4hvNV'); - if not Assigned(glMultiTexCoord4hvNV) then Exit; - glFogCoordhNV := wglGetProcAddress('glFogCoordhNV'); - if not Assigned(glFogCoordhNV) then Exit; - glFogCoordhvNV := wglGetProcAddress('glFogCoordhvNV'); - if not Assigned(glFogCoordhvNV) then Exit; - glSecondaryColor3hNV := wglGetProcAddress('glSecondaryColor3hNV'); - if not Assigned(glSecondaryColor3hNV) then Exit; - glSecondaryColor3hvNV := wglGetProcAddress('glSecondaryColor3hvNV'); - if not Assigned(glSecondaryColor3hvNV) then Exit; - glVertexWeighthNV := wglGetProcAddress('glVertexWeighthNV'); - if not Assigned(glVertexWeighthNV) then Exit; - glVertexWeighthvNV := wglGetProcAddress('glVertexWeighthvNV'); - if not Assigned(glVertexWeighthvNV) then Exit; - glVertexAttrib1hNV := wglGetProcAddress('glVertexAttrib1hNV'); - if not Assigned(glVertexAttrib1hNV) then Exit; - glVertexAttrib1hvNV := wglGetProcAddress('glVertexAttrib1hvNV'); - if not Assigned(glVertexAttrib1hvNV) then Exit; - glVertexAttrib2hNV := wglGetProcAddress('glVertexAttrib2hNV'); - if not Assigned(glVertexAttrib2hNV) then Exit; - glVertexAttrib2hvNV := wglGetProcAddress('glVertexAttrib2hvNV'); - if not Assigned(glVertexAttrib2hvNV) then Exit; - glVertexAttrib3hNV := wglGetProcAddress('glVertexAttrib3hNV'); - if not Assigned(glVertexAttrib3hNV) then Exit; - glVertexAttrib3hvNV := wglGetProcAddress('glVertexAttrib3hvNV'); - if not Assigned(glVertexAttrib3hvNV) then Exit; - glVertexAttrib4hNV := wglGetProcAddress('glVertexAttrib4hNV'); - if not Assigned(glVertexAttrib4hNV) then Exit; - glVertexAttrib4hvNV := wglGetProcAddress('glVertexAttrib4hvNV'); - if not Assigned(glVertexAttrib4hvNV) then Exit; - glVertexAttribs1hvNV := wglGetProcAddress('glVertexAttribs1hvNV'); - if not Assigned(glVertexAttribs1hvNV) then Exit; - glVertexAttribs2hvNV := wglGetProcAddress('glVertexAttribs2hvNV'); - if not Assigned(glVertexAttribs2hvNV) then Exit; - glVertexAttribs3hvNV := wglGetProcAddress('glVertexAttribs3hvNV'); - if not Assigned(glVertexAttribs3hvNV) then Exit; - glVertexAttribs4hvNV := wglGetProcAddress('glVertexAttribs4hvNV'); - if not Assigned(glVertexAttribs4hvNV) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_map_object_buffer: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_map_object_buffer', extstring) then - begin - glMapObjectBufferATI := wglGetProcAddress('glMapObjectBufferATI'); - if not Assigned(glMapObjectBufferATI) then Exit; - glUnmapObjectBufferATI := wglGetProcAddress('glUnmapObjectBufferATI'); - if not Assigned(glUnmapObjectBufferATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_separate_stencil: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_separate_stencil', extstring) then - begin - glStencilOpSeparateATI := wglGetProcAddress('glStencilOpSeparateATI'); - if not Assigned(glStencilOpSeparateATI) then Exit; - glStencilFuncSeparateATI := wglGetProcAddress('glStencilFuncSeparateATI'); - if not Assigned(glStencilFuncSeparateATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ATI_vertex_attrib_array_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ATI_vertex_attrib_array_object', extstring) then - begin - glVertexAttribArrayObjectATI := wglGetProcAddress('glVertexAttribArrayObjectATI'); - if not Assigned(glVertexAttribArrayObjectATI) then Exit; - glGetVertexAttribArrayObjectfvATI := wglGetProcAddress('glGetVertexAttribArrayObjectfvATI'); - if not Assigned(glGetVertexAttribArrayObjectfvATI) then Exit; - glGetVertexAttribArrayObjectivATI := wglGetProcAddress('glGetVertexAttribArrayObjectivATI'); - if not Assigned(glGetVertexAttribArrayObjectivATI) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_vertex_buffer_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_vertex_buffer_object', extstring) then - begin - glBindBufferARB := wglGetProcAddress('glBindBufferARB'); - if not Assigned(glBindBufferARB) then Exit; - glDeleteBuffersARB := wglGetProcAddress('glDeleteBuffersARB'); - if not Assigned(glDeleteBuffersARB) then Exit; - glGenBuffersARB := wglGetProcAddress('glGenBuffersARB'); - if not Assigned(glGenBuffersARB) then Exit; - glIsBufferARB := wglGetProcAddress('glIsBufferARB'); - if not Assigned(glIsBufferARB) then Exit; - glBufferDataARB := wglGetProcAddress('glBufferDataARB'); - if not Assigned(glBufferDataARB) then Exit; - glBufferSubDataARB := wglGetProcAddress('glBufferSubDataARB'); - if not Assigned(glBufferSubDataARB) then Exit; - glGetBufferSubDataARB := wglGetProcAddress('glGetBufferSubDataARB'); - if not Assigned(glGetBufferSubDataARB) then Exit; - glMapBufferARB := wglGetProcAddress('glMapBufferARB'); - if not Assigned(glMapBufferARB) then Exit; - glUnmapBufferARB := wglGetProcAddress('glUnmapBufferARB'); - if not Assigned(glUnmapBufferARB) then Exit; - glGetBufferParameterivARB := wglGetProcAddress('glGetBufferParameterivARB'); - if not Assigned(glGetBufferParameterivARB) then Exit; - glGetBufferPointervARB := wglGetProcAddress('glGetBufferPointervARB'); - if not Assigned(glGetBufferPointervARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_occlusion_query: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_occlusion_query', extstring) then - begin - glGenQueriesARB := wglGetProcAddress('glGenQueriesARB'); - if not Assigned(glGenQueriesARB) then Exit; - glDeleteQueriesARB := wglGetProcAddress('glDeleteQueriesARB'); - if not Assigned(glDeleteQueriesARB) then Exit; - glIsQueryARB := wglGetProcAddress('glIsQueryARB'); - if not Assigned(glIsQueryARB) then Exit; - glBeginQueryARB := wglGetProcAddress('glBeginQueryARB'); - if not Assigned(glBeginQueryARB) then Exit; - glEndQueryARB := wglGetProcAddress('glEndQueryARB'); - if not Assigned(glEndQueryARB) then Exit; - glGetQueryivARB := wglGetProcAddress('glGetQueryivARB'); - if not Assigned(glGetQueryivARB) then Exit; - glGetQueryObjectivARB := wglGetProcAddress('glGetQueryObjectivARB'); - if not Assigned(glGetQueryObjectivARB) then Exit; - glGetQueryObjectuivARB := wglGetProcAddress('glGetQueryObjectuivARB'); - if not Assigned(glGetQueryObjectuivARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_shader_objects: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_shader_objects', extstring) then - begin - glDeleteObjectARB := wglGetProcAddress('glDeleteObjectARB'); - if not Assigned(glDeleteObjectARB) then Exit; - glGetHandleARB := wglGetProcAddress('glGetHandleARB'); - if not Assigned(glGetHandleARB) then Exit; - glDetachObjectARB := wglGetProcAddress('glDetachObjectARB'); - if not Assigned(glDetachObjectARB) then Exit; - glCreateShaderObjectARB := wglGetProcAddress('glCreateShaderObjectARB'); - if not Assigned(glCreateShaderObjectARB) then Exit; - glShaderSourceARB := wglGetProcAddress('glShaderSourceARB'); - if not Assigned(glShaderSourceARB) then Exit; - glCompileShaderARB := wglGetProcAddress('glCompileShaderARB'); - if not Assigned(glCompileShaderARB) then Exit; - glCreateProgramObjectARB := wglGetProcAddress('glCreateProgramObjectARB'); - if not Assigned(glCreateProgramObjectARB) then Exit; - glAttachObjectARB := wglGetProcAddress('glAttachObjectARB'); - if not Assigned(glAttachObjectARB) then Exit; - glLinkProgramARB := wglGetProcAddress('glLinkProgramARB'); - if not Assigned(glLinkProgramARB) then Exit; - glUseProgramObjectARB := wglGetProcAddress('glUseProgramObjectARB'); - if not Assigned(glUseProgramObjectARB) then Exit; - glValidateProgramARB := wglGetProcAddress('glValidateProgramARB'); - if not Assigned(glValidateProgramARB) then Exit; - glUniform1fARB := wglGetProcAddress('glUniform1fARB'); - if not Assigned(glUniform1fARB) then Exit; - glUniform2fARB := wglGetProcAddress('glUniform2fARB'); - if not Assigned(glUniform2fARB) then Exit; - glUniform3fARB := wglGetProcAddress('glUniform3fARB'); - if not Assigned(glUniform3fARB) then Exit; - glUniform4fARB := wglGetProcAddress('glUniform4fARB'); - if not Assigned(glUniform4fARB) then Exit; - glUniform1iARB := wglGetProcAddress('glUniform1iARB'); - if not Assigned(glUniform1iARB) then Exit; - glUniform2iARB := wglGetProcAddress('glUniform2iARB'); - if not Assigned(glUniform2iARB) then Exit; - glUniform3iARB := wglGetProcAddress('glUniform3iARB'); - if not Assigned(glUniform3iARB) then Exit; - glUniform4iARB := wglGetProcAddress('glUniform4iARB'); - if not Assigned(glUniform4iARB) then Exit; - glUniform1fvARB := wglGetProcAddress('glUniform1fvARB'); - if not Assigned(glUniform1fvARB) then Exit; - glUniform2fvARB := wglGetProcAddress('glUniform2fvARB'); - if not Assigned(glUniform2fvARB) then Exit; - glUniform3fvARB := wglGetProcAddress('glUniform3fvARB'); - if not Assigned(glUniform3fvARB) then Exit; - glUniform4fvARB := wglGetProcAddress('glUniform4fvARB'); - if not Assigned(glUniform4fvARB) then Exit; - glUniform1ivARB := wglGetProcAddress('glUniform1ivARB'); - if not Assigned(glUniform1ivARB) then Exit; - glUniform2ivARB := wglGetProcAddress('glUniform2ivARB'); - if not Assigned(glUniform2ivARB) then Exit; - glUniform3ivARB := wglGetProcAddress('glUniform3ivARB'); - if not Assigned(glUniform3ivARB) then Exit; - glUniform4ivARB := wglGetProcAddress('glUniform4ivARB'); - if not Assigned(glUniform4ivARB) then Exit; - glUniformMatrix2fvARB := wglGetProcAddress('glUniformMatrix2fvARB'); - if not Assigned(glUniformMatrix2fvARB) then Exit; - glUniformMatrix3fvARB := wglGetProcAddress('glUniformMatrix3fvARB'); - if not Assigned(glUniformMatrix3fvARB) then Exit; - glUniformMatrix4fvARB := wglGetProcAddress('glUniformMatrix4fvARB'); - if not Assigned(glUniformMatrix4fvARB) then Exit; - glGetObjectParameterfvARB := wglGetProcAddress('glGetObjectParameterfvARB'); - if not Assigned(glGetObjectParameterfvARB) then Exit; - glGetObjectParameterivARB := wglGetProcAddress('glGetObjectParameterivARB'); - if not Assigned(glGetObjectParameterivARB) then Exit; - glGetInfoLogARB := wglGetProcAddress('glGetInfoLogARB'); - if not Assigned(glGetInfoLogARB) then Exit; - glGetAttachedObjectsARB := wglGetProcAddress('glGetAttachedObjectsARB'); - if not Assigned(glGetAttachedObjectsARB) then Exit; - glGetUniformLocationARB := wglGetProcAddress('glGetUniformLocationARB'); - if not Assigned(glGetUniformLocationARB) then Exit; - glGetActiveUniformARB := wglGetProcAddress('glGetActiveUniformARB'); - if not Assigned(glGetActiveUniformARB) then Exit; - glGetUniformfvARB := wglGetProcAddress('glGetUniformfvARB'); - if not Assigned(glGetUniformfvARB) then Exit; - glGetUniformivARB := wglGetProcAddress('glGetUniformivARB'); - if not Assigned(glGetUniformivARB) then Exit; - glGetShaderSourceARB := wglGetProcAddress('glGetShaderSourceARB'); - if not Assigned(glGetShaderSourceARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_vertex_shader: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_vertex_shader', extstring) then - begin - glVertexAttrib1fARB := wglGetProcAddress('glVertexAttrib1fARB'); - if not Assigned(glVertexAttrib1fARB) then Exit; - glVertexAttrib1sARB := wglGetProcAddress('glVertexAttrib1sARB'); - if not Assigned(glVertexAttrib1sARB) then Exit; - glVertexAttrib1dARB := wglGetProcAddress('glVertexAttrib1dARB'); - if not Assigned(glVertexAttrib1dARB) then Exit; - glVertexAttrib2fARB := wglGetProcAddress('glVertexAttrib2fARB'); - if not Assigned(glVertexAttrib2fARB) then Exit; - glVertexAttrib2sARB := wglGetProcAddress('glVertexAttrib2sARB'); - if not Assigned(glVertexAttrib2sARB) then Exit; - glVertexAttrib2dARB := wglGetProcAddress('glVertexAttrib2dARB'); - if not Assigned(glVertexAttrib2dARB) then Exit; - glVertexAttrib3fARB := wglGetProcAddress('glVertexAttrib3fARB'); - if not Assigned(glVertexAttrib3fARB) then Exit; - glVertexAttrib3sARB := wglGetProcAddress('glVertexAttrib3sARB'); - if not Assigned(glVertexAttrib3sARB) then Exit; - glVertexAttrib3dARB := wglGetProcAddress('glVertexAttrib3dARB'); - if not Assigned(glVertexAttrib3dARB) then Exit; - glVertexAttrib4fARB := wglGetProcAddress('glVertexAttrib4fARB'); - if not Assigned(glVertexAttrib4fARB) then Exit; - glVertexAttrib4sARB := wglGetProcAddress('glVertexAttrib4sARB'); - if not Assigned(glVertexAttrib4sARB) then Exit; - glVertexAttrib4dARB := wglGetProcAddress('glVertexAttrib4dARB'); - if not Assigned(glVertexAttrib4dARB) then Exit; - glVertexAttrib4NubARB := wglGetProcAddress('glVertexAttrib4NubARB'); - if not Assigned(glVertexAttrib4NubARB) then Exit; - glVertexAttrib1fvARB := wglGetProcAddress('glVertexAttrib1fvARB'); - if not Assigned(glVertexAttrib1fvARB) then Exit; - glVertexAttrib1svARB := wglGetProcAddress('glVertexAttrib1svARB'); - if not Assigned(glVertexAttrib1svARB) then Exit; - glVertexAttrib1dvARB := wglGetProcAddress('glVertexAttrib1dvARB'); - if not Assigned(glVertexAttrib1dvARB) then Exit; - glVertexAttrib2fvARB := wglGetProcAddress('glVertexAttrib2fvARB'); - if not Assigned(glVertexAttrib2fvARB) then Exit; - glVertexAttrib2svARB := wglGetProcAddress('glVertexAttrib2svARB'); - if not Assigned(glVertexAttrib2svARB) then Exit; - glVertexAttrib2dvARB := wglGetProcAddress('glVertexAttrib2dvARB'); - if not Assigned(glVertexAttrib2dvARB) then Exit; - glVertexAttrib3fvARB := wglGetProcAddress('glVertexAttrib3fvARB'); - if not Assigned(glVertexAttrib3fvARB) then Exit; - glVertexAttrib3svARB := wglGetProcAddress('glVertexAttrib3svARB'); - if not Assigned(glVertexAttrib3svARB) then Exit; - glVertexAttrib3dvARB := wglGetProcAddress('glVertexAttrib3dvARB'); - if not Assigned(glVertexAttrib3dvARB) then Exit; - glVertexAttrib4fvARB := wglGetProcAddress('glVertexAttrib4fvARB'); - if not Assigned(glVertexAttrib4fvARB) then Exit; - glVertexAttrib4svARB := wglGetProcAddress('glVertexAttrib4svARB'); - if not Assigned(glVertexAttrib4svARB) then Exit; - glVertexAttrib4dvARB := wglGetProcAddress('glVertexAttrib4dvARB'); - if not Assigned(glVertexAttrib4dvARB) then Exit; - glVertexAttrib4ivARB := wglGetProcAddress('glVertexAttrib4ivARB'); - if not Assigned(glVertexAttrib4ivARB) then Exit; - glVertexAttrib4bvARB := wglGetProcAddress('glVertexAttrib4bvARB'); - if not Assigned(glVertexAttrib4bvARB) then Exit; - glVertexAttrib4ubvARB := wglGetProcAddress('glVertexAttrib4ubvARB'); - if not Assigned(glVertexAttrib4ubvARB) then Exit; - glVertexAttrib4usvARB := wglGetProcAddress('glVertexAttrib4usvARB'); - if not Assigned(glVertexAttrib4usvARB) then Exit; - glVertexAttrib4uivARB := wglGetProcAddress('glVertexAttrib4uivARB'); - if not Assigned(glVertexAttrib4uivARB) then Exit; - glVertexAttrib4NbvARB := wglGetProcAddress('glVertexAttrib4NbvARB'); - if not Assigned(glVertexAttrib4NbvARB) then Exit; - glVertexAttrib4NsvARB := wglGetProcAddress('glVertexAttrib4NsvARB'); - if not Assigned(glVertexAttrib4NsvARB) then Exit; - glVertexAttrib4NivARB := wglGetProcAddress('glVertexAttrib4NivARB'); - if not Assigned(glVertexAttrib4NivARB) then Exit; - glVertexAttrib4NubvARB := wglGetProcAddress('glVertexAttrib4NubvARB'); - if not Assigned(glVertexAttrib4NubvARB) then Exit; - glVertexAttrib4NusvARB := wglGetProcAddress('glVertexAttrib4NusvARB'); - if not Assigned(glVertexAttrib4NusvARB) then Exit; - glVertexAttrib4NuivARB := wglGetProcAddress('glVertexAttrib4NuivARB'); - if not Assigned(glVertexAttrib4NuivARB) then Exit; - glVertexAttribPointerARB := wglGetProcAddress('glVertexAttribPointerARB'); - if not Assigned(glVertexAttribPointerARB) then Exit; - glEnableVertexAttribArrayARB := wglGetProcAddress('glEnableVertexAttribArrayARB'); - if not Assigned(glEnableVertexAttribArrayARB) then Exit; - glDisableVertexAttribArrayARB := wglGetProcAddress('glDisableVertexAttribArrayARB'); - if not Assigned(glDisableVertexAttribArrayARB) then Exit; - glBindAttribLocationARB := wglGetProcAddress('glBindAttribLocationARB'); - if not Assigned(glBindAttribLocationARB) then Exit; - glGetActiveAttribARB := wglGetProcAddress('glGetActiveAttribARB'); - if not Assigned(glGetActiveAttribARB) then Exit; - glGetAttribLocationARB := wglGetProcAddress('glGetAttribLocationARB'); - if not Assigned(glGetAttribLocationARB) then Exit; - glGetVertexAttribdvARB := wglGetProcAddress('glGetVertexAttribdvARB'); - if not Assigned(glGetVertexAttribdvARB) then Exit; - glGetVertexAttribfvARB := wglGetProcAddress('glGetVertexAttribfvARB'); - if not Assigned(glGetVertexAttribfvARB) then Exit; - glGetVertexAttribivARB := wglGetProcAddress('glGetVertexAttribivARB'); - if not Assigned(glGetVertexAttribivARB) then Exit; - glGetVertexAttribPointervARB := wglGetProcAddress('glGetVertexAttribPointervARB'); - if not Assigned(glGetVertexAttribPointervARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_fragment_shader: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_fragment_shader', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_shading_language_100: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_shading_language_100', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_non_power_of_two: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_non_power_of_two', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_point_sprite: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_point_sprite', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_depth_bounds_test: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_depth_bounds_test', extstring) then - begin - glDepthBoundsEXT := wglGetProcAddress('glDepthBoundsEXT'); - if not Assigned(glDepthBoundsEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_secondary_color: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_secondary_color', extstring) then - begin - glSecondaryColor3bEXT := wglGetProcAddress('glSecondaryColor3bEXT'); - if not Assigned(glSecondaryColor3bEXT) then Exit; - glSecondaryColor3sEXT := wglGetProcAddress('glSecondaryColor3sEXT'); - if not Assigned(glSecondaryColor3sEXT) then Exit; - glSecondaryColor3iEXT := wglGetProcAddress('glSecondaryColor3iEXT'); - if not Assigned(glSecondaryColor3iEXT) then Exit; - glSecondaryColor3fEXT := wglGetProcAddress('glSecondaryColor3fEXT'); - if not Assigned(glSecondaryColor3fEXT) then Exit; - glSecondaryColor3dEXT := wglGetProcAddress('glSecondaryColor3dEXT'); - if not Assigned(glSecondaryColor3dEXT) then Exit; - glSecondaryColor3ubEXT := wglGetProcAddress('glSecondaryColor3ubEXT'); - if not Assigned(glSecondaryColor3ubEXT) then Exit; - glSecondaryColor3usEXT := wglGetProcAddress('glSecondaryColor3usEXT'); - if not Assigned(glSecondaryColor3usEXT) then Exit; - glSecondaryColor3uiEXT := wglGetProcAddress('glSecondaryColor3uiEXT'); - if not Assigned(glSecondaryColor3uiEXT) then Exit; - glSecondaryColor3bvEXT := wglGetProcAddress('glSecondaryColor3bvEXT'); - if not Assigned(glSecondaryColor3bvEXT) then Exit; - glSecondaryColor3svEXT := wglGetProcAddress('glSecondaryColor3svEXT'); - if not Assigned(glSecondaryColor3svEXT) then Exit; - glSecondaryColor3ivEXT := wglGetProcAddress('glSecondaryColor3ivEXT'); - if not Assigned(glSecondaryColor3ivEXT) then Exit; - glSecondaryColor3fvEXT := wglGetProcAddress('glSecondaryColor3fvEXT'); - if not Assigned(glSecondaryColor3fvEXT) then Exit; - glSecondaryColor3dvEXT := wglGetProcAddress('glSecondaryColor3dvEXT'); - if not Assigned(glSecondaryColor3dvEXT) then Exit; - glSecondaryColor3ubvEXT := wglGetProcAddress('glSecondaryColor3ubvEXT'); - if not Assigned(glSecondaryColor3ubvEXT) then Exit; - glSecondaryColor3usvEXT := wglGetProcAddress('glSecondaryColor3usvEXT'); - if not Assigned(glSecondaryColor3usvEXT) then Exit; - glSecondaryColor3uivEXT := wglGetProcAddress('glSecondaryColor3uivEXT'); - if not Assigned(glSecondaryColor3uivEXT) then Exit; - glSecondaryColorPointerEXT := wglGetProcAddress('glSecondaryColorPointerEXT'); - if not Assigned(glSecondaryColorPointerEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_mirror_clamp: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_mirror_clamp', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_blend_equation_separate: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_blend_equation_separate', extstring) then - begin - glBlendEquationSeparateEXT := wglGetProcAddress('glBlendEquationSeparateEXT'); - if not Assigned(glBlendEquationSeparateEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_MESA_pack_invert: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_MESA_pack_invert', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_MESA_ycbcr_texture: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_MESA_ycbcr_texture', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_fragment_program_shadow: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_fragment_program_shadow', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_fog_coord: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_fog_coord', extstring) then - begin - glFogCoordfEXT := wglGetProcAddress('glFogCoordfEXT'); - if not Assigned(glFogCoordfEXT) then Exit; - glFogCoorddEXT := wglGetProcAddress('glFogCoorddEXT'); - if not Assigned(glFogCoorddEXT) then Exit; - glFogCoordfvEXT := wglGetProcAddress('glFogCoordfvEXT'); - if not Assigned(glFogCoordfvEXT) then Exit; - glFogCoorddvEXT := wglGetProcAddress('glFogCoorddvEXT'); - if not Assigned(glFogCoorddvEXT) then Exit; - glFogCoordPointerEXT := wglGetProcAddress('glFogCoordPointerEXT'); - if not Assigned(glFogCoordPointerEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_NV_fragment_program_option: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_fragment_program_option', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_pixel_buffer_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_pixel_buffer_object', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_fragment_program2: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_fragment_program2', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_vertex_program2_option: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_vertex_program2_option', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_NV_vertex_program3: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_NV_vertex_program3', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_draw_buffers: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_draw_buffers', extstring) then - begin - glDrawBuffersARB := wglGetProcAddress('glDrawBuffersARB'); - if not Assigned(glDrawBuffersARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_rectangle: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_rectangle', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_color_buffer_float: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_color_buffer_float', extstring) then - begin - glClampColorARB := wglGetProcAddress('glClampColorARB'); - if not Assigned(glClampColorARB) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_ARB_half_float_pixel: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_half_float_pixel', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_texture_float: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_texture_float', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_texture_compression_dxt1: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_texture_compression_dxt1', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_ARB_pixel_buffer_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_ARB_pixel_buffer_object', extstring) then - begin - Result := TRUE; - end; - -end; - -function Load_GL_EXT_framebuffer_object: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - if glext_ExtensionSupported('GL_EXT_framebuffer_object', extstring) then - begin - glIsRenderbufferEXT := wglGetProcAddress('glIsRenderbufferEXT'); - if not Assigned(glIsRenderbufferEXT) then Exit; - glBindRenderbufferEXT := wglGetProcAddress('glBindRenderbufferEXT'); - if not Assigned(glBindRenderbufferEXT) then Exit; - glDeleteRenderbuffersEXT := wglGetProcAddress('glDeleteRenderbuffersEXT'); - if not Assigned(glDeleteRenderbuffersEXT) then Exit; - glGenRenderbuffersEXT := wglGetProcAddress('glGenRenderbuffersEXT'); - if not Assigned(glGenRenderbuffersEXT) then Exit; - glRenderbufferStorageEXT := wglGetProcAddress('glRenderbufferStorageEXT'); - if not Assigned(glRenderbufferStorageEXT) then Exit; - glGetRenderbufferParameterivEXT := wglGetProcAddress('glGetRenderbufferParameterivEXT'); - if not Assigned(glGetRenderbufferParameterivEXT) then Exit; - glIsFramebufferEXT := wglGetProcAddress('glIsFramebufferEXT'); - if not Assigned(glIsFramebufferEXT) then Exit; - glBindFramebufferEXT := wglGetProcAddress('glBindFramebufferEXT'); - if not Assigned(glBindFramebufferEXT) then Exit; - glDeleteFramebuffersEXT := wglGetProcAddress('glDeleteFramebuffersEXT'); - if not Assigned(glDeleteFramebuffersEXT) then Exit; - glGenFramebuffersEXT := wglGetProcAddress('glGenFramebuffersEXT'); - if not Assigned(glGenFramebuffersEXT) then Exit; - glCheckFramebufferStatusEXT := wglGetProcAddress('glCheckFramebufferStatusEXT'); - if not Assigned(glCheckFramebufferStatusEXT) then Exit; - glFramebufferTexture1DEXT := wglGetProcAddress('glFramebufferTexture1DEXT'); - if not Assigned(glFramebufferTexture1DEXT) then Exit; - glFramebufferTexture2DEXT := wglGetProcAddress('glFramebufferTexture2DEXT'); - if not Assigned(glFramebufferTexture2DEXT) then Exit; - glFramebufferTexture3DEXT := wglGetProcAddress('glFramebufferTexture3DEXT'); - if not Assigned(glFramebufferTexture3DEXT) then Exit; - glFramebufferRenderbufferEXT := wglGetProcAddress('glFramebufferRenderbufferEXT'); - if not Assigned(glFramebufferRenderbufferEXT) then Exit; - glGetFramebufferAttachmentParameterivEXT := wglGetProcAddress('glGetFramebufferAttachmentParameterivEXT'); - if not Assigned(glGetFramebufferAttachmentParameterivEXT) then Exit; - glGenerateMipmapEXT := wglGetProcAddress('glGenerateMipmapEXT'); - if not Assigned(glGenerateMipmapEXT) then Exit; - Result := TRUE; - end; - -end; - -function Load_GL_version_1_4: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - glBlendFuncSeparate := wglGetProcAddress('glBlendFuncSeparate'); - if not Assigned(glBlendFuncSeparate) then Exit; - glFogCoordf := wglGetProcAddress('glFogCoordf'); - if not Assigned(glFogCoordf) then Exit; - glFogCoordfv := wglGetProcAddress('glFogCoordfv'); - if not Assigned(glFogCoordfv) then Exit; - glFogCoordd := wglGetProcAddress('glFogCoordd'); - if not Assigned(glFogCoordd) then Exit; - glFogCoorddv := wglGetProcAddress('glFogCoorddv'); - if not Assigned(glFogCoorddv) then Exit; - glFogCoordPointer := wglGetProcAddress('glFogCoordPointer'); - if not Assigned(glFogCoordPointer) then Exit; - glMultiDrawArrays := wglGetProcAddress('glMultiDrawArrays'); - if not Assigned(glMultiDrawArrays) then Exit; - glMultiDrawElements := wglGetProcAddress('glMultiDrawElements'); - if not Assigned(glMultiDrawElements) then Exit; - glPointParameterf := wglGetProcAddress('glPointParameterf'); - if not Assigned(glPointParameterf) then Exit; - glPointParameterfv := wglGetProcAddress('glPointParameterfv'); - if not Assigned(glPointParameterfv) then Exit; - glPointParameteri := wglGetProcAddress('glPointParameteri'); - if not Assigned(glPointParameteri) then Exit; - glPointParameteriv := wglGetProcAddress('glPointParameteriv'); - if not Assigned(glPointParameteriv) then Exit; - glSecondaryColor3b := wglGetProcAddress('glSecondaryColor3b'); - if not Assigned(glSecondaryColor3b) then Exit; - glSecondaryColor3bv := wglGetProcAddress('glSecondaryColor3bv'); - if not Assigned(glSecondaryColor3bv) then Exit; - glSecondaryColor3d := wglGetProcAddress('glSecondaryColor3d'); - if not Assigned(glSecondaryColor3d) then Exit; - glSecondaryColor3dv := wglGetProcAddress('glSecondaryColor3dv'); - if not Assigned(glSecondaryColor3dv) then Exit; - glSecondaryColor3f := wglGetProcAddress('glSecondaryColor3f'); - if not Assigned(glSecondaryColor3f) then Exit; - glSecondaryColor3fv := wglGetProcAddress('glSecondaryColor3fv'); - if not Assigned(glSecondaryColor3fv) then Exit; - glSecondaryColor3i := wglGetProcAddress('glSecondaryColor3i'); - if not Assigned(glSecondaryColor3i) then Exit; - glSecondaryColor3iv := wglGetProcAddress('glSecondaryColor3iv'); - if not Assigned(glSecondaryColor3iv) then Exit; - glSecondaryColor3s := wglGetProcAddress('glSecondaryColor3s'); - if not Assigned(glSecondaryColor3s) then Exit; - glSecondaryColor3sv := wglGetProcAddress('glSecondaryColor3sv'); - if not Assigned(glSecondaryColor3sv) then Exit; - glSecondaryColor3ub := wglGetProcAddress('glSecondaryColor3ub'); - if not Assigned(glSecondaryColor3ub) then Exit; - glSecondaryColor3ubv := wglGetProcAddress('glSecondaryColor3ubv'); - if not Assigned(glSecondaryColor3ubv) then Exit; - glSecondaryColor3ui := wglGetProcAddress('glSecondaryColor3ui'); - if not Assigned(glSecondaryColor3ui) then Exit; - glSecondaryColor3uiv := wglGetProcAddress('glSecondaryColor3uiv'); - if not Assigned(glSecondaryColor3uiv) then Exit; - glSecondaryColor3us := wglGetProcAddress('glSecondaryColor3us'); - if not Assigned(glSecondaryColor3us) then Exit; - glSecondaryColor3usv := wglGetProcAddress('glSecondaryColor3usv'); - if not Assigned(glSecondaryColor3usv) then Exit; - glSecondaryColorPointer := wglGetProcAddress('glSecondaryColorPointer'); - if not Assigned(glSecondaryColorPointer) then Exit; - glWindowPos2d := wglGetProcAddress('glWindowPos2d'); - if not Assigned(glWindowPos2d) then Exit; - glWindowPos2dv := wglGetProcAddress('glWindowPos2dv'); - if not Assigned(glWindowPos2dv) then Exit; - glWindowPos2f := wglGetProcAddress('glWindowPos2f'); - if not Assigned(glWindowPos2f) then Exit; - glWindowPos2fv := wglGetProcAddress('glWindowPos2fv'); - if not Assigned(glWindowPos2fv) then Exit; - glWindowPos2i := wglGetProcAddress('glWindowPos2i'); - if not Assigned(glWindowPos2i) then Exit; - glWindowPos2iv := wglGetProcAddress('glWindowPos2iv'); - if not Assigned(glWindowPos2iv) then Exit; - glWindowPos2s := wglGetProcAddress('glWindowPos2s'); - if not Assigned(glWindowPos2s) then Exit; - glWindowPos2sv := wglGetProcAddress('glWindowPos2sv'); - if not Assigned(glWindowPos2sv) then Exit; - glWindowPos3d := wglGetProcAddress('glWindowPos3d'); - if not Assigned(glWindowPos3d) then Exit; - glWindowPos3dv := wglGetProcAddress('glWindowPos3dv'); - if not Assigned(glWindowPos3dv) then Exit; - glWindowPos3f := wglGetProcAddress('glWindowPos3f'); - if not Assigned(glWindowPos3f) then Exit; - glWindowPos3fv := wglGetProcAddress('glWindowPos3fv'); - if not Assigned(glWindowPos3fv) then Exit; - glWindowPos3i := wglGetProcAddress('glWindowPos3i'); - if not Assigned(glWindowPos3i) then Exit; - glWindowPos3iv := wglGetProcAddress('glWindowPos3iv'); - if not Assigned(glWindowPos3iv) then Exit; - glWindowPos3s := wglGetProcAddress('glWindowPos3s'); - if not Assigned(glWindowPos3s) then Exit; - glWindowPos3sv := wglGetProcAddress('glWindowPos3sv'); - if not Assigned(glWindowPos3sv) then Exit; - Result := TRUE; - -end; - -function Load_GL_version_1_5: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - glGenQueries := wglGetProcAddress('glGenQueries'); - if not Assigned(glGenQueries) then Exit; - glDeleteQueries := wglGetProcAddress('glDeleteQueries'); - if not Assigned(glDeleteQueries) then Exit; - glIsQuery := wglGetProcAddress('glIsQuery'); - if not Assigned(glIsQuery) then Exit; - glBeginQuery := wglGetProcAddress('glBeginQuery'); - if not Assigned(glBeginQuery) then Exit; - glEndQuery := wglGetProcAddress('glEndQuery'); - if not Assigned(glEndQuery) then Exit; - glGetQueryiv := wglGetProcAddress('glGetQueryiv'); - if not Assigned(glGetQueryiv) then Exit; - glGetQueryObjectiv := wglGetProcAddress('glGetQueryObjectiv'); - if not Assigned(glGetQueryObjectiv) then Exit; - glGetQueryObjectuiv := wglGetProcAddress('glGetQueryObjectuiv'); - if not Assigned(glGetQueryObjectuiv) then Exit; - glBindBuffer := wglGetProcAddress('glBindBuffer'); - if not Assigned(glBindBuffer) then Exit; - glDeleteBuffers := wglGetProcAddress('glDeleteBuffers'); - if not Assigned(glDeleteBuffers) then Exit; - glGenBuffers := wglGetProcAddress('glGenBuffers'); - if not Assigned(glGenBuffers) then Exit; - glIsBuffer := wglGetProcAddress('glIsBuffer'); - if not Assigned(glIsBuffer) then Exit; - glBufferData := wglGetProcAddress('glBufferData'); - if not Assigned(glBufferData) then Exit; - glBufferSubData := wglGetProcAddress('glBufferSubData'); - if not Assigned(glBufferSubData) then Exit; - glGetBufferSubData := wglGetProcAddress('glGetBufferSubData'); - if not Assigned(glGetBufferSubData) then Exit; - glMapBuffer := wglGetProcAddress('glMapBuffer'); - if not Assigned(glMapBuffer) then Exit; - glUnmapBuffer := wglGetProcAddress('glUnmapBuffer'); - if not Assigned(glUnmapBuffer) then Exit; - glGetBufferParameteriv := wglGetProcAddress('glGetBufferParameteriv'); - if not Assigned(glGetBufferParameteriv) then Exit; - glGetBufferPointerv := wglGetProcAddress('glGetBufferPointerv'); - if not Assigned(glGetBufferPointerv) then Exit; - Result := TRUE; - -end; - -function Load_GL_version_2_0: Boolean; -var - extstring: String; -begin - - Result := FALSE; - extstring := String(PChar(glGetString(GL_EXTENSIONS))); - - glBlendEquationSeparate := wglGetProcAddress('glBlendEquationSeparate'); - if not Assigned(glBlendEquationSeparate) then Exit; - glDrawBuffers := wglGetProcAddress('glDrawBuffers'); - if not Assigned(glDrawBuffers) then Exit; - glStencilOpSeparate := wglGetProcAddress('glStencilOpSeparate'); - if not Assigned(glStencilOpSeparate) then Exit; - glStencilFuncSeparate := wglGetProcAddress('glStencilFuncSeparate'); - if not Assigned(glStencilFuncSeparate) then Exit; - glStencilMaskSeparate := wglGetProcAddress('glStencilMaskSeparate'); - if not Assigned(glStencilMaskSeparate) then Exit; - glAttachShader := wglGetProcAddress('glAttachShader'); - if not Assigned(glAttachShader) then Exit; - glBindAttribLocation := wglGetProcAddress('glBindAttribLocation'); - if not Assigned(glBindAttribLocation) then Exit; - glCompileShader := wglGetProcAddress('glCompileShader'); - if not Assigned(glCompileShader) then Exit; - glCreateProgram := wglGetProcAddress('glCreateProgram'); - if not Assigned(glCreateProgram) then Exit; - glCreateShader := wglGetProcAddress('glCreateShader'); - if not Assigned(glCreateShader) then Exit; - glDeleteProgram := wglGetProcAddress('glDeleteProgram'); - if not Assigned(glDeleteProgram) then Exit; - glDeleteShader := wglGetProcAddress('glDeleteShader'); - if not Assigned(glDeleteShader) then Exit; - glDetachShader := wglGetProcAddress('glDetachShader'); - if not Assigned(glDetachShader) then Exit; - glDisableVertexAttribArray := wglGetProcAddress('glDisableVertexAttribArray'); - if not Assigned(glDisableVertexAttribArray) then Exit; - glEnableVertexAttribArray := wglGetProcAddress('glEnableVertexAttribArray'); - if not Assigned(glEnableVertexAttribArray) then Exit; - glGetActiveAttrib := wglGetProcAddress('glGetActiveAttrib'); - if not Assigned(glGetActiveAttrib) then Exit; - glGetActiveUniform := wglGetProcAddress('glGetActiveUniform'); - if not Assigned(glGetActiveUniform) then Exit; - glGetAttachedShaders := wglGetProcAddress('glGetAttachedShaders'); - if not Assigned(glGetAttachedShaders) then Exit; - glGetAttribLocation := wglGetProcAddress('glGetAttribLocation'); - if not Assigned(glGetAttribLocation) then Exit; - glGetProgramiv := wglGetProcAddress('glGetProgramiv'); - if not Assigned(glGetProgramiv) then Exit; - glGetProgramInfoLog := wglGetProcAddress('glGetProgramInfoLog'); - if not Assigned(glGetProgramInfoLog) then Exit; - glGetShaderiv := wglGetProcAddress('glGetShaderiv'); - if not Assigned(glGetShaderiv) then Exit; - glGetShaderInfoLog := wglGetProcAddress('glGetShaderInfoLog'); - if not Assigned(glGetShaderInfoLog) then Exit; - glGetShaderSource := wglGetProcAddress('glGetShaderSource'); - if not Assigned(glGetShaderSource) then Exit; - glGetUniformLocation := wglGetProcAddress('glGetUniformLocation'); - if not Assigned(glGetUniformLocation) then Exit; - glGetUniformfv := wglGetProcAddress('glGetUniformfv'); - if not Assigned(glGetUniformfv) then Exit; - glGetUniformiv := wglGetProcAddress('glGetUniformiv'); - if not Assigned(glGetUniformiv) then Exit; - glGetVertexAttribdv := wglGetProcAddress('glGetVertexAttribdv'); - if not Assigned(glGetVertexAttribdv) then Exit; - glGetVertexAttribfv := wglGetProcAddress('glGetVertexAttribfv'); - if not Assigned(glGetVertexAttribfv) then Exit; - glGetVertexAttribiv := wglGetProcAddress('glGetVertexAttribiv'); - if not Assigned(glGetVertexAttribiv) then Exit; - glGetVertexAttribPointerv := wglGetProcAddress('glGetVertexAttribPointerv'); - if not Assigned(glGetVertexAttribPointerv) then Exit; - glIsProgram := wglGetProcAddress('glIsProgram'); - if not Assigned(glIsProgram) then Exit; - glIsShader := wglGetProcAddress('glIsShader'); - if not Assigned(glIsShader) then Exit; - glLinkProgram := wglGetProcAddress('glLinkProgram'); - if not Assigned(glLinkProgram) then Exit; - glShaderSource := wglGetProcAddress('glShaderSource'); - if not Assigned(glShaderSource) then Exit; - glUseProgram := wglGetProcAddress('glUseProgram'); - if not Assigned(glUseProgram) then Exit; - glUniform1f := wglGetProcAddress('glUniform1f'); - if not Assigned(glUniform1f) then Exit; - glUniform2f := wglGetProcAddress('glUniform2f'); - if not Assigned(glUniform2f) then Exit; - glUniform3f := wglGetProcAddress('glUniform3f'); - if not Assigned(glUniform3f) then Exit; - glUniform4f := wglGetProcAddress('glUniform4f'); - if not Assigned(glUniform4f) then Exit; - glUniform1i := wglGetProcAddress('glUniform1i'); - if not Assigned(glUniform1i) then Exit; - glUniform2i := wglGetProcAddress('glUniform2i'); - if not Assigned(glUniform2i) then Exit; - glUniform3i := wglGetProcAddress('glUniform3i'); - if not Assigned(glUniform3i) then Exit; - glUniform4i := wglGetProcAddress('glUniform4i'); - if not Assigned(glUniform4i) then Exit; - glUniform1fv := wglGetProcAddress('glUniform1fv'); - if not Assigned(glUniform1fv) then Exit; - glUniform2fv := wglGetProcAddress('glUniform2fv'); - if not Assigned(glUniform2fv) then Exit; - glUniform3fv := wglGetProcAddress('glUniform3fv'); - if not Assigned(glUniform3fv) then Exit; - glUniform4fv := wglGetProcAddress('glUniform4fv'); - if not Assigned(glUniform4fv) then Exit; - glUniform1iv := wglGetProcAddress('glUniform1iv'); - if not Assigned(glUniform1iv) then Exit; - glUniform2iv := wglGetProcAddress('glUniform2iv'); - if not Assigned(glUniform2iv) then Exit; - glUniform3iv := wglGetProcAddress('glUniform3iv'); - if not Assigned(glUniform3iv) then Exit; - glUniform4iv := wglGetProcAddress('glUniform4iv'); - if not Assigned(glUniform4iv) then Exit; - glUniformMatrix2fv := wglGetProcAddress('glUniformMatrix2fv'); - if not Assigned(glUniformMatrix2fv) then Exit; - glUniformMatrix3fv := wglGetProcAddress('glUniformMatrix3fv'); - if not Assigned(glUniformMatrix3fv) then Exit; - glUniformMatrix4fv := wglGetProcAddress('glUniformMatrix4fv'); - if not Assigned(glUniformMatrix4fv) then Exit; - glValidateProgram := wglGetProcAddress('glValidateProgram'); - if not Assigned(glValidateProgram) then Exit; - glVertexAttrib1d := wglGetProcAddress('glVertexAttrib1d'); - if not Assigned(glVertexAttrib1d) then Exit; - glVertexAttrib1dv := wglGetProcAddress('glVertexAttrib1dv'); - if not Assigned(glVertexAttrib1dv) then Exit; - glVertexAttrib1f := wglGetProcAddress('glVertexAttrib1f'); - if not Assigned(glVertexAttrib1f) then Exit; - glVertexAttrib1fv := wglGetProcAddress('glVertexAttrib1fv'); - if not Assigned(glVertexAttrib1fv) then Exit; - glVertexAttrib1s := wglGetProcAddress('glVertexAttrib1s'); - if not Assigned(glVertexAttrib1s) then Exit; - glVertexAttrib1sv := wglGetProcAddress('glVertexAttrib1sv'); - if not Assigned(glVertexAttrib1sv) then Exit; - glVertexAttrib2d := wglGetProcAddress('glVertexAttrib2d'); - if not Assigned(glVertexAttrib2d) then Exit; - glVertexAttrib2dv := wglGetProcAddress('glVertexAttrib2dv'); - if not Assigned(glVertexAttrib2dv) then Exit; - glVertexAttrib2f := wglGetProcAddress('glVertexAttrib2f'); - if not Assigned(glVertexAttrib2f) then Exit; - glVertexAttrib2fv := wglGetProcAddress('glVertexAttrib2fv'); - if not Assigned(glVertexAttrib2fv) then Exit; - glVertexAttrib2s := wglGetProcAddress('glVertexAttrib2s'); - if not Assigned(glVertexAttrib2s) then Exit; - glVertexAttrib2sv := wglGetProcAddress('glVertexAttrib2sv'); - if not Assigned(glVertexAttrib2sv) then Exit; - glVertexAttrib3d := wglGetProcAddress('glVertexAttrib3d'); - if not Assigned(glVertexAttrib3d) then Exit; - glVertexAttrib3dv := wglGetProcAddress('glVertexAttrib3dv'); - if not Assigned(glVertexAttrib3dv) then Exit; - glVertexAttrib3f := wglGetProcAddress('glVertexAttrib3f'); - if not Assigned(glVertexAttrib3f) then Exit; - glVertexAttrib3fv := wglGetProcAddress('glVertexAttrib3fv'); - if not Assigned(glVertexAttrib3fv) then Exit; - glVertexAttrib3s := wglGetProcAddress('glVertexAttrib3s'); - if not Assigned(glVertexAttrib3s) then Exit; - glVertexAttrib3sv := wglGetProcAddress('glVertexAttrib3sv'); - if not Assigned(glVertexAttrib3sv) then Exit; - glVertexAttrib4Nbv := wglGetProcAddress('glVertexAttrib4Nbv'); - if not Assigned(glVertexAttrib4Nbv) then Exit; - glVertexAttrib4Niv := wglGetProcAddress('glVertexAttrib4Niv'); - if not Assigned(glVertexAttrib4Niv) then Exit; - glVertexAttrib4Nsv := wglGetProcAddress('glVertexAttrib4Nsv'); - if not Assigned(glVertexAttrib4Nsv) then Exit; - glVertexAttrib4Nub := wglGetProcAddress('glVertexAttrib4Nub'); - if not Assigned(glVertexAttrib4Nub) then Exit; - glVertexAttrib4Nubv := wglGetProcAddress('glVertexAttrib4Nubv'); - if not Assigned(glVertexAttrib4Nubv) then Exit; - glVertexAttrib4Nuiv := wglGetProcAddress('glVertexAttrib4Nuiv'); - if not Assigned(glVertexAttrib4Nuiv) then Exit; - glVertexAttrib4Nusv := wglGetProcAddress('glVertexAttrib4Nusv'); - if not Assigned(glVertexAttrib4Nusv) then Exit; - glVertexAttrib4bv := wglGetProcAddress('glVertexAttrib4bv'); - if not Assigned(glVertexAttrib4bv) then Exit; - glVertexAttrib4d := wglGetProcAddress('glVertexAttrib4d'); - if not Assigned(glVertexAttrib4d) then Exit; - glVertexAttrib4dv := wglGetProcAddress('glVertexAttrib4dv'); - if not Assigned(glVertexAttrib4dv) then Exit; - glVertexAttrib4f := wglGetProcAddress('glVertexAttrib4f'); - if not Assigned(glVertexAttrib4f) then Exit; - glVertexAttrib4fv := wglGetProcAddress('glVertexAttrib4fv'); - if not Assigned(glVertexAttrib4fv) then Exit; - glVertexAttrib4iv := wglGetProcAddress('glVertexAttrib4iv'); - if not Assigned(glVertexAttrib4iv) then Exit; - glVertexAttrib4s := wglGetProcAddress('glVertexAttrib4s'); - if not Assigned(glVertexAttrib4s) then Exit; - glVertexAttrib4sv := wglGetProcAddress('glVertexAttrib4sv'); - if not Assigned(glVertexAttrib4sv) then Exit; - glVertexAttrib4ubv := wglGetProcAddress('glVertexAttrib4ubv'); - if not Assigned(glVertexAttrib4ubv) then Exit; - glVertexAttrib4uiv := wglGetProcAddress('glVertexAttrib4uiv'); - if not Assigned(glVertexAttrib4uiv) then Exit; - glVertexAttrib4usv := wglGetProcAddress('glVertexAttrib4usv'); - if not Assigned(glVertexAttrib4usv) then Exit; - glVertexAttribPointer := wglGetProcAddress('glVertexAttribPointer'); - if not Assigned(glVertexAttribPointer) then Exit; - Result := TRUE; - -end; - -function glext_LoadExtension(ext: String): Boolean; -begin - - Result := FALSE; - - if ext = 'GL_version_1_2' then Result := Load_GL_version_1_2 - else if ext = 'GL_ARB_imaging' then Result := Load_GL_ARB_imaging - else if ext = 'GL_version_1_3' then Result := Load_GL_version_1_3 - else if ext = 'GL_ARB_multitexture' then Result := Load_GL_ARB_multitexture - else if ext = 'GL_ARB_transpose_matrix' then Result := Load_GL_ARB_transpose_matrix - else if ext = 'GL_ARB_multisample' then Result := Load_GL_ARB_multisample - else if ext = 'GL_ARB_texture_env_add' then Result := Load_GL_ARB_texture_env_add - else if ext = 'WGL_ARB_extensions_string' then Result := Load_WGL_ARB_extensions_string - else if ext = 'WGL_ARB_buffer_region' then Result := Load_WGL_ARB_buffer_region - else if ext = 'GL_ARB_texture_cube_map' then Result := Load_GL_ARB_texture_cube_map - else if ext = 'GL_ARB_depth_texture' then Result := Load_GL_ARB_depth_texture - else if ext = 'GL_ARB_point_parameters' then Result := Load_GL_ARB_point_parameters - else if ext = 'GL_ARB_shadow' then Result := Load_GL_ARB_shadow - else if ext = 'GL_ARB_shadow_ambient' then Result := Load_GL_ARB_shadow_ambient - else if ext = 'GL_ARB_texture_border_clamp' then Result := Load_GL_ARB_texture_border_clamp - else if ext = 'GL_ARB_texture_compression' then Result := Load_GL_ARB_texture_compression - else if ext = 'GL_ARB_texture_env_combine' then Result := Load_GL_ARB_texture_env_combine - else if ext = 'GL_ARB_texture_env_crossbar' then Result := Load_GL_ARB_texture_env_crossbar - else if ext = 'GL_ARB_texture_env_dot3' then Result := Load_GL_ARB_texture_env_dot3 - else if ext = 'GL_ARB_texture_mirrored_repeat' then Result := Load_GL_ARB_texture_mirrored_repeat - else if ext = 'GL_ARB_vertex_blend' then Result := Load_GL_ARB_vertex_blend - else if ext = 'GL_ARB_vertex_program' then Result := Load_GL_ARB_vertex_program - else if ext = 'GL_ARB_window_pos' then Result := Load_GL_ARB_window_pos - else if ext = 'GL_EXT_422_pixels' then Result := Load_GL_EXT_422_pixels - else if ext = 'GL_EXT_abgr' then Result := Load_GL_EXT_abgr - else if ext = 'GL_EXT_bgra' then Result := Load_GL_EXT_bgra - else if ext = 'GL_EXT_blend_color' then Result := Load_GL_EXT_blend_color - else if ext = 'GL_EXT_blend_func_separate' then Result := Load_GL_EXT_blend_func_separate - else if ext = 'GL_EXT_blend_logic_op' then Result := Load_GL_EXT_blend_logic_op - else if ext = 'GL_EXT_blend_minmax' then Result := Load_GL_EXT_blend_minmax - else if ext = 'GL_EXT_blend_subtract' then Result := Load_GL_EXT_blend_subtract - else if ext = 'GL_EXT_clip_volume_hint' then Result := Load_GL_EXT_clip_volume_hint - else if ext = 'GL_EXT_color_subtable' then Result := Load_GL_EXT_color_subtable - else if ext = 'GL_EXT_compiled_vertex_array' then Result := Load_GL_EXT_compiled_vertex_array - else if ext = 'GL_EXT_convolution' then Result := Load_GL_EXT_convolution - else if ext = 'GL_EXT_histogram' then Result := Load_GL_EXT_histogram - else if ext = 'GL_EXT_multi_draw_arrays' then Result := Load_GL_EXT_multi_draw_arrays - else if ext = 'GL_EXT_packed_pixels' then Result := Load_GL_EXT_packed_pixels - else if ext = 'GL_EXT_paletted_texture' then Result := Load_GL_EXT_paletted_texture - else if ext = 'GL_EXT_point_parameters' then Result := Load_GL_EXT_point_parameters - else if ext = 'GL_EXT_polygon_offset' then Result := Load_GL_EXT_polygon_offset - else if ext = 'GL_EXT_separate_specular_color' then Result := Load_GL_EXT_separate_specular_color - else if ext = 'GL_EXT_shadow_funcs' then Result := Load_GL_EXT_shadow_funcs - else if ext = 'GL_EXT_shared_texture_palette' then Result := Load_GL_EXT_shared_texture_palette - else if ext = 'GL_EXT_stencil_two_side' then Result := Load_GL_EXT_stencil_two_side - else if ext = 'GL_EXT_stencil_wrap' then Result := Load_GL_EXT_stencil_wrap - else if ext = 'GL_EXT_subtexture' then Result := Load_GL_EXT_subtexture - else if ext = 'GL_EXT_texture3D' then Result := Load_GL_EXT_texture3D - else if ext = 'GL_EXT_texture_compression_s3tc' then Result := Load_GL_EXT_texture_compression_s3tc - else if ext = 'GL_EXT_texture_env_add' then Result := Load_GL_EXT_texture_env_add - else if ext = 'GL_EXT_texture_env_combine' then Result := Load_GL_EXT_texture_env_combine - else if ext = 'GL_EXT_texture_env_dot3' then Result := Load_GL_EXT_texture_env_dot3 - else if ext = 'GL_EXT_texture_filter_anisotropic' then Result := Load_GL_EXT_texture_filter_anisotropic - else if ext = 'GL_EXT_texture_lod_bias' then Result := Load_GL_EXT_texture_lod_bias - else if ext = 'GL_EXT_texture_object' then Result := Load_GL_EXT_texture_object - else if ext = 'GL_EXT_vertex_array' then Result := Load_GL_EXT_vertex_array - else if ext = 'GL_EXT_vertex_shader' then Result := Load_GL_EXT_vertex_shader - else if ext = 'GL_EXT_vertex_weighting' then Result := Load_GL_EXT_vertex_weighting - else if ext = 'GL_HP_occlusion_test' then Result := Load_GL_HP_occlusion_test - else if ext = 'GL_NV_blend_square' then Result := Load_GL_NV_blend_square - else if ext = 'GL_NV_copy_depth_to_color' then Result := Load_GL_NV_copy_depth_to_color - else if ext = 'GL_NV_depth_clamp' then Result := Load_GL_NV_depth_clamp - else if ext = 'GL_NV_evaluators' then Result := Load_GL_NV_evaluators - else if ext = 'GL_NV_fence' then Result := Load_GL_NV_fence - else if ext = 'GL_NV_fog_distance' then Result := Load_GL_NV_fog_distance - else if ext = 'GL_NV_light_max_exponent' then Result := Load_GL_NV_light_max_exponent - else if ext = 'GL_NV_multisample_filter_hint' then Result := Load_GL_NV_multisample_filter_hint - else if ext = 'GL_NV_occlusion_query' then Result := Load_GL_NV_occlusion_query - else if ext = 'GL_NV_packed_depth_stencil' then Result := Load_GL_NV_packed_depth_stencil - else if ext = 'GL_NV_point_sprite' then Result := Load_GL_NV_point_sprite - else if ext = 'GL_NV_register_combiners' then Result := Load_GL_NV_register_combiners - else if ext = 'GL_NV_register_combiners2' then Result := Load_GL_NV_register_combiners2 - else if ext = 'GL_NV_texgen_emboss' then Result := Load_GL_NV_texgen_emboss - else if ext = 'GL_NV_texgen_reflection' then Result := Load_GL_NV_texgen_reflection - else if ext = 'GL_NV_texture_compression_vtc' then Result := Load_GL_NV_texture_compression_vtc - else if ext = 'GL_NV_texture_env_combine4' then Result := Load_GL_NV_texture_env_combine4 - else if ext = 'GL_NV_texture_rectangle' then Result := Load_GL_NV_texture_rectangle - else if ext = 'GL_NV_texture_shader' then Result := Load_GL_NV_texture_shader - else if ext = 'GL_NV_texture_shader2' then Result := Load_GL_NV_texture_shader2 - else if ext = 'GL_NV_texture_shader3' then Result := Load_GL_NV_texture_shader3 - else if ext = 'GL_NV_vertex_array_range' then Result := Load_GL_NV_vertex_array_range - else if ext = 'GL_NV_vertex_array_range2' then Result := Load_GL_NV_vertex_array_range2 - else if ext = 'GL_NV_vertex_program' then Result := Load_GL_NV_vertex_program - else if ext = 'GL_NV_vertex_program1_1' then Result := Load_GL_NV_vertex_program1_1 - else if ext = 'GL_ATI_element_array' then Result := Load_GL_ATI_element_array - else if ext = 'GL_ATI_envmap_bumpmap' then Result := Load_GL_ATI_envmap_bumpmap - else if ext = 'GL_ATI_fragment_shader' then Result := Load_GL_ATI_fragment_shader - else if ext = 'GL_ATI_pn_triangles' then Result := Load_GL_ATI_pn_triangles - else if ext = 'GL_ATI_texture_mirror_once' then Result := Load_GL_ATI_texture_mirror_once - else if ext = 'GL_ATI_vertex_array_object' then Result := Load_GL_ATI_vertex_array_object - else if ext = 'GL_ATI_vertex_streams' then Result := Load_GL_ATI_vertex_streams - else if ext = 'WGL_I3D_image_buffer' then Result := Load_WGL_I3D_image_buffer - else if ext = 'WGL_I3D_swap_frame_lock' then Result := Load_WGL_I3D_swap_frame_lock - else if ext = 'WGL_I3D_swap_frame_usage' then Result := Load_WGL_I3D_swap_frame_usage - else if ext = 'GL_3DFX_texture_compression_FXT1' then Result := Load_GL_3DFX_texture_compression_FXT1 - else if ext = 'GL_IBM_cull_vertex' then Result := Load_GL_IBM_cull_vertex - else if ext = 'GL_IBM_multimode_draw_arrays' then Result := Load_GL_IBM_multimode_draw_arrays - else if ext = 'GL_IBM_raster_pos_clip' then Result := Load_GL_IBM_raster_pos_clip - else if ext = 'GL_IBM_texture_mirrored_repeat' then Result := Load_GL_IBM_texture_mirrored_repeat - else if ext = 'GL_IBM_vertex_array_lists' then Result := Load_GL_IBM_vertex_array_lists - else if ext = 'GL_MESA_resize_buffers' then Result := Load_GL_MESA_resize_buffers - else if ext = 'GL_MESA_window_pos' then Result := Load_GL_MESA_window_pos - else if ext = 'GL_OML_interlace' then Result := Load_GL_OML_interlace - else if ext = 'GL_OML_resample' then Result := Load_GL_OML_resample - else if ext = 'GL_OML_subsample' then Result := Load_GL_OML_subsample - else if ext = 'GL_SGIS_generate_mipmap' then Result := Load_GL_SGIS_generate_mipmap - else if ext = 'GL_SGIS_multisample' then Result := Load_GL_SGIS_multisample - else if ext = 'GL_SGIS_pixel_texture' then Result := Load_GL_SGIS_pixel_texture - else if ext = 'GL_SGIS_texture_border_clamp' then Result := Load_GL_SGIS_texture_border_clamp - else if ext = 'GL_SGIS_texture_color_mask' then Result := Load_GL_SGIS_texture_color_mask - else if ext = 'GL_SGIS_texture_edge_clamp' then Result := Load_GL_SGIS_texture_edge_clamp - else if ext = 'GL_SGIS_texture_lod' then Result := Load_GL_SGIS_texture_lod - else if ext = 'GL_SGIS_depth_texture' then Result := Load_GL_SGIS_depth_texture - else if ext = 'GL_SGIX_fog_offset' then Result := Load_GL_SGIX_fog_offset - else if ext = 'GL_SGIX_interlace' then Result := Load_GL_SGIX_interlace - else if ext = 'GL_SGIX_shadow_ambient' then Result := Load_GL_SGIX_shadow_ambient - else if ext = 'GL_SGI_color_matrix' then Result := Load_GL_SGI_color_matrix - else if ext = 'GL_SGI_color_table' then Result := Load_GL_SGI_color_table - else if ext = 'GL_SGI_texture_color_table' then Result := Load_GL_SGI_texture_color_table - else if ext = 'GL_SUN_vertex' then Result := Load_GL_SUN_vertex - else if ext = 'GL_ARB_fragment_program' then Result := Load_GL_ARB_fragment_program - else if ext = 'GL_ATI_text_fragment_shader' then Result := Load_GL_ATI_text_fragment_shader - else if ext = 'GL_APPLE_client_storage' then Result := Load_GL_APPLE_client_storage - else if ext = 'GL_APPLE_element_array' then Result := Load_GL_APPLE_element_array - else if ext = 'GL_APPLE_fence' then Result := Load_GL_APPLE_fence - else if ext = 'GL_APPLE_vertex_array_object' then Result := Load_GL_APPLE_vertex_array_object - else if ext = 'GL_APPLE_vertex_array_range' then Result := Load_GL_APPLE_vertex_array_range - else if ext = 'WGL_ARB_pixel_format' then Result := Load_WGL_ARB_pixel_format - else if ext = 'WGL_ARB_make_current_read' then Result := Load_WGL_ARB_make_current_read - else if ext = 'WGL_ARB_pbuffer' then Result := Load_WGL_ARB_pbuffer - else if ext = 'WGL_EXT_swap_control' then Result := Load_WGL_EXT_swap_control - else if ext = 'WGL_ARB_render_texture' then Result := Load_WGL_ARB_render_texture - else if ext = 'WGL_EXT_extensions_string' then Result := Load_WGL_EXT_extensions_string - else if ext = 'WGL_EXT_make_current_read' then Result := Load_WGL_EXT_make_current_read - else if ext = 'WGL_EXT_pbuffer' then Result := Load_WGL_EXT_pbuffer - else if ext = 'WGL_EXT_pixel_format' then Result := Load_WGL_EXT_pixel_format - else if ext = 'WGL_I3D_digital_video_control' then Result := Load_WGL_I3D_digital_video_control - else if ext = 'WGL_I3D_gamma' then Result := Load_WGL_I3D_gamma - else if ext = 'WGL_I3D_genlock' then Result := Load_WGL_I3D_genlock - else if ext = 'GL_ARB_matrix_palette' then Result := Load_GL_ARB_matrix_palette - else if ext = 'GL_NV_element_array' then Result := Load_GL_NV_element_array - else if ext = 'GL_NV_float_buffer' then Result := Load_GL_NV_float_buffer - else if ext = 'GL_NV_fragment_program' then Result := Load_GL_NV_fragment_program - else if ext = 'GL_NV_primitive_restart' then Result := Load_GL_NV_primitive_restart - else if ext = 'GL_NV_vertex_program2' then Result := Load_GL_NV_vertex_program2 - else if ext = 'WGL_NV_render_texture_rectangle' then Result := Load_WGL_NV_render_texture_rectangle - else if ext = 'GL_NV_pixel_data_range' then Result := Load_GL_NV_pixel_data_range - else if ext = 'GL_EXT_texture_rectangle' then Result := Load_GL_EXT_texture_rectangle - else if ext = 'GL_S3_s3tc' then Result := Load_GL_S3_s3tc - else if ext = 'GL_ATI_draw_buffers' then Result := Load_GL_ATI_draw_buffers - else if ext = 'WGL_ATI_pixel_format_float' then Result := Load_WGL_ATI_pixel_format_float - else if ext = 'GL_ATI_texture_env_combine3' then Result := Load_GL_ATI_texture_env_combine3 - else if ext = 'GL_ATI_texture_float' then Result := Load_GL_ATI_texture_float - else if ext = 'GL_NV_texture_expand_normal' then Result := Load_GL_NV_texture_expand_normal - else if ext = 'GL_NV_half_float' then Result := Load_GL_NV_half_float - else if ext = 'GL_ATI_map_object_buffer' then Result := Load_GL_ATI_map_object_buffer - else if ext = 'GL_ATI_separate_stencil' then Result := Load_GL_ATI_separate_stencil - else if ext = 'GL_ATI_vertex_attrib_array_object' then Result := Load_GL_ATI_vertex_attrib_array_object - else if ext = 'GL_ARB_vertex_buffer_object' then Result := Load_GL_ARB_vertex_buffer_object - else if ext = 'GL_ARB_occlusion_query' then Result := Load_GL_ARB_occlusion_query - else if ext = 'GL_ARB_shader_objects' then Result := Load_GL_ARB_shader_objects - else if ext = 'GL_ARB_vertex_shader' then Result := Load_GL_ARB_vertex_shader - else if ext = 'GL_ARB_fragment_shader' then Result := Load_GL_ARB_fragment_shader - else if ext = 'GL_ARB_shading_language_100' then Result := Load_GL_ARB_shading_language_100 - else if ext = 'GL_ARB_texture_non_power_of_two' then Result := Load_GL_ARB_texture_non_power_of_two - else if ext = 'GL_ARB_point_sprite' then Result := Load_GL_ARB_point_sprite - else if ext = 'GL_EXT_depth_bounds_test' then Result := Load_GL_EXT_depth_bounds_test - else if ext = 'GL_EXT_secondary_color' then Result := Load_GL_EXT_secondary_color - else if ext = 'GL_EXT_texture_mirror_clamp' then Result := Load_GL_EXT_texture_mirror_clamp - else if ext = 'GL_EXT_blend_equation_separate' then Result := Load_GL_EXT_blend_equation_separate - else if ext = 'GL_MESA_pack_invert' then Result := Load_GL_MESA_pack_invert - else if ext = 'GL_MESA_ycbcr_texture' then Result := Load_GL_MESA_ycbcr_texture - else if ext = 'GL_ARB_fragment_program_shadow' then Result := Load_GL_ARB_fragment_program_shadow - else if ext = 'GL_EXT_fog_coord' then Result := Load_GL_EXT_fog_coord - else if ext = 'GL_NV_fragment_program_option' then Result := Load_GL_NV_fragment_program_option - else if ext = 'GL_EXT_pixel_buffer_object' then Result := Load_GL_EXT_pixel_buffer_object - else if ext = 'GL_NV_fragment_program2' then Result := Load_GL_NV_fragment_program2 - else if ext = 'GL_NV_vertex_program2_option' then Result := Load_GL_NV_vertex_program2_option - else if ext = 'GL_NV_vertex_program3' then Result := Load_GL_NV_vertex_program3 - else if ext = 'GL_ARB_draw_buffers' then Result := Load_GL_ARB_draw_buffers - else if ext = 'GL_ARB_texture_rectangle' then Result := Load_GL_ARB_texture_rectangle - else if ext = 'GL_ARB_color_buffer_float' then Result := Load_GL_ARB_color_buffer_float - else if ext = 'GL_ARB_half_float_pixel' then Result := Load_GL_ARB_half_float_pixel - else if ext = 'GL_ARB_texture_float' then Result := Load_GL_ARB_texture_float - else if ext = 'GL_EXT_texture_compression_dxt1' then Result := Load_GL_EXT_texture_compression_dxt1 - else if ext = 'GL_ARB_pixel_buffer_object' then Result := Load_GL_ARB_pixel_buffer_object - else if ext = 'GL_EXT_framebuffer_object' then Result := Load_GL_EXT_framebuffer_object - else if ext = 'GL_version_1_4' then Result := Load_GL_version_1_4 - else if ext = 'GL_version_1_5' then Result := Load_GL_version_1_5 - else if ext = 'GL_version_2_0' then Result := Load_GL_version_2_0 - -end; - -end. diff --git a/src/lib/vampimg/Imaging.pas b/src/lib/vampimg/Imaging.pas new file mode 100644 index 0000000..f21fa64 --- /dev/null +++ b/src/lib/vampimg/Imaging.pas @@ -0,0 +1,4252 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit is heart of Imaging library. It contains basic functions for + manipulating image data as well as various image file format support.} +unit Imaging; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, Classes, Types, ImagingTypes; + +type + { Default Imaging excepton class } + EImagingError = class(Exception); + { Raised when function receives bad image (not passed TestImage).} + EImagingBadImage = class(Exception) + public + constructor Create; + end; + + { Dynamic array of TImageData records } + TDynImageDataArray = array of TImageData; + + +{ ------------------------------------------------------------------------ + Low Level Interface Functions + ------------------------------------------------------------------------} + +{ General Functions } + +{ Initializes image (all is set to zeroes). Call this for each image + before using it (before calling every other function) to be sure there + are no random-filled bytes (which would cause errors later).} +procedure InitImage(var Image: TImageData); +{ Creates empty image of given dimensions and format. Image is filled with + transparent black color (A=0, R=0, G=0, B=0).} +function NewImage(Width, Height: LongInt; Format: TImageFormat; + var Image: TImageData): Boolean; +{ Returns True if given TImageData record is valid.} +function TestImage(const Image: TImageData): Boolean; +{ Frees given image data. Ater this call image is in the same state + as after calling InitImage. If image is not valid (dost not pass TestImage + test) it is only zeroed by calling InitImage.} +procedure FreeImage(var Image: TImageData); +{ Call FreeImage() on all images in given dynamic array and sets its + length to zero.} +procedure FreeImagesInArray(var Images: TDynImageDataArray); +{ Returns True if all TImageData records in given array are valid. Returns False + if at least one is invalid or if array is empty.} +function TestImagesInArray(const Images: TDynImageDataArray): Boolean; +{ Checks given file for every supported image file format and if + the file is in one of them returns its string identifier + (which can be used in LoadFromStream/LoadFromMem type functions). + If file is not in any of the supported formats empty string is returned.} +function DetermineFileFormat(const FileName: string): string; +{ Checks given stream for every supported image file format and if + the stream is in one of them returns its string identifier + (which can be used in LoadFromStream/LoadFromMem type functions). + If stream is not in any of the supported formats empty string is returned.} +function DetermineStreamFormat(Stream: TStream): string; +{ Checks given memory for every supported image file format and if + the memory is in one of them returns its string identifier + (which can be used in LoadFromStream/LoadFromMem type functions). + If memory is not in any of the supported formats empty string is returned.} +function DetermineMemoryFormat(Data: Pointer; Size: LongInt): string; +{ Checks that an apropriate file format is supported purely from inspecting + the given file name's extension (not contents of the file itself). + The file need not exist.} +function IsFileFormatSupported(const FileName: string): Boolean; +{ Enumerates all registered image file formats. Descriptive name, + default extension, masks (like '*.jpg,*.jfif') and some capabilities + of each format are returned. To enumerate all formats start with Index at 0 and + call EnumFileFormats with given Index in loop until it returns False (Index is + automatically increased by 1 in function's body on successful call).} +function EnumFileFormats(var Index: LongInt; var Name, DefaultExt, Masks: string; + var CanSaveImages, IsMultiImageFormat: Boolean): Boolean; + +{ Loading Functions } + +{ Loads single image from given file.} +function LoadImageFromFile(const FileName: string; var Image: TImageData): Boolean; +{ Loads single image from given stream. If function fails stream position + is not changed.} +function LoadImageFromStream(Stream: TStream; var Image: TImageData): Boolean; +{ Loads single image from given memory location.} +function LoadImageFromMemory(Data: Pointer; Size: LongInt; var Image: TImageData): Boolean; +{ Loads multiple images from given file.} +function LoadMultiImageFromFile(const FileName: string; + var Images: TDynImageDataArray): Boolean; +{ Loads multiple images from given stream. If function fails stream position + is not changed.} +function LoadMultiImageFromStream(Stream: TStream; + var Images: TDynImageDataArray): Boolean; +{ Loads multiple images from given memory location.} +function LoadMultiImageFromMemory(Data: Pointer; Size: LongInt; + var Images: TDynImageDataArray): Boolean; + +{ Saving Functions } + +{ Saves single image to given file.} +function SaveImageToFile(const FileName: string; const Image: TImageData): Boolean; +{ Saves single image to given stream. If function fails stream position + is not changed. Ext identifies desired image file format (jpg, png, dds, ...).} +function SaveImageToStream(const Ext: string; Stream: TStream; + const Image: TImageData): Boolean; +{ Saves single image to given memory location. Memory must be allocated and its + size is passed in Size parameter in which number of written bytes is returned. + Ext identifies desired image file format (jpg, png, dds, ...).} +function SaveImageToMemory(const Ext: string; Data: Pointer; var Size: LongInt; + const Image: TImageData): Boolean; +{ Saves multiple images to given file. If format supports + only single level images and there are multiple images to be saved, + they are saved as sequence of files img000.jpg, img001.jpg ....).} +function SaveMultiImageToFile(const FileName: string; + const Images: TDynImageDataArray): Boolean; +{ Saves multiple images to given stream. If format supports + only single level images and there are multiple images to be saved, + they are saved one after another to the stream. If function fails stream + position is not changed. Ext identifies desired image file format (jpg, png, dds, ...).} +function SaveMultiImageToStream(const Ext: string; Stream: TStream; + const Images: TDynImageDataArray): Boolean; +{ Saves multiple images to given memory location. If format supports + only single level images and there are multiple images to be saved, + they are saved one after another to the memory. Memory must be allocated and + its size is passed in Size parameter in which number of written bytes is returned. + Ext identifies desired image file format (jpg, png, dds, ...).} +function SaveMultiImageToMemory(const Ext: string; Data: Pointer; + var Size: LongInt; const Images: TDynImageDataArray): Boolean; + +{ Manipulation Functions } + +{ Creates identical copy of image data. Clone should be initialized + by InitImage or it should be vaild image which will be freed by CloneImage.} +function CloneImage(const Image: TImageData; var Clone: TImageData): Boolean; +{ Converts image to the given format.} +function ConvertImage(var Image: TImageData; DestFormat: TImageFormat): Boolean; +{ Flips given image. Reverses the image along its horizontal axis - the top + becomes the bottom and vice versa.} +function FlipImage(var Image: TImageData): Boolean; +{ Mirrors given image. Reverses the image along its vertical axis — the left + side becomes the right and vice versa.} +function MirrorImage(var Image: TImageData): Boolean; +{ Resizes given image to new dimensions. Nearest, bilinear, or bicubic filtering + can be used. Input Image must already be created - use NewImage to create new images.} +function ResizeImage(var Image: TImageData; NewWidth, NewHeight: LongInt; + Filter: TResizeFilter): Boolean; +{ Swaps SrcChannel and DstChannel color or alpha channels of image. + Use ChannelRed, ChannelBlue, ChannelGreen, ChannelAlpha constants to + identify channels.} +function SwapChannels(var Image: TImageData; SrcChannel, DstChannel: LongInt): Boolean; +{ Reduces the number of colors of the Image. Currently MaxColors must be in + range <2, 4096>. Color reduction works also for alpha channel. Note that for + large images and big number of colors it can be very slow. + Output format of the image is the same as input format.} +function ReduceColors(var Image: TImageData; MaxColors: LongInt): Boolean; +{ Generates mipmaps for image. Levels is the number of desired mipmaps levels + with zero (or some invalid number) meaning all possible levels.} +function GenerateMipMaps(const Image: TImageData; Levels: LongInt; + var MipMaps: TDynImageDataArray): Boolean; +{ Maps image to existing palette producing image in ifIndex8 format. + Pal must be allocated to at least Entries * SizeOf(TColor32Rec) bytes. + As resulting image is in 8bit indexed format Entries must be lower or + equal to 256.} +function MapImageToPalette(var Image: TImageData; Pal: PPalette32; + Entries: LongInt): Boolean; +{ Splits image into XChunks x YChunks subimages. Default size of each chunk is + ChunkWidth x ChunkHeight. If PreserveSize si True chunks at the edges of + the image are also ChunkWidth x ChunkHeight sized and empty space is filled + with optional Fill pixels. After calling this function XChunks contains number of + chunks along x axis and YChunks along y axis. To access chunk [X, Y] use this + index: Chunks[Y * XChunks + X].} +function SplitImage(var Image: TImageData; var Chunks: TDynImageDataArray; + ChunkWidth, ChunkHeight: LongInt; var XChunks, YChunks: LongInt; + PreserveSize: Boolean; Fill: Pointer = nil): Boolean; +{ Creates palette with MaxColors based on the colors of images in Images array. + Use it when you want to convert several images to indexed format using + single palette for all of them. If ConvertImages is True images in array + are converted to indexed format using resulting palette. if it is False + images are left intact and only resulting palatte is returned in Pal. + Pal must be allocated to have at least MaxColors entries.} +function MakePaletteForImages(var Images: TDynImageDataArray; Pal: PPalette32; + MaxColors: LongInt; ConvertImages: Boolean): Boolean; +{ Rotates image by Angle degrees counterclockwise. All angles are allowed.} +procedure RotateImage(var Image: TImageData; Angle: Single); + +{ Drawing/Pixel functions } + +{ Copies rectangular part of SrcImage to DstImage. No blending is performed - + alpha is simply copied to destination image. Operates also with + negative X and Y coordinates. + Note that copying is fastest for images in the same data format + (and slowest for images in special formats).} +function CopyRect(const SrcImage: TImageData; SrcX, SrcY, Width, Height: LongInt; + var DstImage: TImageData; DstX, DstY: LongInt): Boolean; +{ Fills given rectangle of image with given pixel fill data. Fill should point + to the pixel in the same format as the given image is in.} +function FillRect(var Image: TImageData; X, Y, Width, Height: LongInt; FillColor: Pointer): Boolean; +{ Replaces pixels with OldPixel in the given rectangle by NewPixel. + OldPixel and NewPixel should point to the pixels in the same format + as the given image is in.} +function ReplaceColor(var Image: TImageData; X, Y, Width, Height: LongInt; + OldColor, NewColor: Pointer): Boolean; +{ Stretches the contents of the source rectangle to the destination rectangle + with optional resampling. No blending is performed - alpha is + simply copied/resampled to destination image. Note that stretching is + fastest for images in the same data format (and slowest for + images in special formats).} +function StretchRect(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt; Filter: TResizeFilter): Boolean; +{ Copies pixel of Image at [X, Y] to memory pointed at by Pixel. Doesn't + work with special formats.} +procedure GetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer); +{ Copies pixel from memory pointed at by Pixel to Image at position [X, Y]. + Doesn't work with special formats.} +procedure SetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer); +{ Function for getting pixel colors. Native pixel is read from Image and + then translated to 32 bit ARGB. Works for all image formats (except special) + so it is not very fast.} +function GetPixel32(const Image: TImageData; X, Y: LongInt): TColor32Rec; +{ Procedure for setting pixel colors. Input 32 bit ARGB color is translated to + native format and then written to Image. Works for all image formats (except special) + so it is not very fast.} +procedure SetPixel32(const Image: TImageData; X, Y: LongInt; const Color: TColor32Rec); +{ Function for getting pixel colors. Native pixel is read from Image and + then translated to FP ARGB. Works for all image formats (except special) + so it is not very fast.} +function GetPixelFP(const Image: TImageData; X, Y: LongInt): TColorFPRec; +{ Procedure for setting pixel colors. Input FP ARGB color is translated to + native format and then written to Image. Works for all image formats (except special) + so it is not very fast.} +procedure SetPixelFP(const Image: TImageData; X, Y: LongInt; const Color: TColorFPRec); + +{ Palette Functions } + +{ Allocates new palette with Entries ARGB color entries.} +procedure NewPalette(Entries: LongInt; var Pal: PPalette32); +{ Frees given palette.} +procedure FreePalette(var Pal: PPalette32); +{ Copies Count palette entries from SrcPal starting at index SrcIdx to + DstPal at index DstPal.} +procedure CopyPalette(SrcPal, DstPal: PPalette32; SrcIdx, DstIdx, Count: LongInt); +{ Returns index of color in palette or index of nearest color if exact match + is not found. Pal must have at least Entries color entries.} +function FindColor(Pal: PPalette32; Entries: LongInt; Color: TColor32): LongInt; +{ Creates grayscale palette where each color channel has the same value. + Pal must have at least Entries color entries.} +procedure FillGrayscalePalette(Pal: PPalette32; Entries: LongInt); +{ Creates palette with given bitcount for each channel. + 2^(RBits + GBits + BBits) should be equl to Entries. Examples: + (3, 3, 2) will create palette with all possible colors of R3G3B2 format + and (8, 0, 0) will create palette with 256 shades of red. + Pal must be allocated to at least Entries * SizeOf(TColor32Rec) bytes.} +procedure FillCustomPalette(Pal: PPalette32; Entries: LongInt; RBits, GBits, + BBits: Byte; Alpha: Byte = $FF); +{ Swaps SrcChannel and DstChannel color or alpha channels of palette. + Use ChannelRed, ChannelBlue, ChannelGreen, ChannelAlpha constants to + identify channels. Pal must be allocated to at least + Entries * SizeOf(TColor32Rec) bytes.} +procedure SwapChannelsOfPalette(Pal: PPalette32; Entries, SrcChannel, + DstChannel: LongInt); + +{ Options Functions } + +{ Sets value of integer option specified by OptionId parameter. + Option Ids are constans starting ImagingXXX.} +function SetOption(OptionId, Value: LongInt): Boolean; +{ Returns value of integer option specified by OptionId parameter. If OptionId is + invalid, InvalidOption is returned. Option Ids are constans + starting ImagingXXX.} +function GetOption(OptionId: LongInt): LongInt; +{ Pushes current values of all options on the stack. Returns True + if successfull (max stack depth is 8 now). } +function PushOptions: Boolean; +{ Pops back values of all options from the top of the stack. Returns True + if successfull (max stack depth is 8 now). } +function PopOptions: Boolean; + +{ Image Format Functions } + +{ Returns short information about given image format.} +function GetImageFormatInfo(Format: TImageFormat; out Info: TImageFormatInfo): Boolean; +{ Returns size in bytes of Width x Height area of pixels. Works for all formats.} +function GetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; + +{ IO Functions } + +{ User can set his own file IO functions used when loading from/saving to + files by this function.} +procedure SetUserFileIO(OpenProc: TOpenProc; CloseProc: TCloseProc; EofProc: TEofProc; SeekProc: + TSeekProc; TellProc: TTellProc; ReadProc: TReadProc; WriteProc: TWriteProc); +{ Sets file IO functions to Imaging default.} +procedure ResetFileIO; + +{ Raw Image IO Functions } + +procedure ReadRawImageFromFile(const FileName: string; Width, Height: Integer; + Format: TImageFormat; var Image: TImageData; Offset: Integer = 0; RowLength: Integer = 0); +procedure ReadRawImageFromStream(Stream: TStream; Width, Height: Integer; + Format: TImageFormat; var Image: TImageData; Offset: Integer = 0; RowLength: Integer = 0); +procedure ReadRawImageFromMemory(Data: Pointer; DataSize: Integer; Width, Height: Integer; + Format: TImageFormat; var Image: TImageData; Offset: Integer = 0; RowLength: Integer = 0); +procedure ReadRawImageRect(Data: Pointer; Left, Top, Width, Height: Integer; + var Image: TImageData; Offset: Integer = 0; RowLength: Integer = 0); + +procedure WriteRawImageToFile(const FileName: string; const Image: TImageData; + Offset: Integer = 0; RowLength: Integer = 0); +procedure WriteRawImageToStream(Stream: TStream; const Image: TImageData; + Offset: Integer = 0; RowLength: Integer = 0); +procedure WriteRawImageToMemory(Data: Pointer; DataSize: Integer; const Image: TImageData; + Offset: Integer = 0; RowLength: Integer = 0); +procedure WriteRawImageRect(Data: Pointer; Left, Top, Width, Height: Integer; + const Image: TImageData; Offset: Integer = 0; RowLength: Integer = 0); + +{ Convenience/helper Functions } + +procedure ResizeImageToFit(const SrcImage: TImageData; FitWidth, FitHeight: Integer; + Filter: TResizeFilter; var DestImage: TImageData); + + +{ ------------------------------------------------------------------------ + Other Imaging Stuff + ------------------------------------------------------------------------} + +type + { Set of TImageFormat enum.} + TImageFormats = set of TImageFormat; + + { Record containg set of IO functions internaly used by image loaders/savers.} + TIOFunctions = record + Open: TOpenProc; + Close: TCloseProc; + Eof: TEofProc; + Seek: TSeekProc; + Tell: TTellProc; + Read: TReadProc; + Write: TWriteProc; + end; + PIOFunctions = ^TIOFunctions; + +type + TFileFormatFeature = ( + ffLoad, + ffSave, + ffMultiImage, + ffReadOnSave, + ffProgress, + ffReadScanlines); + + TFileFormatFeatures = set of TFileFormatFeature; + + TMetadata = class; + + { Base class for various image file format loaders/savers which + descend from this class. If you want to add support for new image file + format the best way is probably to look at TImageFileFormat descendants' + implementations that are already part of Imaging.} +{$TYPEINFO ON} + TImageFileFormat = class + private + FExtensions: TStringList; + FMasks: TStringList; + function GetCanLoad: Boolean; + function GetCanSave: Boolean; + function GetIsMultiImageFormat: Boolean; + { Does various checks and actions before LoadData method is called.} + function PrepareLoad(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstFrame: Boolean): Boolean; + { Processes some actions according to result of LoadData.} + function PostLoadCheck(var Images: TDynImageDataArray; LoadResult: Boolean): Boolean; + { Helper function to be called in SaveData methods of descendants (ensures proper + index and sets FFirstIdx and FLastIdx for multi-images).} + function PrepareSave(Handle: TImagingHandle; const Images: TDynImageDataArray; + var Index: LongInt): Boolean; + { Returns file open mode used for saving images. Depends on defined Features.} + function GetSaveOpenMode: TOpenMode; + protected + FName: string; + FFeatures: TFileFormatFeatures; + FSupportedFormats: TImageFormats; + FFirstIdx, FLastIdx: LongInt; + FMetadata: TMetadata; + { Descendants must override this method and define file format name and + capabilities.} + procedure Define; virtual; + { Defines filename masks for this image file format. AMasks should be + in format '*.ext1,*.ext2,umajo.*'.} + procedure AddMasks(const AMasks: string); + function GetFormatInfo(Format: TImageFormat): TImageFormatInfo; + { Returns set of TImageData formats that can be saved in this file format + without need for conversion.} + function GetSupportedFormats: TImageFormats; virtual; + { Method which must be overrided in descendants if they' are be capable + of loading images. Images are already freed and length is set to zero + whenever this method gets called. Also Handle is assured to be valid + and contains data that passed TestFormat method's check.} + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstFrame: Boolean): Boolean; virtual; + { Method which must be overriden in descendants if they are be capable + of saving images. Images are checked to have length >0 and + that they contain valid images. For single-image file formats + Index contain valid index to Images array (to image which should be saved). + Multi-image formats should use FFirstIdx and FLastIdx fields to + to get all images that are to be saved.} + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; virtual; + { This method is called internaly by MakeCompatible when input image + is in format not supported by this file format. Image is clone of + MakeCompatible's input and Info is its extended format info.} + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); virtual; + { Returns True if given image is supported for saving by this file format. + Most file formats don't need to override this method. It checks + (in this base class) if Image's format is in SupportedFromats set. + But you may override it if you want further checks + (proper widht and height for example).} + function IsSupported(const Image: TImageData): Boolean; virtual; + public + constructor Create(AMetadata: TMetadata = nil); virtual; + destructor Destroy; override; + + { Loads images from file source.} + function LoadFromFile(const FileName: string; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean = False): Boolean; + { Loads images from stream source.} + function LoadFromStream(Stream: TStream; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean = False): Boolean; + { Loads images from memory source.} + function LoadFromMemory(Data: Pointer; Size: LongInt; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean = False): Boolean; + + { Saves images to file. If format supports only single level images and + there are multiple images to be saved, they are saved as sequence of + independent images (for example SaveToFile saves sequence of + files img000.jpg, img001.jpg ....).} + function SaveToFile(const FileName: string; const Images: TDynImageDataArray; + OnlyFirstLevel: Boolean = False): Boolean; + { Saves images to stream. If format supports only single level images and + there are multiple images to be saved, they are saved as sequence of + independent images.} + function SaveToStream(Stream: TStream; const Images: TDynImageDataArray; + OnlyFirstLevel: Boolean = False): Boolean; + { Saves images to memory. If format supports only single level images and + there are multiple images to be saved, they are saved as sequence of + independent images. Data must be already allocated and their size passed + as Size parameter, number of written bytes is then returned in the same + parameter.} + function SaveToMemory(Data: Pointer; var Size: LongInt; + const Images: TDynImageDataArray; OnlyFirstLevel: Boolean = False): Boolean; + + { Makes Image compatible with this file format (that means it is in one + of data formats in Supported formats set). If input is already + in supported format then Compatible just use value from input + (Compatible := Image) so must not free it after you are done with it + (image bits pointer points to input image's bits). + If input is not in supported format then it is cloned to Compatible + and concerted to one of supported formats (which one dependeds on + this file format). If image is cloned MustBeFreed is set to True + to indicated that you must free Compatible after you are done with it.} + function MakeCompatible(const Image: TImageData; var Compatible: TImageData; + out MustBeFreed: Boolean): Boolean; + { Returns True if data located in source identified by Handle + represent valid image in current format.} + function TestFormat(Handle: TImagingHandle): Boolean; virtual; + { Resturns True if the given FileName matches filter for this file format. + For most formats it just checks filename extensions. + It uses filename masks in from Masks property so it can recognize + filenames like this 'umajoXXXumajo.j0j' if one of themasks is + 'umajo*umajo.j?j'.} + function TestFileName(const FileName: string): Boolean; + { Descendants use this method to check if their options (registered with + constant Ids for SetOption/GetOption interface or accessible as properties + of descendants) have valid values and make necessary changes.} + procedure CheckOptionsValidity; virtual; + + { Description of this format.} + property Name: string read FName; + { Indicates whether images in this format can be loaded.} + property CanLoad: Boolean read GetCanLoad; + { Indicates whether images in this format can be saved.} + property CanSave: Boolean read GetCanSave; + { Indicates whether images in this format can contain multiple image levels.} + property IsMultiImageFormat: Boolean read GetIsMultiImageFormat; + { List of filename extensions for this format.} + property Extensions: TStringList read FExtensions; + { List of filename masks that are used to associate filenames + with TImageFileFormat descendants. Typical mask looks like + '*.bmp' or 'texture.*' (supports file formats which use filename instead + of extension to identify image files).} + property Masks: TStringList read FMasks; + { Set of TImageFormats supported by saving functions of this format. Images + can be saved only in one those formats.} + property SupportedFormats: TImageFormats read GetSupportedFormats; + end; +{$TYPEINFO OFF} + + { Class reference for TImageFileFormat class} + TImageFileFormatClass = class of TImageFileFormat; + + { Physical resolution unit.} + TResolutionUnit = ( + ruSizeInMicroMeters, // value is pixel size in micrometers + ruDpi, // value is pixels/dots per inch + ruDpm, // value is pixels/dots per meter + ruDpcm // value is pixels/dots per centimeter + ); + + { Class for storage of single metadata item.} + TMetadataItem = class + public + Id: string; + ImageIndex: Integer; + Value: Variant; + end; + + { Metadata manager class.} + TMetadata = class + private + FLoadMetaItems: TStringList; + FSaveMetaItems: TStringList; + procedure AddMetaToList(List: TStringList; const Id: string; const Value: Variant; ImageIndex: Integer); + procedure ClearMetaList(List: TStringList); + function GetMetaById(const Id: string): Variant; + function GetMetaByIdMulti(const Id: string; ImageIndex: Integer): Variant; + function GetMetaCount: Integer; + function GetMetaByIdx(Index: Integer): TMetadataItem; + function GetSaveMetaById(const Id: string): Variant; + function GetSaveMetaByIdMulti(const Id: string; ImageIndex: Integer): Variant; + procedure TranslateUnits(ResolutionUnit: TResolutionUnit; var XRes, YRes: Single); + public + constructor Create; + destructor Destroy; override; + + procedure SetMetaItem(const Id: string; const Value: Variant; ImageIndex: Integer = 0); + procedure SetMetaItemForSaving(const Id: string; const Value: Variant; ImageIndex: Integer = 0); + function HasMetaItem(const Id: string; ImageIndex: Integer = 0): Boolean; + function HasMetaItemForSaving(const Id: string; ImageIndex: Integer = 0): Boolean; + + procedure ClearMetaItems; + procedure ClearMetaItemsForSaving; + function GetMetaItemName(const Id: string; ImageIndex: Integer): string; + { Copies loaded meta items to items-for-save stack. Use this when you want to + save metadata that have been just loaded (e.g. resaving image in + different file format but keeping the metadata).} + procedure CopyLoadedMetaItemsForSaving; + + function GetPhysicalPixelSize(ResUnit: TResolutionUnit; var XSize, + YSize: Single; MetaForSave: Boolean = False; ImageIndex: Integer = 0): Boolean; + procedure SetPhysicalPixelSize(ResUnit: TResolutionUnit; XSize, YSize: Single; + MetaForSave: Boolean = False; ImageIndex: Integer = 0); + + property MetaItems[const Id: string]: Variant read GetMetaById; + property MetaItemsMulti[const Id: string; ImageIndex: Integer]: Variant read GetMetaByIdMulti; + { Number of loaded metadata items.} + property MetaItemCount: Integer read GetMetaCount; + property MetaItemsByIdx[Index: Integer]: TMetadataItem read GetMetaByIdx; + property MetaItemsForSaving[const Id: string]: Variant read GetSaveMetaById; + property MetaItemsForSavingMulti[const Id: string; ImageIndex: Integer]: Variant read GetSaveMetaByIdMulti; + end; + +const + { Metadata item id constants } + + { Physical size of one pixel in micrometers. Type of value is Float.} + SMetaPhysicalPixelSizeX = 'PhysicalPixelSizeX'; + SMetaPhysicalPixelSizeY = 'PhysicalPixelSizeY'; + { Delay for frame of animation (how long it should stay visible) in milliseconds. + Type of value is Integer.} + SMetaFrameDelay = 'FrameDelay'; + { Number of times animation should be looped (0 = infinite looping). Type is Int. } + SMetaAnimationLoops = 'AnimationLoops'; + { Gamma correction value. Type is Float.} + SMetaGamma = 'Gamma'; + { Exposure value for HDR etc. Type is Float.} + SMetaExposure = 'Exposure'; + { EXIF image metadata raw blob.} + SMetaExifBlob = 'ExifBlob'; + { XMP image metadata raw blob.} + SMetaXmpBlob = 'XmpBlob'; + { IPTC image metadata raw blob.} + SMetaIptcBlob = 'IptcBlob'; + +var + GlobalMetadata: TMetadata; + +{ Returns symbolic name of given format.} +function GetFormatName(Format: TImageFormat): string; +{ Returns string with information about given Image.} +function ImageToStr(const Image: TImageData): string; +{ Returns Imaging version string in format 'Major.Minor.Patch'.} +function GetVersionStr: string; +{ If Condition is True then TruePart is retured, otherwise FalsePart is returned.} +function IffFormat(Condition: Boolean; const TruePart, FalsePart: TImageFormat): TImageFormat; + +{ Registers new option so it can be used by SetOption and GetOption functions. + Returns True if registration was succesful - that is Id is valid and is + not already taken by another option.} +function RegisterOption(OptionId: LongInt; Variable: PLongInt): Boolean; + +{ Registers new image loader/saver so it can be used by LoadFrom/SaveTo + functions.} +procedure RegisterImageFileFormat(AClass: TImageFileFormatClass); +{ Returns image format loader/saver according to given extension + or nil if not found.} +function FindImageFileFormatByExt(const Ext: string): TImageFileFormat; +{ Returns image format loader/saver according to given filename + or nil if not found.} +function FindImageFileFormatByName(const FileName: string): TImageFileFormat; +{ Returns image format loader/saver based on its class + or nil if not found or not registered.} +function FindImageFileFormatByClass(AClass: TImageFileFormatClass): TImageFileFormat; +{ Returns number of registered image file format loaders/saver.} +function GetFileFormatCount: LongInt; +{ Returns image file format loader/saver at given index. Index must be + in range [0..GetFileFormatCount - 1] otherwise nil is returned.} +function GetFileFormatAtIndex(Index: LongInt): TImageFileFormat; +{ Returns filter string for usage with open and save picture dialogs + which contains all registered image file formats. + Set OpenFileFilter to True if you want filter for open dialog + and to False if you want save dialog filter (formats that cannot save to files + are not added then). + For open dialog filter for all known graphic files + (like All(*.jpg;*.png;....) is added too at the first index.} +function GetImageFileFormatsFilter(OpenFileFilter: Boolean): string; +{ Returns file extension (without dot) of image format selected + by given filter index. Used filter string is defined by GetImageFileFormatsFilter + function. This function can be used with save dialogs (with filters created + by GetImageFileFormatsFilter) to get the extension of file format selected + in dialog quickly. Index is in range 1..N (as FilterIndex property + of TOpenDialog/TSaveDialog)} +function GetFilterIndexExtension(Index: LongInt; OpenFileFilter: Boolean): string; +{ Returns filter index of image file format of file specified by FileName. Used filter + string is defined by GetImageFileFormatsFilter function. + Returned index is in range 1..N (as FilterIndex property of TOpenDialog/TSaveDialog)} +function GetFileNameFilterIndex(const FileName: string; OpenFileFilter: Boolean): LongInt; + +{ Returns current IO functions.} +function GetIO: TIOFunctions; +{ Raises EImagingError with given message.} +procedure RaiseImaging(const Msg: string; const Args: array of const); overload; +procedure RaiseImaging(const Msg: string); overload; {$IFDEF USE_INLINE}inline;{$ENDIF} + +const + SImagingLibTitle = 'Vampyre Imaging Library'; + +implementation + +uses +{$IFNDEF DONT_LINK_BITMAP} + ImagingBitmap, +{$ENDIF} +{$IFNDEF DONT_LINK_JPEG} + ImagingJpeg, +{$ENDIF} +{$IF not Defined(DONT_LINK_PNG) or not Defined(DONT_LINK_MNG) or not Defined(DONT_LINK_JNG)} + ImagingNetworkGraphics, +{$IFEND} +{$IFNDEF DONT_LINK_GIF} + ImagingGif, +{$ENDIF} +{$IFNDEF DONT_LINK_DDS} + ImagingDds, +{$ENDIF} +{$IFNDEF DONT_LINK_TARGA} + ImagingTarga, +{$ENDIF} +{$IFNDEF DONT_LINK_PNM} + ImagingPortableMaps, +{$ENDIF} +{$IFNDEF DONT_LINK_RADHDR} + ImagingRadiance, +{$ENDIF} +{$IFNDEF DONT_LINK_EXTRAS} + ImagingExtras, +{$ENDIF} + //ImagingDebug, + ImagingFormats, ImagingUtility, ImagingIO, Variants; + +resourcestring + SExceptMsg = 'Exception Message'; + SAllFilter = 'All Images'; + SUnknownFormat = 'Unknown and unsupported format'; + + SErrorFreeImage = 'Error while freeing image. %s'; + SErrorCloneImage = 'Error while cloning image. %s'; + SErrorFlipImage = 'Error while flipping image. %s'; + SErrorMirrorImage = 'Error while mirroring image. %s'; + SErrorResizeImage = 'Error while resizing image. %s'; + SErrorSwapImage = 'Error while swapping channels of image. %s'; + SFileFormatCanNotLoad = 'Image Format "%s" does not support loading images.'; + SFileFormatCanNotSave = 'Image Format "%s" does not support saving images.'; + SErrorNewImage = 'Error while creating image data with params: Width=%d ' + + 'Height=%d Format=%s.'; + SErrorConvertImage = 'Error while converting image to format "%s". %s'; + SImageInfo = 'Image @%p info: Width = %dpx, Height = %dpx, ' + + 'Format = %s, Size = %.0n %s, Bits @%p, Palette @%p.'; + SImageInfoInvalid = 'Access violation encountered when getting info on ' + + 'image at address %p.'; + SFileNotValid = 'File "%s" is not valid image in "%s" format.'; + SStreamNotValid = 'Stream %p does not contain valid image in "%s" format.'; + SMemoryNotValid = 'Memory %p (%d Bytes) does not contain valid image ' + + 'in "%s" format.'; + SErrorLoadingFile = 'Error while loading images from file "%s" (file format: %s).'; + SErrorLoadingStream = 'Error while loading images from stream %p (file format: %s).'; + SErrorLoadingMemory = 'Error while loading images from memory %p (%d Bytes) (file format: %s).'; + SErrorSavingFile = 'Error while saving images to file "%s" (file format: %s).'; + SErrorSavingStream = 'Error while saving images to stream %p (file format: %s).'; + SErrorSavingMemory = 'Error while saving images to memory %p (%d Bytes) (file format: %s).'; + SErrorFindColor = 'Error while finding color in palette @%p with %d entries.'; + SErrorGrayscalePalette = 'Error while filling grayscale palette @%p with %d entries.'; + SErrorCustomPalette = 'Error while filling custom palette @%p with %d entries.'; + SErrorSwapPalette = 'Error while swapping channels of palette @%p with %d entries.'; + SErrorReduceColors = 'Error while reducing number of colors of image to %d. %s'; + SErrorGenerateMipMaps = 'Error while generating %d mipmap levels for image %s'; + SImagesNotValid = 'One or more images are not valid.'; + SErrorCopyRect = 'Error while copying rect from image %s to image %s.'; + SErrorMapImage = 'Error while mapping image %s to palette.'; + SErrorFillRect = 'Error while filling rectangle X:%d Y:%d W:%d H:%d in image %s'; + SErrorSplitImage = 'Error while splitting image %s to %dx%d sized chunks.'; + SErrorMakePaletteForImages = 'Error while making %d color palette for %d images.'; + SErrorNewPalette = 'Error while creating new palette with %d entries'; + SErrorFreePalette = 'Error while freeing palette @%p'; + SErrorCopyPalette = 'Error while copying %d entries from palette @%p to @%p'; + SErrorReplaceColor = 'Error while replacing colors in rectangle X:%d Y:%d W:%d H:%d of image %s'; + SErrorRotateImage = 'Error while rotating image %s by %.2n degrees'; + SErrorStretchRect = 'Error while stretching rect from image %s to image %s.'; + SErrorEmptyStream = 'Input stream has no data. Check Position property.'; + SErrorInvalidInputImage = 'Invalid input image.'; + + SErrorBadImage = 'Bad image detected.'; + +const + // Initial size of array with options information + InitialOptions = 256; + // Max depth of the option stack + OptionStackDepth = 8; + // Do not change the default format now, its too late + DefaultImageFormat: TImageFormat = ifA8R8G8B8; + // Format used to create metadata IDs for frames loaded form multiimages. + SMetaIdForSubImage = '%s/%d'; + +type + TOptionArray = array of PLongInt; + TOptionValueArray = array of LongInt; + + TOptionStack = class(TObject) + private + FStack: array[0..OptionStackDepth - 1] of TOptionValueArray; + FPosition: LongInt; + public + constructor Create; + destructor Destroy; override; + function Push: Boolean; + function Pop: Boolean; + end; + +var + // Currently set IO functions + IO: TIOFunctions; + // List with all registered TImageFileFormat classes + ImageFileFormats: TList = nil; + // Aarray with registered options (pointers to their values) + Options: TOptionArray = nil; + // Array containing addional infomation about every image format + ImageFormatInfos: TImageFormatInfoArray; + // Stack used by PushOptions/PopOtions functions + OptionStack: TOptionStack = nil; +var + // Variable for ImagingColorReduction option + ColorReductionMask: LongInt = $FF; + // Variable for ImagingLoadOverrideFormat option + LoadOverrideFormat: TImageFormat = ifUnknown; + // Variable for ImagingSaveOverrideFormat option + SaveOverrideFormat: TImageFormat = ifUnknown; + // Variable for ImagingSaveOverrideFormat option + MipMapFilter: TSamplingFilter = sfLinear; + // Variable for ImagingBinaryTreshold option + BinaryTreshold: Integer = 128; + +{ Exceptions } + +constructor EImagingBadImage.Create; +begin + inherited Create(SErrorBadImage); +end; + +{ Internal unit functions } + +{ Modifies option value to be in the allowed range. Works only + for options registered in this unit.} +function CheckOptionValue(OptionId, Value: LongInt): LongInt; forward; +{ Sets IO functions to file IO.} +procedure SetFileIO; forward; +{ Sets IO functions to stream IO.} +procedure SetStreamIO; forward; +{ Sets IO functions to memory IO.} +procedure SetMemoryIO; forward; +{ Inits image format infos array.} +procedure InitImageFormats; forward; +{ Freew image format infos array.} +procedure FreeImageFileFormats; forward; +{ Creates options array and stack.} +procedure InitOptions; forward; +{ Frees options array and stack.} +procedure FreeOptions; forward; + +function UpdateExceptMessage(E: Exception; const MsgToPrepend: string; const Args: array of const): Exception; +begin + Result := E; + E.Message := Format(MsgToPrepend, Args) + ' ' + SExceptMsg + ': ' + E.Message +end; + +{ ------------------------------------------------------------------------ + Low Level Interface Functions + ------------------------------------------------------------------------} + +{ General Functions } + +procedure InitImage(var Image: TImageData); +begin + FillChar(Image, SizeOf(Image), 0); +end; + +function NewImage(Width, Height: LongInt; Format: TImageFormat; var Image: + TImageData): Boolean; +var + FInfo: PImageFormatInfo; +begin + Assert((Width > 0) and (Height >0)); + Assert(IsImageFormatValid(Format)); + Result := False; + FreeImage(Image); + try + Image.Width := Width; + Image.Height := Height; + // Select default data format if selected + if (Format = ifDefault) then + Image.Format := DefaultImageFormat + else + Image.Format := Format; + // Get extended format info + FInfo := ImageFormatInfos[Image.Format]; + if FInfo = nil then + begin + InitImage(Image); + Exit; + end; + // Check image dimensions and calculate its size in bytes + FInfo.CheckDimensions(FInfo.Format, Image.Width, Image.Height); + Image.Size := FInfo.GetPixelsSize(FInfo.Format, Image.Width, Image.Height); + if Image.Size = 0 then + begin + InitImage(Image); + Exit; + end; + // Image bits are allocated and set to zeroes + GetMem(Image.Bits, Image.Size); + FillChar(Image.Bits^, Image.Size, 0); + // Palette is allocated and set to zeroes + if FInfo.PaletteEntries > 0 then + begin + GetMem(Image.Palette, FInfo.PaletteEntries * SizeOf(TColor32Rec)); + FillChar(Image.Palette^, FInfo.PaletteEntries * SizeOf(TColor32Rec), 0); + end; + Result := TestImage(Image); + except + on E: Exception do + begin + FreeMem(Image.Bits); + FreeMem(Image.Palette); + InitImage(Image); + raise UpdateExceptMessage(E, SErrorNewImage, [Width, Height, GetFormatName(Format)]); + end; + end; +end; + +function TestImage(const Image: TImageData): Boolean; +begin + try + Result := (LongInt(Image.Format) >= LongInt(Low(TImageFormat))) and + (LongInt(Image.Format) <= LongInt(High(TImageFormat))) and + (ImageFormatInfos[Image.Format] <> nil) and + (Assigned(ImageFormatInfos[Image.Format].GetPixelsSize) and + (ImageFormatInfos[Image.Format].GetPixelsSize(Image.Format, + Image.Width, Image.Height) = Image.Size)); + except + // Possible int overflows or other errors + Result := False; + end; +end; + +procedure FreeImage(var Image: TImageData); +begin + try + if TestImage(Image) then + begin + FreeMemNil(Image.Bits); + FreeMemNil(Image.Palette); + end; + InitImage(Image); + except + raise UpdateExceptMessage(GetExceptObject, SErrorFreeImage, [ImageToStr(Image)]); + end; +end; + +procedure FreeImagesInArray(var Images: TDynImageDataArray); +var + I: LongInt; +begin + if Length(Images) > 0 then + begin + for I := 0 to Length(Images) - 1 do + FreeImage(Images[I]); + SetLength(Images, 0); + end; +end; + +function TestImagesInArray(const Images: TDynImageDataArray): Boolean; +var + I: LongInt; +begin + if Length(Images) > 0 then + begin + Result := True; + for I := 0 to Length(Images) - 1 do + begin + Result := Result and TestImage(Images[I]); + if not Result then + Break; + end; + end + else + Result := False; +end; + +function DetermineFileFormat(const FileName: string): string; +var + I: LongInt; + Fmt: TImageFileFormat; + Handle: TImagingHandle; +begin + Assert(FileName <> ''); + Result := ''; + SetFileIO; + Handle := IO.Open(PChar(FileName), omReadOnly); + try + // First file format according to FileName and test if the data in + // file is really in that format + for I := 0 to ImageFileFormats.Count - 1 do + begin + Fmt := TImageFileFormat(ImageFileFormats[I]); + if Fmt.TestFileName(FileName) and Fmt.TestFormat(Handle) then + begin + Result := Fmt.Extensions[0]; + Exit; + end; + end; + // No file format was found with filename search so try data-based search + for I := 0 to ImageFileFormats.Count - 1 do + begin + Fmt := TImageFileFormat(ImageFileFormats[I]); + if Fmt.TestFormat(Handle) then + begin + Result := Fmt.Extensions[0]; + Exit; + end; + end; + finally + IO.Close(Handle); + end; +end; + +function DetermineStreamFormat(Stream: TStream): string; +var + I: LongInt; + Fmt: TImageFileFormat; + Handle: TImagingHandle; +begin + Assert(Stream <> nil); + Result := ''; + SetStreamIO; + Handle := IO.Open(Pointer(Stream), omReadOnly); + try + for I := 0 to ImageFileFormats.Count - 1 do + begin + Fmt := TImageFileFormat(ImageFileFormats[I]); + if Fmt.TestFormat(Handle) then + begin + Result := Fmt.Extensions[0]; + Exit; + end; + end; + finally + IO.Close(Handle); + end; +end; + +function DetermineMemoryFormat(Data: Pointer; Size: LongInt): string; +var + I: LongInt; + Fmt: TImageFileFormat; + Handle: TImagingHandle; + IORec: TMemoryIORec; +begin + Assert((Data <> nil) and (Size > 0)); + Result := ''; + SetMemoryIO; + IORec.Data := Data; + IORec.Position := 0; + IORec.Size := Size; + Handle := IO.Open(@IORec, omReadOnly); + try + for I := 0 to ImageFileFormats.Count - 1 do + begin + Fmt := TImageFileFormat(ImageFileFormats[I]); + if Fmt.TestFormat(Handle) then + begin + Result := Fmt.Extensions[0]; + Exit; + end; + end; + finally + IO.Close(Handle); + end; +end; + +function IsFileFormatSupported(const FileName: string): Boolean; +begin + Result := FindImageFileFormatByName(FileName) <> nil; +end; + +function EnumFileFormats(var Index: LongInt; var Name, DefaultExt, Masks: string; + var CanSaveImages, IsMultiImageFormat: Boolean): Boolean; +var + FileFmt: TImageFileFormat; +begin + FileFmt := GetFileFormatAtIndex(Index); + Result := FileFmt <> nil; + if Result then + begin + Name := FileFmt.Name; + DefaultExt := FileFmt.Extensions[0]; + Masks := FileFmt.Masks.DelimitedText; + CanSaveImages := FileFmt.CanSave; + IsMultiImageFormat := FileFmt.IsMultiImageFormat; + Inc(Index); + end + else + begin + Name := ''; + DefaultExt := ''; + Masks := ''; + CanSaveImages := False; + IsMultiImageFormat := False; + end; +end; + +{ Loading Functions } + +function LoadImageFromFile(const FileName: string; var Image: TImageData): + Boolean; +var + Format: TImageFileFormat; + IArray: TDynImageDataArray; + I: LongInt; +begin + Assert(FileName <> ''); + Result := False; + Format := FindImageFileFormatByExt(DetermineFileFormat(FileName)); + if Format <> nil then + begin + FreeImage(Image); + Result := Format.LoadFromFile(FileName, IArray, True); + if Result and (Length(IArray) > 0) then + begin + Image := IArray[0]; + for I := 1 to Length(IArray) - 1 do + FreeImage(IArray[I]); + end + else + Result := False; + end; +end; + +function LoadImageFromStream(Stream: TStream; var Image: TImageData): Boolean; +var + Format: TImageFileFormat; + IArray: TDynImageDataArray; + I: LongInt; +begin + Assert(Stream <> nil); + if Stream.Size - Stream.Position = 0 then + RaiseImaging(SErrorEmptyStream, []); + Result := False; + Format := FindImageFileFormatByExt(DetermineStreamFormat(Stream)); + if Format <> nil then + begin + FreeImage(Image); + Result := Format.LoadFromStream(Stream, IArray, True); + if Result and (Length(IArray) > 0) then + begin + Image := IArray[0]; + for I := 1 to Length(IArray) - 1 do + FreeImage(IArray[I]); + end + else + Result := False; + end; +end; + +function LoadImageFromMemory(Data: Pointer; Size: LongInt; var Image: TImageData): Boolean; +var + Format: TImageFileFormat; + IArray: TDynImageDataArray; + I: LongInt; +begin + Assert((Data <> nil) and (Size > 0)); + Result := False; + Format := FindImageFileFormatByExt(DetermineMemoryFormat(Data, Size)); + if Format <> nil then + begin + FreeImage(Image); + Result := Format.LoadFromMemory(Data, Size, IArray, True); + if Result and (Length(IArray) > 0) then + begin + Image := IArray[0]; + for I := 1 to Length(IArray) - 1 do + FreeImage(IArray[I]); + end + else + Result := False; + end; +end; + +function LoadMultiImageFromFile(const FileName: string; var Images: + TDynImageDataArray): Boolean; +var + Format: TImageFileFormat; +begin + Assert(FileName <> ''); + Result := False; + Format := FindImageFileFormatByExt(DetermineFileFormat(FileName)); + if Format <> nil then + begin + FreeImagesInArray(Images); + Result := Format.LoadFromFile(FileName, Images); + end; +end; + +function LoadMultiImageFromStream(Stream: TStream; var Images: TDynImageDataArray): Boolean; +var + Format: TImageFileFormat; +begin + Assert(Stream <> nil); + if Stream.Size - Stream.Position = 0 then + RaiseImaging(SErrorEmptyStream, []); + Result := False; + Format := FindImageFileFormatByExt(DetermineStreamFormat(Stream)); + if Format <> nil then + begin + FreeImagesInArray(Images); + Result := Format.LoadFromStream(Stream, Images); + end; +end; + +function LoadMultiImageFromMemory(Data: Pointer; Size: LongInt; + var Images: TDynImageDataArray): Boolean; +var + Format: TImageFileFormat; +begin + Assert((Data <> nil) and (Size > 0)); + Result := False; + Format := FindImageFileFormatByExt(DetermineMemoryFormat(Data, Size)); + if Format <> nil then + begin + FreeImagesInArray(Images); + Result := Format.LoadFromMemory(Data, Size, Images); + end; +end; + +{ Saving Functions } + +function SaveImageToFile(const FileName: string; const Image: TImageData): Boolean; +var + Format: TImageFileFormat; + IArray: TDynImageDataArray; +begin + Assert(FileName <> ''); + Result := False; + Format := FindImageFileFormatByName(FileName); + if Format <> nil then + begin + SetLength(IArray, 1); + IArray[0] := Image; + Result := Format.SaveToFile(FileName, IArray, True); + end; +end; + +function SaveImageToStream(const Ext: string; Stream: TStream; + const Image: TImageData): Boolean; +var + Format: TImageFileFormat; + IArray: TDynImageDataArray; +begin + Assert((Ext <> '') and (Stream <> nil)); + Result := False; + Format := FindImageFileFormatByExt(Ext); + if Format <> nil then + begin + SetLength(IArray, 1); + IArray[0] := Image; + Result := Format.SaveToStream(Stream, IArray, True); + end; +end; + +function SaveImageToMemory(const Ext: string; Data: Pointer; var Size: LongInt; + const Image: TImageData): Boolean; +var + Format: TImageFileFormat; + IArray: TDynImageDataArray; +begin + Assert((Ext <> '') and (Data <> nil) and (Size > 0)); + Result := False; + Format := FindImageFileFormatByExt(Ext); + if Format <> nil then + begin + SetLength(IArray, 1); + IArray[0] := Image; + Result := Format.SaveToMemory(Data, Size, IArray, True); + end; +end; + +function SaveMultiImageToFile(const FileName: string; + const Images: TDynImageDataArray): Boolean; +var + Format: TImageFileFormat; +begin + Assert(FileName <> ''); + Result := False; + Format := FindImageFileFormatByName(FileName); + if Format <> nil then + Result := Format.SaveToFile(FileName, Images); +end; + +function SaveMultiImageToStream(const Ext: string; Stream: TStream; + const Images: TDynImageDataArray): Boolean; +var + Format: TImageFileFormat; +begin + Assert((Ext <> '') and (Stream <> nil)); + Result := False; + Format := FindImageFileFormatByExt(Ext); + if Format <> nil then + Result := Format.SaveToStream(Stream, Images); +end; + +function SaveMultiImageToMemory(const Ext: string; Data: Pointer; + var Size: LongInt; const Images: TDynImageDataArray): Boolean; +var + Format: TImageFileFormat; +begin + Assert((Ext <> '') and (Data <> nil) and (Size > 0)); + Result := False; + Format := FindImageFileFormatByExt(Ext); + if Format <> nil then + Result := Format.SaveToMemory(Data, Size, Images); +end; + +{ Manipulation Functions } + +function CloneImage(const Image: TImageData; var Clone: TImageData): Boolean; +var + Info: PImageFormatInfo; +begin + Result := False; + if TestImage(Image) then + try + if TestImage(Clone) and (Image.Bits <> Clone.Bits) then + FreeImage(Clone) + else + InitImage(Clone); + + Info := ImageFormatInfos[Image.Format]; + Clone.Width := Image.Width; + Clone.Height := Image.Height; + Clone.Format := Image.Format; + Clone.Size := Image.Size; + + if Info.PaletteEntries > 0 then + begin + GetMem(Clone.Palette, Info.PaletteEntries * SizeOf(TColor32Rec)); + Move(Image.Palette^, Clone.Palette^, Info.PaletteEntries * + SizeOf(TColor32Rec)); + end; + + GetMem(Clone.Bits, Clone.Size); + Move(Image.Bits^, Clone.Bits^, Clone.Size); + Result := True; + except + raise UpdateExceptMessage(GetExceptObject, SErrorCloneImage, [ImageToStr(Image)]); + end; +end; + +function ConvertImage(var Image: TImageData; DestFormat: TImageFormat): Boolean; +var + NewData: Pointer; + NewPal: PPalette32; + NewSize, NumPixels: LongInt; + SrcInfo, DstInfo: PImageFormatInfo; +begin + Assert(IsImageFormatValid(DestFormat)); + Result := False; + if TestImage(Image) then + with Image do + try + // If default format is set we use DefaultImageFormat + if DestFormat = ifDefault then + DestFormat := DefaultImageFormat; + SrcInfo := ImageFormatInfos[Format]; + DstInfo := ImageFormatInfos[DestFormat]; + if SrcInfo = DstInfo then + begin + // There is nothing to convert - src is alredy in dest format + Result := True; + Exit; + end; + // Exit Src or Dest format is invalid + if (SrcInfo = nil) or (DstInfo = nil) then Exit; + // If dest format is just src with swapped channels we call + // SwapChannels instead + if (SrcInfo.RBSwapFormat = DestFormat) and + (DstInfo.RBSwapFormat = SrcInfo.Format) then + begin + Result := SwapChannels(Image, ChannelRed, ChannelBlue); + Image.Format := SrcInfo.RBSwapFormat; + Exit; + end; + + if (not SrcInfo.IsSpecial) and (not DstInfo.IsSpecial) then + begin + NumPixels := Width * Height; + NewSize := NumPixels * DstInfo.BytesPerPixel; + GetMem(NewData, NewSize); + FillChar(NewData^, NewSize, 0); + GetMem(NewPal, DstInfo.PaletteEntries * SizeOf(TColor32Rec)); + FillChar(NewPal^, DstInfo.PaletteEntries * SizeOf(TColor32Rec), 0); + + if SrcInfo.IsIndexed then + begin + // Source: indexed format + if DstInfo.IsIndexed then + IndexToIndex(NumPixels, Bits, NewData, SrcInfo, DstInfo, Palette, NewPal) + else if DstInfo.HasGrayChannel then + IndexToGray(NumPixels, Bits, NewData, SrcInfo, DstInfo, Palette) + else if DstInfo.IsFloatingPoint then + IndexToFloat(NumPixels, Bits, NewData, SrcInfo, DstInfo, Palette) + else + IndexToChannel(NumPixels, Bits, NewData, SrcInfo, DstInfo, Palette); + end + else if SrcInfo.HasGrayChannel then + begin + // Source: grayscale format + if DstInfo.IsIndexed then + GrayToIndex(NumPixels, Bits, NewData, SrcInfo, DstInfo, NewPal) + else if DstInfo.HasGrayChannel then + GrayToGray(NumPixels, Bits, NewData, SrcInfo, DstInfo) + else if DstInfo.IsFloatingPoint then + GrayToFloat(NumPixels, Bits, NewData, SrcInfo, DstInfo) + else + GrayToChannel(NumPixels, Bits, NewData, SrcInfo, DstInfo); + end + else if SrcInfo.IsFloatingPoint then + begin + // Source: floating point format + if DstInfo.IsIndexed then + FloatToIndex(NumPixels, Bits, NewData, SrcInfo, DstInfo, NewPal) + else if DstInfo.HasGrayChannel then + FloatToGray(NumPixels, Bits, NewData, SrcInfo, DstInfo) + else if DstInfo.IsFloatingPoint then + FloatToFloat(NumPixels, Bits, NewData, SrcInfo, DstInfo) + else + FloatToChannel(NumPixels, Bits, NewData, SrcInfo, DstInfo); + end + else + begin + // Source: standard multi channel image + if DstInfo.IsIndexed then + ChannelToIndex(NumPixels, Bits, NewData, SrcInfo, DstInfo, NewPal) + else if DstInfo.HasGrayChannel then + ChannelToGray(NumPixels, Bits, NewData, SrcInfo, DstInfo) + else if DstInfo.IsFloatingPoint then + ChannelToFloat(NumPixels, Bits, NewData, SrcInfo, DstInfo) + else + ChannelToChannel(NumPixels, Bits, NewData, SrcInfo, DstInfo); + end; + + FreeMemNil(Bits); + FreeMemNil(Palette); + Format := DestFormat; + Bits := NewData; + Size := NewSize; + Palette := NewPal; + end + else + ConvertSpecial(Image, SrcInfo, DstInfo); + + Assert(SrcInfo.Format <> Image.Format); + + Result := True; + except + raise UpdateExceptMessage(GetExceptObject, SErrorConvertImage, [GetFormatName(DestFormat), ImageToStr(Image)]); + end; +end; + +function FlipImage(var Image: TImageData): Boolean; +var + P1, P2, Buff: Pointer; + WidthBytes, I: LongInt; + OldFmt: TImageFormat; +begin + Result := False; + OldFmt := Image.Format; + if TestImage(Image) then + with Image do + try + if ImageFormatInfos[OldFmt].IsSpecial then + ConvertImage(Image, ifDefault); + + WidthBytes := Width * ImageFormatInfos[Format].BytesPerPixel; + GetMem(Buff, WidthBytes); + try + // Swap all scanlines of image + for I := 0 to Height div 2 - 1 do + begin + P1 := @PByteArray(Bits)[I * WidthBytes]; + P2 := @PByteArray(Bits)[(Height - I - 1) * WidthBytes]; + Move(P1^, Buff^, WidthBytes); + Move(P2^, P1^, WidthBytes); + Move(Buff^, P2^, WidthBytes); + end; + finally + FreeMemNil(Buff); + end; + + if OldFmt <> Format then + ConvertImage(Image, OldFmt); + + Result := True; + except + RaiseImaging(SErrorFlipImage, [ImageToStr(Image)]); + end; +end; + +function MirrorImage(var Image: TImageData): Boolean; +var + Scanline: PByte; + Buff: TColorFPRec; + Bpp, Y, X, WidthDiv2, WidthBytes, XLeft, XRight: LongInt; + OldFmt: TImageFormat; +begin + Result := False; + OldFmt := Image.Format; + if TestImage(Image) then + with Image do + try + if ImageFormatInfos[OldFmt].IsSpecial then + ConvertImage(Image, ifDefault); + + Bpp := ImageFormatInfos[Format].BytesPerPixel; + WidthDiv2 := Width div 2; + WidthBytes := Width * Bpp; + // Mirror all pixels on each scanline of image + for Y := 0 to Height - 1 do + begin + Scanline := @PByteArray(Bits)[Y * WidthBytes]; + XLeft := 0; + XRight := (Width - 1) * Bpp; + for X := 0 to WidthDiv2 - 1 do + begin + CopyPixel(@PByteArray(Scanline)[XLeft], @Buff, Bpp); + CopyPixel(@PByteArray(Scanline)[XRight], + @PByteArray(Scanline)[XLeft], Bpp); + CopyPixel(@Buff, @PByteArray(Scanline)[XRight], Bpp); + Inc(XLeft, Bpp); + Dec(XRight, Bpp); + end; + end; + + if OldFmt <> Format then + ConvertImage(Image, OldFmt); + + Result := True; + except + RaiseImaging(SErrorMirrorImage, [ImageToStr(Image)]); + end; +end; + +function ResizeImage(var Image: TImageData; NewWidth, NewHeight: LongInt; + Filter: TResizeFilter): Boolean; +var + WorkImage: TImageData; +begin + Assert((NewWidth > 0) and (NewHeight > 0), 'New width or height is zero.'); + Result := False; + if TestImage(Image) and ((Image.Width <> NewWidth) or (Image.Height <> NewHeight)) then + try + InitImage(WorkImage); + // Create new image with desired dimensions + NewImage(NewWidth, NewHeight, Image.Format, WorkImage); + // Stretch pixels from old image to new one + StretchRect(Image, 0, 0, Image.Width, Image.Height, + WorkImage, 0, 0, WorkImage.Width, WorkImage.Height, Filter); + // Free old image and assign new image to it + FreeMemNil(Image.Bits); + if Image.Palette <> nil then + begin + FreeMem(WorkImage.Palette); + WorkImage.Palette := Image.Palette; + end; + Image := WorkImage; + Result := True; + except + raise UpdateExceptMessage(GetExceptObject, SErrorResizeImage, [ImageToStr(Image)]); + end; +end; + +function SwapChannels(var Image: TImageData; SrcChannel, DstChannel: LongInt): Boolean; +var + I, NumPixels: LongInt; + Info: PImageFormatInfo; + Swap, Alpha: Word; + Data: PByte; + Pix64: TColor64Rec; + PixF: TColorFPRec; + SwapF: Single; +begin + Assert((SrcChannel in [0..3]) and (DstChannel in [0..3])); + Result := False; + if TestImage(Image) and (SrcChannel <> DstChannel) then + with Image do + try + NumPixels := Width * Height; + Info := ImageFormatInfos[Format]; + Data := Bits; + + if (Info.Format = ifR8G8B8) or ((Info.Format = ifA8R8G8B8) and + (SrcChannel <> ChannelAlpha) and (DstChannel <> ChannelAlpha)) then + begin + // Swap channels of most common formats R8G8B8 and A8R8G8B8 (no alpha) + for I := 0 to NumPixels - 1 do + with PColor24Rec(Data)^ do + begin + Swap := Channels[SrcChannel]; + Channels[SrcChannel] := Channels[DstChannel]; + Channels[DstChannel] := Swap; + Inc(Data, Info.BytesPerPixel); + end; + end + else if Info.IsIndexed then + begin + // Swap palette channels of indexed images + SwapChannelsOfPalette(Palette, Info.PaletteEntries, SrcChannel, DstChannel) + end + else if Info.IsFloatingPoint then + begin + // Swap channels of floating point images + for I := 0 to NumPixels - 1 do + begin + FloatGetSrcPixel(Data, Info, PixF); + with PixF do + begin + SwapF := Channels[SrcChannel]; + Channels[SrcChannel] := Channels[DstChannel]; + Channels[DstChannel] := SwapF; + end; + FloatSetDstPixel(Data, Info, PixF); + Inc(Data, Info.BytesPerPixel); + end; + end + else if Info.IsSpecial then + begin + // Swap channels of special format images + ConvertImage(Image, ifDefault); + SwapChannels(Image, SrcChannel, DstChannel); + ConvertImage(Image, Info.Format); + end + else if Info.HasGrayChannel and Info.HasAlphaChannel and + ((SrcChannel = ChannelAlpha) or (DstChannel = ChannelAlpha)) then + begin + for I := 0 to NumPixels - 1 do + begin + // If we have grayscale image with alpha and alpha is channel + // to be swapped, we swap it. No other alternative for gray images, + // just alpha and something + GrayGetSrcPixel(Data, Info, Pix64, Alpha); + Swap := Alpha; + Alpha := Pix64.A; + Pix64.A := Swap; + GraySetDstPixel(Data, Info, Pix64, Alpha); + Inc(Data, Info.BytesPerPixel); + end; + end + else + begin + // Then do general swap on other channel image formats + for I := 0 to NumPixels - 1 do + begin + ChannelGetSrcPixel(Data, Info, Pix64); + with Pix64 do + begin + Swap := Channels[SrcChannel]; + Channels[SrcChannel] := Channels[DstChannel]; + Channels[DstChannel] := Swap; + end; + ChannelSetDstPixel(Data, Info, Pix64); + Inc(Data, Info.BytesPerPixel); + end; + end; + + Result := True; + except + RaiseImaging(SErrorSwapImage, [ImageToStr(Image)]); + end; +end; + +function ReduceColors(var Image: TImageData; MaxColors: LongInt): Boolean; +var + TmpInfo: TImageFormatInfo; + Data, Index: PWord; + I, NumPixels: LongInt; + Pal: PPalette32; + Col:PColor32Rec; + OldFmt: TImageFormat; +begin + Result := False; + if TestImage(Image) then + with Image do + try + // First create temp image info and allocate output bits and palette + MaxColors := ClampInt(MaxColors, 2, High(Word)); + OldFmt := Format; + FillChar(TmpInfo, SizeOf(TmpInfo), 0); + TmpInfo.PaletteEntries := MaxColors; + TmpInfo.BytesPerPixel := 2; + NumPixels := Width * Height; + GetMem(Data, NumPixels * TmpInfo.BytesPerPixel); + GetMem(Pal, MaxColors * SizeOf(TColor32Rec)); + ConvertImage(Image, ifA8R8G8B8); + // We use median cut algorithm to create reduced palette and to + // fill Data with indices to this palette + ReduceColorsMedianCut(NumPixels, Bits, PByte(Data), + ImageFormatInfos[Format], @TmpInfo, MaxColors, ColorReductionMask, Pal); + Col := Bits; + Index := Data; + // Then we write reduced colors to the input image + for I := 0 to NumPixels - 1 do + begin + Col.Color := Pal[Index^].Color; + Inc(Col); + Inc(Index); + end; + FreeMemNil(Data); + FreeMemNil(Pal); + // And convert it to its original format + ConvertImage(Image, OldFmt); + Result := True; + except + RaiseImaging(SErrorReduceColors, [MaxColors, ImageToStr(Image)]); + end; +end; + +function GenerateMipMaps(const Image: TImageData; Levels: LongInt; + var MipMaps: TDynImageDataArray): Boolean; +var + Width, Height, I, Count: LongInt; + Info: TImageFormatInfo; + CompatibleCopy: TImageData; +begin + Result := False; + if TestImage(Image) then + try + Width := Image.Width; + Height := Image.Height; + // We compute number of possible mipmap levels and if + // the given levels are invalid or zero we use this value + Count := GetNumMipMapLevels(Width, Height); + if (Levels <= 0) or (Levels > Count) then + Levels := Count; + + // If we have special format image we create copy to allow pixel access. + // This is also done in FillMipMapLevel which is called for each level + // but then the main big image would be converted to compatible + // for every level. + GetImageFormatInfo(Image.Format, Info); + if Info.IsSpecial then + begin + InitImage(CompatibleCopy); + CloneImage(Image, CompatibleCopy); + ConvertImage(CompatibleCopy, ifDefault); + end + else + CompatibleCopy := Image; + + FreeImagesInArray(MipMaps); + SetLength(MipMaps, Levels); + CloneImage(Image, MipMaps[0]); + + for I := 1 to Levels - 1 do + begin + Width := Width shr 1; + Height := Height shr 1; + if Width < 1 then Width := 1; + if Height < 1 then Height := 1; + FillMipMapLevel(CompatibleCopy, Width, Height, MipMaps[I]); + end; + + if CompatibleCopy.Format <> MipMaps[0].Format then + begin + // Must convert smaller levels to proper format + for I := 1 to High(MipMaps) do + ConvertImage(MipMaps[I], MipMaps[0].Format); + FreeImage(CompatibleCopy); + end; + + Result := True; + except + RaiseImaging(SErrorGenerateMipMaps, [Levels, ImageToStr(Image)]); + end; +end; + +function MapImageToPalette(var Image: TImageData; Pal: PPalette32; + Entries: LongInt): Boolean; + + function FindNearestColor(Pal: PPalette32; Entries: LongInt; Col: TColor32Rec): LongInt; + var + I, MinDif, Dif: LongInt; + begin + Result := 0; + MinDif := 1020; + for I := 0 to Entries - 1 do + with Pal[I] do + begin + Dif := Abs(R - Col.R); + if Dif > MinDif then Continue; + Dif := Dif + Abs(G - Col.G); + if Dif > MinDif then Continue; + Dif := Dif + Abs(B - Col.B); + if Dif > MinDif then Continue; + Dif := Dif + Abs(A - Col.A); + if Dif < MinDif then + begin + MinDif := Dif; + Result := I; + end; + end; + end; + +var + I, MaxEntries: LongInt; + PIndex: PByte; + PColor: PColor32Rec; + CloneARGB: TImageData; + Info: PImageFormatInfo; +begin + Assert((Entries >= 2) and (Entries <= 256)); + Result := False; + + if TestImage(Image) then + try + // We create clone of source image in A8R8G8B8 and + // then recreate source image in ifIndex8 format + // with palette taken from Pal parameter + InitImage(CloneARGB); + CloneImage(Image, CloneARGB); + ConvertImage(CloneARGB, ifA8R8G8B8); + FreeImage(Image); + NewImage(CloneARGB.Width, CloneARGB.Height, ifIndex8, Image); + + Info := ImageFormatInfos[Image.Format]; + MaxEntries := Min(Info.PaletteEntries, Entries); + Move(Pal^, Image.Palette^, MaxEntries * SizeOf(TColor32Rec)); + PIndex := Image.Bits; + PColor := CloneARGB.Bits; + + // For every pixel of ARGB clone we find closest color in + // given palette and assign its index to resulting image's pixel + // procedure used here is very slow but simple and memory usage friendly + // (contrary to other methods) + for I := 0 to Image.Width * Image.Height - 1 do + begin + PIndex^ := Byte(FindNearestColor(Image.Palette, MaxEntries, PColor^)); + Inc(PIndex); + Inc(PColor); + end; + + FreeImage(CloneARGB); + Result := True; + except + raise UpdateExceptMessage(GetExceptObject, SErrorMapImage, [ImageToStr(Image)]); + end; +end; + +function SplitImage(var Image: TImageData; var Chunks: TDynImageDataArray; + ChunkWidth, ChunkHeight: LongInt; var XChunks, YChunks: LongInt; + PreserveSize: Boolean; Fill: Pointer): Boolean; +var + X, Y, XTrunc, YTrunc: LongInt; + NotOnEdge: Boolean; + Info: PImageFormatInfo; + OldFmt: TImageFormat; +begin + Assert((ChunkWidth > 0) and (ChunkHeight > 0)); + Result := False; + OldFmt := Image.Format; + FreeImagesInArray(Chunks); + + if TestImage(Image) then + try + Info := ImageFormatInfos[Image.Format]; + if Info.IsSpecial then + ConvertImage(Image, ifDefault); + + // We compute make sure that chunks are not larger than source image or negative + ChunkWidth := ClampInt(ChunkWidth, 0, Image.Width); + ChunkHeight := ClampInt(ChunkHeight, 0, Image.Height); + // Number of chunks along X and Y axes is computed + XChunks := Trunc(Ceil(Image.Width / ChunkWidth)); + YChunks := Trunc(Ceil(Image.Height / ChunkHeight)); + SetLength(Chunks, XChunks * YChunks); + + // For every chunk we create new image and copy a portion of + // the source image to it. If chunk is on the edge of the source image + // we fill enpty space with Fill pixel data if PreserveSize is set or + // make the chunk smaller if it is not set + for Y := 0 to YChunks - 1 do + for X := 0 to XChunks - 1 do + begin + // Determine if current chunk is on the edge of original image + NotOnEdge := ((X < XChunks - 1) and (Y < YChunks - 1)) or + ((Image.Width mod ChunkWidth = 0) and (Image.Height mod ChunkHeight = 0)); + + if PreserveSize or NotOnEdge then + begin + // We should preserve chunk sizes or we are somewhere inside original image + NewImage(ChunkWidth, ChunkHeight, Image.Format, Chunks[Y * XChunks + X]); + if (not NotOnEdge) and (Fill <> nil) then + FillRect(Chunks[Y * XChunks + X], 0, 0, ChunkWidth, ChunkHeight, Fill); + CopyRect(Image, X * ChunkWidth, Y * ChunkHeight, ChunkWidth, ChunkHeight, + Chunks[Y * XChunks + X], 0, 0); + end + else + begin + // Create smaller edge chunk + XTrunc := Image.Width - X * ChunkWidth; + YTrunc := Image.Height - Y * ChunkHeight; + NewImage(XTrunc, YTrunc, Image.Format, Chunks[Y * XChunks + X]); + CopyRect(Image, X * ChunkWidth, Y * ChunkHeight, XTrunc, YTrunc, + Chunks[Y * XChunks + X], 0, 0); + end; + + // If source image is in indexed format we copy its palette to chunk + if Info.IsIndexed then + begin + Move(Image.Palette^, Chunks[Y * XChunks + X].Palette^, + Info.PaletteEntries * SizeOf(TColor32Rec)); + end; + end; + + if OldFmt <> Image.Format then + begin + ConvertImage(Image, OldFmt); + for X := 0 to Length(Chunks) - 1 do + ConvertImage(Chunks[X], OldFmt); + end; + + Result := True; + except + raise UpdateExceptMessage(GetExceptObject, SErrorSplitImage, + [ImageToStr(Image), ChunkWidth, ChunkHeight]); + end; +end; + +function MakePaletteForImages(var Images: TDynImageDataArray; Pal: PPalette32; + MaxColors: LongInt; ConvertImages: Boolean): Boolean; +var + I: Integer; + SrcInfo, DstInfo: PImageFormatInfo; + Target, TempImage: TImageData; + DstFormat: TImageFormat; +begin + Assert((Pal <> nil) and (MaxColors > 0)); + Result := False; + InitImage(TempImage); + + if TestImagesInArray(Images) then + try + // Null the color histogram + ReduceColorsMedianCut(0, nil, nil, nil, nil, 0, 0, nil, [raCreateHistogram]); + for I := 0 to Length(Images) - 1 do + begin + SrcInfo := ImageFormatInfos[Images[I].Format]; + if SrcInfo.IsIndexed or SrcInfo.IsSpecial then + begin + // create temp image in supported format for updating histogram + CloneImage(Images[I], TempImage); + ConvertImage(TempImage, ifA8R8G8B8); + SrcInfo := ImageFormatInfos[TempImage.Format]; + end + else + TempImage := Images[I]; + + // Update histogram with colors of each input image + ReduceColorsMedianCut(TempImage.Width * TempImage.Height, TempImage.Bits, + nil, SrcInfo, nil, MaxColors, ColorReductionMask, nil, [raUpdateHistogram]); + + if Images[I].Bits <> TempImage.Bits then + FreeImage(TempImage); + end; + // Construct reduced color map from the histogram + ReduceColorsMedianCut(0, nil, nil, nil, nil, MaxColors, ColorReductionMask, + Pal, [raMakeColorMap]); + + if ConvertImages then + begin + DstFormat := ifIndex8; + DstInfo := ImageFormatInfos[DstFormat]; + MaxColors := Min(DstInfo.PaletteEntries, MaxColors); + + for I := 0 to Length(Images) - 1 do + begin + SrcInfo := ImageFormatInfos[Images[I].Format]; + if SrcInfo.IsIndexed or SrcInfo.IsSpecial then + begin + // If source image is in format not supported by ReduceColorsMedianCut + // we convert it + ConvertImage(Images[I], ifA8R8G8B8); + SrcInfo := ImageFormatInfos[Images[I].Format]; + end; + + InitImage(Target); + NewImage(Images[I].Width, Images[I].Height, DstFormat, Target); + // We map each input image to reduced palette and replace + // image in array with mapped image + ReduceColorsMedianCut(Images[I].Width * Images[I].Height, Images[I].Bits, + Target.Bits, SrcInfo, DstInfo, MaxColors, 0, nil, [raMapImage]); + Move(Pal^, Target.Palette^, MaxColors * SizeOf(TColor32Rec)); + + FreeImage(Images[I]); + Images[I] := Target; + end; + end; + Result := True; + except + RaiseImaging(SErrorMakePaletteForImages, [MaxColors, Length(Images)]); + end; +end; + +procedure RotateImage(var Image: TImageData; Angle: Single); +var + OldFmt: TImageFormat; + + procedure XShear(var Src, Dst: TImageData; Row, Offset, Weight, Bpp: Integer); + var + I, J, XPos: Integer; + PixSrc, PixLeft, PixOldLeft: TColor32Rec; + LineDst: PByteArray; + SrcPtr: PColor32; + begin + SrcPtr := @PByteArray(Src.Bits)[Row * Src.Width * Bpp]; + LineDst := @PByteArray(Dst.Bits)[Row * Dst.Width * Bpp]; + PixOldLeft.Color := 0; + + for I := 0 to Src.Width - 1 do + begin + CopyPixel(SrcPtr, @PixSrc, Bpp); + for J := 0 to Bpp - 1 do + PixLeft.Channels[J] := MulDiv(PixSrc.Channels[J], Weight, 256); + + XPos := I + Offset; + if (XPos >= 0) and (XPos < Dst.Width) then + begin + for J := 0 to Bpp - 1 do + PixSrc.Channels[J] := ClampToByte(PixSrc.Channels[J] - (PixLeft.Channels[J] - PixOldLeft.Channels[J])); + CopyPixel(@PixSrc, @LineDst[XPos * Bpp], Bpp); + end; + PixOldLeft := PixLeft; + Inc(PByte(SrcPtr), Bpp); + end; + + XPos := Src.Width + Offset; + if XPos < Dst.Width then + CopyPixel(@PixOldLeft, @LineDst[XPos * Bpp], Bpp); + end; + + procedure YShear(var Src, Dst: TImageData; Col, Offset, Weight, Bpp: Integer); + var + I, J, YPos: Integer; + PixSrc, PixLeft, PixOldLeft: TColor32Rec; + SrcPtr: PByte; + begin + SrcPtr := @PByteArray(Src.Bits)[Col * Bpp]; + PixOldLeft.Color := 0; + + for I := 0 to Src.Height - 1 do + begin + CopyPixel(SrcPtr, @PixSrc, Bpp); + for J := 0 to Bpp - 1 do + PixLeft.Channels[J] := MulDiv(PixSrc.Channels[J], Weight, 256); + + YPos := I + Offset; + if (YPos >= 0) and (YPos < Dst.Height) then + begin + for J := 0 to Bpp - 1 do + PixSrc.Channels[J] := ClampToByte(PixSrc.Channels[J] - (PixLeft.Channels[J] - PixOldLeft.Channels[J])); + CopyPixel(@PixSrc, @PByteArray(Dst.Bits)[(YPos * Dst.Width + Col) * Bpp], Bpp); + end; + PixOldLeft := PixLeft; + Inc(SrcPtr, Src.Width * Bpp); + end; + + YPos := Src.Height + Offset; + if YPos < Dst.Height then + CopyPixel(@PixOldLeft, @PByteArray(Dst.Bits)[(YPos * Dst.Width + Col) * Bpp], Bpp); + end; + + procedure Rotate45(var Image: TImageData; Angle: Single); + var + TempImage1, TempImage2: TImageData; + AngleRad, AngleTan, AngleSin, AngleCos, Shear: Single; + I, DstWidth, DstHeight, SrcWidth, SrcHeight, Bpp: Integer; + SrcFmt, TempFormat: TImageFormat; + Info: TImageFormatInfo; + begin + AngleRad := Angle * Pi / 180; + AngleSin := Sin(AngleRad); + AngleCos := Cos(AngleRad); + AngleTan := Sin(AngleRad / 2) / Cos(AngleRad / 2); + SrcWidth := Image.Width; + SrcHeight := Image.Height; + SrcFmt := Image.Format; + + if not (SrcFmt in [ifR8G8B8..ifX8R8G8B8, ifGray8..ifGray32, ifA16Gray16]) then + ConvertImage(Image, ifA8R8G8B8); + + TempFormat := Image.Format; + GetImageFormatInfo(TempFormat, Info); + Bpp := Info.BytesPerPixel; + + // 1st shear (horizontal) + DstWidth := Trunc(SrcWidth + SrcHeight * Abs(AngleTan) + 0.5); + DstHeight := SrcHeight; + InitImage(TempImage1); + NewImage(DstWidth, DstHeight, TempFormat, TempImage1); + + for I := 0 to DstHeight - 1 do + begin + if AngleTan >= 0 then + Shear := (I + 0.5) * AngleTan + else + Shear := (I - DstHeight + 0.5) * AngleTan; + XShear(Image, TempImage1, I, Floor(Shear), Trunc(255 * (Shear - Floor(Shear)) + 1), Bpp); + end; + + // 2nd shear (vertical) + FreeImage(Image); + DstHeight := Trunc(SrcWidth * Abs(AngleSin) + SrcHeight * AngleCos + 0.5) + 1; + InitImage(TempImage2); + NewImage(DstWidth, DstHeight, TempFormat, TempImage2); + + if AngleSin >= 0 then + Shear := (SrcWidth - 1) * AngleSin + else + Shear := (SrcWidth - DstWidth) * -AngleSin; + + for I := 0 to DstWidth - 1 do + begin + YShear(TempImage1, TempImage2, I, Floor(Shear), Trunc(255 * (Shear - Floor(Shear)) + 1), Bpp); + Shear := Shear - AngleSin; + end; + + // 3rd shear (horizontal) + FreeImage(TempImage1); + DstWidth := Trunc(SrcHeight * Abs(AngleSin) + SrcWidth * AngleCos + 0.5) + 1; + NewImage(DstWidth, DstHeight, TempFormat, Image); + + if AngleSin >= 0 then + Shear := (SrcWidth - 1) * AngleSin * -AngleTan + else + Shear := ((SrcWidth - 1) * -AngleSin + (1 - DstHeight)) * AngleTan; + + for I := 0 to DstHeight - 1 do + begin + XShear(TempImage2, Image, I, Floor(Shear), Trunc(255 * (Shear - Floor(Shear)) + 1), Bpp); + Shear := Shear + AngleTan; + end; + + FreeImage(TempImage2); + if Image.Format <> SrcFmt then + ConvertImage(Image, SrcFmt); + end; + + procedure RotateMul90(var Image: TImageData; Angle: Integer); + var + RotImage: TImageData; + X, Y, BytesPerPixel: Integer; + RotPix, Pix: PByte; + begin + InitImage(RotImage); + BytesPerPixel := ImageFormatInfos[Image.Format].BytesPerPixel; + + if ((Angle = 90) or (Angle = 270)) and (Image.Width <> Image.Height) then + NewImage(Image.Height, Image.Width, Image.Format, RotImage) + else + NewImage(Image.Width, Image.Height, Image.Format, RotImage); + + RotPix := RotImage.Bits; + case Angle of + 90: + begin + for Y := 0 to RotImage.Height - 1 do + begin + Pix := @PByteArray(Image.Bits)[(Image.Width - Y - 1) * BytesPerPixel]; + for X := 0 to RotImage.Width - 1 do + begin + CopyPixel(Pix, RotPix, BytesPerPixel); + Inc(RotPix, BytesPerPixel); + Inc(Pix, Image.Width * BytesPerPixel); + end; + end; + end; + 180: + begin + Pix := @PByteArray(Image.Bits)[((Image.Height - 1) * Image.Width + + (Image.Width - 1)) * BytesPerPixel]; + for Y := 0 to RotImage.Height - 1 do + for X := 0 to RotImage.Width - 1 do + begin + CopyPixel(Pix, RotPix, BytesPerPixel); + Inc(RotPix, BytesPerPixel); + Dec(Pix, BytesPerPixel); + end; + end; + 270: + begin + for Y := 0 to RotImage.Height - 1 do + begin + Pix := @PByteArray(Image.Bits)[((Image.Height - 1) * Image.Width + Y) * BytesPerPixel]; + for X := 0 to RotImage.Width - 1 do + begin + CopyPixel(Pix, RotPix, BytesPerPixel); + Inc(RotPix, BytesPerPixel); + Dec(Pix, Image.Width * BytesPerPixel); + end; + end; + end; + end; + + FreeMemNil(Image.Bits); + RotImage.Palette := Image.Palette; + Image := RotImage; + end; + +begin + if TestImage(Image) then + try + while Angle >= 360 do + Angle := Angle - 360; + while Angle < 0 do + Angle := Angle + 360; + + if (Angle = 0) or (Abs(Angle) = 360) then + Exit; + + OldFmt := Image.Format; + if ImageFormatInfos[Image.Format].IsSpecial then + ConvertImage(Image, ifDefault); + + if (Angle > 45) and (Angle <= 135) then + begin + RotateMul90(Image, 90); + Angle := Angle - 90; + end + else if (Angle > 135) and (Angle <= 225) then + begin + RotateMul90(Image, 180); + Angle := Angle - 180; + end + else if (Angle > 225) and (Angle <= 315) then + begin + RotateMul90(Image, 270); + Angle := Angle - 270; + end; + + if Angle <> 0 then + Rotate45(Image, Angle); + + if OldFmt <> Image.Format then + ConvertImage(Image, OldFmt); + + except + raise UpdateExceptMessage(GetExceptObject, SErrorRotateImage, [ImageToStr(Image), Angle]); + end; +end; + +{ Drawing/Pixel functions } + +function CopyRect(const SrcImage: TImageData; SrcX, SrcY, Width, Height: LongInt; + var DstImage: TImageData; DstX, DstY: LongInt): Boolean; +var + Info: PImageFormatInfo; + I, SrcWidthBytes, DstWidthBytes, MoveBytes: LongInt; + SrcPointer, DstPointer: PByte; + WorkImage: TImageData; + OldFormat: TImageFormat; +begin + Result := False; + OldFormat := ifUnknown; + if TestImage(SrcImage) and TestImage(DstImage) then + try + // Make sure we are still copying image to image, not invalid pointer to protected memory + ClipCopyBounds(SrcX, SrcY, Width, Height, DstX, DstY, SrcImage.Width, SrcImage.Height, + Rect(0, 0, DstImage.Width, DstImage.Height)); + + if (Width > 0) and (Height > 0) then + begin + Info := ImageFormatInfos[DstImage.Format]; + if Info.IsSpecial then + begin + // If dest image is in special format we convert it to default + OldFormat := Info.Format; + ConvertImage(DstImage, ifDefault); + Info := ImageFormatInfos[DstImage.Format]; + end; + if SrcImage.Format <> DstImage.Format then + begin + // If images are in different format source is converted to dest's format + InitImage(WorkImage); + CloneImage(SrcImage, WorkImage); + ConvertImage(WorkImage, DstImage.Format); + end + else + WorkImage := SrcImage; + + MoveBytes := Width * Info.BytesPerPixel; + DstWidthBytes := DstImage.Width * Info.BytesPerPixel; + DstPointer := @PByteArray(DstImage.Bits)[DstY * DstWidthBytes + + DstX * Info.BytesPerPixel]; + SrcWidthBytes := WorkImage.Width * Info.BytesPerPixel; + SrcPointer := @PByteArray(WorkImage.Bits)[SrcY * SrcWidthBytes + + SrcX * Info.BytesPerPixel]; + + for I := 0 to Height - 1 do + begin + Move(SrcPointer^, DstPointer^, MoveBytes); + Inc(SrcPointer, SrcWidthBytes); + Inc(DstPointer, DstWidthBytes); + end; + // If dest image was in special format we convert it back + if OldFormat <> ifUnknown then + ConvertImage(DstImage, OldFormat); + // Working image must be freed if it is not the same as source image + if WorkImage.Bits <> SrcImage.Bits then + FreeImage(WorkImage); + + Result := True; + end; + except + RaiseImaging(SErrorCopyRect, [ImageToStr(SrcImage), ImageToStr(DstImage)]); + end; +end; + +function FillRect(var Image: TImageData; X, Y, Width, Height: LongInt; + FillColor: Pointer): Boolean; +var + Info: PImageFormatInfo; + I, J, ImageWidthBytes, RectWidthBytes, Bpp: Longint; + LinePointer, PixPointer: PByte; + OldFmt: TImageFormat; +begin + Result := False; + if TestImage(Image) then + try + ClipRectBounds(X, Y, Width, Height, Rect(0, 0, Image.Width, Image.Height)); + + if (Width > 0) and (Height > 0) then + begin + OldFmt := Image.Format; + if ImageFormatInfos[OldFmt].IsSpecial then + ConvertImage(Image, ifDefault); + + Info := ImageFormatInfos[Image.Format]; + Bpp := Info.BytesPerPixel; + ImageWidthBytes := Image.Width * Bpp; + RectWidthBytes := Width * Bpp; + LinePointer := @PByteArray(Image.Bits)[Y * ImageWidthBytes + X * Bpp]; + + for I := 0 to Height - 1 do + begin + case Bpp of + 1: FillMemoryByte(LinePointer, RectWidthBytes, PByte(FillColor)^); + 2: FillMemoryWord(LinePointer, RectWidthBytes, PWord(FillColor)^); + 4: FillMemoryLongWord(LinePointer, RectWidthBytes, PLongWord(FillColor)^); + else + PixPointer := LinePointer; + for J := 0 to Width - 1 do + begin + CopyPixel(FillColor, PixPointer, Bpp); + Inc(PixPointer, Bpp); + end; + end; + Inc(LinePointer, ImageWidthBytes); + end; + + if OldFmt <> Image.Format then + ConvertImage(Image, OldFmt); + end; + + Result := True; + except + RaiseImaging(SErrorFillRect, [X, Y, Width, Height, ImageToStr(Image)]); + end; +end; + +function ReplaceColor(var Image: TImageData; X, Y, Width, Height: LongInt; + OldColor, NewColor: Pointer): Boolean; +var + Info: PImageFormatInfo; + I, J, WidthBytes, Bpp: Longint; + LinePointer, PixPointer: PByte; + OldFmt: TImageFormat; +begin + Assert((OldColor <> nil) and (NewColor <> nil)); + Result := False; + if TestImage(Image) then + try + ClipRectBounds(X, Y, Width, Height, Rect(0, 0, Image.Width, Image.Height)); + + if (Width > 0) and (Height > 0) then + begin + OldFmt := Image.Format; + if ImageFormatInfos[OldFmt].IsSpecial then + ConvertImage(Image, ifDefault); + + Info := ImageFormatInfos[Image.Format]; + Bpp := Info.BytesPerPixel; + WidthBytes := Image.Width * Bpp; + LinePointer := @PByteArray(Image.Bits)[Y * WidthBytes + X * Bpp]; + + for I := 0 to Height - 1 do + begin + PixPointer := LinePointer; + for J := 0 to Width - 1 do + begin + if ComparePixels(PixPointer, OldColor, Bpp) then + CopyPixel(NewColor, PixPointer, Bpp); + Inc(PixPointer, Bpp); + end; + Inc(LinePointer, WidthBytes); + end; + + if OldFmt <> Image.Format then + ConvertImage(Image, OldFmt); + end; + + Result := True; + except + RaiseImaging(SErrorReplaceColor, [X, Y, Width, Height, ImageToStr(Image)]); + end; +end; + +function StretchRect(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt; Filter: TResizeFilter): Boolean; +var + Info: PImageFormatInfo; + WorkImage: TImageData; + OldFormat: TImageFormat; + Resampling: TSamplingFilter; +begin + Result := False; + OldFormat := ifUnknown; + if TestImage(SrcImage) and TestImage(DstImage) then + try + // Make sure we are still copying image to image, not invalid pointer to protected memory + ClipStretchBounds(SrcX, SrcY, SrcWidth, SrcHeight, DstX, DstY, DstWidth, DstHeight, + SrcImage.Width, SrcImage.Height, Rect(0, 0, DstImage.Width, DstImage.Height)); + + if (SrcWidth = DstWidth) and (SrcHeight = DstHeight) then + begin + // If source and dest rectangles have the same size call CopyRect + Result := CopyRect(SrcImage, SrcX, SrcY, SrcWidth, SrcHeight, DstImage, DstX, DstY); + end + else if (SrcWidth > 0) and (SrcHeight > 0) and (DstWidth > 0) and (DstHeight > 0) then + begin + // If source and dest rectangles don't have the same size we do stretch + Info := ImageFormatInfos[DstImage.Format]; + + if Info.IsSpecial then + begin + // If dest image is in special format we convert it to default + OldFormat := Info.Format; + ConvertImage(DstImage, ifDefault); + Info := ImageFormatInfos[DstImage.Format]; + end; + + if SrcImage.Format <> DstImage.Format then + begin + // If images are in different format source is converted to dest's format + InitImage(WorkImage); + CloneImage(SrcImage, WorkImage); + ConvertImage(WorkImage, DstImage.Format); + end + else + WorkImage := SrcImage; + + // Only pixel resize is supported for indexed images + if Info.IsIndexed then + Filter := rfNearest; + + if Filter = rfNearest then + begin + StretchNearest(WorkImage, SrcX, SrcY, SrcWidth, SrcHeight, + DstImage, DstX, DstY, DstWidth, DstHeight); + end + else + begin + Resampling := sfNearest; + case Filter of + rfBilinear: Resampling := sfLinear; + rfBicubic: Resampling := DefaultCubicFilter; + rfLanczos: Resampling := sfLanczos; + end; + StretchResample(WorkImage, SrcX, SrcY, SrcWidth, SrcHeight, + DstImage, DstX, DstY, DstWidth, DstHeight, Resampling); + end; + + // If dest image was in special format we convert it back + if OldFormat <> ifUnknown then + ConvertImage(DstImage, OldFormat); + // Working image must be freed if it is not the same as source image + if WorkImage.Bits <> SrcImage.Bits then + FreeImage(WorkImage); + + Result := True; + end; + except + RaiseImaging(SErrorStretchRect, [ImageToStr(SrcImage), ImageToStr(DstImage)]); + end; +end; + +procedure GetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer); +var + BytesPerPixel: LongInt; +begin + Assert(Pixel <> nil); + BytesPerPixel := ImageFormatInfos[Image.Format].BytesPerPixel; + CopyPixel(@PByteArray(Image.Bits)[(Y * Image.Width + X) * BytesPerPixel], + Pixel, BytesPerPixel); +end; + +procedure SetPixelDirect(const Image: TImageData; X, Y: LongInt; Pixel: Pointer); +var + BytesPerPixel: LongInt; +begin + Assert(Pixel <> nil); + BytesPerPixel := ImageFormatInfos[Image.Format].BytesPerPixel; + CopyPixel(Pixel, @PByteArray(Image.Bits)[(Y * Image.Width + X) * BytesPerPixel], + BytesPerPixel); +end; + +function GetPixel32(const Image: TImageData; X, Y: LongInt): TColor32Rec; +var + Info: PImageFormatInfo; + Data: PByte; +begin + Info := ImageFormatInfos[Image.Format]; + Data := @PByteArray(Image.Bits)[(Y * Image.Width + X) * Info.BytesPerPixel]; + Result := GetPixel32Generic(Data, Info, Image.Palette); +end; + +procedure SetPixel32(const Image: TImageData; X, Y: LongInt; const Color: TColor32Rec); +var + Info: PImageFormatInfo; + Data: PByte; +begin + Info := ImageFormatInfos[Image.Format]; + Data := @PByteArray(Image.Bits)[(Y * Image.Width + X) * Info.BytesPerPixel]; + SetPixel32Generic(Data, Info, Image.Palette, Color); +end; + +function GetPixelFP(const Image: TImageData; X, Y: LongInt): TColorFPRec; +var + Info: PImageFormatInfo; + Data: PByte; +begin + Info := ImageFormatInfos[Image.Format]; + Data := @PByteArray(Image.Bits)[(Y * Image.Width + X) * Info.BytesPerPixel]; + Result := GetPixelFPGeneric(Data, Info, Image.Palette); +end; + +procedure SetPixelFP(const Image: TImageData; X, Y: LongInt; const Color: TColorFPRec); +var + Info: PImageFormatInfo; + Data: PByte; +begin + Info := ImageFormatInfos[Image.Format]; + Data := @PByteArray(Image.Bits)[(Y * Image.Width + X) * Info.BytesPerPixel]; + SetPixelFPGeneric(Data, Info, Image.Palette, Color); +end; + +{ Palette Functions } + +procedure NewPalette(Entries: LongInt; var Pal: PPalette32); +begin + Assert((Entries > 2) and (Entries <= 65535)); + try + GetMem(Pal, Entries * SizeOf(TColor32Rec)); + FillChar(Pal^, Entries * SizeOf(TColor32Rec), $FF); + except + RaiseImaging(SErrorNewPalette, [Entries]); + end; +end; + +procedure FreePalette(var Pal: PPalette32); +begin + try + FreeMemNil(Pal); + except + RaiseImaging(SErrorFreePalette, [Pal]); + end; +end; + +procedure CopyPalette(SrcPal, DstPal: PPalette32; SrcIdx, DstIdx, Count: LongInt); +begin + Assert((SrcPal <> nil) and (DstPal <> nil)); + Assert((SrcIdx >= 0) and (DstIdx >= 0) and (Count >= 0)); + try + Move(SrcPal[SrcIdx], DstPal[DstIdx], Count * SizeOf(TColor32Rec)); + except + RaiseImaging(SErrorCopyPalette, [Count, SrcPal, DstPal]); + end; +end; + +function FindColor(Pal: PPalette32; Entries: LongInt; Color: TColor32): + LongInt; +var + Col: TColor32Rec; + I, MinDif, Dif: LongInt; +begin + Assert(Pal <> nil); + Result := -1; + Col.Color := Color; + try + // First try to find exact match + for I := 0 to Entries - 1 do + with Pal[I] do + begin + if (A = Col.A) and (R = Col.R) and + (G = Col.G) and (B = Col.B) then + begin + Result := I; + Exit; + end; + end; + + // If exact match was not found, find nearest color + MinDif := 1020; + for I := 0 to Entries - 1 do + with Pal[I] do + begin + Dif := Abs(R - Col.R); + if Dif > MinDif then Continue; + Dif := Dif + Abs(G - Col.G); + if Dif > MinDif then Continue; + Dif := Dif + Abs(B - Col.B); + if Dif > MinDif then Continue; + Dif := Dif + Abs(A - Col.A); + if Dif < MinDif then + begin + MinDif := Dif; + Result := I; + end; + end; + except + RaiseImaging(SErrorFindColor, [Pal, Entries]); + end; +end; + +procedure FillGrayscalePalette(Pal: PPalette32; Entries: LongInt); +var + I: LongInt; +begin + Assert(Pal <> nil); + try + for I := 0 to Entries - 1 do + with Pal[I] do + begin + A := $FF; + R := Byte(I); + G := Byte(I); + B := Byte(I); + end; + except + RaiseImaging(SErrorGrayscalePalette, [Pal, Entries]); + end; +end; + +procedure FillCustomPalette(Pal: PPalette32; Entries: LongInt; RBits, GBits, + BBits: Byte; Alpha: Byte = $FF); +var + I, TotalBits, MaxEntries: LongInt; +begin + Assert(Pal <> nil); + TotalBits := RBits + GBits + BBits; + MaxEntries := Min(Pow2Int(TotalBits), Entries); + FillChar(Pal^, Entries * SizeOf(TColor32Rec), 0); + try + for I := 0 to MaxEntries - 1 do + with Pal[I] do + begin + A := Alpha; + if RBits > 0 then + R := ((I shr Max(0, GBits + BBits - 1)) and (1 shl RBits - 1)) * 255 div (1 shl RBits - 1); + if GBits > 0 then + G := ((I shr Max(0, BBits - 1)) and (1 shl GBits - 1)) * 255 div (1 shl GBits - 1); + if BBits > 0 then + B := ((I shr 0) and (1 shl BBits - 1)) * 255 div (1 shl BBits - 1); + end; + except + RaiseImaging(SErrorCustomPalette, [Pal, Entries]); + end; +end; + +procedure SwapChannelsOfPalette(Pal: PPalette32; Entries, SrcChannel, + DstChannel: LongInt); +var + I: LongInt; + Swap: Byte; +begin + Assert(Pal <> nil); + Assert((SrcChannel in [0..3]) and (DstChannel in [0..3])); + try + for I := 0 to Entries - 1 do + with Pal[I] do + begin + Swap := Channels[SrcChannel]; + Channels[SrcChannel] := Channels[DstChannel]; + Channels[DstChannel] := Swap; + end; + except + RaiseImaging(SErrorSwapPalette, [Pal, Entries]); + end; +end; + +{ Options Functions } + +function SetOption(OptionId, Value: LongInt): Boolean; +begin + Result := False; + if (OptionId >= 0) and (OptionId < Length(Options)) and + (Options[OptionID] <> nil) then + begin + Options[OptionID]^ := CheckOptionValue(OptionId, Value); + Result := True; + end; +end; + +function GetOption(OptionId: LongInt): LongInt; +begin + Result := InvalidOption; + if (OptionId >= 0) and (OptionId < Length(Options)) and + (Options[OptionID] <> nil) then + begin + Result := Options[OptionID]^; + end; +end; + +function PushOptions: Boolean; +begin + Result := OptionStack.Push; +end; + +function PopOptions: Boolean; +begin + Result := OptionStack.Pop; +end; + +{ Image Format Functions } + +function GetImageFormatInfo(Format: TImageFormat; out Info: TImageFormatInfo): Boolean; +begin + FillChar(Info, SizeOf(Info), 0); + if ImageFormatInfos[Format] <> nil then + begin + Info := ImageFormatInfos[Format]^; + Result := True; + end + else + Result := False; +end; + +function GetPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; +begin + if ImageFormatInfos[Format] <> nil then + Result := ImageFormatInfos[Format].GetPixelsSize(Format, Width, Height) + else + Result := 0; +end; + +{ IO Functions } + +procedure SetUserFileIO(OpenProc: TOpenProc; + CloseProc: TCloseProc; EofProc: TEofProc; SeekProc: TSeekProc; TellProc: + TTellProc; ReadProc: TReadProc; WriteProc: TWriteProc); +begin + FileIO.Open := OpenProc; + FileIO.Close := CloseProc; + FileIO.Eof := EofProc; + FileIO.Seek := SeekProc; + FileIO.Tell := TellProc; + FileIO.Read := ReadProc; + FileIO.Write := WriteProc; +end; + +procedure ResetFileIO; +begin + FileIO := OriginalFileIO; +end; + +{ Raw Image IO Functions } + +procedure ReadRawImage(Handle: TImagingHandle; Width, Height: Integer; + Format: TImageFormat; out Image: TImageData; Offset, RowLength: Integer); +var + WidthBytes, I: Integer; + Info: PImageFormatInfo; +begin + Info := ImageFormatInfos[Format]; + // Calc scanline size + WidthBytes := Info.GetPixelsSize(Format, Width, 1); + if RowLength = 0 then + RowLength := WidthBytes; + // Create new image if needed - don't need to allocate new one if there is already + // one with desired size and format + if (Image.Width <> Width) or (Image.Height <> Height) or (Image.Format <> Format) then + NewImage(Width, Height, Format, Image); + // Move past the header + IO.Seek(Handle, Offset, smFromCurrent); + // Read scanlines from input + for I := 0 to Height - 1 do + begin + IO.Read(Handle, @PByteArray(Image.Bits)[I * WidthBytes], WidthBytes); + IO.Seek(Handle, RowLength - WidthBytes, smFromCurrent); + end; +end; + +procedure ReadRawImageFromFile(const FileName: string; Width, Height: Integer; + Format: TImageFormat; var Image: TImageData; Offset, RowLength: Integer); +var + Handle: TImagingHandle; +begin + Assert(FileName <> ''); + // Set IO ops to file ops and open given file + SetFileIO; + Handle := IO.Open(PChar(FileName), omReadOnly); + try + ReadRawImage(Handle, Width, Height, Format, Image, Offset, RowLength); + finally + IO.Close(Handle); + end; +end; + +procedure ReadRawImageFromStream(Stream: TStream; Width, Height: Integer; + Format: TImageFormat; var Image: TImageData; Offset, RowLength: Integer); +var + Handle: TImagingHandle; +begin + Assert(Stream <> nil); + if Stream.Size - Stream.Position = 0 then + RaiseImaging(SErrorEmptyStream, []); + // Set IO ops to stream ops and open given stream + SetStreamIO; + Handle := IO.Open(Pointer(Stream), omReadOnly); + try + ReadRawImage(Handle, Width, Height, Format, Image, Offset, RowLength); + finally + IO.Close(Handle); + end; +end; + +procedure ReadRawImageFromMemory(Data: Pointer; DataSize: Integer; Width, Height: Integer; + Format: TImageFormat; var Image: TImageData; Offset, RowLength: Integer); +var + Handle: TImagingHandle; + MemRec: TMemoryIORec; +begin + Assert((Data <> nil) and (DataSize > 0)); + // Set IO ops to memory ops and open given stream + SetMemoryIO; + MemRec := PrepareMemIO(Data, DataSize); + Handle := IO.Open(@MemRec, omReadOnly); + try + ReadRawImage(Handle, Width, Height, Format, Image, Offset, RowLength); + finally + IO.Close(Handle); + end; +end; + +procedure ReadRawImageRect(Data: Pointer; Left, Top, Width, Height: Integer; + var Image: TImageData; Offset, RowLength: Integer); +var + DestScanBytes, RectBytes, I: Integer; + Info: PImageFormatInfo; + Src, Dest: PByte; +begin + Assert(Data <> nil); + Assert((Left + Width <= Image.Width) and (Top + Height <= Image.Height)); + Info := ImageFormatInfos[Image.Format]; + + // Calc scanline size + DestScanBytes := Info.GetPixelsSize(Info.Format, Image.Width, 1); + RectBytes := Info.GetPixelsSize(Info.Format, Width, 1); + if RowLength = 0 then + RowLength := RectBytes; + + Src := Data; + Dest := @PByteArray(Image.Bits)[Top * DestScanBytes + Info.GetPixelsSize(Info.Format, Left, 1)]; + // Move past the header + Inc(Src, Offset); + + // Read lines into rect in the existing image + for I := 0 to Height - 1 do + begin + Move(Src^, Dest^, RectBytes); + Inc(Src, RowLength); + Inc(Dest, DestScanBytes); + end; +end; + +procedure WriteRawImage(Handle: TImagingHandle; const Image: TImageData; + Offset, RowLength: Integer); +var + WidthBytes, I: Integer; + Info: PImageFormatInfo; +begin + Info := ImageFormatInfos[Image.Format]; + // Calc scanline size + WidthBytes := Info.GetPixelsSize(Image.Format, Image.Width, 1); + if RowLength = 0 then + RowLength := WidthBytes; + // Move past the header + IO.Seek(Handle, Offset, smFromCurrent); + // Write scanlines to output + for I := 0 to Image.Height - 1 do + begin + IO.Write(Handle, @PByteArray(Image.Bits)[I * WidthBytes], WidthBytes); + IO.Seek(Handle, RowLength - WidthBytes, smFromCurrent); + end; +end; + +procedure WriteRawImageToFile(const FileName: string; const Image: TImageData; + Offset, RowLength: Integer); +var + Handle: TImagingHandle; +begin + Assert(FileName <> ''); + // Set IO ops to file ops and open given file + SetFileIO; + Handle := IO.Open(PChar(FileName), omCreate); + try + WriteRawImage(Handle, Image, Offset, RowLength); + finally + IO.Close(Handle); + end; +end; + +procedure WriteRawImageToStream(Stream: TStream; const Image: TImageData; + Offset, RowLength: Integer); +var + Handle: TImagingHandle; +begin + Assert(Stream <> nil); + // Set IO ops to stream ops and open given stream + SetStreamIO; + Handle := IO.Open(Pointer(Stream), omCreate); + try + WriteRawImage(Handle, Image, Offset, RowLength); + finally + IO.Close(Handle); + end; +end; + +procedure WriteRawImageToMemory(Data: Pointer; DataSize: Integer; const Image: TImageData; + Offset, RowLength: Integer); +var + Handle: TImagingHandle; + MemRec: TMemoryIORec; +begin + Assert((Data <> nil) and (DataSize > 0)); + // Set IO ops to memory ops and open given stream + SetMemoryIO; + MemRec := PrepareMemIO(Data, DataSize); + Handle := IO.Open(@MemRec, omCreate); + try + WriteRawImage(Handle, Image, Offset, RowLength); + finally + IO.Close(Handle); + end; +end; + +procedure WriteRawImageRect(Data: Pointer; Left, Top, Width, Height: Integer; + const Image: TImageData; Offset, RowLength: Integer); +var + SrcScanBytes, RectBytes, I: Integer; + Info: PImageFormatInfo; + Src, Dest: PByte; +begin + Assert(Data <> nil); + Assert((Left + Width <= Image.Width) and (Top + Height <= Image.Height)); + Info := ImageFormatInfos[Image.Format]; + + // Calc scanline size + SrcScanBytes := Info.GetPixelsSize(Info.Format, Image.Width, 1); + RectBytes := Info.GetPixelsSize(Info.Format, Width, 1); + if RowLength = 0 then + RowLength := RectBytes; + + Src := @PByteArray(Image.Bits)[Top * SrcScanBytes + Info.GetPixelsSize(Info.Format, Left, 1)]; + Dest := Data; + // Move past the header + Inc(Dest, Offset); + + // Write lines from rect of the existing image + for I := 0 to Height - 1 do + begin + Move(Src^, Dest^, RectBytes); + Inc(Dest, RowLength); + Inc(Src, SrcScanBytes); + end; +end; + +{ Convenience/helper Functions } + +procedure ResizeImageToFit(const SrcImage: TImageData; FitWidth, FitHeight: Integer; + Filter: TResizeFilter; var DestImage: TImageData); +var + CurSize, FitSize, DestSize: TSize; +begin + if not TestImage(SrcImage) then + raise EImagingError.Create(SErrorInvalidInputImage); + + FitSize.CX := FitWidth; + FitSize.CY := FitHeight; + CurSize.CX := SrcImage.Width; + CurSize.CY := SrcImage.Height; + DestSize := ImagingUtility.ScaleSizeToFit(CurSize, FitSize); + + NewImage(Max(DestSize.CX, 1), Max(DestSize.CY, 1), SrcImage.Format, DestImage); + if SrcImage.Palette <> nil then + CopyPalette(SrcImage.Palette, DestImage.Palette, 0, 0, ImageFormatInfos[SrcImage.Format].PaletteEntries); + + StretchRect(SrcImage, 0, 0, CurSize.CX, CurSize.CY, DestImage, 0, 0, + DestSize.CX, DestSize.CY, Filter); +end; + +{ ------------------------------------------------------------------------ + Other Imaging Stuff + ------------------------------------------------------------------------} + +function GetFormatName(Format: TImageFormat): string; +begin + if ImageFormatInfos[Format] <> nil then + Result := ImageFormatInfos[Format].Name + else + Result := SUnknownFormat; +end; + +function ImageToStr(const Image: TImageData): string; +var + ImgSize: Integer; +begin + if TestImage(Image) then + with Image do + begin + ImgSize := Size; + if ImgSize > 8192 then + ImgSize := ImgSize div 1024; + Result := SysUtils.Format(SImageInfo, [@Image, Width, Height, + GetFormatName(Format), ImgSize + 0.0, Iff(ImgSize = Size, 'B', 'KiB'), Bits, + Palette]); + end + else + Result := SysUtils.Format(SImageInfoInvalid, [@Image]); +end; + +function GetVersionStr: string; +begin + Result := Format('%.1d.%.2d.%.1d', [ImagingVersionMajor, + ImagingVersionMinor, ImagingVersionPatch]); +end; + +function IffFormat(Condition: Boolean; const TruePart, FalsePart: TImageFormat): TImageFormat; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +procedure RegisterImageFileFormat(AClass: TImageFileFormatClass); +begin + Assert(AClass <> nil); + if ImageFileFormats = nil then + ImageFileFormats := TList.Create; + if GlobalMetadata = nil then + GlobalMetadata := TMetadata.Create; + if ImageFileFormats <> nil then + ImageFileFormats.Add(AClass.Create); +end; + +function RegisterOption(OptionId: LongInt; Variable: PLongInt): Boolean; +begin + Result := False; + if Options = nil then + InitOptions; + + Assert(Variable <> nil); + + if OptionId >= Length(Options) then + SetLength(Options, OptionId + InitialOptions); + if (OptionId >= 0) and (OptionId < Length(Options)) {and (Options[OptionId] = nil) - must be able to override existing } then + begin + Options[OptionId] := Variable; + Result := True; + end; +end; + +function FindImageFileFormatByExt(const Ext: string): TImageFileFormat; +var + I: LongInt; +begin + Result := nil; + for I := ImageFileFormats.Count - 1 downto 0 do + if TImageFileFormat(ImageFileFormats[I]).Extensions.IndexOf(Ext) >= 0 then + begin + Result := TImageFileFormat(ImageFileFormats[I]); + Exit; + end; +end; + +function FindImageFileFormatByName(const FileName: string): TImageFileFormat; +var + I: LongInt; +begin + Result := nil; + for I := ImageFileFormats.Count - 1 downto 0 do + if TImageFileFormat(ImageFileFormats[I]).TestFileName(FileName) then + begin + Result := TImageFileFormat(ImageFileFormats[I]); + Exit; + end; +end; + +function FindImageFileFormatByClass(AClass: TImageFileFormatClass): TImageFileFormat; +var + I: LongInt; +begin + Result := nil; + for I := 0 to ImageFileFormats.Count - 1 do + if TImageFileFormat(ImageFileFormats[I]) is AClass then + begin + Result := TObject(ImageFileFormats[I]) as TImageFileFormat; + Break; + end; +end; + +function GetFileFormatCount: LongInt; +begin + Result := ImageFileFormats.Count; +end; + +function GetFileFormatAtIndex(Index: LongInt): TImageFileFormat; +begin + if (Index >= 0) and (Index < ImageFileFormats.Count) then + Result := TImageFileFormat(ImageFileFormats[Index]) + else + Result := nil; +end; + +function GetImageFileFormatsFilter(OpenFileFilter: Boolean): string; +var + I, J, Count: LongInt; + Descriptions: string; + Filters, CurFilter: string; + FileFormat: TImageFileFormat; +begin + Descriptions := ''; + Filters := ''; + Count := 0; + + for I := 0 to ImageFileFormats.Count - 1 do + begin + FileFormat := TObject(ImageFileFormats[I]) as TImageFileFormat; + + // If we are creating filter for save dialog and this format cannot save + // files the we skip it + if not OpenFileFilter and not FileFormat.CanSave then + Continue; + + CurFilter := ''; + for J := 0 to FileFormat.Masks.Count - 1 do + begin + CurFilter := CurFilter + FileFormat.Masks[J]; + if J < FileFormat.Masks.Count - 1 then + CurFilter := CurFilter + ';'; + end; + + FmtStr(Descriptions, '%s%s (%s)|%2:s', [Descriptions, FileFormat.Name, CurFilter]); + if Filters <> '' then + FmtStr(Filters, '%s;%s', [Filters, CurFilter]) + else + Filters := CurFilter; + + if I < ImageFileFormats.Count - 1 then + Descriptions := Descriptions + '|'; + + Inc(Count); + end; + + if (Count > 1) and OpenFileFilter then + FmtStr(Descriptions, '%s (%s)|%1:s|%s', [SAllFilter, Filters, Descriptions]); + + Result := Descriptions; +end; + +function GetFilterIndexExtension(Index: LongInt; OpenFileFilter: Boolean): string; +var + I, Count: LongInt; + FileFormat: TImageFileFormat; +begin + // -1 because filter indices are in 1..n range + Index := Index - 1; + Result := ''; + if OpenFileFilter then + begin + if Index > 0 then + Index := Index - 1; + end; + + if (Index >= 0) and (Index < ImageFileFormats.Count) then + begin + Count := 0; + for I := 0 to ImageFileFormats.Count - 1 do + begin + FileFormat := TObject(ImageFileFormats[I]) as TImageFileFormat; + if not OpenFileFilter and not FileFormat.CanSave then + Continue; + if Index = Count then + begin + if FileFormat.Extensions.Count > 0 then + Result := FileFormat.Extensions[0]; + Exit; + end; + Inc(Count); + end; + end; +end; + +function GetFileNameFilterIndex(const FileName: string; OpenFileFilter: Boolean): LongInt; +var + I: LongInt; + FileFormat: TImageFileFormat; +begin + Result := 0; + for I := 0 to ImageFileFormats.Count - 1 do + begin + FileFormat := TObject(ImageFileFormats[I]) as TImageFileFormat; + if not OpenFileFilter and not FileFormat.CanSave then + Continue; + if FileFormat.TestFileName(FileName) then + begin + // +1 because filter indices are in 1..n range + Inc(Result); + if OpenFileFilter then + Inc(Result); + Exit; + end; + Inc(Result); + end; + Result := -1; +end; + +function GetIO: TIOFunctions; +begin + Result := IO; +end; + +procedure RaiseImaging(const Msg: string; const Args: array of const); +var + WholeMsg: string; +begin + WholeMsg := Msg; + if GetExceptObject <> nil then + begin + WholeMsg := WholeMsg + ' ' + SExceptMsg + ': ' + + GetExceptObject.Message; + end; + raise EImagingError.CreateFmt(WholeMsg, Args); +end; + +procedure RaiseImaging(const Msg: string); +begin + RaiseImaging(Msg, []); +end; + +{ Internal unit functions } + +function CheckOptionValue(OptionId, Value: LongInt): LongInt; +begin + case OptionId of + ImagingColorReductionMask: + Result := ClampInt(Value, 0, $FF); + ImagingLoadOverrideFormat, ImagingSaveOverrideFormat: + Result := Iff(ImagingFormats.IsImageFormatValid(TImageFormat(Value)), + Value, LongInt(ifUnknown)); + ImagingMipMapFilter: Result := ClampInt(Value, Ord(Low(TSamplingFilter)), + Ord(High(TSamplingFilter))); + else + Result := Value; + end; +end; + +procedure SetFileIO; +begin + IO := FileIO; +end; + +procedure SetStreamIO; +begin + IO := StreamIO; +end; + +procedure SetMemoryIO; +begin + IO := MemoryIO; +end; + +procedure InitImageFormats; +begin + ImagingFormats.InitImageFormats(ImageFormatInfos); +end; + +procedure FreeImageFileFormats; +var + I: LongInt; +begin + if ImageFileFormats <> nil then + for I := 0 to ImageFileFormats.Count - 1 do + TImageFileFormat(ImageFileFormats[I]).Free; + FreeAndNil(ImageFileFormats); +end; + +procedure InitOptions; +begin + SetLength(Options, InitialOptions); + OptionStack := TOptionStack.Create; +end; + +procedure FreeOptions; +begin + SetLength(Options, 0); + FreeAndNil(OptionStack); +end; + +{ + TImageFileFormat class implementation +} + +constructor TImageFileFormat.Create(AMetadata: TMetadata); +begin + inherited Create; + FName := SUnknownFormat; + FExtensions := TStringList.Create; + FMasks := TStringList.Create; + if AMetadata = nil then + FMetadata := GlobalMetadata + else + FMetadata := AMetadata; + Define; +end; + +destructor TImageFileFormat.Destroy; +begin + FExtensions.Free; + FMasks.Free; + inherited Destroy; +end; + +procedure TImageFileFormat.Define; +begin +end; + +function TImageFileFormat.PrepareLoad(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstFrame: Boolean): Boolean; +begin + FMetadata.ClearMetaItems; // Clear old metadata + FreeImagesInArray(Images); + SetLength(Images, 0); + Result := Handle <> nil; +end; + +function TImageFileFormat.PostLoadCheck(var Images: TDynImageDataArray; + LoadResult: Boolean): Boolean; +var + I: LongInt; +begin + if not LoadResult then + begin + FreeImagesInArray(Images); + SetLength(Images, 0); + Result := False; + end + else + begin + Result := (Length(Images) > 0) and TestImagesInArray(Images); + + if Result then + begin + // Convert to overriden format if it is set + if LoadOverrideFormat <> ifUnknown then + for I := Low(Images) to High(Images) do + ConvertImage(Images[I], LoadOverrideFormat); + end; + end; +end; + +function TImageFileFormat.PrepareSave(Handle: TImagingHandle; + const Images: TDynImageDataArray; var Index: Integer): Boolean; +var + Len, I: LongInt; +begin + CheckOptionsValidity; + Result := False; + if CanSave then + begin + Len := Length(Images); + Assert(Len > 0); + + // If there are no images to be saved exit + if Len = 0 then Exit; + + // Check index of image to be saved (-1 as index means save all images) + if IsMultiImageFormat then + begin + if (Index >= Len) then + Index := 0; + + if Index < 0 then + begin + Index := 0; + FFirstIdx := 0; + FLastIdx := Len - 1; + end + else + begin + FFirstIdx := Index; + FLastIdx := Index; + end; + + for I := FFirstIdx to FLastIdx - 1 do + begin + if not TestImage(Images[I]) then + Exit; + end; + end + else + begin + if (Index >= Len) or (Index < 0) then + Index := 0; + if not TestImage(Images[Index]) then + Exit; + end; + + Result := True; + end; +end; + +procedure TImageFileFormat.AddMasks(const AMasks: string); +var + I: LongInt; + Ext: string; +begin + FExtensions.Clear; + FMasks.CommaText := AMasks; + FMasks.Delimiter := ';'; + + for I := 0 to FMasks.Count - 1 do + begin + FMasks[I] := Trim(FMasks[I]); + Ext := GetFileExt(FMasks[I]); + if (Ext <> '') and (Ext <> '*') then + FExtensions.Add(Ext); + end; +end; + +function TImageFileFormat.GetFormatInfo(Format: TImageFormat): TImageFormatInfo; +begin + Result := ImageFormatInfos[Format]^; +end; + +function TImageFileFormat.GetSupportedFormats: TImageFormats; +begin + Result := FSupportedFormats; +end; + +function TImageFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstFrame: Boolean): Boolean; +begin + Result := False; + RaiseImaging(SFileFormatCanNotLoad, [FName]); +end; + +function TImageFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +begin + Result := False; + RaiseImaging(SFileFormatCanNotSave, [FName]); +end; + +procedure TImageFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +begin +end; + +function TImageFileFormat.IsSupported(const Image: TImageData): Boolean; +begin + Result := Image.Format in GetSupportedFormats; +end; + +function TImageFileFormat.LoadFromFile(const FileName: string; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Handle: TImagingHandle; +begin + Result := False; + if CanLoad then + try + // Set IO ops to file ops and open given file + SetFileIO; + Handle := IO.Open(PChar(FileName), omReadOnly); + try + // Test if file contains valid image and if so then load it + if TestFormat(Handle) then + begin + Result := PrepareLoad(Handle, Images, OnlyFirstLevel) and + LoadData(Handle, Images, OnlyFirstlevel); + Result := PostLoadCheck(Images, Result); + end + else + RaiseImaging(SFileNotValid, [FileName, Name]); + finally + IO.Close(Handle); + end; + except + RaiseImaging(SErrorLoadingFile, [FileName, FExtensions[0]]); + end; +end; + +function TImageFileFormat.LoadFromStream(Stream: TStream; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Handle: TImagingHandle; + OldPosition: Int64; +begin + Result := False; + OldPosition := Stream.Position; + if CanLoad then + try + // Set IO ops to stream ops and "open" given memory + SetStreamIO; + Handle := IO.Open(Pointer(Stream), omReadOnly); + try + // Test if stream contains valid image and if so then load it + if TestFormat(Handle) then + begin + Result := PrepareLoad(Handle, Images, OnlyFirstLevel) and + LoadData(Handle, Images, OnlyFirstlevel); + Result := PostLoadCheck(Images, Result); + end + else + RaiseImaging(SStreamNotValid, [@Stream, Name]); + finally + IO.Close(Handle); + end; + except + Stream.Position := OldPosition; + FreeImagesInArray(Images); + RaiseImaging(SErrorLoadingStream, [@Stream, FExtensions[0]]); + end; +end; + +function TImageFileFormat.LoadFromMemory(Data: Pointer; Size: LongInt; var + Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Handle: TImagingHandle; + IORec: TMemoryIORec; +begin + Result := False; + if CanLoad then + try + // Set IO ops to memory ops and "open" given memory + SetMemoryIO; + IORec := PrepareMemIO(Data, Size); + Handle := IO.Open(@IORec,omReadOnly); + try + // Test if memory contains valid image and if so then load it + if TestFormat(Handle) then + begin + Result := PrepareLoad(Handle, Images, OnlyFirstLevel) and + LoadData(Handle, Images, OnlyFirstlevel); + Result := PostLoadCheck(Images, Result); + end + else + RaiseImaging(SMemoryNotValid, [Data, Size, Name]); + finally + IO.Close(Handle); + end; + except + RaiseImaging(SErrorLoadingMemory, [Data, Size, FExtensions[0]]); + end; +end; + +function TImageFileFormat.SaveToFile(const FileName: string; + const Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Handle: TImagingHandle; + Len, Index, I: LongInt; + Ext, FName: string; +begin + Result := False; + if CanSave and TestImagesInArray(Images) then + try + SetFileIO; + Len := Length(Images); + if IsMultiImageFormat or + (not IsMultiImageFormat and (OnlyFirstLevel or (Len = 1))) then + begin + Handle := IO.Open(PChar(FileName), GetSaveOpenMode); + try + if OnlyFirstLevel then + Index := 0 + else + Index := -1; + // Write multi image to one file + Result := PrepareSave(Handle, Images, Index) and SaveData(Handle, Images, Index); + finally + IO.Close(Handle); + end; + end + else + begin + // Write multi image to file sequence + Ext := ExtractFileExt(FileName); + FName := ChangeFileExt(FileName, ''); + Result := True; + for I := 0 to Len - 1 do + begin + Handle := IO.Open(PChar(Format(FName + '%.3d' + Ext, [I])), GetSaveOpenMode); + try + Index := I; + Result := Result and PrepareSave(Handle, Images, Index) and + SaveData(Handle, Images, Index); + if not Result then + Break; + finally + IO.Close(Handle); + end; + end; + end; + except + raise UpdateExceptMessage(GetExceptObject, SErrorSavingFile, [FileName, FExtensions[0]]); + end; +end; + +function TImageFileFormat.SaveToStream(Stream: TStream; + const Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Handle: TImagingHandle; + Len, Index, I: LongInt; + OldPosition: Int64; +begin + Result := False; + OldPosition := Stream.Position; + if CanSave and TestImagesInArray(Images) then + try + SetStreamIO; + Handle := IO.Open(PChar(Stream), GetSaveOpenMode); + try + if IsMultiImageFormat or OnlyFirstLevel then + begin + if OnlyFirstLevel then + Index := 0 + else + Index := -1; + // Write multi image in one run + Result := PrepareSave(Handle, Images, Index) and SaveData(Handle, Images, Index); + end + else + begin + // Write multi image to sequence + Result := True; + Len := Length(Images); + for I := 0 to Len - 1 do + begin + Index := I; + Result := Result and PrepareSave(Handle, Images, Index) and + SaveData(Handle, Images, Index); + if not Result then + Break; + end; + end; + finally + IO.Close(Handle); + end; + except + Stream.Position := OldPosition; + raise UpdateExceptMessage(GetExceptObject, SErrorSavingStream, [@Stream, FExtensions[0]]); + end; +end; + +function TImageFileFormat.SaveToMemory(Data: Pointer; var Size: LongInt; + const Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Handle: TImagingHandle; + Len, Index, I: LongInt; + IORec: TMemoryIORec; +begin + Result := False; + if CanSave and TestImagesInArray(Images) then + try + SetMemoryIO; + IORec := PrepareMemIO(Data, Size); + Handle := IO.Open(PChar(@IORec), GetSaveOpenMode); + try + if IsMultiImageFormat or OnlyFirstLevel then + begin + if OnlyFirstLevel then + Index := 0 + else + Index := -1; + // Write multi image in one run + Result := PrepareSave(Handle, Images, Index) and SaveData(Handle, Images, Index); + end + else + begin + // Write multi image to sequence + Result := True; + Len := Length(Images); + for I := 0 to Len - 1 do + begin + Index := I; + Result := Result and PrepareSave(Handle, Images, Index) and + SaveData(Handle, Images, Index); + if not Result then + Break; + end; + end; + Size := IORec.Position; + finally + IO.Close(Handle); + end; + except + raise UpdateExceptMessage(GetExceptObject, SErrorSavingMemory, [Data, Size, FExtensions[0]]); + end; +end; + +function TImageFileFormat.MakeCompatible(const Image: TImageData; + var Compatible: TImageData; out MustBeFreed: Boolean): Boolean; +begin + InitImage(Compatible); + + if SaveOverrideFormat <> ifUnknown then + begin + // Save format override is active. Clone input and convert it to override format. + CloneImage(Image, Compatible); + ConvertImage(Compatible, SaveOverrideFormat); + // Now check if override format is supported by file format. If it is not + // then file format specific conversion (virtual method) is called. + Result := IsSupported(Compatible); + if not Result then + begin + ConvertToSupported(Compatible, GetFormatInfo(Compatible.Format)); + Result := IsSupported(Compatible); + end; + end // Add IsCompatible function! not only checking by Format + else if IsSupported(Image) then + begin + // No save format override and input is in format supported by this + // file format. Just copy Image's fields to Compatible + Compatible := Image; + Result := True; + end + else + begin + // No override and input's format is not compatible with file format. + // Clone it and the call file format specific conversion (virtual method). + CloneImage(Image, Compatible); + ConvertToSupported(Compatible, GetFormatInfo(Compatible.Format)); + Result := IsSupported(Compatible); + end; + // Tell the user that he must free Compatible after he's done with it + // (if necessary). + MustBeFreed := Image.Bits <> Compatible.Bits; +end; + +function TImageFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +begin + Result := False; +end; + +function TImageFileFormat.TestFileName(const FileName: string): Boolean; +var + I: LongInt; + OnlyName: string; +begin + OnlyName := ExtractFileName(FileName); + // For each mask test if filename matches it + for I := 0 to FMasks.Count - 1 do + if StrMaskMatch(OnlyName, FMasks[I], False) then + begin + Result := True; + Exit; + end; + Result := False; +end; + +procedure TImageFileFormat.CheckOptionsValidity; +begin +end; + +function TImageFileFormat.GetCanLoad: Boolean; +begin + Result := ffLoad in FFeatures; +end; + +function TImageFileFormat.GetCanSave: Boolean; +begin + Result := ffSave in FFeatures; +end; + +function TImageFileFormat.GetIsMultiImageFormat: Boolean; +begin + Result := ffMultiImage in FFeatures; +end; + +function TImageFileFormat.GetSaveOpenMode: TOpenMode; +begin + // TODO: fix + //if ffReadOnSave in FFeatures then + // Result := omReadWrite + //else + Result := omCreate; +end; + +{ TOptionStack class implementation } + +constructor TOptionStack.Create; +begin + inherited Create; + FPosition := -1; +end; + +destructor TOptionStack.Destroy; +var + I: LongInt; +begin + for I := 0 to OptionStackDepth - 1 do + SetLength(FStack[I], 0); + inherited Destroy; +end; + +function TOptionStack.Pop: Boolean; +var + I: LongInt; +begin + Result := False; + if FPosition >= 0 then + begin + SetLength(Options, Length(FStack[FPosition])); + for I := 0 to Length(FStack[FPosition]) - 1 do + if Options[I] <> nil then + Options[I]^ := FStack[FPosition, I]; + Dec(FPosition); + Result := True; + end; +end; + +function TOptionStack.Push: Boolean; +var + I: LongInt; +begin + Result := False; + if FPosition < OptionStackDepth - 1 then + begin + Inc(FPosition); + SetLength(FStack[FPosition], Length(Options)); + for I := 0 to Length(Options) - 1 do + if Options[I] <> nil then + FStack[FPosition, I] := Options[I]^; + Result := True; + end; +end; + +{ TMetadata } + +procedure TMetadata.SetMetaItem(const Id: string; const Value: Variant; + ImageIndex: Integer); +begin + AddMetaToList(FLoadMetaItems, Id, Value, ImageIndex); +end; + +procedure TMetadata.SetMetaItemForSaving(const Id: string; const Value: Variant; + ImageIndex: Integer); +begin + AddMetaToList(FSaveMetaItems, Id, Value, ImageIndex); +end; + +procedure TMetadata.AddMetaToList(List: TStringList; const Id: string; + const Value: Variant; ImageIndex: Integer); +var + Item: TMetadataItem; + Idx: Integer; + FullId: string; +begin + FullId := GetMetaItemName(Id, ImageIndex); + if List.Find(FullId, Idx) then + (List.Objects[Idx] as TMetadataItem).Value := Value + else + begin + Item := TMetadataItem.Create; + Item.Id := Id; + Item.ImageIndex := ImageIndex; + Item.Value := Value; + List.AddObject(FullId, Item); + end; +end; + +procedure TMetadata.ClearMetaItems; +begin + ClearMetaList(FLoadMetaItems); +end; + +procedure TMetadata.ClearMetaItemsForSaving; +begin + ClearMetaList(FSaveMetaItems); +end; + +procedure TMetadata.ClearMetaList(List: TStringList); +var + I: Integer; +begin + for I := 0 to List.Count - 1 do + List.Objects[I].Free; + List.Clear; +end; + +procedure TMetadata.CopyLoadedMetaItemsForSaving; +var + I: Integer; + Copy, Orig: TMetadataItem; +begin + ClearMetaItemsForSaving; + for I := 0 to FLoadMetaItems.Count - 1 do + begin + Orig := TMetadataItem(FLoadMetaItems.Objects[I]); + Copy := TMetadataItem.Create; + Copy.Id := Orig.Id; + Copy.ImageIndex := Orig.ImageIndex; + Copy.Value := Orig.Value; + FSaveMetaItems.AddObject(GetMetaItemName(Copy.Id, Copy.ImageIndex), Copy); + end; +end; + +constructor TMetadata.Create; +begin + inherited; + FLoadMetaItems := TStringList.Create; + FLoadMetaItems.Sorted := True; + FSaveMetaItems := TStringList.Create; + FSaveMetaItems.Sorted := True; +end; + +destructor TMetadata.Destroy; +begin + ClearMetaItems; + ClearMetaItemsForSaving; + FLoadMetaItems.Free; + FSaveMetaItems.Free; + inherited; +end; + +function TMetadata.GetMetaById(const Id: string): Variant; +var + Idx: Integer; +begin + if FLoadMetaItems.Find(Id, Idx) then + Result := (FLoadMetaItems.Objects[Idx] as TMetadataItem).Value + else + Result := Variants.Null; +end; + +function TMetadata.GetMetaByIdMulti(const Id: string; ImageIndex: Integer): Variant; +begin + Result := GetMetaById(GetMetaItemName(Id, ImageIndex)); +end; + +function TMetadata.GetSaveMetaById(const Id: string): Variant; +var + Idx: Integer; +begin + if FSaveMetaItems.Find(Id, Idx) then + Result := (FSaveMetaItems.Objects[Idx] as TMetadataItem).Value + else + Result := Variants.Null; +end; + +function TMetadata.GetSaveMetaByIdMulti(const Id: string; + ImageIndex: Integer): Variant; +begin + Result := GetSaveMetaById(GetMetaItemName(Id, ImageIndex)); +end; + +function TMetadata.GetMetaByIdx(Index: Integer): TMetadataItem; +begin + Result := FLoadMetaItems.Objects[Index] as TMetadataItem; +end; + +function TMetadata.GetMetaCount: Integer; +begin + Result := FLoadMetaItems.Count; +end; + +function TMetadata.GetMetaItemName(const Id: string; + ImageIndex: Integer): string; +begin + Result := Iff(ImageIndex = 0, Id, Format(SMetaIdForSubImage, [Id, ImageIndex])); +end; + +function TMetadata.GetPhysicalPixelSize(ResUnit: TResolutionUnit; var XSize, + YSize: Single; MetaForSave: Boolean; ImageIndex: Integer): Boolean; +type + TGetter = function(const Id: string; ImageIndex: Integer): Variant of object; +var + Getter: TGetter; + XMeta, YMeta: Variant; +begin + if MetaForSave then + Getter := GetSaveMetaByIdMulti + else + Getter := GetMetaByIdMulti; + + XMeta := Getter(SMetaPhysicalPixelSizeX, ImageIndex); + YMeta := Getter(SMetaPhysicalPixelSizeY, ImageIndex); + XSize := -1; + YSize := -1; + + Result := not VarIsNull(XMeta) or not VarIsNull(YMeta); + + if not Result then + Exit; + + if not VarIsNull(XMeta) then + XSize := XMeta; + if not VarIsNull(YMeta) then + YSize := YMeta; + + if XSize < 0 then + XSize := YSize; + if YSize < 0 then + YSize := XSize; + + TranslateUnits(ResUnit, XSize, YSize); +end; + +procedure TMetadata.SetPhysicalPixelSize(ResUnit: TResolutionUnit; XSize, + YSize: Single; MetaForSave: Boolean; ImageIndex: Integer); +type + TAdder = procedure(const Id: string; const Value: Variant; ImageIndex: Integer) of object; +var + Adder: TAdder; +begin + TranslateUnits(ResUnit, XSize, YSize); + + if MetaForSave then + Adder := SetMetaItemForSaving + else + Adder := SetMetaItem; + + Adder(SMetaPhysicalPixelSizeX, XSize, ImageIndex); + Adder(SMetaPhysicalPixelSizeY, YSize, ImageIndex); +end; + +procedure TMetadata.TranslateUnits(ResolutionUnit: TResolutionUnit; var XRes, + YRes: Single); +var + UnitSize: Single; +begin + case ResolutionUnit of + ruDpi: UnitSize := 25400; + ruDpm: UnitSize := 1e06; + ruDpcm: UnitSize := 1e04; + else + UnitSize := 1; + end; + if ResolutionUnit <> ruSizeInMicroMeters then + begin + XRes := UnitSize / XRes; + YRes := UnitSize / YRes; + end; +end; + +function TMetadata.HasMetaItem(const Id: string; ImageIndex: Integer): Boolean; +begin + Result := GetMetaByIdMulti(Id, ImageIndex) <> Variants.Null; +end; + +function TMetadata.HasMetaItemForSaving(const Id: string; ImageIndex: Integer): Boolean; +begin + Result := GetSaveMetaByIdMulti(Id, ImageIndex) <> Variants.Null; +end; + +initialization +{$IFDEF MEMCHECK} + {$IF CompilerVersion >= 18} + System.ReportMemoryLeaksOnShutdown := True; + {$IFEND} +{$ENDIF} + if GlobalMetadata = nil then + GlobalMetadata := TMetadata.Create; + if ImageFileFormats = nil then + ImageFileFormats := TList.Create; + InitImageFormats; + RegisterOption(ImagingColorReductionMask, @ColorReductionMask); + RegisterOption(ImagingLoadOverrideFormat, @LoadOverrideFormat); + RegisterOption(ImagingSaveOverrideFormat, @SaveOverrideFormat); + RegisterOption(ImagingMipMapFilter, @MipMapFilter); + RegisterOption(ImagingBinaryTreshold, @BinaryTreshold); +finalization + FreeOptions; + FreeImageFileFormats; + GlobalMetadata.Free; + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 --------------------------------------------------- + - Updated IO Open functions according to changes in ImagingTypes. + - Fixed bug in SplitImage that could cause wrong size of edge chunks. + - Metadata support fixes and extensions (frame delays, animation loops). + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Started reworking exception raising to keep the original class type + (e.g. in NewImage EOutOfMemory could be raised but was hidden + by EImagingError raised afterwards in NewImage try/except). + - Fixed possible AV in Rotate45 subproc of RotateImage. + - Added ReadRawXXX and WriteRawXXX functions for raw image bits IO. + - Implemented ImagingBinaryTreshold option. + - Added support for simple image metadata loading/saving. + - Moved file format definition (name, exts, caps, ...) from + constructor to new Define method. + - Fixed some memory leaks caused by failures during image loading. + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Extended RotateImage to allow arbitrary angle rotations. + - Reversed the order file formats list is searched so + if you register a new one it will be found sooner than + built in formats. + - Fixed memory leak in ResizeImage ocurring when resizing + indexed images. + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - Added position/size checks to LoadFromStream functions. + - Changed conditional compilation in impl. uses section to reflect changes + in LINK symbols. + + -- 0.24.3 Changes/Bug Fixes --------------------------------- + - GenerateMipMaps now generates all smaller levels from + original big image (better results when using more advanced filters). + Also conversion to compatible image format is now done here not + in FillMipMapLevel (that is called for every mipmap level). + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - MakePaletteForImages now works correctly for indexed and special format images + - Fixed bug in StretchRect: Image was not properly stretched if + src and dst dimensions differed only in height. + - ConvertImage now fills new image with zeroes to avoid random data in + some conversions (RGB->XRGB) + - Changed RegisterOption procedure to function + - Changed bunch of palette functions from low level interface to procedure + (there was no reason for them to be functions). + - Changed FreeImage and FreeImagesInArray functions to procedures. + - Added many assertions, come try-finally, other checks, and small code + and doc changes. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - GenerateMipMaps threw failed assertion when input was indexed or special, + fixed. + - Added CheckOptionsValidity to TImageFileFormat and its decendants. + - Unit ImagingExtras which registers file formats in Extras package + is now automatically added to uses clause if LINK_EXTRAS symbol is + defined in ImagingOptions.inc file. + - Added EnumFileFormats function to low level interface. + - Fixed bug in SwapChannels which could cause AV when swapping alpha + channel of A8R8G8B8 images. + - Converting loaded images to ImagingOverrideFormat is now done + in PostLoadCheck method to avoid code duplicity. + - Added GetFileFormatCount and GetFileFormatAtIndex functions + - Bug in ConvertImage: if some format was converted to similar format + only with swapped channels (R16G16B16<>B16G16R16) then channels were + swapped correctly but new data format (swapped one) was not set. + - Made TImageFileFormat.MakeCompatible public non-virtual method + (and modified its function). Created new virtual + ConvertToSupported which should be overriden by descendants. + Main reason for doint this is to avoid duplicate code that was in all + TImageFileFormat's descendants. + - Changed TImageFileFormat.GetFormatInfo's result type to TImageFormatInfo. + - Split overloaded FindImageFileFormat functions to + FindImageFileFormatByClass and FindImageFileFormatByExt and created new + FindImageFileFormatByName which operates on whole filenames. + - Function GetExtensionFilterIndex renamed to GetFileNameFilterIndex + (because it now works with filenames not extensions). + - DetermineFileFormat now first searches by filename and if not found + then by data. + - Added TestFileName method to TImageFileFormat. + - Updated GetImageFileFormatsFilter to uses Masks instead of Extensions + property of TImageFileFormat. Also you can now request + OpenDialog and SaveDialog type filters + - Added Masks property and AddMasks method to TImageFileFormat. + AddMasks replaces AddExtensions, it uses filename masks instead + of sime filename extensions to identify supported files. + - Changed TImageFileFormat.LoadData procedure to function and + moved varios duplicate code from its descandats (check index,...) + here to TImageFileFormat helper methods. + - Changed TImageFileFormat.SaveData procedure to function and + moved varios duplicate code from its descandats (check index,...) + here to TImageFileFormat helper methods. + - Removed RAISE_EXCEPTIONS define, exceptions are now raised everytime + - Added MustBeFreed parameter to TImageFileFormat.MakeComptible method + that indicates that compatible image returned by this method must be + freed after its usage. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - fixed bug in NewImage: if given format was ifDefault it wasn't + replaced with DefaultImageFormat constant which caused problems later + in other units + - fixed bug in RotateImage which caused that rotated special format + images were whole black + - LoadImageFromXXX and LoadMultiImageFromXXX now use DetermineXXXFormat + when choosing proper loader, this eliminated need for Ext parameter + in stream and memory loading functions + - added GetVersionStr function + - fixed bug in ResizeImage which caued indexed images to lose their + palette during process resulting in whole black image + - Clipping in ...Rect functions now uses clipping procs from ImagingUtility, + it also works better + - FillRect optimization for 8, 16, and 32 bit formats + - added pixel set/get functions to low level interface: + GetPixelDirect, SetPixelDirect, GetPixel32, SetPixel32, + GetPixelFP, SetPixelFP + - removed GetPixelBytes low level intf function - redundant + (same data can be obtained by GetImageFormatInfo) + - made small changes in many parts of library to compile + on AMD64 CPU (Linux with FPC) + - changed InitImage to procedure (function was pointless) + - Method TestFormat of TImageFileFormat class made public + (was protected) + - added function IsFileFormatSupported to low level interface + (contributed by Paul Michell) + - fixed some missing format arguments from error strings + which caused Format function to raise exception + - removed forgotten debug code that disabled filtered resizing of images with + channel bitcounts > 8 + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - changed order of parameters of CopyRect function + - GenerateMipMaps now filters mipmap levels + - ResizeImage functions was extended to allow bilinear and bicubic filtering + - added StretchRect function to low level interface + - added functions GetImageFileFormatsFilter, GetFilterIndexExtension, + and GetExtensionFilterIndex + + -- 0.15 Changes/Bug Fixes ----------------------------------- + - added function RotateImage to low level interface + - moved TImageFormatInfo record and types required by it to + ImagingTypes unit, changed GetImageFormatInfo low level + interface function to return TImageFormatInfo instead of short info + - added checking of options values validity before they are used + - fixed possible memory leak in CloneImage + - added ReplaceColor function to low level interface + - new function FindImageFileFormat by class added + + -- 0.13 Changes/Bug Fixes ----------------------------------- + - added DetermineFileFormat, DetermineStreamFormat, DetermineMemoryFormat, + GetPixelsSize functions to low level interface + - added NewPalette, CopyPalette, FreePalette functions + to low level interface + - added MapImageToPalette, FillRect, SplitImage, MakePaletteForImages + functions to low level interface + - fixed buggy FillCustomPalette function (possible div by zero and others) + - added CopyRect function to low level interface + - Member functions of TImageFormatInfo record implemented for all formats + - before saving images TestImagesInArray is called now + - added TestImagesInArray function to low level interface + - added GenerateMipMaps function to low level interface + - stream position in load/save from/to stream is now set to position before + function was called if error occurs + - when error occured during load/save from/to file file handle + was not released + - CloneImage returned always False + +} +end. diff --git a/src/lib/vampimg/ImagingBitmap.pas b/src/lib/vampimg/ImagingBitmap.pas new file mode 100644 index 0000000..4c4aac6 --- /dev/null +++ b/src/lib/vampimg/ImagingBitmap.pas @@ -0,0 +1,855 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ + This unit contains image format loader/saver for Windows Bitmap images. +} +unit ImagingBitmap; + +{$I ImagingOptions.inc} + +interface + +uses + ImagingTypes, Imaging, ImagingUtility, ImagingFormats, ImagingIO; + +type + { Class for loading and saving Windows Bitmap images. + It can load/save 8bit indexed, 16, 24, 32 bit RGB or ARGB + images with or without RLE compression. It can also load 1/4 bit + indexed images and OS2 bitmaps.} + TBitmapFileFormat = class(TImageFileFormat) + protected + FUseRLE: LongBool; + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + published + { Controls that RLE compression is used during saving. Accessible trough + ImagingBitmapRLE option.} + property UseRLE: LongBool read FUseRLE write FUseRLE; + end; + +implementation + +const + SBitmapFormatName = 'Windows Bitmap Image'; + SBitmapMasks = '*.bmp,*.dib'; + BitmapSupportedFormats: TImageFormats = [ifIndex8, ifA1R5G5B5, ifA4R4G4B4, + ifR5G6B5, ifR8G8B8, ifA8R8G8B8, ifX1R5G5B5, ifX4R4G4B4, ifX8R8G8B8]; + BitmapDefaultRLE = True; + +const + { Bitmap file identifier 'BM'.} + BMMagic: Word = 19778; + + { Constants for the TBitmapInfoHeader.Compression field.} + BI_RGB = 0; + BI_RLE8 = 1; + BI_RLE4 = 2; + BI_BITFIELDS = 3; + + V3InfoHeaderSize = 40; + V4InfoHeaderSize = 108; + +type + { File Header for Windows/OS2 bitmap file.} + TBitmapFileHeader = packed record + ID: Word; // Is always 19778 : 'BM' + Size: LongWord; // Filesize + Reserved1: Word; + Reserved2: Word; + Offset: LongWord; // Offset from start pos to beginning of image bits + end; + + { Info Header for Windows bitmap file version 4.} + TBitmapInfoHeader = packed record + Size: LongWord; + Width: LongInt; + Height: LongInt; + Planes: Word; + BitCount: Word; + Compression: LongWord; + SizeImage: LongWord; + XPelsPerMeter: LongInt; + YPelsPerMeter: LongInt; + ClrUsed: LongInt; + ClrImportant: LongInt; + RedMask: LongWord; + GreenMask: LongWord; + BlueMask: LongWord; + AlphaMask: LongWord; + CSType: LongWord; + EndPoints: array[0..8] of LongWord; + GammaRed: LongWord; + GammaGreen: LongWord; + GammaBlue: LongWord; + end; + + { Info Header for OS2 bitmaps.} + TBitmapCoreHeader = packed record + Size: LongWord; + Width: Word; + Height: Word; + Planes: Word; + BitCount: Word; + end; + + { Used in RLE encoding and decoding.} + TRLEOpcode = packed record + Count: Byte; + Command: Byte; + end; + PRLEOpcode = ^TRLEOpcode; + +{ TBitmapFileFormat class implementation } + +procedure TBitmapFileFormat.Define; +begin + inherited; + FName := SBitmapFormatName; + FFeatures := [ffLoad, ffSave]; + FSupportedFormats := BitmapSupportedFormats; + + FUseRLE := BitmapDefaultRLE; + + AddMasks(SBitmapMasks); + RegisterOption(ImagingBitmapRLE, @FUseRLE); +end; + +function TBitmapFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + BF: TBitmapFileHeader; + BI: TBitmapInfoHeader; + BC: TBitmapCoreHeader; + IsOS2: Boolean; + PalRGB: PPalette24; + I, FPalSize, AlignedSize, StartPos, HeaderSize, AlignedWidthBytes, WidthBytes: LongInt; + Info: TImageFormatInfo; + Data: Pointer; + + procedure LoadRGB; + var + I: LongInt; + LineBuffer: PByte; + begin + with Images[0], GetIO do + begin + // If BI.Height is < 0 then image data are stored non-flipped + // but default in windows is flipped so if Height is positive we must + // flip it + + if BI.BitCount < 8 then + begin + // For 1 and 4 bit images load aligned data, they will be converted to + // 8 bit and unaligned later + GetMem(Data, AlignedSize); + + if BI.Height < 0 then + Read(Handle, Data, AlignedSize) + else + for I := Height - 1 downto 0 do + Read(Handle, @PByteArray(Data)[I * AlignedWidthBytes], AlignedWidthBytes); + end + else + begin + // Images with pixels of size >= 1 Byte are read line by line and + // copied to image bits without padding bytes + GetMem(LineBuffer, AlignedWidthBytes); + try + if BI.Height < 0 then + for I := 0 to Height - 1 do + begin + Read(Handle, LineBuffer, AlignedWidthBytes); + Move(LineBuffer^, PByteArray(Bits)[I * WidthBytes], WidthBytes); + end + else + for I := Height - 1 downto 0 do + begin + Read(Handle, LineBuffer, AlignedWidthBytes); + Move(LineBuffer^, PByteArray(Bits)[I * WidthBytes], WidthBytes); + end; + finally + FreeMemNil(LineBuffer); + end; + end; + end; + end; + + procedure LoadRLE4; + var + RLESrc: PByteArray; + Row, Col, WriteRow, I: LongInt; + SrcPos: LongWord; + DeltaX, DeltaY, Low, High: Byte; + Pixels: PByteArray; + OpCode: TRLEOpcode; + NegHeightBitmap: Boolean; + begin + GetMem(RLESrc, BI.SizeImage); + GetIO.Read(Handle, RLESrc, BI.SizeImage); + with Images[0] do + try + Low := 0; + Pixels := Bits; + SrcPos := 0; + NegHeightBitmap := BI.Height < 0; + Row := 0; // Current row in dest image + Col := 0; // Current column in dest image + // Row in dest image where actuall writting will be done + WriteRow := Iff(NegHeightBitmap, Row, Height - 1 - Row); + while (Row < Height) and (SrcPos < BI.SizeImage) do + begin + // Read RLE op-code + OpCode := PRLEOpcode(@RLESrc[SrcPos])^; + Inc(SrcPos, SizeOf(OpCode)); + if OpCode.Count = 0 then + begin + // A byte Count of zero means that this is a special + // instruction. + case OpCode.Command of + 0: + begin + // Move to next row + Inc(Row); + WriteRow := Iff(NegHeightBitmap, Row, Height - 1 - Row); + Col := 0; + end ; + 1: Break; // Image is finished + 2: + begin + // Move to a new relative position + DeltaX := RLESrc[SrcPos]; + DeltaY := RLESrc[SrcPos + 1]; + Inc(SrcPos, 2); + Inc(Col, DeltaX); + Inc(Row, DeltaY); + end + else + // Do not read data after EOF + if SrcPos + OpCode.Command > BI.SizeImage then + OpCode.Command := BI.SizeImage - SrcPos; + // Take padding bytes and nibbles into account + if Col + OpCode.Command > Width then + OpCode.Command := Width - Col; + // Store absolute data. Command code is the + // number of absolute bytes to store + for I := 0 to OpCode.Command - 1 do + begin + if (I and 1) = 0 then + begin + High := RLESrc[SrcPos] shr 4; + Low := RLESrc[SrcPos] and $F; + Pixels[WriteRow * Width + Col] := High; + Inc(SrcPos); + end + else + Pixels[WriteRow * Width + Col] := Low; + Inc(Col); + end; + // Odd number of bytes is followed by a pad byte + if (OpCode.Command mod 4) in [1, 2] then + Inc(SrcPos); + end; + end + else + begin + // Take padding bytes and nibbles into account + if Col + OpCode.Count > Width then + OpCode.Count := Width - Col; + // Store a run of the same color value + for I := 0 to OpCode.Count - 1 do + begin + if (I and 1) = 0 then + Pixels[WriteRow * Width + Col] := OpCode.Command shr 4 + else + Pixels[WriteRow * Width + Col] := OpCode.Command and $F; + Inc(Col); + end; + end; + end; + finally + FreeMem(RLESrc); + end; + end; + + procedure LoadRLE8; + var + RLESrc: PByteArray; + SrcCount, Row, Col, WriteRow: LongInt; + SrcPos: LongWord; + DeltaX, DeltaY: Byte; + Pixels: PByteArray; + OpCode: TRLEOpcode; + NegHeightBitmap: Boolean; + begin + GetMem(RLESrc, BI.SizeImage); + GetIO.Read(Handle, RLESrc, BI.SizeImage); + with Images[0] do + try + Pixels := Bits; + SrcPos := 0; + NegHeightBitmap := BI.Height < 0; + Row := 0; // Current row in dest image + Col := 0; // Current column in dest image + // Row in dest image where actuall writting will be done + WriteRow := Iff(NegHeightBitmap, Row, Height - 1 - Row); + while (Row < Height) and (SrcPos < BI.SizeImage) do + begin + // Read RLE op-code + OpCode := PRLEOpcode(@RLESrc[SrcPos])^; + Inc(SrcPos, SizeOf(OpCode)); + if OpCode.Count = 0 then + begin + // A byte Count of zero means that this is a special + // instruction. + case OpCode.Command of + 0: + begin + // Move to next row + Inc(Row); + WriteRow := Iff(NegHeightBitmap, Row, Height - 1 - Row); + Col := 0; + end ; + 1: Break; // Image is finished + 2: + begin + // Move to a new relative position + DeltaX := RLESrc[SrcPos]; + DeltaY := RLESrc[SrcPos + 1]; + Inc(SrcPos, 2); + Inc(Col, DeltaX); + Inc(Row, DeltaY); + end + else + SrcCount := OpCode.Command; + // Do not read data after EOF + if SrcPos + OpCode.Command > BI.SizeImage then + OpCode.Command := BI.SizeImage - SrcPos; + // Take padding bytes into account + if Col + OpCode.Command > Width then + OpCode.Command := Width - Col; + // Store absolute data. Command code is the + // number of absolute bytes to store + Move(RLESrc[SrcPos], Pixels[WriteRow * Width + Col], OpCode.Command); + Inc(SrcPos, SrcCount); + Inc(Col, OpCode.Command); + // Odd number of bytes is followed by a pad byte + if (SrcCount mod 2) = 1 then + Inc(SrcPos); + end; + end + else + begin + // Take padding bytes into account + if Col + OpCode.Count > Width then + OpCode.Count := Width - Col; + // Store a run of the same color value. Count is number of bytes to store + FillChar(Pixels [WriteRow * Width + Col], OpCode.Count, OpCode.Command); + Inc(Col, OpCode.Count); + end; + end; + finally + FreeMem(RLESrc); + end; + end; + +begin + Data := nil; + SetLength(Images, 1); + with GetIO, Images[0] do + try + FillChar(BI, SizeOf(BI), 0); + StartPos := Tell(Handle); + Read(Handle, @BF, SizeOf(BF)); + Read(Handle, @BI.Size, SizeOf(BI.Size)); + IsOS2 := BI.Size = SizeOf(TBitmapCoreHeader); + + // Bitmap Info reading + if IsOS2 then + begin + // OS/2 type bitmap, reads info header without 4 already read bytes + Read(Handle, @PByteArray(@BC)[SizeOf(BI.Size)], + SizeOf(TBitmapCoreHeader) - SizeOf(BI.Size)); + with BI do + begin + ClrUsed := 0; + Compression := BI_RGB; + BitCount := BC.BitCount; + Height := BC.Height; + Width := BC.Width; + end; + end + else + begin + // Windows type bitmap + HeaderSize := Min(BI.Size - SizeOf(BI.Size), SizeOf(BI) - SizeOf(BI.Size)); // do not read more than size of BI! + Read(Handle, @PByteArray(@BI)[SizeOf(BI.Size)], HeaderSize); + // SizeImage can be 0 for BI_RGB images, but it is here because of: + // I saved 8bit bitmap in Paint Shop Pro 8 as OS2 RLE compressed. + // It wrote strange 64 Byte Info header with SizeImage set to 0 + // Some progs were able to open it, some were not. + if BI.SizeImage = 0 then + BI.SizeImage := BF.Size - BF.Offset; + end; + // Bit mask reading. Only read it if there is V3 header, V4 header has + // masks laoded already (only masks for RGB in V3). + if (BI.Compression = BI_BITFIELDS) and (BI.Size = V3InfoHeaderSize) then + Read(Handle, @BI.RedMask, SizeOf(BI.RedMask) * 3); + + case BI.BitCount of + 1, 4, 8: Format := ifIndex8; + 16: + if BI.RedMask = $0F00 then + // Set XRGB4 or ARGB4 according to value of alpha mask + Format := IffFormat(BI.AlphaMask = 0, ifX4R4G4B4, ifA4R4G4B4) + else if BI.RedMask = $F800 then + Format := ifR5G6B5 + else + // R5G5B5 is default 16bit format (with Compression = BI_RGB or masks). + // We set it to A1.. and later there is a check if there are any alpha values + // and if not it is changed to X1R5G5B5 + Format := ifA1R5G5B5; + 24: Format := ifR8G8B8; + 32: Format := ifA8R8G8B8; // As with R5G5B5 there is alpha check later + end; + + NewImage(BI.Width, Abs(BI.Height), Format, Images[0]); + Info := GetFormatInfo(Format); + WidthBytes := Width * Info.BytesPerPixel; + AlignedWidthBytes := (((Width * BI.BitCount) + 31) shr 5) * 4; + AlignedSize := Height * LongInt(AlignedWidthBytes); + + // Palette settings and reading + if BI.BitCount <= 8 then + begin + // Seek to the begining of palette + Seek(Handle, StartPos + SizeOf(TBitmapFileHeader) + LongInt(BI.Size), + smFromBeginning); + if IsOS2 then + begin + // OS/2 type + FPalSize := 1 shl BI.BitCount; + GetMem(PalRGB, FPalSize * SizeOf(TColor24Rec)); + try + Read(Handle, PalRGB, FPalSize * SizeOf(TColor24Rec)); + for I := 0 to FPalSize - 1 do + with PalRGB[I] do + begin + Palette[I].R := R; + Palette[I].G := G; + Palette[I].B := B; + end; + finally + FreeMemNil(PalRGB); + end; + end + else + begin + // Windows type + FPalSize := BI.ClrUsed; + if FPalSize = 0 then + FPalSize := 1 shl BI.BitCount; + Read(Handle, Palette, FPalSize * SizeOf(TColor32Rec)); + end; + for I := 0 to Info.PaletteEntries - 1 do + Palette[I].A := $FF; + end; + + // Seek to the beginning of image bits + Seek(Handle, StartPos + LongInt(BF.Offset), smFromBeginning); + + case BI.Compression of + BI_RGB: LoadRGB; + BI_RLE4: LoadRLE4; + BI_RLE8: LoadRLE8; + BI_BITFIELDS: LoadRGB; + end; + + if BI.AlphaMask = 0 then + begin + // Alpha mask is not stored in file (V3) or not defined. + // Check alpha channels of loaded images if they might contain them. + if Format = ifA1R5G5B5 then + begin + // Check if there is alpha channel present in A1R5GB5 images, if it is not + // change format to X1R5G5B5 + if not Has16BitImageAlpha(Width * Height, Bits) then + Format := ifX1R5G5B5; + end + else if Format = ifA8R8G8B8 then + begin + // Check if there is alpha channel present in A8R8G8B8 images, if it is not + // change format to X8R8G8B8 + if not Has32BitImageAlpha(Width * Height, Bits) then + Format := ifX8R8G8B8; + end; + end; + + if BI.BitCount < 8 then + begin + // 1 and 4 bpp images are supported only for loading which is now + // so we now convert them to 8bpp (and unalign scanlines). + case BI.BitCount of + 1: Convert1To8(Data, Bits, Width, Height, AlignedWidthBytes, False); + 4: + begin + // RLE4 bitmaps are translated to 8bit during RLE decoding + if BI.Compression <> BI_RLE4 then + Convert4To8(Data, Bits, Width, Height, AlignedWidthBytes, False); + end; + end; + // Enlarge palette + ReallocMem(Palette, Info.PaletteEntries * SizeOf(TColor32Rec)); + end; + + Result := True; + finally + FreeMemNil(Data); + end; +end; + +function TBitmapFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +var + StartPos, EndPos, I, Pad, PadSize, WidthBytes: LongInt; + BF: TBitmapFileHeader; + BI: TBitmapInfoHeader; + Info: TImageFormatInfo; + ImageToSave: TImageData; + MustBeFreed: Boolean; + + procedure SaveRLE8; + const + BufferSize = 8 * 1024; + var + X, Y, I, SrcPos: LongInt; + DiffCount, SameCount: Byte; + Pixels: PByteArray; + Buffer: array[0..BufferSize - 1] of Byte; + BufferPos: LongInt; + + procedure WriteByte(ByteToWrite: Byte); + begin + if BufferPos = BufferSize then + begin + // Flush buffer if necessary + GetIO.Write(Handle, @Buffer, BufferPos); + BufferPos := 0; + end; + Buffer[BufferPos] := ByteToWrite; + Inc(BufferPos); + end; + + begin + BufferPos := 0; + with GetIO, ImageToSave do + begin + for Y := Height - 1 downto 0 do + begin + X := 0; + SrcPos := 0; + Pixels := @PByteArray(Bits)[Y * Width]; + + while X < Width do + begin + SameCount := 1; + DiffCount := 0; + // Determine run length + while X + SameCount < Width do + begin + // If we reach max run length or byte with different value + // we end this run + if (SameCount = 255) or (Pixels[SrcPos + SameCount] <> Pixels[SrcPos]) then + Break; + Inc(SameCount); + end; + + if SameCount = 1 then + begin + // If there are not some bytes with the same value we + // compute how many different bytes are there + while X + DiffCount < Width do + begin + // Stop diff byte counting if there two bytes with the same value + // or DiffCount is too big + if (DiffCount = 255) or (Pixels[SrcPos + DiffCount + 1] = + Pixels[SrcPos + DiffCount]) then + Break; + Inc(DiffCount); + end; + end; + + // Now store absolute data (direct copy image->file) or + // store RLE code only (number of repeats + byte to be repeated) + if DiffCount > 2 then + begin + // Save 'Absolute Data' (0 + number of bytes) but only + // if number is >2 because (0+1) and (0+2) are other special commands + WriteByte(0); + WriteByte(DiffCount); + // Write absolute data to buffer + for I := 0 to DiffCount - 1 do + WriteByte(Pixels[SrcPos + I]); + Inc(X, DiffCount); + Inc(SrcPos, DiffCount); + // Odd number of bytes must be padded + if (DiffCount mod 2) = 1 then + WriteByte(0); + end + else + begin + // Save number of repeats and byte that should be repeated + WriteByte(SameCount); + WriteByte(Pixels[SrcPos]); + Inc(X, SameCount); + Inc(SrcPos, SameCount); + end; + end; + // Save 'End Of Line' command + WriteByte(0); + WriteByte(0); + end; + // Save 'End Of Bitmap' command + WriteByte(0); + WriteByte(1); + // Flush buffer + GetIO.Write(Handle, @Buffer, BufferPos); + end; + end; + +begin + Result := False; + if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then + with GetIO, ImageToSave do + try + Info := GetFormatInfo(Format); + StartPos := Tell(Handle); + FillChar(BF, SizeOf(BF), 0); + FillChar(BI, SizeOf(BI), 0); + // Other fields will be filled later - we don't know all values now + BF.ID := BMMagic; + Write(Handle, @BF, SizeOf(BF)); + if Info.HasAlphaChannel and (Info.BytesPerPixel = 2){V4 temp hack} then + // Save images with alpha in V4 format + BI.Size := V4InfoHeaderSize + else + // Save images without alpha in V3 format - for better compatibility + BI.Size := V3InfoHeaderSize; + BI.Width := Width; + BI.Height := Height; + BI.Planes := 1; + BI.BitCount := Info.BytesPerPixel * 8; + BI.XPelsPerMeter := 2835; // 72 dpi + BI.YPelsPerMeter := 2835; // 72 dpi + // Set compression + if (Info.BytesPerPixel = 1) and FUseRLE then + BI.Compression := BI_RLE8 + else if (Info.HasAlphaChannel or + ((BI.BitCount = 16) and (Format <> ifX1R5G5B5))) and (Info.BytesPerPixel = 2){V4 temp hack} then + BI.Compression := BI_BITFIELDS + else + BI.Compression := BI_RGB; + // Write header (first time) + Write(Handle, @BI, BI.Size); + + // Write mask info + if BI.Compression = BI_BITFIELDS then + begin + if BI.BitCount = 16 then + with Info.PixelFormat^ do + begin + BI.RedMask := RBitMask; + BI.GreenMask := GBitMask; + BI.BlueMask := BBitMask; + BI.AlphaMask := ABitMask; + end + else + begin + // Set masks for A8R8G8B8 + BI.RedMask := $00FF0000; + BI.GreenMask := $0000FF00; + BI.BlueMask := $000000FF; + BI.AlphaMask := $FF000000; + end; + // If V3 header is used RGB masks must be written to file separately. + // V4 header has embedded masks (V4 is default for formats with alpha). + if BI.Size = V3InfoHeaderSize then + Write(Handle, @BI.RedMask, SizeOf(BI.RedMask) * 3); + end; + // Write palette + if Palette <> nil then + Write(Handle, Palette, Info.PaletteEntries * SizeOf(TColor32Rec)); + + BF.Offset := Tell(Handle) - StartPos; + + if BI.Compression <> BI_RLE8 then + begin + // Save uncompressed data, scanlines must be filled with pad bytes + // to be multiples of 4, save as bottom-up (Windows native) bitmap + Pad := 0; + WidthBytes := Width * Info.BytesPerPixel; + PadSize := ((Width * BI.BitCount + 31) div 32) * 4 - WidthBytes; + + for I := Height - 1 downto 0 do + begin + Write(Handle, @PByteArray(Bits)[I * WidthBytes], WidthBytes); + if PadSize > 0 then + Write(Handle, @Pad, PadSize); + end; + end + else + begin + // Save data with RLE8 compression + SaveRLE8; + end; + + EndPos := Tell(Handle); + Seek(Handle, StartPos, smFromBeginning); + // Rewrite header with new values + BF.Size := EndPos - StartPos; + BI.SizeImage := BF.Size - BF.Offset; + Write(Handle, @BF, SizeOf(BF)); + Write(Handle, @BI, BI.Size); + Seek(Handle, EndPos, smFromBeginning); + + Result := True; + finally + if MustBeFreed then + FreeImage(ImageToSave); + end; +end; + +procedure TBitmapFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if Info.IsFloatingPoint then + // Convert FP image to RGB/ARGB according to presence of alpha channel + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA8R8G8B8, ifR8G8B8) + else if Info.HasGrayChannel or Info.IsIndexed then + // Convert all grayscale and indexed images to Index8 unless they have alpha + // (preserve it) + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA8R8G8B8, ifIndex8) + else if Info.HasAlphaChannel then + // Convert images with alpha channel to A8R8G8B8 + ConvFormat := ifA8R8G8B8 + else if Info.UsePixelFormat then + // Convert 16bit RGB images (no alpha) to X1R5G5B5 + ConvFormat := ifX1R5G5B5 + else + // Convert all other formats to R8G8B8 + ConvFormat := ifR8G8B8; + + ConvertImage(Image, ConvFormat); +end; + +function TBitmapFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Hdr: TBitmapFileHeader; + ReadCount: LongInt; +begin + Result := False; + if Handle <> nil then + with GetIO do + begin + ReadCount := Read(Handle, @Hdr, SizeOf(Hdr)); + Seek(Handle, -ReadCount, smFromCurrent); + Result := (Hdr.ID = BMMagic) and (ReadCount = SizeOf(Hdr)); + end; +end; + +initialization + RegisterImageFileFormat(TBitmapFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + - Add option to choose to save V3 or V4 headers. + + -- 0.25.0 Changes/Bug Fixes --------------------------------- + - Fixed problem with indexed BMP loading - some pal entries + could end up with alpha=0. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Now saves bitmaps as bottom-up for better compatibility + (mainly Lazarus' TImage!). + - Fixed crash when loading bitmaps with headers larger than V4. + - Temp hacks to disable V4 headers for 32bit images (compatibility with + other soft). + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Removed temporary data allocation for image with aligned scanlines. + They are now directly written to output so memory requirements are + much lower now. + - Now uses and recognizes BITMAPINFOHEADERV4 when loading/saving. + Mainly for formats with alpha channels. + - Added ifR5G6B5 to supported formats, changed converting to supported + formats little bit. + - Rewritten SaveRLE8 nested procedure. Old code was long and + mysterious - new is short and much more readable. + - MakeCompatible method moved to base class, put ConvertToSupported here. + GetSupportedFormats removed, it is now set in constructor. + - Rewritten LoadRLE4 and LoadRLE8 nested procedures. + Should be less buggy an more readable (load inspired by Colosseum Builders' code). + - Made public properties for options registered to SetOption/GetOption + functions. + - Addded alpha check to 32b bitmap loading too (teh same as in 16b + bitmap loading). + - Moved Convert1To8 and Convert4To8 to ImagingFormats + - Changed extensions to filename masks. + - Changed SaveData, LoadData, and MakeCompatible methods according + to changes in base class in Imaging unit. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - fixed wrong const that caused A4R4G4B4 BMPs to load as A1R5G5B5 + - fixed the bug that caused 8bit RLE compressed bitmaps to load as + whole black + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - 16 bit images are usually without alpha but some has alpha + channel and there is no indication of it - so I have added + a check: if all pixels of image are with alpha = 0 image is treated + as X1R5G5B5 otherwise as A1R5G5B5 + + -- 0.13 Changes/Bug Fixes ----------------------------------- + - when loading 1/4 bit images with dword aligned dimensions + there was ugly memory rewritting bug causing image corruption + +} + +end. diff --git a/src/lib/vampimg/ImagingCanvases.pas b/src/lib/vampimg/ImagingCanvases.pas new file mode 100644 index 0000000..448191c --- /dev/null +++ b/src/lib/vampimg/ImagingCanvases.pas @@ -0,0 +1,2110 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains canvas classes for drawing and applying effects.} +unit ImagingCanvases; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, Types, Classes, ImagingTypes, Imaging, ImagingClasses, + ImagingFormats, ImagingUtility; + +const + { Color constants in ifA8R8G8B8 format.} + pcClear = $00000000; + pcBlack = $FF000000; + pcWhite = $FFFFFFFF; + pcMaroon = $FF800000; + pcGreen = $FF008000; + pcOlive = $FF808000; + pcNavy = $FF000080; + pcPurple = $FF800080; + pcTeal = $FF008080; + pcGray = $FF808080; + pcSilver = $FFC0C0C0; + pcRed = $FFFF0000; + pcLime = $FF00FF00; + pcYellow = $FFFFFF00; + pcBlue = $FF0000FF; + pcFuchsia = $FFFF00FF; + pcAqua = $FF00FFFF; + pcLtGray = $FFC0C0C0; + pcDkGray = $FF808080; + + MaxPenWidth = 256; + +type + EImagingCanvasError = class(EImagingError); + EImagingCanvasBlendingError = class(EImagingError); + + { Fill mode used when drawing filled objects on canvas.} + TFillMode = ( + fmSolid, // Solid fill using current fill color + fmClear // No filling done + ); + + { Pen mode used when drawing lines, object outlines, and similar on canvas.} + TPenMode = ( + pmSolid, // Draws solid lines using current pen color. + pmClear // No drawing done + ); + + { Source and destination blending factors for drawing functions with blending. + Blending formula: SrcColor * SrcFactor + DestColor * DestFactor } + TBlendingFactor = ( + bfIgnore, // Don't care + bfZero, // For Src and Dest, Factor = (0, 0, 0, 0) + bfOne, // For Src and Dest, Factor = (1, 1, 1, 1) + bfSrcAlpha, // For Src and Dest, Factor = (Src.A, Src.A, Src.A, Src.A) + bfOneMinusSrcAlpha, // For Src and Dest, Factor = (1 - Src.A, 1 - Src.A, 1 - Src.A, 1 - Src.A) + bfDstAlpha, // For Src and Dest, Factor = (Dest.A, Dest.A, Dest.A, Dest.A) + bfOneMinusDstAlpha, // For Src and Dest, Factor = (1 - Dest.A, 1 - Dest.A, 1 - Dest.A, 1 - Dest.A) + bfSrcColor, // For Dest, Factor = (Src.R, Src.R, Src.B, Src.A) + bfOneMinusSrcColor, // For Dest, Factor = (1 - Src.R, 1 - Src.G, 1 - Src.B, 1 - Src.A) + bfDstColor, // For Src, Factor = (Dest.R, Dest.G, Dest.B, Dest.A) + bfOneMinusDstColor // For Src, Factor = (1 - Dest.R, 1 - Dest.G, 1 - Dest.B, 1 - Dest.A) + ); + + { Procedure for custom pixel write modes with blending.} + TPixelWriteProc = procedure(const SrcPix: TColorFPRec; DestPtr: PByte; + DestInfo: PImageFormatInfo; SrcFactor, DestFactor: TBlendingFactor); + + { Represents 3x3 convolution filter kernel.} + TConvolutionFilter3x3 = record + Kernel: array[0..2, 0..2] of LongInt; + Divisor: LongInt; + Bias: Single; + end; + + { Represents 5x5 convolution filter kernel.} + TConvolutionFilter5x5 = record + Kernel: array[0..4, 0..4] of LongInt; + Divisor: LongInt; + Bias: Single; + end; + + TPointTransformFunction = function(const Pixel: TColorFPRec; + Param1, Param2, Param3: Single): TColorFPRec; + + TDynFPPixelArray = array of TColorFPRec; + + THistogramArray = array[Byte] of Integer; + + TSelectPixelFunction = function(var Pixels: TDynFPPixelArray): TColorFPRec; + + { Base canvas class for drawing objects, applying effects, and other. + Constructor takes TBaseImage (or pointer to TImageData). Source image + bits are not copied but referenced so all canvas functions affect + source image and vice versa. When you change format or resolution of + source image you must call UpdateCanvasState method (so canvas could + recompute some data size related stuff). + + TImagingCanvas works for all image data formats except special ones + (compressed). Because of this its methods are quite slow (they usually work + with colors in ifA32R32G32B32F format). If you want fast drawing you + can use one of fast canvas clases. These descendants of TImagingCanvas + work only for few select formats (or only one) but they are optimized thus + much faster. + } + TImagingCanvas = class(TObject) + private + FDataSizeOnUpdate: LongInt; + FLineRecursion: Boolean; + function GetPixel32(X, Y: LongInt): TColor32; virtual; + function GetPixelFP(X, Y: LongInt): TColorFPRec; virtual; + function GetValid: Boolean; {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetPixel32(X, Y: LongInt; const Value: TColor32); virtual; + procedure SetPixelFP(X, Y: LongInt; const Value: TColorFPRec); virtual; + procedure SetPenColor32(const Value: TColor32); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetPenColorFP(const Value: TColorFPRec); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetPenWidth(const Value: LongInt); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetFillColor32(const Value: TColor32); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetFillColorFP(const Value: TColorFPRec); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetClipRect(const Value: TRect); + procedure CheckBeforeBlending(SrcFactor, DestFactor: TBlendingFactor; DestCanvas: TImagingCanvas); + protected + FPData: PImageData; + FClipRect: TRect; + FPenColorFP: TColorFPRec; + FPenColor32: TColor32; + FPenMode: TPenMode; + FPenWidth: LongInt; + FFillColorFP: TColorFPRec; + FFillColor32: TColor32; + FFillMode: TFillMode; + FNativeColor: TColorFPRec; + FFormatInfo: TImageFormatInfo; + + { Returns pointer to pixel at given position.} + function GetPixelPointer(X, Y: LongInt): Pointer; {$IFDEF USE_INLINE}inline;{$ENDIF} + { Translates given FP color to native format of canvas and stores it + in FNativeColor field (its bit copy) or user pointer (in overloaded method).} + procedure TranslateFPToNative(const Color: TColorFPRec); overload; {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure TranslateFPToNative(const Color: TColorFPRec; Native: Pointer); overload; {$IFDEF USE_INLINE}inline;{$ENDIF} + { Clipping function used by horizontal and vertical line drawing functions.} + function ClipAxisParallelLine(var A1, A2, B: LongInt; + AStart, AStop, BStart, BStop: LongInt): Boolean; + { Internal horizontal line drawer used mainly for filling inside of objects + like ellipses and circles.} + procedure HorzLineInternal(X1, X2, Y: LongInt; Color: Pointer; Bpp: LongInt); virtual; + procedure CopyPixelInternal(X, Y: LongInt; Pixel: Pointer; Bpp: LongInt); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure DrawInternal(const SrcRect: TRect; DestCanvas: TImagingCanvas; + DestX, DestY: Integer; SrcFactor, DestFactor: TBlendingFactor; PixelWriteProc: TPixelWriteProc); + procedure StretchDrawInternal(const SrcRect: TRect; DestCanvas: TImagingCanvas; + const DestRect: TRect; SrcFactor, DestFactor: TBlendingFactor; + Filter: TResizeFilter; PixelWriteProc: TPixelWriteProc); + public + constructor CreateForData(ImageDataPointer: PImageData); + constructor CreateForImage(Image: TBaseImage); + destructor Destroy; override; + + { Call this method when you change size or format of image this canvas + operates on (like calling ResizeImage, ConvertImage, or changing Format + property of TBaseImage descendants).} + procedure UpdateCanvasState; virtual; + { Resets clipping rectangle to Rect(0, 0, ImageWidth, ImageHeight).} + procedure ResetClipRect; + + { Clears entire canvas with current fill color (ignores clipping rectangle + and always uses fmSolid fill mode).} + procedure Clear; + + { Draws horizontal line with current pen settings.} + procedure HorzLine(X1, X2, Y: LongInt); virtual; + { Draws vertical line with current pen settings.} + procedure VertLine(X, Y1, Y2: LongInt); virtual; + { Draws line from [X1, Y1] to [X2, Y2] with current pen settings.} + procedure Line(X1, Y1, X2, Y2: LongInt); virtual; + { Draws a rectangle using current pen settings.} + procedure FrameRect(const Rect: TRect); + { Fills given rectangle with current fill settings.} + procedure FillRect(const Rect: TRect); virtual; + { Fills given rectangle with current fill settings and pixel blending.} + procedure FillRectBlend(const Rect: TRect; SrcFactor, DestFactor: TBlendingFactor); + { Draws rectangle which is outlined by using the current pen settings and + filled by using the current fill settings.} + procedure Rectangle(const Rect: TRect); + { Draws ellipse which is outlined by using the current pen settings and + filled by using the current fill settings. Rect specifies bounding rectangle + of ellipse to be drawn.} + procedure Ellipse(const Rect: TRect); + { Fills area of canvas with current fill color starting at point [X, Y] and + coloring its neighbors. Default flood fill mode changes color of all + neighbors with the same color as pixel [X, Y]. With BoundaryFillMode + set to True neighbors are recolored regardless of their old color, + but area which will be recolored has boundary (specified by current pen color).} + procedure FloodFill(X, Y: Integer; BoundaryFillMode: Boolean = False); + + { Draws contents of this canvas onto another canvas with pixel blending. + Blending factors are chosen using TBlendingFactor parameters. + Resulting destination pixel color is: + SrcColor * SrcFactor + DstColor * DstFactor} + procedure DrawBlend(const SrcRect: TRect; DestCanvas: TImagingCanvas; + DestX, DestY: Integer; SrcFactor, DestFactor: TBlendingFactor); + { Draws contents of this canvas onto another one with typical alpha + blending (Src 'over' Dest, factors are bfSrcAlpha and bfOneMinusSrcAlpha.)} + procedure DrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer); virtual; + { Draws contents of this canvas onto another one using additive blending + (source and dest factors are bfOne).} + procedure DrawAdd(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer); + { Draws stretched and filtered contents of this canvas onto another canvas + with pixel blending. Blending factors are chosen using TBlendingFactor parameters. + Resulting destination pixel color is: + SrcColor * SrcFactor + DstColor * DstFactor} + procedure StretchDrawBlend(const SrcRect: TRect; DestCanvas: TImagingCanvas; + const DestRect: TRect; SrcFactor, DestFactor: TBlendingFactor; + Filter: TResizeFilter = rfBilinear); + { Draws contents of this canvas onto another one with typical alpha + blending (Src 'over' Dest, factors are bfSrcAlpha and bfOneMinusSrcAlpha.)} + procedure StretchDrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; + const DestRect: TRect; Filter: TResizeFilter = rfBilinear); virtual; + { Draws contents of this canvas onto another one using additive blending + (source and dest factors are bfOne).} + procedure StretchDrawAdd(const SrcRect: TRect; DestCanvas: TImagingCanvas; + const DestRect: TRect; Filter: TResizeFilter = rfBilinear); + + { Convolves canvas' image with given 3x3 filter kernel. You can use + predefined filter kernels or define your own.} + procedure ApplyConvolution3x3(const Filter: TConvolutionFilter3x3); + { Convolves canvas' image with given 5x5 filter kernel. You can use + predefined filter kernels or define your own.} + procedure ApplyConvolution5x5(const Filter: TConvolutionFilter5x5); + { Computes 2D convolution of canvas' image and given filter kernel. + Kernel is in row format and KernelSize must be odd number >= 3. Divisor + is normalizing value based on Kernel (usually sum of all kernel's cells). + The Bias number shifts each color value by a fixed amount (color values + are usually in range [0, 1] during processing). If ClampChannels + is True all output color values are clamped to [0, 1]. You can use + predefined filter kernels or define your own.} + procedure ApplyConvolution(Kernel: PLongInt; KernelSize, Divisor: LongInt; + Bias: Single = 0.0; ClampChannels: Boolean = True); virtual; + + { Applies custom non-linear filter. Filter size is diameter of pixel + neighborhood. Typical values are 3, 5, or 7. } + procedure ApplyNonLinearFilter(FilterSize: Integer; SelectFunc: TSelectPixelFunction); + { Applies median non-linear filter with user defined pixel neighborhood. + Selects median pixel from the neighborhood as new pixel + (current implementation is quite slow).} + procedure ApplyMedianFilter(FilterSize: Integer); + { Applies min non-linear filter with user defined pixel neighborhood. + Selects min pixel from the neighborhood as new pixel.} + procedure ApplyMinFilter(FilterSize: Integer); + { Applies max non-linear filter with user defined pixel neighborhood. + Selects max pixel from the neighborhood as new pixel.} + procedure ApplyMaxFilter(FilterSize: Integer); + + { Transforms pixels one by one by given function. Pixel neighbors are + not taken into account. Param 1-3 are optional parameters + for transform function.} + procedure PointTransform(Transform: TPointTransformFunction; + Param1, Param2, Param3: Single); + { Modifies image contrast and brightness. Parameters should be + in range <-100; 100>.} + procedure ModifyContrastBrightness(Contrast, Brightness: Single); + { Gamma correction of individual color channels. Range is (0, +inf), + 1.0 means no change.} + procedure GammaCorection(Red, Green, Blue: Single); + { Inverts colors of all image pixels, makes negative image. Ignores alpha channel.} + procedure InvertColors; virtual; + { Simple single level thresholding with threshold level (in range [0, 1]) + for each color channel.} + procedure Threshold(Red, Green, Blue: Single); + { Adjusts the color levels of the image by scaling the + colors falling between specified white and black points to full [0, 1] range. + The black point specifies the darkest color in the image, white point + specifies the lightest color, and mid point is gamma aplied to image. + Black and white point must be in range [0, 1].} + procedure AdjustColorLevels(BlackPoint, WhitePoint: Single; MidPoint: Single = 1.0); + { Premultiplies color channel values by alpha. Needed for some platforms/APIs + to display images with alpha properly.} + procedure PremultiplyAlpha; + { Reverses PremultiplyAlpha operation.} + procedure UnPremultiplyAlpha; + + { Calculates image histogram for each channel and also gray values. Each + channel has 256 values available. Channel values of data formats with higher + precision are scaled and rounded. Example: Red[126] specifies number of pixels + in image with red channel = 126.} + procedure GetHistogram(out Red, Green, Blue, Alpha, Gray: THistogramArray); + { Fills image channel with given value leaving other channels intact. + Use ChannelAlpha, ChannelRed, etc. constants from ImagingTypes as + channel identifier.} + procedure FillChannel(ChannelId: Integer; NewChannelValue: Byte); overload; + { Fills image channel with given value leaving other channels intact. + Use ChannelAlpha, ChannelRed, etc. constants from ImagingTypes as + channel identifier.} + procedure FillChannelFP(ChannelId: Integer; NewChannelValue: Single); overload; + + { Color used when drawing lines, frames, and outlines of objects.} + property PenColor32: TColor32 read FPenColor32 write SetPenColor32; + { Color used when drawing lines, frames, and outlines of objects.} + property PenColorFP: TColorFPRec read FPenColorFP write SetPenColorFP; + { Pen mode used when drawing lines, object outlines, and similar on canvas.} + property PenMode: TPenMode read FPenMode write FPenMode; + { Width with which objects like lines, frames, etc. (everything which uses + PenColor) are drawn.} + property PenWidth: LongInt read FPenWidth write SetPenWidth; + { Color used for filling when drawing various objects.} + property FillColor32: TColor32 read FFillColor32 write SetFillColor32; + { Color used for filling when drawing various objects.} + property FillColorFP: TColorFPRec read FFillColorFP write SetFillColorFP; + { Fill mode used when drawing filled objects on canvas.} + property FillMode: TFillMode read FFillMode write FFillMode; + { Specifies the current color of the pixels of canvas. Native pixel is + read from canvas and then translated to 32bit ARGB. Reverse operation + is made when setting pixel color.} + property Pixels32[X, Y: LongInt]: TColor32 read GetPixel32 write SetPixel32; + { Specifies the current color of the pixels of canvas. Native pixel is + read from canvas and then translated to FP ARGB. Reverse operation + is made when setting pixel color.} + property PixelsFP[X, Y: LongInt]: TColorFPRec read GetPixelFP write SetPixelFP; + { Clipping rectangle of this canvas. No pixels outside this rectangle are + altered by canvas methods if Clipping property is True. Clip rect gets + reseted when UpdateCanvasState is called.} + property ClipRect: TRect read FClipRect write SetClipRect; + { Extended format information.} + property FormatInfo: TImageFormatInfo read FFormatInfo; + { Indicates that this canvas is in valid state. If False canvas oprations + may crash.} + property Valid: Boolean read GetValid; + + { Returns all formats supported by this canvas class.} + class function GetSupportedFormats: TImageFormats; virtual; + end; + + TImagingCanvasClass = class of TImagingCanvas; + + TScanlineArray = array[0..MaxInt div SizeOf(Pointer) - 1] of PColor32RecArray; + PScanlineArray = ^TScanlineArray; + + { Fast canvas class for ifA8R8G8B8 format images.} + TFastARGB32Canvas = class(TImagingCanvas) + protected + FScanlines: PScanlineArray; + procedure AlphaBlendPixels(SrcPix, DestPix: PColor32Rec); {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetPixel32(X, Y: LongInt): TColor32; override; + procedure SetPixel32(X, Y: LongInt; const Value: TColor32); override; + public + destructor Destroy; override; + + procedure UpdateCanvasState; override; + + procedure DrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; DestX, DestY: Integer); override; + procedure StretchDrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; + const DestRect: TRect; Filter: TResizeFilter = rfBilinear); override; + procedure InvertColors; override; + + property Scanlines: PScanlineArray read FScanlines; + + class function GetSupportedFormats: TImageFormats; override; + end; + +const + { Kernel for 3x3 average smoothing filter.} + FilterAverage3x3: TConvolutionFilter3x3 = ( + Kernel: ((1, 1, 1), + (1, 1, 1), + (1, 1, 1)); + Divisor: 9); + + { Kernel for 5x5 average smoothing filter.} + FilterAverage5x5: TConvolutionFilter5x5 = ( + Kernel: ((1, 1, 1, 1, 1), + (1, 1, 1, 1, 1), + (1, 1, 1, 1, 1), + (1, 1, 1, 1, 1), + (1, 1, 1, 1, 1)); + Divisor: 25); + + { Kernel for 3x3 Gaussian smoothing filter.} + FilterGaussian3x3: TConvolutionFilter3x3 = ( + Kernel: ((1, 2, 1), + (2, 4, 2), + (1, 2, 1)); + Divisor: 16); + + { Kernel for 5x5 Gaussian smoothing filter.} + FilterGaussian5x5: TConvolutionFilter5x5 = ( + Kernel: ((1, 4, 6, 4, 1), + (4, 16, 24, 16, 4), + (6, 24, 36, 24, 6), + (4, 16, 24, 16, 4), + (1, 4, 6, 4, 1)); + Divisor: 256); + + { Kernel for 3x3 Sobel horizontal edge detection filter (1st derivative approximation).} + FilterSobelHorz3x3: TConvolutionFilter3x3 = ( + Kernel: (( 1, 2, 1), + ( 0, 0, 0), + (-1, -2, -1)); + Divisor: 1); + + { Kernel for 3x3 Sobel vertical edge detection filter (1st derivative approximation).} + FilterSobelVert3x3: TConvolutionFilter3x3 = ( + Kernel: ((-1, 0, 1), + (-2, 0, 2), + (-1, 0, 1)); + Divisor: 1); + + { Kernel for 3x3 Prewitt horizontal edge detection filter.} + FilterPrewittHorz3x3: TConvolutionFilter3x3 = ( + Kernel: (( 1, 1, 1), + ( 0, 0, 0), + (-1, -1, -1)); + Divisor: 1); + + { Kernel for 3x3 Prewitt vertical edge detection filter.} + FilterPrewittVert3x3: TConvolutionFilter3x3 = ( + Kernel: ((-1, 0, 1), + (-1, 0, 1), + (-1, 0, 1)); + Divisor: 1); + + { Kernel for 3x3 Kirsh horizontal edge detection filter.} + FilterKirshHorz3x3: TConvolutionFilter3x3 = ( + Kernel: (( 5, 5, 5), + (-3, 0, -3), + (-3, -3, -3)); + Divisor: 1); + + { Kernel for 3x3 Kirsh vertical edge detection filter.} + FilterKirshVert3x3: TConvolutionFilter3x3 = ( + Kernel: ((5, -3, -3), + (5, 0, -3), + (5, -3, -3)); + Divisor: 1); + + { Kernel for 3x3 Laplace omni-directional edge detection filter + (2nd derivative approximation).} + FilterLaplace3x3: TConvolutionFilter3x3 = ( + Kernel: ((-1, -1, -1), + (-1, 8, -1), + (-1, -1, -1)); + Divisor: 1); + + { Kernel for 5x5 Laplace omni-directional edge detection filter + (2nd derivative approximation).} + FilterLaplace5x5: TConvolutionFilter5x5 = ( + Kernel: ((-1, -1, -1, -1, -1), + (-1, -1, -1, -1, -1), + (-1, -1, 24, -1, -1), + (-1, -1, -1, -1, -1), + (-1, -1, -1, -1, -1)); + Divisor: 1); + + { Kernel for 3x3 spharpening filter (Laplacian + original color).} + FilterSharpen3x3: TConvolutionFilter3x3 = ( + Kernel: ((-1, -1, -1), + (-1, 9, -1), + (-1, -1, -1)); + Divisor: 1); + + { Kernel for 5x5 spharpening filter (Laplacian + original color).} + FilterSharpen5x5: TConvolutionFilter5x5 = ( + Kernel: ((-1, -1, -1, -1, -1), + (-1, -1, -1, -1, -1), + (-1, -1, 25, -1, -1), + (-1, -1, -1, -1, -1), + (-1, -1, -1, -1, -1)); + Divisor: 1); + + { Kernel for 5x5 glow filter.} + FilterGlow5x5: TConvolutionFilter5x5 = ( + Kernel: (( 1, 2, 2, 2, 1), + ( 2, 0, 0, 0, 2), + ( 2, 0, -20, 0, 2), + ( 2, 0, 0, 0, 2), + ( 1, 2, 2, 2, 1)); + Divisor: 8); + + { Kernel for 3x3 edge enhancement filter.} + FilterEdgeEnhance3x3: TConvolutionFilter3x3 = ( + Kernel: ((-1, -2, -1), + (-2, 16, -2), + (-1, -2, -1)); + Divisor: 4); + + { Kernel for 3x3 contour enhancement filter.} + FilterTraceControur3x3: TConvolutionFilter3x3 = ( + Kernel: ((-6, -6, -2), + (-1, 32, -1), + (-6, -2, -6)); + Divisor: 4; + Bias: 240/255); + + { Kernel for filter that negates all images pixels.} + FilterNegative3x3: TConvolutionFilter3x3 = ( + Kernel: ((0, 0, 0), + (0, -1, 0), + (0, 0, 0)); + Divisor: 1; + Bias: 1); + + { Kernel for 3x3 horz/vert embossing filter.} + FilterEmboss3x3: TConvolutionFilter3x3 = ( + Kernel: ((2, 0, 0), + (0, -1, 0), + (0, 0, -1)); + Divisor: 1; + Bias: 0.5); + + +{ You can register your own canvas class. List of registered canvases is used + by FindBestCanvasForImage functions to find best canvas for given image. + If two different canvases which support the same image data format are + registered then the one that was registered later is returned (so you can + override builtin Imaging canvases).} +procedure RegisterCanvas(CanvasClass: TImagingCanvasClass); +{ Returns best canvas for given TImageFormat.} +function FindBestCanvasForImage(ImageFormat: TImageFormat): TImagingCanvasClass; overload; +{ Returns best canvas for given TImageData.} +function FindBestCanvasForImage(const ImageData: TImageData): TImagingCanvasClass; overload; +{ Returns best canvas for given TBaseImage.} +function FindBestCanvasForImage(Image: TBaseImage): TImagingCanvasClass; overload; + +implementation + +resourcestring + SConstructorInvalidPointer = 'Invalid pointer (%p) to TImageData passed to TImagingCanvas constructor.'; + SConstructorInvalidImage = 'Invalid image data passed to TImagingCanvas constructor (%s).'; + SConstructorUnsupportedFormat = 'Image passed to TImagingCanvas constructor is in unsupported format (%s)'; + +var + // list with all registered TImagingCanvas classes + CanvasClasses: TList = nil; + +procedure RegisterCanvas(CanvasClass: TImagingCanvasClass); +begin + Assert(CanvasClass <> nil); + if CanvasClasses = nil then + CanvasClasses := TList.Create; + if CanvasClasses.IndexOf(CanvasClass) < 0 then + CanvasClasses.Add(CanvasClass); +end; + +function FindBestCanvasForImage(ImageFormat: TImageFormat): TImagingCanvasClass; overload; +var + I: LongInt; +begin + for I := CanvasClasses.Count - 1 downto 0 do + begin + if ImageFormat in TImagingCanvasClass(CanvasClasses[I]).GetSupportedFormats then + begin + Result := TImagingCanvasClass(CanvasClasses[I]); + Exit; + end; + end; + Result := TImagingCanvas; +end; + +function FindBestCanvasForImage(const ImageData: TImageData): TImagingCanvasClass; +begin + Result := FindBestCanvasForImage(ImageData.Format); +end; + +function FindBestCanvasForImage(Image: TBaseImage): TImagingCanvasClass; +begin + Result := FindBestCanvasForImage(Image.Format); +end; + +{ Canvas helper functions } + +procedure PixelBlendProc(const SrcPix: TColorFPRec; DestPtr: PByte; + DestInfo: PImageFormatInfo; SrcFactor, DestFactor: TBlendingFactor); +var + DestPix, FSrc, FDst: TColorFPRec; +begin + // Get set pixel color + DestPix := DestInfo.GetPixelFP(DestPtr, DestInfo, nil); + // Determine current blending factors + case SrcFactor of + bfZero: FSrc := ColorFP(0, 0, 0, 0); + bfOne: FSrc := ColorFP(1, 1, 1, 1); + bfSrcAlpha: FSrc := ColorFP(SrcPix.A, SrcPix.A, SrcPix.A, SrcPix.A); + bfOneMinusSrcAlpha: FSrc := ColorFP(1 - SrcPix.A, 1 - SrcPix.A, 1 - SrcPix.A, 1 - SrcPix.A); + bfDstAlpha: FSrc := ColorFP(DestPix.A, DestPix.A, DestPix.A, DestPix.A); + bfOneMinusDstAlpha: FSrc := ColorFP(1 - DestPix.A, 1 - DestPix.A, 1 - DestPix.A, 1 - DestPix.A); + bfDstColor: FSrc := ColorFP(DestPix.A, DestPix.R, DestPix.G, DestPix.B); + bfOneMinusDstColor: FSrc := ColorFP(1 - DestPix.A, 1 - DestPix.R, 1 - DestPix.G, 1 - DestPix.B); + end; + case DestFactor of + bfZero: FDst := ColorFP(0, 0, 0, 0); + bfOne: FDst := ColorFP(1, 1, 1, 1); + bfSrcAlpha: FDst := ColorFP(SrcPix.A, SrcPix.A, SrcPix.A, SrcPix.A); + bfOneMinusSrcAlpha: FDst := ColorFP(1 - SrcPix.A, 1 - SrcPix.A, 1 - SrcPix.A, 1 - SrcPix.A); + bfDstAlpha: FDst := ColorFP(DestPix.A, DestPix.A, DestPix.A, DestPix.A); + bfOneMinusDstAlpha: FDst := ColorFP(1 - DestPix.A, 1 - DestPix.A, 1 - DestPix.A, 1 - DestPix.A); + bfSrcColor: FDst := ColorFP(SrcPix.A, SrcPix.R, SrcPix.G, SrcPix.B); + bfOneMinusSrcColor: FDst := ColorFP(1 - SrcPix.A, 1 - SrcPix.R, 1 - SrcPix.G, 1 - SrcPix.B); + end; + // Compute blending formula + DestPix.R := SrcPix.R * FSrc.R + DestPix.R * FDst.R; + DestPix.G := SrcPix.G * FSrc.G + DestPix.G * FDst.G; + DestPix.B := SrcPix.B * FSrc.B + DestPix.B * FDst.B; + DestPix.A := SrcPix.A * FSrc.A + DestPix.A * FDst.A; + // Write blended pixel + DestInfo.SetPixelFP(DestPtr, DestInfo, nil, DestPix); +end; + +procedure PixelAlphaProc(const SrcPix: TColorFPRec; DestPtr: PByte; + DestInfo: PImageFormatInfo; SrcFactor, DestFactor: TBlendingFactor); +var + DestPix: TColorFPRec; + SrcAlpha, DestAlpha: Single; +begin + DestPix := DestInfo.GetPixelFP(DestPtr, DestInfo, nil); + // Blend the two pixels (Src 'over' Dest alpha composition operation) + DestPix.A := SrcPix.A + DestPix.A - SrcPix.A * DestPix.A; + if DestPix.A = 0 then + SrcAlpha := 0 + else + SrcAlpha := SrcPix.A / DestPix.A; + DestAlpha := 1.0 - SrcAlpha; + DestPix.R := SrcPix.R * SrcAlpha + DestPix.R * DestAlpha; + DestPix.G := SrcPix.G * SrcAlpha + DestPix.G * DestAlpha; + DestPix.B := SrcPix.B * SrcAlpha + DestPix.B * DestAlpha; + // Write blended pixel + DestInfo.SetPixelFP(DestPtr, DestInfo, nil, DestPix); +end; + +procedure PixelAddProc(const SrcPix: TColorFPRec; DestPtr: PByte; + DestInfo: PImageFormatInfo; SrcFactor, DestFactor: TBlendingFactor); +var + DestPix: TColorFPRec; +begin + // Just add Src and Dest + DestPix := DestInfo.GetPixelFP(DestPtr, DestInfo, nil); + DestPix.R := SrcPix.R + DestPix.R; + DestPix.G := SrcPix.G + DestPix.G; + DestPix.B := SrcPix.B + DestPix.B; + DestPix.A := SrcPix.A + DestPix.A; + DestInfo.SetPixelFP(DestPtr, DestInfo, nil, DestPix); +end; + +function CompareColors(const C1, C2: TColorFPRec): Single; {$IFDEF USE_INLINE}inline;{$ENDIF} +begin + Result := (C1.R * GrayConv.R + C1.G * GrayConv.G + C1.B * GrayConv.B) - + (C2.R * GrayConv.R + C2.G * GrayConv.G + C2.B * GrayConv.B); +end; + +function MedianSelect(var Pixels: TDynFPPixelArray): TColorFPRec; + + procedure QuickSort(L, R: Integer); + var + I, J: Integer; + P, Temp: TColorFPRec; + begin + repeat + I := L; + J := R; + P := Pixels[(L + R) shr 1]; + repeat + while CompareColors(Pixels[I], P) < 0 do Inc(I); + while CompareColors(Pixels[J], P) > 0 do Dec(J); + if I <= J then + begin + Temp := Pixels[I]; + Pixels[I] := Pixels[J]; + Pixels[J] := Temp; + Inc(I); + Dec(J); + end; + until I > J; + if L < J then + QuickSort(L, J); + L := I; + until I >= R; + end; + +begin + // First sort pixels + QuickSort(0, High(Pixels)); + // Select middle pixel + Result := Pixels[Length(Pixels) div 2]; +end; + +function MinSelect(var Pixels: TDynFPPixelArray): TColorFPRec; +var + I: Integer; +begin + Result := Pixels[0]; + for I := 1 to High(Pixels) do + begin + if CompareColors(Pixels[I], Result) < 0 then + Result := Pixels[I]; + end; +end; + +function MaxSelect(var Pixels: TDynFPPixelArray): TColorFPRec; +var + I: Integer; +begin + Result := Pixels[0]; + for I := 1 to High(Pixels) do + begin + if CompareColors(Pixels[I], Result) > 0 then + Result := Pixels[I]; + end; +end; + +function TransformContrastBrightness(const Pixel: TColorFPRec; C, B, P3: Single): TColorFPRec; +begin + Result.A := Pixel.A; + Result.R := Pixel.R * C + B; + Result.G := Pixel.G * C + B; + Result.B := Pixel.B * C + B; +end; + +function TransformGamma(const Pixel: TColorFPRec; R, G, B: Single): TColorFPRec; +begin + Result.A := Pixel.A; + Result.R := Power(Pixel.R, 1.0 / R); + Result.G := Power(Pixel.G, 1.0 / G); + Result.B := Power(Pixel.B, 1.0 / B); +end; + +function TransformInvert(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec; +begin + Result.A := Pixel.A; + Result.R := 1.0 - Pixel.R; + Result.G := 1.0 - Pixel.G; + Result.B := 1.0 - Pixel.B; +end; + +function TransformThreshold(const Pixel: TColorFPRec; R, G, B: Single): TColorFPRec; +begin + Result.A := Pixel.A; + Result.R := IffFloat(Pixel.R >= R, 1.0, 0.0); + Result.G := IffFloat(Pixel.G >= G, 1.0, 0.0); + Result.B := IffFloat(Pixel.B >= B, 1.0, 0.0); +end; + +function TransformLevels(const Pixel: TColorFPRec; BlackPoint, WhitePoint, Exp: Single): TColorFPRec; +begin + Result.A := Pixel.A; + if Pixel.R > BlackPoint then + Result.R := Power((Pixel.R - BlackPoint) / (WhitePoint - BlackPoint), Exp) + else + Result.R := 0.0; + if Pixel.G > BlackPoint then + Result.G := Power((Pixel.G - BlackPoint) / (WhitePoint - BlackPoint), Exp) + else + Result.G := 0.0; + if Pixel.B > BlackPoint then + Result.B := Power((Pixel.B - BlackPoint) / (WhitePoint - BlackPoint), Exp) + else + Result.B := 0.0; +end; + +function TransformPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec; +begin + Result.A := Pixel.A; + Result.R := Result.R * Pixel.A; + Result.G := Result.G * Pixel.A; + Result.B := Result.B * Pixel.A; +end; + +function TransformUnPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec; +begin + Result.A := Pixel.A; + if Pixel.A <> 0.0 then + begin + Result.R := Result.R / Pixel.A; + Result.G := Result.G / Pixel.A; + Result.B := Result.B / Pixel.A; + end + else + begin + Result.R := 0; + Result.G := 0; + Result.B := 0; + end; +end; + + +{ TImagingCanvas class implementation } + +constructor TImagingCanvas.CreateForData(ImageDataPointer: PImageData); +begin + if ImageDataPointer = nil then + raise EImagingCanvasError.CreateFmt(SConstructorInvalidPointer, [ImageDataPointer]); + + if not TestImage(ImageDataPointer^) then + raise EImagingCanvasError.CreateFmt(SConstructorInvalidImage, [Imaging.ImageToStr(ImageDataPointer^)]); + + if not (ImageDataPointer.Format in GetSupportedFormats) then + raise EImagingCanvasError.CreateFmt(SConstructorUnsupportedFormat, [Imaging.ImageToStr(ImageDataPointer^)]); + + FPData := ImageDataPointer; + FPenWidth := 1; + SetPenColor32(pcWhite); + SetFillColor32(pcBlack); + FFillMode := fmSolid; + + UpdateCanvasState; +end; + +constructor TImagingCanvas.CreateForImage(Image: TBaseImage); +begin + CreateForData(Image.ImageDataPointer); +end; + +destructor TImagingCanvas.Destroy; +begin + inherited Destroy; +end; + +function TImagingCanvas.GetPixel32(X, Y: LongInt): TColor32; +begin + Result := Imaging.GetPixel32(FPData^, X, Y).Color; +end; + +function TImagingCanvas.GetPixelFP(X, Y: LongInt): TColorFPRec; +begin + Result := Imaging.GetPixelFP(FPData^, X, Y); +end; + +function TImagingCanvas.GetValid: Boolean; +begin + Result := (FPData <> nil) and (FDataSizeOnUpdate = FPData.Size); +end; + +procedure TImagingCanvas.SetPixel32(X, Y: LongInt; const Value: TColor32); +begin + if (X >= FClipRect.Left) and (Y >= FClipRect.Top) and + (X < FClipRect.Right) and (Y < FClipRect.Bottom) then + begin + Imaging.SetPixel32(FPData^, X, Y, TColor32Rec(Value)); + end; +end; + +procedure TImagingCanvas.SetPixelFP(X, Y: LongInt; const Value: TColorFPRec); +begin + if (X >= FClipRect.Left) and (Y >= FClipRect.Top) and + (X < FClipRect.Right) and (Y < FClipRect.Bottom) then + begin + Imaging.SetPixelFP(FPData^, X, Y, TColorFPRec(Value)); + end; +end; + +procedure TImagingCanvas.SetPenColor32(const Value: TColor32); +begin + FPenColor32 := Value; + TranslatePixel(@FPenColor32, @FPenColorFP, ifA8R8G8B8, ifA32R32G32B32F, nil, nil); +end; + +procedure TImagingCanvas.SetPenColorFP(const Value: TColorFPRec); +begin + FPenColorFP := Value; + TranslatePixel(@FPenColorFP, @FPenColor32, ifA32R32G32B32F, ifA8R8G8B8, nil, nil); +end; + +procedure TImagingCanvas.SetPenWidth(const Value: LongInt); +begin + FPenWidth := ClampInt(Value, 0, MaxPenWidth); +end; + +procedure TImagingCanvas.SetFillColor32(const Value: TColor32); +begin + FFillColor32 := Value; + TranslatePixel(@FFillColor32, @FFillColorFP, ifA8R8G8B8, ifA32R32G32B32F, nil, nil); +end; + +procedure TImagingCanvas.SetFillColorFP(const Value: TColorFPRec); +begin + FFillColorFP := Value; + TranslatePixel(@FFillColorFP, @FFillColor32, ifA32R32G32B32F, ifA8R8G8B8, nil, nil); +end; + +procedure TImagingCanvas.SetClipRect(const Value: TRect); +begin + FClipRect := Value; + SwapMin(FClipRect.Left, FClipRect.Right); + SwapMin(FClipRect.Top, FClipRect.Bottom); + IntersectRect(FClipRect, FClipRect, Rect(0, 0, FPData.Width, FPData.Height)); +end; + +procedure TImagingCanvas.CheckBeforeBlending(SrcFactor, + DestFactor: TBlendingFactor; DestCanvas: TImagingCanvas); +begin + if SrcFactor in [bfSrcColor, bfOneMinusSrcColor] then + raise EImagingCanvasBlendingError.Create('Invalid source blending factor. Check the documentation for TBlendingFactor.'); + if DestFactor in [bfDstColor, bfOneMinusDstColor] then + raise EImagingCanvasBlendingError.Create('Invalid destination blending factor. Check the documentation for TBlendingFactor.'); + if DestCanvas.FormatInfo.IsIndexed then + raise EImagingCanvasBlendingError.Create('Blending destination canvas cannot be in indexed mode.'); +end; + +function TImagingCanvas.GetPixelPointer(X, Y: LongInt): Pointer; +begin + Result := @PByteArray(FPData.Bits)[(Y * FPData.Width + X) * FFormatInfo.BytesPerPixel] +end; + +procedure TImagingCanvas.TranslateFPToNative(const Color: TColorFPRec); +begin + TranslateFPToNative(Color, @FNativeColor); +end; + +procedure TImagingCanvas.TranslateFPToNative(const Color: TColorFPRec; + Native: Pointer); +begin + ImagingFormats.TranslatePixel(@Color, Native, ifA32R32G32B32F, + FPData.Format, nil, FPData.Palette); +end; + +procedure TImagingCanvas.UpdateCanvasState; +begin + FDataSizeOnUpdate := FPData.Size; + ResetClipRect; + Imaging.GetImageFormatInfo(FPData.Format, FFormatInfo) +end; + +procedure TImagingCanvas.ResetClipRect; +begin + FClipRect := Rect(0, 0, FPData.Width, FPData.Height) +end; + +procedure TImagingCanvas.Clear; +begin + TranslateFPToNative(FFillColorFP); + Imaging.FillRect(FPData^, 0, 0, FPData.Width, FPData.Height, @FNativeColor); +end; + +function TImagingCanvas.ClipAxisParallelLine(var A1, A2, B: LongInt; + AStart, AStop, BStart, BStop: LongInt): Boolean; +begin + if (B >= BStart) and (B < BStop) then + begin + SwapMin(A1, A2); + if A1 < AStart then A1 := AStart; + if A2 >= AStop then A2 := AStop - 1; + Result := True; + end + else + Result := False; +end; + +procedure TImagingCanvas.HorzLineInternal(X1, X2, Y: LongInt; Color: Pointer; + Bpp: LongInt); +var + I, WidthBytes: LongInt; + PixelPtr: PByte; +begin + if (Y >= FClipRect.Top) and (Y < FClipRect.Bottom) then + begin + SwapMin(X1, X2); + X1 := Max(X1, FClipRect.Left); + X2 := Min(X2, FClipRect.Right); + PixelPtr := GetPixelPointer(X1, Y); + WidthBytes := (X2 - X1) * Bpp; + case Bpp of + 1: FillMemoryByte(PixelPtr, WidthBytes, PByte(Color)^); + 2: FillMemoryWord(PixelPtr, WidthBytes, PWord(Color)^); + 4: FillMemoryLongWord(PixelPtr, WidthBytes, PLongWord(Color)^); + else + for I := X1 to X2 do + begin + ImagingFormats.CopyPixel(Color, PixelPtr, Bpp); + Inc(PixelPtr, Bpp); + end; + end; + end; +end; + +procedure TImagingCanvas.CopyPixelInternal(X, Y: LongInt; Pixel: Pointer; + Bpp: LongInt); +begin + if (X >= FClipRect.Left) and (Y >= FClipRect.Top) and + (X < FClipRect.Right) and (Y < FClipRect.Bottom) then + begin + ImagingFormats.CopyPixel(Pixel, GetPixelPointer(X, Y), Bpp); + end; +end; + +procedure TImagingCanvas.HorzLine(X1, X2, Y: LongInt); +var + DstRect: TRect; +begin + if FPenMode = pmClear then Exit; + SwapMin(X1, X2); + if IntersectRect(DstRect, Rect(X1, Y - FPenWidth div 2, X2, + Y + FPenWidth div 2 + FPenWidth mod 2), FClipRect) then + begin + TranslateFPToNative(FPenColorFP); + Imaging.FillRect(FPData^, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left, + DstRect.Bottom - DstRect.Top, @FNativeColor); + end; +end; + +procedure TImagingCanvas.VertLine(X, Y1, Y2: LongInt); +var + DstRect: TRect; +begin + if FPenMode = pmClear then Exit; + SwapMin(Y1, Y2); + if IntersectRect(DstRect, Rect(X - FPenWidth div 2, Y1, + X + FPenWidth div 2 + FPenWidth mod 2, Y2), FClipRect) then + begin + TranslateFPToNative(FPenColorFP); + Imaging.FillRect(FPData^, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left, + DstRect.Bottom - DstRect.Top, @FNativeColor); + end; +end; + +procedure TImagingCanvas.Line(X1, Y1, X2, Y2: LongInt); +var + Steep: Boolean; + Error, YStep, DeltaX, DeltaY, X, Y, I, Bpp, W1, W2, Code1, Code2: LongInt; +begin + if FPenMode = pmClear then Exit; + + // If line is vertical or horizontal just call appropriate method + if X2 = X1 then + begin + VertLine(X1, Y1, Y2); + Exit; + end; + if Y2 = Y1 then + begin + HorzLine(X1, X2, Y1); + Exit; + end; + + // Determine if line is steep (angle with X-axis > 45 degrees) + Steep := Abs(Y2 - Y1) > Abs(X2 - X1); + + // If we need to draw thick line we just draw more 1 pixel lines around + // the one we already drawn. Setting FLineRecursion assures that we + // won't be doing recursions till the end of the world. + if (FPenWidth > 1) and not FLineRecursion then + begin + FLineRecursion := True; + W1 := FPenWidth div 2; + W2 := W1; + if FPenWidth mod 2 = 0 then + Dec(W1); + if Steep then + begin + // Add lines left/right + for I := 1 to W1 do + Line(X1, Y1 - I, X2, Y2 - I); + for I := 1 to W2 do + Line(X1, Y1 + I, X2, Y2 + I); + end + else + begin + // Add lines above/under + for I := 1 to W1 do + Line(X1 - I, Y1, X2 - I, Y2); + for I := 1 to W2 do + Line(X1 + I, Y1, X2 + I, Y2); + end; + FLineRecursion := False; + end; + + with FClipRect do + begin + // Use part of Cohen-Sutherland line clipping to determine if any part of line + // is in ClipRect + Code1 := Ord(X1 < Left) + Ord(X1 > Right) shl 1 + Ord(Y1 < Top) shl 2 + Ord(Y1 > Bottom) shl 3; + Code2 := Ord(X2 < Left) + Ord(X2 > Right) shl 1 + Ord(Y2 < Top) shl 2 + Ord(Y2 > Bottom) shl 3; + end; + + if (Code1 and Code2) = 0 then + begin + TranslateFPToNative(FPenColorFP); + Bpp := FFormatInfo.BytesPerPixel; + + // If line is steep swap X and Y coordinates so later we just have one loop + // of two (where only one is used according to steepness). + if Steep then + begin + SwapValues(X1, Y1); + SwapValues(X2, Y2); + end; + if X1 > X2 then + begin + SwapValues(X1, X2); + SwapValues(Y1, Y2); + end; + + DeltaX := X2 - X1; + DeltaY := Abs(Y2 - Y1); + YStep := Iff(Y2 > Y1, 1, -1); + Error := 0; + Y := Y1; + + // Draw line using Bresenham algorithm. No real line clipping here, + // just don't draw pixels outsize clip rect. + for X := X1 to X2 do + begin + if Steep then + CopyPixelInternal(Y, X, @FNativeColor, Bpp) + else + CopyPixelInternal(X, Y, @FNativeColor, Bpp); + Error := Error + DeltaY; + if Error * 2 >= DeltaX then + begin + Inc(Y, YStep); + Dec(Error, DeltaX); + end; + end; + end; +end; + +procedure TImagingCanvas.FrameRect(const Rect: TRect); +var + HalfPen, PenMod: LongInt; +begin + if FPenMode = pmClear then Exit; + HalfPen := FPenWidth div 2; + PenMod := FPenWidth mod 2; + HorzLine(Rect.Left - HalfPen, Rect.Right + HalfPen + PenMod - 1, Rect.Top); + HorzLine(Rect.Left - HalfPen, Rect.Right + HalfPen + PenMod - 1, Rect.Bottom - 1); + VertLine(Rect.Left, Rect.Top, Rect.Bottom); + VertLine(Rect.Right - 1, Rect.Top, Rect.Bottom); +end; + +procedure TImagingCanvas.FillRect(const Rect: TRect); +var + DstRect: TRect; +begin + if (FFillMode <> fmClear) and IntersectRect(DstRect, Rect, FClipRect) then + begin + TranslateFPToNative(FFillColorFP); + Imaging.FillRect(FPData^, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left, + DstRect.Bottom - DstRect.Top, @FNativeColor); + end; +end; + +procedure TImagingCanvas.FillRectBlend(const Rect: TRect; SrcFactor, + DestFactor: TBlendingFactor); +var + DstRect: TRect; + X, Y: Integer; + Line: PByte; +begin + if (FFillMode <> fmClear) and IntersectRect(DstRect, Rect, FClipRect) then + begin + CheckBeforeBlending(SrcFactor, DestFactor, Self); + for Y := DstRect.Top to DstRect.Bottom - 1 do + begin + Line := @PByteArray(FPData.Bits)[(Y * FPData.Width + DstRect.Left) * FFormatInfo.BytesPerPixel]; + for X := DstRect.Left to DstRect.Right - 1 do + begin + PixelBlendProc(FFillColorFP, Line, @FFormatInfo, SrcFactor, DestFactor); + Inc(Line, FFormatInfo.BytesPerPixel); + end; + end; + end; +end; + +procedure TImagingCanvas.Rectangle(const Rect: TRect); +begin + FillRect(Rect); + FrameRect(Rect); +end; + +procedure TImagingCanvas.Ellipse(const Rect: TRect); +var + RadX, RadY, DeltaX, DeltaY, R, RX, RY: LongInt; + X1, X2, Y1, Y2, Bpp, OldY: LongInt; + Fill, Pen: TColorFPRec; +begin + // TODO: Use PenWidth + X1 := Rect.Left; + X2 := Rect.Right; + Y1 := Rect.Top; + Y2 := Rect.Bottom; + + TranslateFPToNative(FPenColorFP, @Pen); + TranslateFPToNative(FFillColorFP, @Fill); + Bpp := FFormatInfo.BytesPerPixel; + + SwapMin(X1, X2); + SwapMin(Y1, Y2); + + RadX := (X2 - X1) div 2; + RadY := (Y2 - Y1) div 2; + + Y1 := Y1 + RadY; + Y2 := Y1; + OldY := Y1; + + DeltaX := (RadX * RadX); + DeltaY := (RadY * RadY); + R := RadX * RadY * RadY; + RX := R; + RY := 0; + + if (FFillMode <> fmClear) then + HorzLineInternal(X1, X2, Y1, @Fill, Bpp); + CopyPixelInternal(X1, Y1, @Pen, Bpp); + CopyPixelInternal(X2, Y1, @Pen, Bpp); + + while RadX > 0 do + begin + if R > 0 then + begin + Inc(Y1); + Dec(Y2); + Inc(RY, DeltaX); + Dec(R, RY); + end; + if R <= 0 then + begin + Dec(RadX); + Inc(X1); + Dec(X2); + Dec(RX, DeltaY); + Inc(R, RX); + end; + + if (OldY <> Y1) and (FFillMode <> fmClear) then + begin + HorzLineInternal(X1, X2, Y1, @Fill, Bpp); + HorzLineInternal(X1, X2, Y2, @Fill, Bpp); + end; + OldY := Y1; + + CopyPixelInternal(X1, Y1, @Pen, Bpp); + CopyPixelInternal(X2, Y1, @Pen, Bpp); + CopyPixelInternal(X1, Y2, @Pen, Bpp); + CopyPixelInternal(X2, Y2, @Pen, Bpp); + end; +end; + +procedure TImagingCanvas.FloodFill(X, Y: Integer; BoundaryFillMode: Boolean); +var + Stack: array of TPoint; + StackPos, Y1: Integer; + OldColor: TColor32; + SpanLeft, SpanRight: Boolean; + + procedure Push(AX, AY: Integer); + begin + if StackPos < High(Stack) then + begin + Inc(StackPos); + Stack[StackPos].X := AX; + Stack[StackPos].Y := AY; + end + else + begin + SetLength(Stack, Length(Stack) + FPData.Width); + Push(AX, AY); + end; + end; + + function Pop(out AX, AY: Integer): Boolean; + begin + if StackPos > 0 then + begin + AX := Stack[StackPos].X; + AY := Stack[StackPos].Y; + Dec(StackPos); + Result := True; + end + else + Result := False; + end; + + function Compare(AX, AY: Integer): Boolean; + var + Color: TColor32; + begin + Color := GetPixel32(AX, AY); + if BoundaryFillMode then + Result := (Color <> FFillColor32) and (Color <> FPenColor32) + else + Result := Color = OldColor; + end; + +begin + // Scanline Floodfill Algorithm With Stack + // http://student.kuleuven.be/~m0216922/CG/floodfill.html + + if not PtInRect(FClipRect, Point(X, Y)) then Exit; + + SetLength(Stack, FPData.Width * 4); + StackPos := 0; + + OldColor := GetPixel32(X, Y); + + Push(X, Y); + + while Pop(X, Y) do + begin + Y1 := Y; + while (Y1 >= FClipRect.Top) and Compare(X, Y1) do + Dec(Y1); + + Inc(Y1); + SpanLeft := False; + SpanRight := False; + + while (Y1 < FClipRect.Bottom) and Compare(X, Y1) do + begin + SetPixel32(X, Y1, FFillColor32); + if not SpanLeft and (X > FClipRect.Left) and Compare(X - 1, Y1) then + begin + Push(X - 1, Y1); + SpanLeft := True; + end + else if SpanLeft and (X > FClipRect.Left) and not Compare(X - 1, Y1) then + SpanLeft := False + else if not SpanRight and (X < FClipRect.Right - 1) and Compare(X + 1, Y1)then + begin + Push(X + 1, Y1); + SpanRight := True; + end + else if SpanRight and (X < FClipRect.Right - 1) and not Compare(X + 1, Y1) then + SpanRight := False; + + Inc(Y1); + end; + end; +end; + +procedure TImagingCanvas.DrawInternal(const SrcRect: TRect; + DestCanvas: TImagingCanvas; DestX, DestY: Integer; SrcFactor, + DestFactor: TBlendingFactor; PixelWriteProc: TPixelWriteProc); +var + X, Y, SrcX, SrcY, Width, Height, SrcBpp, DestBpp: Integer; + PSrc: TColorFPRec; + SrcPointer, DestPointer: PByte; +begin + CheckBeforeBlending(SrcFactor, DestFactor, DestCanvas); + SrcX := SrcRect.Left; + SrcY := SrcRect.Top; + Width := SrcRect.Right - SrcRect.Left; + Height := SrcRect.Bottom - SrcRect.Top; + SrcBpp := FFormatInfo.BytesPerPixel; + DestBpp := DestCanvas.FFormatInfo.BytesPerPixel; + // Clip src and dst rects + ClipCopyBounds(SrcX, SrcY, Width, Height, DestX, DestY, + FPData.Width, FPData.Height, DestCanvas.ClipRect); + + for Y := 0 to Height - 1 do + begin + // Get src and dst scanlines + SrcPointer := @PByteArray(FPData.Bits)[((SrcY + Y) * FPData.Width + SrcX) * SrcBpp]; + DestPointer := @PByteArray(DestCanvas.FPData.Bits)[((DestY + Y) * DestCanvas.FPData.Width + DestX) * DestBpp]; + + for X := 0 to Width - 1 do + begin + PSrc := FFormatInfo.GetPixelFP(SrcPointer, @FFormatInfo, FPData.Palette); + // Call pixel writer procedure - combine source and dest pixels + PixelWriteProc(PSrc, DestPointer, @DestCanvas.FFormatInfo, SrcFactor, DestFactor); + // Increment pixel pointers + Inc(SrcPointer, SrcBpp); + Inc(DestPointer, DestBpp); + end; + end; +end; + +procedure TImagingCanvas.DrawBlend(const SrcRect: TRect; DestCanvas: TImagingCanvas; + DestX, DestY: Integer; SrcFactor, DestFactor: TBlendingFactor); +begin + DrawInternal(SrcRect, DestCanvas, DestX, DestY, SrcFactor, DestFactor, PixelBlendProc); +end; + +procedure TImagingCanvas.DrawAlpha(const SrcRect: TRect; DestCanvas: TImagingCanvas; + DestX, DestY: Integer); +begin + DrawInternal(SrcRect, DestCanvas, DestX, DestY, bfIgnore, bfIgnore, PixelAlphaProc); +end; + +procedure TImagingCanvas.DrawAdd(const SrcRect: TRect; + DestCanvas: TImagingCanvas; DestX, DestY: Integer); +begin + DrawInternal(SrcRect, DestCanvas, DestX, DestY, bfIgnore, bfIgnore, PixelAddProc); +end; + +procedure TImagingCanvas.StretchDrawInternal(const SrcRect: TRect; + DestCanvas: TImagingCanvas; const DestRect: TRect; + SrcFactor, DestFactor: TBlendingFactor; Filter: TResizeFilter; + PixelWriteProc: TPixelWriteProc); +const + FilterMapping: array[TResizeFilter] of TSamplingFilter = + (sfNearest, sfLinear, DefaultCubicFilter, sfLanczos); +var + X, Y, I, J, SrcX, SrcY, SrcWidth, SrcHeight: Integer; + DestX, DestY, DestWidth, DestHeight, SrcBpp, DestBpp: Integer; + SrcPix: TColorFPRec; + MapX, MapY: TMappingTable; + XMinimum, XMaximum: Integer; + LineBuffer: array of TColorFPRec; + ClusterX, ClusterY: TCluster; + Weight, AccumA, AccumR, AccumG, AccumB: Single; + DestLine: PByte; + FilterFunction: TFilterFunction; + Radius: Single; +begin + CheckBeforeBlending(SrcFactor, DestFactor, DestCanvas); + SrcX := SrcRect.Left; + SrcY := SrcRect.Top; + SrcWidth := SrcRect.Right - SrcRect.Left; + SrcHeight := SrcRect.Bottom - SrcRect.Top; + DestX := DestRect.Left; + DestY := DestRect.Top; + DestWidth := DestRect.Right - DestRect.Left; + DestHeight := DestRect.Bottom - DestRect.Top; + SrcBpp := FFormatInfo.BytesPerPixel; + DestBpp := DestCanvas.FFormatInfo.BytesPerPixel; + // Get actual resampling filter and radius + FilterFunction := SamplingFilterFunctions[FilterMapping[Filter]]; + Radius := SamplingFilterRadii[FilterMapping[Filter]]; + // Clip src and dst rects + ClipStretchBounds(SrcX, SrcY, SrcWidth, SrcHeight, DestX, DestY, DestWidth, DestHeight, + FPData.Width, FPData.Height, DestCanvas.ClipRect); + // Generate mapping tables + MapX := BuildMappingTable(DestX, DestX + DestWidth, SrcX, SrcX + SrcWidth, + FPData.Width, FilterFunction, Radius, False); + MapY := BuildMappingTable(DestY, DestY + DestHeight, SrcY, SrcY + SrcHeight, + FPData.Height, FilterFunction, Radius, False); + FindExtremes(MapX, XMinimum, XMaximum); + SetLength(LineBuffer, XMaximum - XMinimum + 1); + + for J := 0 to DestHeight - 1 do + begin + ClusterY := MapY[J]; + for X := XMinimum to XMaximum do + begin + AccumA := 0.0; + AccumR := 0.0; + AccumG := 0.0; + AccumB := 0.0; + for Y := 0 to Length(ClusterY) - 1 do + begin + Weight := ClusterY[Y].Weight; + SrcPix := FFormatInfo.GetPixelFP(@PByteArray(FPData.Bits)[(ClusterY[Y].Pos * FPData.Width + X) * SrcBpp], + @FFormatInfo, FPData.Palette); + AccumB := AccumB + SrcPix.B * Weight; + AccumG := AccumG + SrcPix.G * Weight; + AccumR := AccumR + SrcPix.R * Weight; + AccumA := AccumA + SrcPix.A * Weight; + end; + with LineBuffer[X - XMinimum] do + begin + A := AccumA; + R := AccumR; + G := AccumG; + B := AccumB; + end; + end; + + DestLine := @PByteArray(DestCanvas.FPData.Bits)[((J + DestY) * DestCanvas.FPData.Width + DestX) * DestBpp]; + + for I := 0 to DestWidth - 1 do + begin + ClusterX := MapX[I]; + AccumA := 0.0; + AccumR := 0.0; + AccumG := 0.0; + AccumB := 0.0; + for X := 0 to Length(ClusterX) - 1 do + begin + Weight := ClusterX[X].Weight; + with LineBuffer[ClusterX[X].Pos - XMinimum] do + begin + AccumB := AccumB + B * Weight; + AccumG := AccumG + G * Weight; + AccumR := AccumR + R * Weight; + AccumA := AccumA + A * Weight; + end; + end; + + SrcPix.A := AccumA; + SrcPix.R := AccumR; + SrcPix.G := AccumG; + SrcPix.B := AccumB; + + // Write resulting blended pixel + PixelWriteProc(SrcPix, DestLine, @DestCanvas.FFormatInfo, SrcFactor, DestFactor); + Inc(DestLine, DestBpp); + end; + end; +end; + +procedure TImagingCanvas.StretchDrawBlend(const SrcRect: TRect; + DestCanvas: TImagingCanvas; const DestRect: TRect; + SrcFactor, DestFactor: TBlendingFactor; Filter: TResizeFilter); +begin + StretchDrawInternal(SrcRect, DestCanvas, DestRect, SrcFactor, DestFactor, Filter, PixelBlendProc); +end; + +procedure TImagingCanvas.StretchDrawAlpha(const SrcRect: TRect; + DestCanvas: TImagingCanvas; const DestRect: TRect; Filter: TResizeFilter); +begin + StretchDrawInternal(SrcRect, DestCanvas, DestRect, bfIgnore, bfIgnore, Filter, PixelAlphaProc); +end; + +procedure TImagingCanvas.StretchDrawAdd(const SrcRect: TRect; + DestCanvas: TImagingCanvas; const DestRect: TRect; Filter: TResizeFilter); +begin + StretchDrawInternal(SrcRect, DestCanvas, DestRect, bfIgnore, bfIgnore, Filter, PixelAddProc); +end; + +procedure TImagingCanvas.ApplyConvolution(Kernel: PLongInt; KernelSize, + Divisor: LongInt; Bias: Single; ClampChannels: Boolean); +var + X, Y, I, J, PosY, PosX, SizeDiv2, KernelValue, WidthBytes, Bpp: LongInt; + R, G, B, DivFloat: Single; + Pixel: TColorFPRec; + TempImage: TImageData; + DstPointer, SrcPointer: PByte; +begin + SizeDiv2 := KernelSize div 2; + DivFloat := IffFloat(Divisor > 1, 1.0 / Divisor, 1.0); + Bpp := FFormatInfo.BytesPerPixel; + WidthBytes := FPData.Width * Bpp; + + InitImage(TempImage); + CloneImage(FPData^, TempImage); + + try + // For every pixel in clip rect + for Y := FClipRect.Top to FClipRect.Bottom - 1 do + begin + DstPointer := @PByteArray(FPData.Bits)[Y * WidthBytes + FClipRect.Left * Bpp]; + + for X := FClipRect.Left to FClipRect.Right - 1 do + begin + // Reset accumulators + R := 0.0; + G := 0.0; + B := 0.0; + + for J := 0 to KernelSize - 1 do + begin + PosY := ClampInt(Y + J - SizeDiv2, FClipRect.Top, FClipRect.Bottom - 1); + + for I := 0 to KernelSize - 1 do + begin + PosX := ClampInt(X + I - SizeDiv2, FClipRect.Left, FClipRect.Right - 1); + SrcPointer := @PByteArray(TempImage.Bits)[PosY * WidthBytes + PosX * Bpp]; + + // Get pixels from neighbourhood of current pixel and add their + // colors to accumulators weighted by filter kernel values + Pixel := FFormatInfo.GetPixelFP(SrcPointer, @FFormatInfo, TempImage.Palette); + KernelValue := PLongIntArray(Kernel)[J * KernelSize + I]; + + R := R + Pixel.R * KernelValue; + G := G + Pixel.G * KernelValue; + B := B + Pixel.B * KernelValue; + end; + end; + + Pixel := FFormatInfo.GetPixelFP(DstPointer, @FFormatInfo, FPData.Palette); + + Pixel.R := R * DivFloat + Bias; + Pixel.G := G * DivFloat + Bias; + Pixel.B := B * DivFloat + Bias; + + if ClampChannels then + ClampFloatPixel(Pixel); + + // Set resulting pixel color + FFormatInfo.SetPixelFP(DstPointer, @FFormatInfo, FPData.Palette, Pixel); + + Inc(DstPointer, Bpp); + end; + end; + + finally + FreeImage(TempImage); + end; +end; + +procedure TImagingCanvas.ApplyConvolution3x3(const Filter: TConvolutionFilter3x3); +begin + ApplyConvolution(@Filter.Kernel, 3, Filter.Divisor, Filter.Bias, True); +end; + +procedure TImagingCanvas.ApplyConvolution5x5(const Filter: TConvolutionFilter5x5); +begin + ApplyConvolution(@Filter.Kernel, 5, Filter.Divisor, Filter.Bias, True); +end; + +procedure TImagingCanvas.ApplyNonLinearFilter(FilterSize: Integer; SelectFunc: TSelectPixelFunction); +var + X, Y, I, J, PosY, PosX, SizeDiv2, WidthBytes, Bpp: LongInt; + Pixel: TColorFPRec; + TempImage: TImageData; + DstPointer, SrcPointer: PByte; + NeighPixels: TDynFPPixelArray; +begin + SizeDiv2 := FilterSize div 2; + Bpp := FFormatInfo.BytesPerPixel; + WidthBytes := FPData.Width * Bpp; + SetLength(NeighPixels, FilterSize * FilterSize); + + InitImage(TempImage); + CloneImage(FPData^, TempImage); + + try + // For every pixel in clip rect + for Y := FClipRect.Top to FClipRect.Bottom - 1 do + begin + DstPointer := @PByteArray(FPData.Bits)[Y * WidthBytes + FClipRect.Left * Bpp]; + + for X := FClipRect.Left to FClipRect.Right - 1 do + begin + for J := 0 to FilterSize - 1 do + begin + PosY := ClampInt(Y + J - SizeDiv2, FClipRect.Top, FClipRect.Bottom - 1); + + for I := 0 to FilterSize - 1 do + begin + PosX := ClampInt(X + I - SizeDiv2, FClipRect.Left, FClipRect.Right - 1); + SrcPointer := @PByteArray(TempImage.Bits)[PosY * WidthBytes + PosX * Bpp]; + + // Get pixels from neighbourhood of current pixel and store them + Pixel := FFormatInfo.GetPixelFP(SrcPointer, @FFormatInfo, TempImage.Palette); + NeighPixels[J * FilterSize + I] := Pixel; + end; + end; + + // Choose pixel using custom function + Pixel := SelectFunc(NeighPixels); + // Set resulting pixel color + FFormatInfo.SetPixelFP(DstPointer, @FFormatInfo, FPData.Palette, Pixel); + + Inc(DstPointer, Bpp); + end; + end; + + finally + FreeImage(TempImage); + end; +end; + +procedure TImagingCanvas.ApplyMedianFilter(FilterSize: Integer); +begin + ApplyNonLinearFilter(FilterSize, MedianSelect); +end; + +procedure TImagingCanvas.ApplyMinFilter(FilterSize: Integer); +begin + ApplyNonLinearFilter(FilterSize, MinSelect); +end; + +procedure TImagingCanvas.ApplyMaxFilter(FilterSize: Integer); +begin + ApplyNonLinearFilter(FilterSize, MaxSelect); +end; + +procedure TImagingCanvas.PointTransform(Transform: TPointTransformFunction; + Param1, Param2, Param3: Single); +var + X, Y, Bpp, WidthBytes: Integer; + PixPointer: PByte; + Pixel: TColorFPRec; +begin + Bpp := FFormatInfo.BytesPerPixel; + WidthBytes := FPData.Width * Bpp; + + // For every pixel in clip rect + for Y := FClipRect.Top to FClipRect.Bottom - 1 do + begin + PixPointer := @PByteArray(FPData.Bits)[Y * WidthBytes + FClipRect.Left * Bpp]; + for X := FClipRect.Left to FClipRect.Right - 1 do + begin + Pixel := FFormatInfo.GetPixelFP(PixPointer, @FFormatInfo, FPData.Palette); + + FFormatInfo.SetPixelFP(PixPointer, @FFormatInfo, FPData.Palette, + Transform(Pixel, Param1, Param2, Param3)); + + Inc(PixPointer, Bpp); + end; + end; +end; + +procedure TImagingCanvas.ModifyContrastBrightness(Contrast, Brightness: Single); +begin + PointTransform(TransformContrastBrightness, 1.0 + Contrast / 100, + Brightness / 100, 0); +end; + +procedure TImagingCanvas.GammaCorection(Red, Green, Blue: Single); +begin + PointTransform(TransformGamma, Red, Green, Blue); +end; + +procedure TImagingCanvas.InvertColors; +begin + PointTransform(TransformInvert, 0, 0, 0); +end; + +procedure TImagingCanvas.Threshold(Red, Green, Blue: Single); +begin + PointTransform(TransformThreshold, Red, Green, Blue); +end; + +procedure TImagingCanvas.AdjustColorLevels(BlackPoint, WhitePoint, MidPoint: Single); +begin + PointTransform(TransformLevels, BlackPoint, WhitePoint, 1.0 / MidPoint); +end; + +procedure TImagingCanvas.PremultiplyAlpha; +begin + PointTransform(TransformPremultiplyAlpha, 0, 0, 0); +end; + +procedure TImagingCanvas.UnPremultiplyAlpha; +begin + PointTransform(TransformUnPremultiplyAlpha, 0, 0, 0); +end; + +procedure TImagingCanvas.GetHistogram(out Red, Green, Blue, Alpha, + Gray: THistogramArray); +var + X, Y, Bpp: Integer; + PixPointer: PByte; + Color32: TColor32Rec; +begin + FillChar(Red, SizeOf(Red), 0); + FillChar(Green, SizeOf(Green), 0); + FillChar(Blue, SizeOf(Blue), 0); + FillChar(Alpha, SizeOf(Alpha), 0); + FillChar(Gray, SizeOf(Gray), 0); + + Bpp := FFormatInfo.BytesPerPixel; + + for Y := FClipRect.Top to FClipRect.Bottom - 1 do + begin + PixPointer := @PByteArray(FPData.Bits)[Y * FPData.Width * Bpp + FClipRect.Left * Bpp]; + for X := FClipRect.Left to FClipRect.Right - 1 do + begin + Color32 := FFormatInfo.GetPixel32(PixPointer, @FFormatInfo, FPData.Palette); + + Inc(Red[Color32.R]); + Inc(Green[Color32.G]); + Inc(Blue[Color32.B]); + Inc(Alpha[Color32.A]); + Inc(Gray[Round(GrayConv.R * Color32.R + GrayConv.G * Color32.G + GrayConv.B * Color32.B)]); + + Inc(PixPointer, Bpp); + end; + end; +end; + +procedure TImagingCanvas.FillChannel(ChannelId: Integer; NewChannelValue: Byte); +var + X, Y, Bpp: Integer; + PixPointer: PByte; + Color32: TColor32Rec; +begin + Bpp := FFormatInfo.BytesPerPixel; + + for Y := FClipRect.Top to FClipRect.Bottom - 1 do + begin + PixPointer := @PByteArray(FPData.Bits)[Y * FPData.Width * Bpp + FClipRect.Left * Bpp]; + for X := FClipRect.Left to FClipRect.Right - 1 do + begin + Color32 := FFormatInfo.GetPixel32(PixPointer, @FFormatInfo, FPData.Palette); + Color32.Channels[ChannelId] := NewChannelValue; + FFormatInfo.SetPixel32(PixPointer, @FFormatInfo, FPData.Palette, Color32); + + Inc(PixPointer, Bpp); + end; + end; +end; + +procedure TImagingCanvas.FillChannelFP(ChannelId: Integer; NewChannelValue: Single); +var + X, Y, Bpp: Integer; + PixPointer: PByte; + ColorFP: TColorFPRec; +begin + Bpp := FFormatInfo.BytesPerPixel; + + for Y := FClipRect.Top to FClipRect.Bottom - 1 do + begin + PixPointer := @PByteArray(FPData.Bits)[Y * FPData.Width * Bpp + FClipRect.Left * Bpp]; + for X := FClipRect.Left to FClipRect.Right - 1 do + begin + ColorFP := FFormatInfo.GetPixelFP(PixPointer, @FFormatInfo, FPData.Palette); + ColorFP.Channels[ChannelId] := NewChannelValue; + FFormatInfo.SetPixelFP(PixPointer, @FFormatInfo, FPData.Palette, ColorFP); + + Inc(PixPointer, Bpp); + end; + end; +end; + +class function TImagingCanvas.GetSupportedFormats: TImageFormats; +begin + Result := [ifIndex8..Pred(ifDXT1)]; +end; + +{ TFastARGB32Canvas } + +destructor TFastARGB32Canvas.Destroy; +begin + FreeMem(FScanlines); + inherited Destroy; +end; + +procedure TFastARGB32Canvas.AlphaBlendPixels(SrcPix, DestPix: PColor32Rec); +var + SrcAlpha, DestAlpha, FinalAlpha: Integer; +begin + FinalAlpha := SrcPix.A + 1 + (DestPix.A * (256 - SrcPix.A)) shr 8; + if FinalAlpha = 0 then + SrcAlpha := 0 + else + SrcAlpha := (SrcPix.A shl 8) div FinalAlpha; + DestAlpha := 256 - SrcAlpha; + + DestPix.A := ClampToByte(FinalAlpha); + DestPix.R := (SrcPix.R * SrcAlpha + DestPix.R * DestAlpha) shr 8; + DestPix.G := (SrcPix.G * SrcAlpha + DestPix.G * DestAlpha) shr 8; + DestPix.B := (SrcPix.B * SrcAlpha + DestPix.B * DestAlpha) shr 8; +end; + +procedure TFastARGB32Canvas.DrawAlpha(const SrcRect: TRect; + DestCanvas: TImagingCanvas; DestX, DestY: Integer); +var + X, Y, SrcX, SrcY, Width, Height: Integer; + SrcPix, DestPix: PColor32Rec; +begin + if DestCanvas.ClassType <> Self.ClassType then + begin + inherited; + Exit; + end; + + SrcX := SrcRect.Left; + SrcY := SrcRect.Top; + Width := SrcRect.Right - SrcRect.Left; + Height := SrcRect.Bottom - SrcRect.Top; + ClipCopyBounds(SrcX, SrcY, Width, Height, DestX, DestY, + FPData.Width, FPData.Height, DestCanvas.ClipRect); + + for Y := 0 to Height - 1 do + begin + SrcPix := @FScanlines[SrcY + Y, SrcX]; + DestPix := @TFastARGB32Canvas(DestCanvas).FScanlines[DestY + Y, DestX]; + for X := 0 to Width - 1 do + begin + AlphaBlendPixels(SrcPix, DestPix); + Inc(SrcPix); + Inc(DestPix); + end; + end; +end; + +function TFastARGB32Canvas.GetPixel32(X, Y: LongInt): TColor32; +begin + Result := FScanlines[Y, X].Color; +end; + +procedure TFastARGB32Canvas.SetPixel32(X, Y: LongInt; const Value: TColor32); +begin + if (X >= FClipRect.Left) and (Y >= FClipRect.Top) and + (X < FClipRect.Right) and (Y < FClipRect.Bottom) then + begin + FScanlines[Y, X].Color := Value; + end; +end; + +procedure TFastARGB32Canvas.StretchDrawAlpha(const SrcRect: TRect; + DestCanvas: TImagingCanvas; const DestRect: TRect; Filter: TResizeFilter); +var + X, Y, ScaleX, ScaleY, Yp, Xp, Weight1, Weight2, Weight3, Weight4, InvFracY, T1, T2: Integer; + FracX, FracY: Cardinal; + SrcX, SrcY, SrcWidth, SrcHeight: Integer; + DestX, DestY, DestWidth, DestHeight: Integer; + SrcLine, SrcLine2: PColor32RecArray; + DestPix: PColor32Rec; + Accum: TColor32Rec; +begin + if (Filter = rfBicubic) or (DestCanvas.ClassType <> Self.ClassType) then + begin + inherited; + Exit; + end; + + SrcX := SrcRect.Left; + SrcY := SrcRect.Top; + SrcWidth := SrcRect.Right - SrcRect.Left; + SrcHeight := SrcRect.Bottom - SrcRect.Top; + DestX := DestRect.Left; + DestY := DestRect.Top; + DestWidth := DestRect.Right - DestRect.Left; + DestHeight := DestRect.Bottom - DestRect.Top; + // Clip src and dst rects + ClipStretchBounds(SrcX, SrcY, SrcWidth, SrcHeight, DestX, DestY, DestWidth, DestHeight, + FPData.Width, FPData.Height, DestCanvas.ClipRect); + ScaleX := (SrcWidth shl 16) div DestWidth; + ScaleY := (SrcHeight shl 16) div DestHeight; + + // Nearest and linear filtering using fixed point math + + if Filter = rfNearest then + begin + Yp := 0; + for Y := DestY to DestY + DestHeight - 1 do + begin + Xp := 0; + SrcLine := @FScanlines[SrcY + Yp shr 16, SrcX]; + DestPix := @TFastARGB32Canvas(DestCanvas).FScanlines[Y, DestX]; + for X := 0 to DestWidth - 1 do + begin + AlphaBlendPixels(@SrcLine[Xp shr 16], DestPix); + Inc(DestPix); + Inc(Xp, ScaleX); + end; + Inc(Yp, ScaleY); + end; + end + else + begin + Yp := (ScaleY shr 1) - $8000; + for Y := DestY to DestY + DestHeight - 1 do + begin + DestPix := @TFastARGB32Canvas(DestCanvas).FScanlines[Y, DestX]; + if Yp < 0 then + begin + T1 := 0; + FracY := 0; + InvFracY := $10000; + end + else + begin + T1 := Yp shr 16; + FracY := Yp and $FFFF; + InvFracY := (not Yp and $FFFF) + 1; + end; + + T2 := Iff(T1 < SrcHeight - 1, T1 + 1, T1); + SrcLine := @Scanlines[T1 + SrcY, SrcX]; + SrcLine2 := @Scanlines[T2 + SrcY, SrcX]; + Xp := (ScaleX shr 1) - $8000; + + for X := 0 to DestWidth - 1 do + begin + if Xp < 0 then + begin + T1 := 0; + FracX := 0; + end + else + begin + T1 := Xp shr 16; + FracX := Xp and $FFFF; + end; + + T2 := Iff(T1 < SrcWidth - 1, T1 + 1, T1); + Weight2:= Integer((Cardinal(InvFracY) * FracX) shr 16); // cast to Card, Int can overflow here + Weight1:= InvFracY - Weight2; + Weight4:= Integer((Cardinal(FracY) * FracX) shr 16); + Weight3:= FracY - Weight4; + + Accum.B := (SrcLine[T1].B * Weight1 + SrcLine[T2].B * Weight2 + + SrcLine2[T1].B * Weight3 + SrcLine2[T2].B * Weight4 + $8000) shr 16; + Accum.G := (SrcLine[T1].G * Weight1 + SrcLine[T2].G * Weight2 + + SrcLine2[T1].G * Weight3 + SrcLine2[T2].G * Weight4 + $8000) shr 16; + Accum.R := (SrcLine[T1].R * Weight1 + SrcLine[T2].R * Weight2 + + SrcLine2[T1].R * Weight3 + SrcLine2[T2].R * Weight4 + $8000) shr 16; + Accum.A := (SrcLine[T1].A * Weight1 + SrcLine[T2].A * Weight2 + + SrcLine2[T1].A * Weight3 + SrcLine2[T2].A * Weight4 + $8000) shr 16; + + AlphaBlendPixels(@Accum, DestPix); + + Inc(Xp, ScaleX); + Inc(DestPix); + end; + Inc(Yp, ScaleY); + end; + end; +end; + +procedure TFastARGB32Canvas.UpdateCanvasState; +var + I: LongInt; + ScanPos: PLongWord; +begin + inherited UpdateCanvasState; + + // Realloc and update scanline array + ReallocMem(FScanlines, FPData.Height * SizeOf(PColor32RecArray)); + ScanPos := FPData.Bits; + + for I := 0 to FPData.Height - 1 do + begin + FScanlines[I] := PColor32RecArray(ScanPos); + Inc(ScanPos, FPData.Width); + end; +end; + +class function TFastARGB32Canvas.GetSupportedFormats: TImageFormats; +begin + Result := [ifA8R8G8B8]; +end; + +procedure TFastARGB32Canvas.InvertColors; +var + X, Y: Integer; + PixPtr: PColor32Rec; +begin + for Y := FClipRect.Top to FClipRect.Bottom - 1 do + begin + PixPtr := @FScanlines[Y, FClipRect.Left]; + for X := FClipRect.Left to FClipRect.Right - 1 do + begin + PixPtr.R := not PixPtr.R; + PixPtr.G := not PixPtr.G; + PixPtr.B := not PixPtr.B; + Inc(PixPtr); + end; + end; +end; + +initialization + RegisterCanvas(TFastARGB32Canvas); + +finalization + FreeAndNil(CanvasClasses); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - more more more ... + - implement pen width everywhere + - more objects (arc, polygon) + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Fixed bug that could raise floating point error in DrawAlpha + and StretchDrawAlpha. + - Fixed bug in TImagingCanvas.Line that caused not drawing + of horz or vert lines. + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Added some methods to TFastARGB32Canvas (InvertColors, DrawAlpha/StretchDrawAlpha) + - Fixed DrawAlpha/StretchDrawAlpha destination alpha calculation. + - Added PremultiplyAlpha and UnPremultiplyAlpha methods. + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - Added FillChannel methods. + - Added FloodFill method. + - Added GetHistogram method. + - Fixed "Invalid FP operation" in AdjustColorLevels in FPC compiled exes + (thanks to Carlos González). + - Added TImagingCanvas.AdjustColorLevels method. + + -- 0.25.0 Changes/Bug Fixes --------------------------------- + - Fixed error that could cause AV in linear and nonlinear filters. + - Added blended rect filling function FillRectBlend. + - Added drawing function with blending (DrawAlpha, StretchDrawAlpha, + StretchDrawAdd, DrawBlend, StretchDrawBlend, ...) + - Added non-linear filters (min, max, median). + - Added point transforms (invert, contrast, gamma, brightness). + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Added some new filter kernels for convolution. + - Added FillMode and PenMode properties. + - Added FrameRect, Rectangle, Ellipse, and Line methods. + - Removed HorzLine and VertLine from TFastARGB32Canvas - new versions + in general canvas is now as fast as those in TFastARGB32Canvas + (only in case of A8R8G8B8 images of course). + - Added PenWidth property, updated HorzLine and VertLine to use it. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - added TFastARGB32Canvas + - added convolutions, hline, vline + - unit created, intial stuff added + +} + +end. diff --git a/src/lib/vampimg/ImagingClasses.pas b/src/lib/vampimg/ImagingClasses.pas new file mode 100644 index 0000000..b196fdd --- /dev/null +++ b/src/lib/vampimg/ImagingClasses.pas @@ -0,0 +1,1091 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains class based wrapper to Imaging library.} +unit ImagingClasses; + +{$I ImagingOptions.inc} + +interface + +uses + Types, Classes, ImagingTypes, Imaging, ImagingFormats, ImagingUtility; + +type + { Base abstract high level class wrapper to low level Imaging structures and + functions.} + TBaseImage = class(TPersistent) + private + function GetEmpty: Boolean; + protected + FPData: PImageData; + FOnDataSizeChanged: TNotifyEvent; + FOnPixelsChanged: TNotifyEvent; + function GetFormat: TImageFormat; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetHeight: Integer; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetSize: Integer; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetWidth: Integer; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetBits: Pointer; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetPalette: PPalette32; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetPaletteEntries: Integer; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetScanline(Index: Integer): Pointer; + function GetPixelPointer(X, Y: Integer): Pointer; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetScanlineSize: Integer; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetFormatInfo: TImageFormatInfo; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetValid: Boolean; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetBoundsRect: TRect; + procedure SetFormat(const Value: TImageFormat); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetHeight(const Value: Integer); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetWidth(const Value: Integer); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetPointer; virtual; abstract; + procedure DoDataSizeChanged; virtual; + procedure DoPixelsChanged; virtual; + public + constructor Create; virtual; + constructor CreateFromImage(AImage: TBaseImage); + destructor Destroy; override; + { Returns info about current image.} + function ToString: string; {$IF Defined(DCC) and (CompilerVersion >= 20.0)}override;{$IFEND} + + { Creates a new image data with the given size and format. Old image + data is lost. Works only for the current image of TMultiImage.} + procedure RecreateImageData(AWidth, AHeight: Integer; AFormat: TImageFormat); + { Maps underlying image data to given TImageData record. Both TBaseImage and + TImageData now share some image memory (bits). So don't call FreeImage + on TImageData afterwards since this TBaseImage would get really broken.} + procedure MapImageData(const ImageData: TImageData); + { Deletes current image.} + procedure Clear; + + { Resizes current image with optional resampling.} + procedure Resize(NewWidth, NewHeight: Integer; Filter: TResizeFilter); + + procedure ResizeToFit(FitWidth, FitHeight: Integer; Filter: TResizeFilter; DstImage: TBaseImage); + { Flips current image. Reverses the image along its horizontal axis the top + becomes the bottom and vice versa.} + procedure Flip; + { Mirrors current image. Reverses the image along its vertical axis the left + side becomes the right and vice versa.} + procedure Mirror; + { Rotates image by Angle degrees counterclockwise.} + procedure Rotate(Angle: Single); + { Copies rectangular part of SrcImage to DstImage. No blending is performed - + alpha is simply copied to destination image. Operates also with + negative X and Y coordinates. + Note that copying is fastest for images in the same data format + (and slowest for images in special formats).} + procedure CopyTo(SrcX, SrcY, Width, Height: Integer; DstImage: TBaseImage; DstX, DstY: Integer); + { Stretches the contents of the source rectangle to the destination rectangle + with optional resampling. No blending is performed - alpha is + simply copied/resampled to destination image. Note that stretching is + fastest for images in the same data format (and slowest for + images in special formats).} + procedure StretchTo(SrcX, SrcY, SrcWidth, SrcHeight: Integer; DstImage: TBaseImage; DstX, DstY, DstWidth, DstHeight: Integer; Filter: TResizeFilter); + { Replaces pixels with OldPixel in the given rectangle by NewPixel. + OldPixel and NewPixel should point to the pixels in the same format + as the given image is in.} + procedure ReplaceColor(X, Y, Width, Height: Integer; OldColor, NewColor: Pointer); + { Swaps SrcChannel and DstChannel color or alpha channels of image. + Use ChannelRed, ChannelBlue, ChannelGreen, ChannelAlpha constants to + identify channels.} + procedure SwapChannels(SrcChannel, DstChannel: Integer); + + { Loads current image data from file.} + procedure LoadFromFile(const FileName: string); virtual; + { Loads current image data from stream.} + procedure LoadFromStream(Stream: TStream); virtual; + + { Saves current image data to file.} + procedure SaveToFile(const FileName: string); + { Saves current image data to stream. Ext identifies desired image file + format (jpg, png, dds, ...)} + procedure SaveToStream(const Ext: string; Stream: TStream); + + { Width of current image in pixels.} + property Width: Integer read GetWidth write SetWidth; + { Height of current image in pixels.} + property Height: Integer read GetHeight write SetHeight; + { Image data format of current image.} + property Format: TImageFormat read GetFormat write SetFormat; + { Size in bytes of current image's data.} + property Size: Integer read GetSize; + { Pointer to memory containing image bits.} + property Bits: Pointer read GetBits; + { Pointer to palette for indexed format images. It is nil for others. + Max palette entry is at index [PaletteEntries - 1].} + property Palette: PPalette32 read GetPalette; + { Number of entries in image's palette} + property PaletteEntries: Integer read GetPaletteEntries; + { Provides indexed access to each line of pixels. Does not work with special + format images (like DXT).} + property Scanline[Index: Integer]: Pointer read GetScanline; + { Returns pointer to image pixel at [X, Y] coordinates.} + property PixelPointer[X, Y: Integer]: Pointer read GetPixelPointer; + { Size/length of one image scanline in bytes.} + property ScanlineSize: Integer read GetScanlineSize; + { Extended image format information.} + property FormatInfo: TImageFormatInfo read GetFormatInfo; + { This gives complete access to underlying TImageData record. + It can be used in functions that take TImageData as parameter + (for example: ReduceColors(SingleImageInstance.ImageData^, 64)).} + property ImageDataPointer: PImageData read FPData; + { Indicates whether the current image is valid (proper format, + allowed dimensions, right size, ...).} + property Valid: Boolean read GetValid; + { Indicates whether image containst any data (size in bytes > 0).} + property Empty: Boolean read GetEmpty; + { Specifies the bounding rectangle of the image.} + property BoundsRect: TRect read GetBoundsRect; + { This event occurs when the image data size has just changed. That means + image width, height, or format has been changed.} + property OnDataSizeChanged: TNotifyEvent read FOnDataSizeChanged write FOnDataSizeChanged; + { This event occurs when some pixels of the image have just changed.} + property OnPixelsChanged: TNotifyEvent read FOnPixelsChanged write FOnPixelsChanged; + end; + + { Extension of TBaseImage which uses single TImageData record to + store image. All methods inherited from TBaseImage work with this record.} + TSingleImage = class(TBaseImage) + protected + FImageData: TImageData; + procedure SetPointer; override; + public + constructor Create; override; + constructor CreateFromParams(AWidth, AHeight: Integer; AFormat: TImageFormat = ifDefault); + constructor CreateFromData(const AData: TImageData); + constructor CreateFromFile(const FileName: string); + constructor CreateFromStream(Stream: TStream); + destructor Destroy; override; + { Assigns single image from another single image or multi image.} + procedure Assign(Source: TPersistent); override; + { Assigns single image from image data record.} + procedure AssignFromImageData(const AImageData: TImageData); + end; + + { Extension of TBaseImage which uses array of TImageData records to + store multiple images. Images are independent on each other and they don't + share any common characteristic. Each can have different size, format, and + palette. All methods inherited from TBaseImage work only with + active image (it could represent mipmap level, animation frame, or whatever). + Methods whose names contain word 'Multi' work with all images in array + (as well as other methods with obvious names).} + TMultiImage = class(TBaseImage) + protected + FDataArray: TDynImageDataArray; + FActiveImage: Integer; + procedure SetActiveImage(Value: Integer); {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetImageCount: Integer; {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetImageCount(Value: Integer); + function GetAllImagesValid: Boolean; {$IFDEF USE_INLINE}inline;{$ENDIF} + function GetImage(Index: Integer): TImageData; {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetImage(Index: Integer; Value: TImageData); {$IFDEF USE_INLINE}inline;{$ENDIF} + procedure SetPointer; override; + function PrepareInsert(Index, Count: Integer): Boolean; + procedure DoInsertImages(Index: Integer; const Images: TDynImageDataArray); + procedure DoInsertNew(Index: Integer; AWidth, AHeight: Integer; AFormat: TImageFormat); + public + constructor Create; override; + constructor CreateFromParams(AWidth, AHeight: Integer; AFormat: TImageFormat; ImageCount: Integer); + constructor CreateFromArray(const ADataArray: TDynImageDataArray); + constructor CreateFromFile(const FileName: string); + constructor CreateFromStream(Stream: TStream); + destructor Destroy; override; + { Assigns multi image from another multi image or single image.} + procedure Assign(Source: TPersistent); override; + { Assigns multi image from array of image data records.} + procedure AssignFromArray(const ADataArray: TDynImageDataArray); + + { Adds new image at the end of the image array. } + function AddImage(AWidth, AHeight: Integer; AFormat: TImageFormat = ifDefault): Integer; overload; + { Adds existing image at the end of the image array. } + function AddImage(const Image: TImageData): Integer; overload; + { Adds existing image (Active image of a TmultiImage) + at the end of the image array. } + function AddImage(Image: TBaseImage): Integer; overload; + { Adds existing image array ((all images of a multi image)) + at the end of the image array. } + procedure AddImages(const Images: TDynImageDataArray); overload; + { Adds existing MultiImage images at the end of the image array. } + procedure AddImages(Images: TMultiImage); overload; + + { Inserts new image image at the given position in the image array. } + procedure InsertImage(Index, AWidth, AHeight: Integer; AFormat: TImageFormat = ifDefault); overload; + { Inserts existing image at the given position in the image array. } + procedure InsertImage(Index: Integer; const Image: TImageData); overload; + { Inserts existing image (Active image of a TmultiImage) + at the given position in the image array. } + procedure InsertImage(Index: Integer; Image: TBaseImage); overload; + { Inserts existing image at the given position in the image array. } + procedure InsertImages(Index: Integer; const Images: TDynImageDataArray); overload; + { Inserts existing images (all images of a TmultiImage) at + the given position in the image array. } + procedure InsertImages(Index: Integer; Images: TMultiImage); overload; + + { Exchanges two images at the given positions in the image array. } + procedure ExchangeImages(Index1, Index2: Integer); + { Deletes image at the given position in the image array.} + procedure DeleteImage(Index: Integer); + { Rearranges images so that the first image will become last and vice versa.} + procedure ReverseImages; + { Deletes all images.} + procedure ClearAll; + + { Converts all images to another image data format.} + procedure ConvertImages(Format: TImageFormat); + { Resizes all images.} + procedure ResizeImages(NewWidth, NewHeight: Integer; Filter: TResizeFilter); + + { Overloaded loading method that will add new image to multiimage if + image array is empty bero loading. } + procedure LoadFromFile(const FileName: string); override; + { Overloaded loading method that will add new image to multiimage if + image array is empty bero loading. } + procedure LoadFromStream(Stream: TStream); override; + + { Loads whole multi image from file.} + procedure LoadMultiFromFile(const FileName: string); + { Loads whole multi image from stream.} + procedure LoadMultiFromStream(Stream: TStream); + { Saves whole multi image to file.} + procedure SaveMultiToFile(const FileName: string); + { Saves whole multi image to stream. Ext identifies desired + image file format (jpg, png, dds, ...).} + procedure SaveMultiToStream(const Ext: string; Stream: TStream); + + { Indicates active image of this multi image. All methods inherited + from TBaseImage operate on this image only.} + property ActiveImage: Integer read FActiveImage write SetActiveImage; + { Number of images of this multi image.} + property ImageCount: Integer read GetImageCount write SetImageCount; + { This value is True if all images of this TMultiImage are valid.} + property AllImagesValid: Boolean read GetAllImagesValid; + { This gives complete access to underlying TDynImageDataArray. + It can be used in functions that take TDynImageDataArray + as parameter.} + property DataArray: TDynImageDataArray read FDataArray; + { Array property for accessing individual images of TMultiImage. When you + set image at given index the old image is freed and the source is cloned.} + property Images[Index: Integer]: TImageData read GetImage write SetImage; default; + end; + +implementation + +const + DefaultWidth = 16; + Defaultheight = 16; + +function GetArrayFromImageData(const ImageData: TImageData): TDynImageDataArray; +begin + SetLength(Result, 1); + Result[0] := ImageData; +end; + +{ TBaseImage class implementation } + +constructor TBaseImage.Create; +begin + SetPointer; +end; + +constructor TBaseImage.CreateFromImage(AImage: TBaseImage); +begin + Create; + Assign(AImage); +end; + +destructor TBaseImage.Destroy; +begin + inherited Destroy; +end; + +function TBaseImage.GetWidth: Integer; +begin + if Valid then + Result := FPData.Width + else + Result := 0; +end; + +function TBaseImage.GetHeight: Integer; +begin + if Valid then + Result := FPData.Height + else + Result := 0; +end; + +function TBaseImage.GetFormat: TImageFormat; +begin + if Valid then + Result := FPData.Format + else + Result := ifUnknown; +end; + +function TBaseImage.GetScanline(Index: Integer): Pointer; +var + Info: TImageFormatInfo; +begin + if Valid then + begin + Info := GetFormatInfo; + if not Info.IsSpecial then + Result := ImagingFormats.GetScanLine(FPData.Bits, Info, FPData.Width, Index) + else + Result := FPData.Bits; + end + else + Result := nil; +end; + +function TBaseImage.GetScanlineSize: Integer; +begin + if Valid then + Result := FormatInfo.GetPixelsSize(Format, Width, 1) + else + Result := 0; +end; + +function TBaseImage.GetPixelPointer(X, Y: Integer): Pointer; +begin + if Valid then + Result := @PByteArray(FPData.Bits)[(Y * FPData.Width + X) * GetFormatInfo.BytesPerPixel] + else + Result := nil; +end; + +function TBaseImage.GetSize: Integer; +begin + if Valid then + Result := FPData.Size + else + Result := 0; +end; + +function TBaseImage.GetBits: Pointer; +begin + if Valid then + Result := FPData.Bits + else + Result := nil; +end; + +function TBaseImage.GetPalette: PPalette32; +begin + if Valid then + Result := FPData.Palette + else + Result := nil; +end; + +function TBaseImage.GetPaletteEntries: Integer; +begin + Result := GetFormatInfo.PaletteEntries; +end; + +function TBaseImage.GetFormatInfo: TImageFormatInfo; +begin + if Valid then + Imaging.GetImageFormatInfo(FPData.Format, Result) + else + FillChar(Result, SizeOf(Result), 0); +end; + +function TBaseImage.GetValid: Boolean; +begin + Result := Assigned(FPData) and Imaging.TestImage(FPData^); +end; + +function TBaseImage.GetBoundsRect: TRect; +begin + Result := Rect(0, 0, GetWidth, GetHeight); +end; + +function TBaseImage.GetEmpty: Boolean; +begin + Result := FPData.Size = 0; +end; + +procedure TBaseImage.SetWidth(const Value: Integer); +begin + Resize(Value, GetHeight, rfNearest); +end; + +procedure TBaseImage.SetHeight(const Value: Integer); +begin + Resize(GetWidth, Value, rfNearest); +end; + +procedure TBaseImage.SetFormat(const Value: TImageFormat); +begin + if Valid and Imaging.ConvertImage(FPData^, Value) then + DoDataSizeChanged; +end; + +procedure TBaseImage.DoDataSizeChanged; +begin + if Assigned(FOnDataSizeChanged) then + FOnDataSizeChanged(Self); + DoPixelsChanged; +end; + +procedure TBaseImage.DoPixelsChanged; +begin + if Assigned(FOnPixelsChanged) then + FOnPixelsChanged(Self); +end; + +procedure TBaseImage.RecreateImageData(AWidth, AHeight: Integer; AFormat: TImageFormat); +begin + if Assigned(FPData) and Imaging.NewImage(AWidth, AHeight, AFormat, FPData^) then + DoDataSizeChanged; +end; + +procedure TBaseImage.MapImageData(const ImageData: TImageData); +begin + Clear; + FPData.Width := ImageData.Width; + FPData.Height := ImageData.Height; + FPData.Format := ImageData.Format; + FPData.Size := ImageData.Size; + FPData.Bits := ImageData.Bits; + FPData.Palette := ImageData.Palette; +end; + +procedure TBaseImage.Clear; +begin + FreeImage(FPData^); +end; + +procedure TBaseImage.Resize(NewWidth, NewHeight: Integer; Filter: TResizeFilter); +begin + if Valid and Imaging.ResizeImage(FPData^, NewWidth, NewHeight, Filter) then + DoDataSizeChanged; +end; + +procedure TBaseImage.ResizeToFit(FitWidth, FitHeight: Integer; + Filter: TResizeFilter; DstImage: TBaseImage); +begin + if Valid and Assigned(DstImage) then + begin + Imaging.ResizeImageToFit(FPData^, FitWidth, FitHeight, Filter, + DstImage.FPData^); + DstImage.DoDataSizeChanged; + end; +end; + +procedure TBaseImage.Flip; +begin + if Valid and Imaging.FlipImage(FPData^) then + DoPixelsChanged; +end; + +procedure TBaseImage.Mirror; +begin + if Valid and Imaging.MirrorImage(FPData^) then + DoPixelsChanged; +end; + +procedure TBaseImage.Rotate(Angle: Single); +begin + if Valid then + begin + Imaging.RotateImage(FPData^, Angle); + DoPixelsChanged; + end; +end; + +procedure TBaseImage.CopyTo(SrcX, SrcY, Width, Height: Integer; + DstImage: TBaseImage; DstX, DstY: Integer); +begin + if Valid and Assigned(DstImage) and DstImage.Valid then + begin + Imaging.CopyRect(FPData^, SrcX, SrcY, Width, Height, DstImage.FPData^, DstX, DstY); + DstImage.DoPixelsChanged; + end; +end; + +procedure TBaseImage.StretchTo(SrcX, SrcY, SrcWidth, SrcHeight: Integer; + DstImage: TBaseImage; DstX, DstY, DstWidth, DstHeight: Integer; Filter: TResizeFilter); +begin + if Valid and Assigned(DstImage) and DstImage.Valid then + begin + Imaging.StretchRect(FPData^, SrcX, SrcY, SrcWidth, SrcHeight, + DstImage.FPData^, DstX, DstY, DstWidth, DstHeight, Filter); + DstImage.DoPixelsChanged; + end; +end; + +procedure TBaseImage.ReplaceColor(X, Y, Width, Height: Integer; OldColor, + NewColor: Pointer); +begin + if Valid then + begin + Imaging.ReplaceColor(FPData^, X, Y, Width, Height, OldColor, NewColor); + DoPixelsChanged; + end; +end; + +procedure TBaseImage.SwapChannels(SrcChannel, DstChannel: Integer); +begin + if Valid then + begin + Imaging.SwapChannels(FPData^, SrcChannel, DstChannel); + DoPixelsChanged; + end; +end; + +function TBaseImage.ToString: string; +begin + Result := Iff(Valid, Imaging.ImageToStr(FPData^), 'empty image'); +end; + +procedure TBaseImage.LoadFromFile(const FileName: string); +begin + if Assigned(FPData) and Imaging.LoadImageFromFile(FileName, FPData^) then + DoDataSizeChanged; +end; + +procedure TBaseImage.LoadFromStream(Stream: TStream); +begin + if Assigned(FPData) and Imaging.LoadImageFromStream(Stream, FPData^) then + DoDataSizeChanged; +end; + +procedure TBaseImage.SaveToFile(const FileName: string); +begin + if Valid then + Imaging.SaveImageToFile(FileName, FPData^); +end; + +procedure TBaseImage.SaveToStream(const Ext: string; Stream: TStream); +begin + if Valid then + Imaging.SaveImageToStream(Ext, Stream, FPData^); +end; + + +{ TSingleImage class implementation } + +constructor TSingleImage.Create; +begin + inherited Create; + Clear; +end; + +constructor TSingleImage.CreateFromParams(AWidth, AHeight: Integer; AFormat: TImageFormat); +begin + inherited Create; + RecreateImageData(AWidth, AHeight, AFormat); +end; + +constructor TSingleImage.CreateFromData(const AData: TImageData); +begin + inherited Create; + AssignFromImageData(AData); +end; + +constructor TSingleImage.CreateFromFile(const FileName: string); +begin + inherited Create; + LoadFromFile(FileName); +end; + +constructor TSingleImage.CreateFromStream(Stream: TStream); +begin + inherited Create; + LoadFromStream(Stream); +end; + +destructor TSingleImage.Destroy; +begin + Imaging.FreeImage(FImageData); + inherited Destroy; +end; + +procedure TSingleImage.SetPointer; +begin + FPData := @FImageData; +end; + +procedure TSingleImage.Assign(Source: TPersistent); +begin + if Source = nil then + begin + Clear; + end + else if Source is TSingleImage then + begin + AssignFromImageData(TSingleImage(Source).FImageData); + end + else if Source is TMultiImage then + begin + if TMultiImage(Source).Valid then + AssignFromImageData(TMultiImage(Source).FPData^) + else + Clear; + end + else + inherited Assign(Source); +end; + +procedure TSingleImage.AssignFromImageData(const AImageData: TImageData); +begin + if Imaging.TestImage(AImageData) then + begin + Imaging.CloneImage(AImageData, FImageData); + DoDataSizeChanged; + end + else + Clear; +end; + +{ TMultiImage class implementation } + +constructor TMultiImage.Create; +begin + inherited Create; +end; + +constructor TMultiImage.CreateFromParams(AWidth, AHeight: Integer; + AFormat: TImageFormat; ImageCount: Integer); +var + I: Integer; +begin + Imaging.FreeImagesInArray(FDataArray); + SetLength(FDataArray, ImageCount); + for I := 0 to GetImageCount - 1 do + Imaging.NewImage(AWidth, AHeight, AFormat, FDataArray[I]); + if GetImageCount > 0 then + SetActiveImage(0); +end; + +constructor TMultiImage.CreateFromArray(const ADataArray: TDynImageDataArray); +begin + AssignFromArray(ADataArray); +end; + +constructor TMultiImage.CreateFromFile(const FileName: string); +begin + LoadMultiFromFile(FileName); +end; + +constructor TMultiImage.CreateFromStream(Stream: TStream); +begin + LoadMultiFromStream(Stream); +end; + +destructor TMultiImage.Destroy; +begin + Imaging.FreeImagesInArray(FDataArray); + inherited Destroy; +end; + +procedure TMultiImage.SetActiveImage(Value: Integer); +begin + FActiveImage := Value; + SetPointer; +end; + +function TMultiImage.GetImageCount: Integer; +begin + Result := Length(FDataArray); +end; + +procedure TMultiImage.SetImageCount(Value: Integer); +var + I, OldCount: Integer; +begin + if Value > GetImageCount then + begin + // Create new empty images if array will be enlarged + OldCount := GetImageCount; + SetLength(FDataArray, Value); + for I := OldCount to Value - 1 do + Imaging.NewImage(DefaultWidth, DefaultHeight, ifDefault, FDataArray[I]); + end + else + begin + // Free images that exceed desired count and shrink array + for I := Value to GetImageCount - 1 do + Imaging.FreeImage(FDataArray[I]); + SetLength(FDataArray, Value); + end; + SetPointer; +end; + +function TMultiImage.GetAllImagesValid: Boolean; +begin + Result := (GetImageCount > 0) and TestImagesInArray(FDataArray); +end; + +function TMultiImage.GetImage(Index: Integer): TImageData; +begin + if (Index >= 0) and (Index < GetImageCount) then + Result := FDataArray[Index]; +end; + +procedure TMultiImage.SetImage(Index: Integer; Value: TImageData); +begin + if (Index >= 0) and (Index < GetImageCount) then + Imaging.CloneImage(Value, FDataArray[Index]); +end; + +procedure TMultiImage.SetPointer; +begin + if GetImageCount > 0 then + begin + FActiveImage := ClampInt(FActiveImage, 0, GetImageCount - 1); + FPData := @FDataArray[FActiveImage]; + end + else + begin + FActiveImage := -1; + FPData := nil + end; +end; + +function TMultiImage.PrepareInsert(Index, Count: Integer): Boolean; +var + I: Integer; +begin + // Inserting to empty image will add image at index 0 + if GetImageCount = 0 then + Index := 0; + + if (Index >= 0) and (Index <= GetImageCount) and (Count > 0) then + begin + SetLength(FDataArray, GetImageCount + Count); + if Index < GetImageCount - 1 then + begin + // Move imges to new position + System.Move(FDataArray[Index], FDataArray[Index + Count], + (GetImageCount - Count - Index) * SizeOf(TImageData)); + // Null old images, not free them! + for I := Index to Index + Count - 1 do + InitImage(FDataArray[I]); + end; + Result := True; + end + else + Result := False; +end; + +procedure TMultiImage.DoInsertImages(Index: Integer; const Images: TDynImageDataArray); +var + I, Len: Integer; +begin + Len := Length(Images); + if PrepareInsert(Index, Len) then + begin + for I := 0 to Len - 1 do + Imaging.CloneImage(Images[I], FDataArray[Index + I]); + end; +end; + +procedure TMultiImage.DoInsertNew(Index, AWidth, AHeight: Integer; + AFormat: TImageFormat); +begin + if PrepareInsert(Index, 1) then + Imaging.NewImage(AWidth, AHeight, AFormat, FDataArray[Index]); +end; + +procedure TMultiImage.Assign(Source: TPersistent); +var + Arr: TDynImageDataArray; +begin + if Source = nil then + begin + ClearAll; + end + else if Source is TMultiImage then + begin + AssignFromArray(TMultiImage(Source).FDataArray); + SetActiveImage(TMultiImage(Source).ActiveImage); + end + else if Source is TSingleImage then + begin + SetLength(Arr, 1); + Arr[0] := TSingleImage(Source).FImageData; + AssignFromArray(Arr); + end + else + inherited Assign(Source); +end; + +procedure TMultiImage.AssignFromArray(const ADataArray: TDynImageDataArray); +var + I: Integer; +begin + Imaging.FreeImagesInArray(FDataArray); + SetLength(FDataArray, Length(ADataArray)); + for I := 0 to GetImageCount - 1 do + begin + // Clone only valid images + if Imaging.TestImage(ADataArray[I]) then + Imaging.CloneImage(ADataArray[I], FDataArray[I]) + else + Imaging.NewImage(DefaultWidth, DefaultHeight, ifDefault, FDataArray[I]); + end; + if GetImageCount > 0 then + SetActiveImage(0); +end; + +function TMultiImage.AddImage(AWidth, AHeight: Integer; AFormat: TImageFormat): Integer; +begin + Result := GetImageCount; + DoInsertNew(Result, AWidth, AHeight, AFormat); +end; + +function TMultiImage.AddImage(const Image: TImageData): Integer; +begin + Result := GetImageCount; + DoInsertImages(Result, GetArrayFromImageData(Image)); +end; + +function TMultiImage.AddImage(Image: TBaseImage): Integer; +begin + if Assigned(Image) and Image.Valid then + begin + Result := GetImageCount; + DoInsertImages(Result, GetArrayFromImageData(Image.FPData^)); + end + else + Result := -1; +end; + +procedure TMultiImage.AddImages(const Images: TDynImageDataArray); +begin + DoInsertImages(GetImageCount, Images); +end; + +procedure TMultiImage.AddImages(Images: TMultiImage); +begin + DoInsertImages(GetImageCount, Images.FDataArray); +end; + +procedure TMultiImage.InsertImage(Index, AWidth, AHeight: Integer; + AFormat: TImageFormat); +begin + DoInsertNew(Index, AWidth, AHeight, AFormat); +end; + +procedure TMultiImage.InsertImage(Index: Integer; const Image: TImageData); +begin + DoInsertImages(Index, GetArrayFromImageData(Image)); +end; + +procedure TMultiImage.InsertImage(Index: Integer; Image: TBaseImage); +begin + if Assigned(Image) and Image.Valid then + DoInsertImages(Index, GetArrayFromImageData(Image.FPData^)); +end; + +procedure TMultiImage.InsertImages(Index: Integer; + const Images: TDynImageDataArray); +begin + DoInsertImages(Index, FDataArray); +end; + +procedure TMultiImage.InsertImages(Index: Integer; Images: TMultiImage); +begin + DoInsertImages(Index, Images.FDataArray); +end; + +procedure TMultiImage.ExchangeImages(Index1, Index2: Integer); +var + TempData: TImageData; +begin + if (Index1 >= 0) and (Index1 < GetImageCount) and + (Index2 >= 0) and (Index2 < GetImageCount) then + begin + TempData := FDataArray[Index1]; + FDataArray[Index1] := FDataArray[Index2]; + FDataArray[Index2] := TempData; + end; +end; + +procedure TMultiImage.DeleteImage(Index: Integer); +var + I: Integer; +begin + if (Index >= 0) and (Index < GetImageCount) then + begin + // Free image at index to be deleted + Imaging.FreeImage(FDataArray[Index]); + if Index < GetImageCount - 1 then + begin + // Move images to new indices if necessary + for I := Index to GetImageCount - 2 do + FDataArray[I] := FDataArray[I + 1]; + end; + // Set new array length and update pointer to active image + SetLength(FDataArray, GetImageCount - 1); + SetPointer; + end; +end; + +procedure TMultiImage.ClearAll; +begin + ImageCount := 0; +end; + +procedure TMultiImage.ConvertImages(Format: TImageFormat); +var + I: Integer; +begin + for I := 0 to GetImageCount - 1 do + Imaging.ConvertImage(FDataArray[I], Format); +end; + +procedure TMultiImage.ResizeImages(NewWidth, NewHeight: Integer; + Filter: TResizeFilter); +var + I: Integer; +begin + for I := 0 to GetImageCount - 1 do + Imaging.ResizeImage(FDataArray[I], NewWidth, NewHeight, Filter); +end; + +procedure TMultiImage.ReverseImages; +var + I: Integer; +begin + for I := 0 to GetImageCount div 2 do + ExchangeImages(I, GetImageCount - 1 - I); +end; + +procedure TMultiImage.LoadFromFile(const FileName: string); +begin + if GetImageCount = 0 then + ImageCount := 1; + inherited LoadFromFile(FileName); +end; + +procedure TMultiImage.LoadFromStream(Stream: TStream); +begin + if GetImageCount = 0 then + ImageCount := 1; + inherited LoadFromStream(Stream); +end; + +procedure TMultiImage.LoadMultiFromFile(const FileName: string); +begin + Imaging.LoadMultiImageFromFile(FileName, FDataArray); + SetActiveImage(0); +end; + +procedure TMultiImage.LoadMultiFromStream(Stream: TStream); +begin + Imaging.LoadMultiImageFromStream(Stream, FDataArray); + SetActiveImage(0); +end; + +procedure TMultiImage.SaveMultiToFile(const FileName: string); +begin + Imaging.SaveMultiImageToFile(FileName, FDataArray); +end; + +procedure TMultiImage.SaveMultiToStream(const Ext: string; Stream: TStream); +begin + Imaging.SaveMultiImageToStream(Ext, Stream, FDataArray); +end; + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 --------------------------------------------------- + - Added TSingleImage.AssignFromData and TMultiImage.AssigntFromArray + as a replacement for constructors used as methods (that is + compiler error in Delphi XE3). + - Added TBaseImage.ResizeToFit method. + - Changed TMultiImage to have default state with no images. + - TMultiImage.AddImage now returns index of newly added image. + - Fixed img index bug in TMultiImage.ResizeImages + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Added MapImageData method to TBaseImage + - Added Empty property to TBaseImage. + - Added Clear method to TBaseImage. + - Added ScanlineSize property to TBaseImage. + + -- 0.24.3 Changes/Bug Fixes --------------------------------- + - Added TMultiImage.ReverseImages method. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added SwapChannels method to TBaseImage. + - Added ReplaceColor method to TBaseImage. + - Added ToString method to TBaseImage. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Inserting images to empty MultiImage will act as Add method. + - MultiImages with empty arrays will now create one image when + LoadFromFile or LoadFromStream is called. + - Fixed bug that caused AVs when getting props like Width, Height, asn Size + and when inlining was off. There was call to Iff but with inlining disabled + params like FPData.Size were evaluated and when FPData was nil => AV. + - Added many FPData validity checks to many methods. There were AVs + when calling most methods on empty TMultiImage. + - Added AllImagesValid property to TMultiImage. + - Fixed memory leak in TMultiImage.CreateFromParams. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - added ResizeImages method to TMultiImage + - removed Ext parameter from various LoadFromStream methods, no + longer needed + - fixed various issues concerning ActiveImage of TMultiImage + (it pointed to invalid location after some operations) + - most of property set/get methods are now inline + - added PixelPointers property to TBaseImage + - added Images default array property to TMultiImage + - renamed methods in TMultiImage to contain 'Image' instead of 'Level' + - added canvas support + - added OnDataSizeChanged and OnPixelsChanged event to TBaseImage + - renamed TSingleImage.NewImage to RecreateImageData, made public, and + moved to TBaseImage + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - added props PaletteEntries and ScanLine to TBaseImage + - aded new constructor to TBaseImage that take TBaseImage source + - TMultiImage levels adding and inserting rewritten internally + - added some new functions to TMultiImage: AddLevels, InsertLevels + - added some new functions to TBaseImage: Flip, Mirror, Rotate, + CopyRect, StretchRect + - TBasicImage.Resize has now filter parameter + - new stuff added to TMultiImage (DataArray prop, ConvertLevels) + + -- 0.13 Changes/Bug Fixes ----------------------------------- + - added AddLevel, InsertLevel, ExchangeLevels and DeleteLevel + methods to TMultiImage + - added TBaseImage, TSingleImage and TMultiImage with initial + members +} + +end. diff --git a/src/lib/vampimg/ImagingColors.pas b/src/lib/vampimg/ImagingColors.pas new file mode 100644 index 0000000..c7fd428 --- /dev/null +++ b/src/lib/vampimg/ImagingColors.pas @@ -0,0 +1,246 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains functions for manipulating and converting color values.} +unit ImagingColors; + +interface + +{$I ImagingOptions.inc} + +uses + SysUtils, ImagingTypes, ImagingUtility; + +{ Converts RGB color to YUV.} +procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte); +{ Converts YIV to RGB color.} +procedure YUVToRGB(Y, U, V: Byte; var R, G, B: Byte); + +{ Converts RGB color to YCbCr as used in JPEG.} +procedure RGBToYCbCr(R, G, B: Byte; var Y, Cb, Cr: Byte); +{ Converts YCbCr as used in JPEG to RGB color.} +procedure YCbCrToRGB(Y, Cb, Cr: Byte; var R, G, B: Byte); +{ Converts RGB color to YCbCr as used in JPEG.} +procedure RGBToYCbCr16(R, G, B: Word; var Y, Cb, Cr: Word); +{ Converts YCbCr as used in JPEG to RGB color.} +procedure YCbCrToRGB16(Y, Cb, Cr: Word; var R, G, B: Word); + +{ Converts RGB color to CMY.} +procedure RGBToCMY(R, G, B: Byte; var C, M, Y: Byte); +{ Converts CMY to RGB color.} +procedure CMYToRGB(C, M, Y: Byte; var R, G, B: Byte); +{ Converts RGB color to CMY.} +procedure RGBToCMY16(R, G, B: Word; var C, M, Y: Word); +{ Converts CMY to RGB color.} +procedure CMYToRGB16(C, M, Y: Word; var R, G, B: Word); + +{ Converts RGB color to CMYK.} +procedure RGBToCMYK(R, G, B: Byte; var C, M, Y, K: Byte); +{ Converts CMYK to RGB color.} +procedure CMYKToRGB(C, M, Y, K: Byte; var R, G, B: Byte); +{ Converts RGB color to CMYK.} +procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word); +{ Converts CMYK to RGB color.} +procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word); + +{ Converts RGB color to YCoCg.} +procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte); +{ Converts YCoCg to RGB color.} +procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte); + +//procedure RGBToHSL(R, G, B: Byte; var H, S, L: Byte); +//procedure HSLToRGB(H, S, L: Byte; var R, G, B: Byte); + +implementation + +procedure RGBToYUV(R, G, B: Byte; var Y, U, V: Byte); +begin + Y := ClampToByte(Round( 0.257 * R + 0.504 * G + 0.098 * B) + 16); + V := ClampToByte(Round( 0.439 * R - 0.368 * G - 0.071 * B) + 128); + U := ClampToByte(Round(-0.148 * R - 0.291 * G + 0.439 * B) + 128); +end; + +procedure YUVToRGB(Y, U, V: Byte; var R, G, B: Byte); +var + CY, CU, CV: LongInt; +begin + CY := Y - 16; + CU := U - 128; + CV := V - 128; + R := ClampToByte(Round(1.164 * CY - 0.002 * CU + 1.596 * CV)); + G := ClampToByte(Round(1.164 * CY - 0.391 * CU - 0.813 * CV)); + B := ClampToByte(Round(1.164 * CY + 2.018 * CU - 0.001 * CV)); +end; + +procedure RGBToYCbCr(R, G, B: Byte; var Y, Cb, Cr: Byte); +begin + Y := ClampToByte(Round( 0.29900 * R + 0.58700 * G + 0.11400 * B)); + Cb := ClampToByte(Round(-0.16874 * R - 0.33126 * G + 0.50000 * B + 128)); + Cr := ClampToByte(Round( 0.50000 * R - 0.41869 * G - 0.08131 * B + 128)); +end; + +procedure YCbCrToRGB(Y, Cb, Cr: Byte; var R, G, B: Byte); +begin + R := ClampToByte(Round(Y + 1.40200 * (Cr - 128))); + G := ClampToByte(Round(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128))); + B := ClampToByte(Round(Y + 1.77200 * (Cb - 128))); +end; + +procedure RGBToYCbCr16(R, G, B: Word; var Y, Cb, Cr: Word); +begin + Y := ClampToWord(Round( 0.29900 * R + 0.58700 * G + 0.11400 * B)); + Cb := ClampToWord(Round(-0.16874 * R - 0.33126 * G + 0.50000 * B + 32768)); + Cr := ClampToWord(Round( 0.50000 * R - 0.41869 * G - 0.08131 * B + 32768)); +end; + +procedure YCbCrToRGB16(Y, Cb, Cr: Word; var R, G, B: Word); +begin + R := ClampToWord(Round(Y + 1.40200 * (Cr - 32768))); + G := ClampToWord(Round(Y - 0.34414 * (Cb - 32768) - 0.71414 * (Cr - 32768))); + B := ClampToWord(Round(Y + 1.77200 * (Cb - 32768))); +end; + +procedure RGBToCMY(R, G, B: Byte; var C, M, Y: Byte); +begin + C := 255 - R; + M := 255 - G; + Y := 255 - B; +end; + +procedure CMYToRGB(C, M, Y: Byte; var R, G, B: Byte); +begin + R := 255 - C; + G := 255 - M; + B := 255 - Y; +end; + +procedure RGBToCMY16(R, G, B: Word; var C, M, Y: Word); +begin + C := 65535 - R; + M := 65535 - G; + Y := 65535 - B; +end; + +procedure CMYToRGB16(C, M, Y: Word; var R, G, B: Word); +begin + R := 65535 - C; + G := 65535 - M; + B := 65535 - Y; +end; + +procedure RGBToCMYK(R, G, B: Byte; var C, M, Y, K: Byte); +begin + RGBToCMY(R, G, B, C, M, Y); + K := Min(C, Min(M, Y)); + if K = 255 then + begin + C := 0; + M := 0; + Y := 0; + end + else + begin + C := ClampToByte(Round((C - K) / (255 - K) * 255)); + M := ClampToByte(Round((M - K) / (255 - K) * 255)); + Y := ClampToByte(Round((Y - K) / (255 - K) * 255)); + end; +end; + +procedure CMYKToRGB(C, M, Y, K: Byte; var R, G, B: Byte); +begin + R := (255 - (C - MulDiv(C, K, 255) + K)); + G := (255 - (M - MulDiv(M, K, 255) + K)); + B := (255 - (Y - MulDiv(Y, K, 255) + K)); +end; + +procedure RGBToCMYK16(R, G, B: Word; var C, M, Y, K: Word); +begin + RGBToCMY16(R, G, B, C, M, Y); + K := Min(C, Min(M, Y)); + if K = 65535 then + begin + C := 0; + M := 0; + Y := 0; + end + else + begin + C := ClampToWord(Round((C - K) / (65535 - K) * 65535)); + M := ClampToWord(Round((M - K) / (65535 - K) * 65535)); + Y := ClampToWord(Round((Y - K) / (65535 - K) * 65535)); + end; +end; + +procedure CMYKToRGB16(C, M, Y, K: Word; var R, G, B: Word); +begin + R := 65535 - (C - MulDiv(C, K, 65535) + K); + G := 65535 - (M - MulDiv(M, K, 65535) + K); + B := 65535 - (Y - MulDiv(Y, K, 65535) + K); +end; + +procedure RGBToYCoCg(R, G, B: Byte; var Y, Co, Cg: Byte); +begin + // C and Delphi's SHR behaviour differs for negative numbers, use div instead. + Y := ClampToByte(( R + G shl 1 + B + 2) div 4); + Co := ClampToByte(( R shl 1 - B shl 1 + 2) div 4 + 128); + Cg := ClampToByte((-R + G shl 1 - B + 2) div 4 + 128); +end; + +procedure YCoCgToRGB(Y, Co, Cg: Byte; var R, G, B: Byte); +var + CoInt, CgInt: Integer; +begin + CoInt := Co - 128; + CgInt := Cg - 128; + R := ClampToByte(Y + CoInt - CgInt); + G := ClampToByte(Y + CgInt); + B := ClampToByte(Y - CoInt - CgInt); +end; + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Added RGB<>YCoCg conversion functions. + - Fixed RGB>>CMYK conversions. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added RGB<>CMY(K) converion functions for 16 bit channels + (needed by PSD loading code). + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Added some color space conversion functions and LUTs + (RGB/YUV/YCrCb/CMY/CMYK). + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - unit created (empty!) +} + +end. diff --git a/src/lib/vampimg/ImagingComponents.pas b/src/lib/vampimg/ImagingComponents.pas new file mode 100644 index 0000000..61451fe --- /dev/null +++ b/src/lib/vampimg/ImagingComponents.pas @@ -0,0 +1,1296 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains VCL/LCL TGraphic descendant which uses Imaging library + for saving and loading.} +unit ImagingComponents; + +{$I ImagingOptions.inc} + +interface + +{$IFDEF LCL} + {$DEFINE COMPONENT_SET_LCL} + {$UNDEF COMPONENT_SET_VCL} +{$ENDIF} + +{$IF not Defined(COMPONENT_SET_LCL) and not Defined(COMPONENT_SET_VCL)} +// If no component sets should be used just include empty unit. +//DOC-IGNORE-BEGIN +implementation +//DOC-IGNORE-END +{$ELSE} + +uses + SysUtils, Types, Classes, +{$IFDEF MSWINDOWS} + Windows, +{$ENDIF} +{$IFDEF COMPONENT_SET_VCL} + Graphics, +{$ENDIF} +{$IFDEF COMPONENT_SET_LCL} + InterfaceBase, + GraphType, + Graphics, + LCLType, + LCLIntf, +{$ENDIF} + ImagingTypes, Imaging, ImagingClasses; + +type + { Graphic class which uses Imaging to load images. + It has standard TBitmap class as ancestor and it can + Assign also to/from TImageData structres and TBaseImage + classes. For saving is uses inherited TBitmap methods. + This class is automatically registered to TPicture for all + file extensions supported by Imaging (useful only for loading). + If you just want to load images in various formats you can use this + class or simply use TPicture.LoadFromXXX which will create this class + automatically. For TGraphic class that saves with Imaging look + at TImagingGraphicForSave class.} + TImagingGraphic = class(TBitmap) + protected + procedure ReadDataFromStream(Stream: TStream); virtual; + procedure AssignTo(Dest: TPersistent); override; + public + constructor Create; override; + + { Loads new image from the stream. It can load all image + file formats supported by Imaging (and enabled of course) + even though it is called by descendant class capable of + saving only one file format.} + procedure LoadFromStream(Stream: TStream); override; + { Copies the image contained in Source to this graphic object. + Supports also TBaseImage descendants from ImagingClasses unit. } + procedure Assign(Source: TPersistent); override; + { Copies the image contained in TBaseImage to this graphic object.} + procedure AssignFromImage(Image: TBaseImage); + { Copies the current image to TBaseImage object.} + procedure AssignToImage(Image: TBaseImage); + { Copies the image contained in TImageData structure to this graphic object.} + procedure AssignFromImageData(const ImageData: TImageData); + { Copies the current image to TImageData structure.} + procedure AssignToImageData(var ImageData: TImageData); + end; + + TImagingGraphicClass = class of TImagingGraphic; + + { Base class for file format specific TGraphic classes that use + Imaging for saving. Each descendant class can load all file formats + supported by Imaging but save only one format (TImagingBitmap + for *.bmp, TImagingJpeg for *.jpg). Format specific classes also + allow easy access to Imaging options that affect saving of files + (they are properties here).} + TImagingGraphicForSave = class(TImagingGraphic) + protected + FDefaultFileExt: string; + FSavingFormat: TImageFormat; + procedure WriteDataToStream(Stream: TStream); virtual; + public + constructor Create; override; + { Saves the current image to the stream. It is saved in the + file format according to the DefaultFileExt property. + So each descendant class can save some other file format.} + procedure SaveToStream(Stream: TStream); override; + { Returns TImageFileFormat descendant for this graphic class.} + class function GetFileFormat: TImageFileFormat; virtual; abstract; + {$IFDEF COMPONENT_SET_LCL} + { Returns file extensions of this graphic class.} + class function GetFileExtensions: string; override; + { Returns default MIME type of this graphic class.} + function GetMimeType: string; override; + {$ENDIF} + { Default (the most common) file extension of this graphic class.} + property DefaultFileExt: string read FDefaultFileExt; + end; + + TImagingGraphicForSaveClass = class of TImagingGraphicForSave; + +{$IFNDEF DONT_LINK_BITMAP} + { TImagingGraphic descendant for loading/saving Windows bitmaps. + VCL/CLX/LCL all have native support for bitmaps so you might + want to disable this class (although you can save bitmaps with + RLE compression with this class).} + TImagingBitmap = class(TImagingGraphicForSave) + protected + FUseRLE: Boolean; + public + constructor Create; override; + procedure SaveToStream(Stream: TStream); override; + class function GetFileFormat: TImageFileFormat; override; + { See ImagingBitmapRLE option for details.} + property UseRLE: Boolean read FUseRLE write FUseRLE; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_JPEG} + { TImagingGraphic descendant for loading/saving JPEG images.} + TImagingJpeg = class(TImagingGraphicForSave) + protected + FQuality: LongInt; + FProgressive: Boolean; + public + constructor Create; override; + procedure SaveToStream(Stream: TStream); override; + class function GetFileFormat: TImageFileFormat; override; + {$IFDEF COMPONENT_SET_LCL} + function GetMimeType: string; override; + {$ENDIF} + { See ImagingJpegQuality option for details.} + property Quality: LongInt read FQuality write FQuality; + { See ImagingJpegProgressive option for details.} + property Progressive: Boolean read FProgressive write FProgressive; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_PNG} + { TImagingGraphic descendant for loading/saving PNG images.} + TImagingPNG = class(TImagingGraphicForSave) + protected + FPreFilter: LongInt; + FCompressLevel: LongInt; + public + constructor Create; override; + procedure SaveToStream(Stream: TStream); override; + class function GetFileFormat: TImageFileFormat; override; + { See ImagingPNGPreFilter option for details.} + property PreFilter: LongInt read FPreFilter write FPreFilter; + { See ImagingPNGCompressLevel option for details.} + property CompressLevel: LongInt read FCompressLevel write FCompressLevel; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_GIF} + { TImagingGraphic descendant for loading/saving GIF images.} + TImagingGIF = class(TImagingGraphicForSave) + public + class function GetFileFormat: TImageFileFormat; override; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_TARGA} + { TImagingGraphic descendant for loading/saving Targa images.} + TImagingTarga = class(TImagingGraphicForSave) + protected + FUseRLE: Boolean; + public + constructor Create; override; + procedure SaveToStream(Stream: TStream); override; + class function GetFileFormat: TImageFileFormat; override; + { See ImagingTargaRLE option for details.} + property UseRLE: Boolean read FUseRLE write FUseRLE; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_DDS} + { Compresssion type used when saving DDS files by TImagingDds.} + TDDSCompresion = (dcNone, dcDXT1, dcDXT3, dcDXT5); + + { TImagingGraphic descendant for loading/saving DDS images.} + TImagingDDS = class(TImagingGraphicForSave) + protected + FCompression: TDDSCompresion; + public + constructor Create; override; + procedure SaveToStream(Stream: TStream); override; + class function GetFileFormat: TImageFileFormat; override; + { You can choose compression type used when saving DDS file. + dcNone means that file will be saved in the current bitmaps pixel format.} + property Compression: TDDSCompresion read FCompression write FCompression; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_MNG} + { TImagingGraphic descendant for loading/saving MNG images.} + TImagingMNG = class(TImagingGraphicForSave) + protected + FLossyCompression: Boolean; + FLossyAlpha: Boolean; + FPreFilter: LongInt; + FCompressLevel: LongInt; + FQuality: LongInt; + FProgressive: Boolean; + public + constructor Create; override; + procedure SaveToStream(Stream: TStream); override; + class function GetFileFormat: TImageFileFormat; override; + {$IFDEF COMPONENT_SET_LCL} + function GetMimeType: string; override; + {$ENDIF} + { See ImagingMNGLossyCompression option for details.} + property LossyCompression: Boolean read FLossyCompression write FLossyCompression; + { See ImagingMNGLossyAlpha option for details.} + property LossyAlpha: Boolean read FLossyAlpha write FLossyAlpha; + { See ImagingMNGPreFilter option for details.} + property PreFilter: LongInt read FPreFilter write FPreFilter; + { See ImagingMNGCompressLevel option for details.} + property CompressLevel: LongInt read FCompressLevel write FCompressLevel; + { See ImagingMNGQuality option for details.} + property Quality: LongInt read FQuality write FQuality; + { See ImagingMNGProgressive option for details.} + property Progressive: Boolean read FProgressive write FProgressive; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_JNG} + { TImagingGraphic descendant for loading/saving JNG images.} + TImagingJNG = class(TImagingGraphicForSave) + protected + FLossyAlpha: Boolean; + FAlphaPreFilter: LongInt; + FAlphaCompressLevel: LongInt; + FQuality: LongInt; + FProgressive: Boolean; + public + constructor Create; override; + procedure SaveToStream(Stream: TStream); override; + class function GetFileFormat: TImageFileFormat; override; + { See ImagingJNGLossyAlpha option for details.} + property LossyAlpha: Boolean read FLossyAlpha write FLossyAlpha; + { See ImagingJNGPreFilter option for details.} + property AlphaPreFilter: LongInt read FAlphaPreFilter write FAlphaPreFilter; + { See ImagingJNGCompressLevel option for details.} + property AlphaCompressLevel: LongInt read FAlphaCompressLevel write FAlphaCompressLevel; + { See ImagingJNGQuality option for details.} + property Quality: LongInt read FQuality write FQuality; + { See ImagingJNGProgressive option for details.} + property Progressive: Boolean read FProgressive write FProgressive; + end; +{$ENDIF} + +{ Returns bitmap pixel format with the closest match with given data format.} +function DataFormatToPixelFormat(Format: TImageFormat): TPixelFormat; +{ Returns data format with closest match with given bitmap pixel format.} +function PixelFormatToDataFormat(Format: TPixelFormat): TImageFormat; + +{ Converts TImageData structure to VCL/CLX/LCL bitmap.} +procedure ConvertDataToBitmap(const Data: TImageData; Bitmap: TBitmap); +{ Converts VCL/CLX/LCL bitmap to TImageData structure.} +procedure ConvertBitmapToData(Bitmap: TBitmap; var Data: TImageData); +{ Converts TBaseImage instance to VCL/CLX/LCL bitmap.} +procedure ConvertImageToBitmap(Image: TBaseImage; Bitmap: TBitmap); +{ Converts VCL/CLX/LCL bitmap to TBaseImage. Image must exist before + procedure is called. It overwrites its current image data. + When Image is TMultiImage only the current image level is overwritten.} +procedure ConvertBitmapToImage(Bitmap: TBitmap; Image: TBaseImage); + +{ Displays image stored in TImageData structure onto TCanvas. This procedure + draws image without converting from Imaging format to TBitmap. + Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this + when you want displaying images that change frequently (because converting to + TBitmap by ConvertImageDataToBitmap is generally slow). Dest and Src + rectangles represent coordinates in the form (X1, Y1, X2, Y2).} +procedure DisplayImageData(DstCanvas: TCanvas; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); +{ Displays image onto TCanvas at position [DstX, DstY]. This procedure + draws image without converting from Imaging format to TBitmap. + Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this + when you want displaying images that change frequently (because converting to + TBitmap by ConvertImageDataToBitmap is generally slow).} +procedure DisplayImage(DstCanvas: TCanvas; DstX, DstY: LongInt; Image: TBaseImage); overload; +{ Displays image onto TCanvas to rectangle DstRect. This procedure + draws image without converting from Imaging format to TBitmap. + Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this + when you want displaying images that change frequently (because converting to + TBitmap by ConvertImageDataToBitmap is generally slow).} +procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage); overload; +{ Displays part of the image specified by SrcRect onto TCanvas to rectangle DstRect. + This procedure draws image without converting from Imaging format to TBitmap. + Only [ifA8R8G8B8, ifX8R8G8B8] image formats are supported. Use this + when you want displaying images that change frequently (because converting to + TBitmap by ConvertImageDataToBitmap is generally slow).} +procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage; const SrcRect: TRect); overload; + +{$IFDEF MSWINDOWS} +{ Displays image stored in TImageData structure onto Windows device context. + Behaviour is the same as of DisplayImageData.} +procedure DisplayImageDataOnDC(DC: HDC; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); +{$ENDIF} + +implementation + +uses +{$IF Defined(LCL)} + {$IF Defined(LCLGTK2)} + GLib2, GDK2, GTK2, GTK2Def, GTK2Proc, + {$IFEND} +{$IFEND} +{$IFNDEF DONT_LINK_BITMAP} + ImagingBitmap, +{$ENDIF} +{$IFNDEF DONT_LINK_JPEG} + ImagingJpeg, +{$ENDIF} +{$IFNDEF DONT_LINK_GIF} + ImagingGif, +{$ENDIF} +{$IFNDEF DONT_LINK_TARGA} + ImagingTarga, +{$ENDIF} +{$IFNDEF DONT_LINK_DDS} + ImagingDds, +{$ENDIF} +{$IF not Defined(DONT_LINK_PNG) or not Defined(DONT_LINK_MNG) or not Defined(DONT_LINK_JNG)} + ImagingNetworkGraphics, +{$IFEND} + ImagingFormats, ImagingUtility; + +resourcestring + SBadFormatDataToBitmap = 'Cannot find compatible bitmap format for image %s'; + SBadFormatBitmapToData = 'Cannot find compatible data format for bitmap %p'; + SBadFormatDisplay = 'Unsupported image format passed'; + SUnsupportedLCLWidgetSet = 'This function is not implemented for current LCL widget set'; + SImagingGraphicName = 'Imaging Graphic AllInOne'; + +{ Registers types to VCL/LCL.} +procedure RegisterTypes; +var + I: LongInt; + + procedure RegisterFileFormatAllInOne(Format: TImageFileFormat); + var + I: LongInt; + begin + for I := 0 to Format.Extensions.Count - 1 do + TPicture.RegisterFileFormat(Format.Extensions[I], SImagingGraphicName, + TImagingGraphic); + end; + + procedure RegisterFileFormat(AClass: TImagingGraphicForSaveClass); + var + I: LongInt; + begin + for I := 0 to AClass.GetFileFormat.Extensions.Count - 1 do + TPicture.RegisterFileFormat(AClass.GetFileFormat.Extensions[I], + AClass.GetFileFormat.Name, AClass); + end; + +begin + for I := Imaging.GetFileFormatCount - 1 downto 0 do + RegisterFileFormatAllInOne(Imaging.GetFileFormatAtIndex(I)); + Classes.RegisterClass(TImagingGraphic); + +{$IFNDEF DONT_LINK_TARGA} + RegisterFileFormat(TImagingTarga); + Classes.RegisterClass(TImagingTarga); +{$ENDIF} +{$IFNDEF DONT_LINK_DDS} + RegisterFileFormat(TImagingDDS); + Classes.RegisterClass(TImagingDDS); +{$ENDIF} +{$IFNDEF DONT_LINK_JNG} + RegisterFileFormat(TImagingJNG); + Classes.RegisterClass(TImagingJNG); +{$ENDIF} +{$IFNDEF DONT_LINK_MNG} + RegisterFileFormat(TImagingMNG); + Classes.RegisterClass(TImagingMNG); +{$ENDIF} +{$IFNDEF DONT_LINK_GIF} + RegisterFileFormat(TImagingGIF); + Classes.RegisterClass(TImagingGIF); +{$ENDIF} +{$IFNDEF DONT_LINK_PNG} + {$IFDEF COMPONENT_SET_LCL} + // Unregister Lazarus´ default PNG loader which crashes on some PNG files + TPicture.UnregisterGraphicClass(TPortableNetworkGraphic); + {$ENDIF} + RegisterFileFormat(TImagingPNG); + Classes.RegisterClass(TImagingPNG); +{$ENDIF} +{$IFNDEF DONT_LINK_JPEG} + RegisterFileFormat(TImagingJpeg); + Classes.RegisterClass(TImagingJpeg); +{$ENDIF} +{$IFNDEF DONT_LINK_BITMAP} + RegisterFileFormat(TImagingBitmap); + Classes.RegisterClass(TImagingBitmap); +{$ENDIF} +end; + +{ Unregisters types from VCL/LCL.} +procedure UnRegisterTypes; +begin +{$IFNDEF DONT_LINK_BITMAP} + TPicture.UnregisterGraphicClass(TImagingBitmap); + Classes.UnRegisterClass(TImagingBitmap); +{$ENDIF} +{$IFNDEF DONT_LINK_JPEG} + TPicture.UnregisterGraphicClass(TImagingJpeg); + Classes.UnRegisterClass(TImagingJpeg); +{$ENDIF} +{$IFNDEF DONT_LINK_PNG} + TPicture.UnregisterGraphicClass(TImagingPNG); + Classes.UnRegisterClass(TImagingPNG); +{$ENDIF} +{$IFNDEF DONT_LINK_GIF} + TPicture.UnregisterGraphicClass(TImagingGIF); + Classes.UnRegisterClass(TImagingGIF); +{$ENDIF} +{$IFNDEF DONT_LINK_TARGA} + TPicture.UnregisterGraphicClass(TImagingTarga); + Classes.UnRegisterClass(TImagingTarga); +{$ENDIF} +{$IFNDEF DONT_LINK_DDS} + TPicture.UnregisterGraphicClass(TImagingDDS); + Classes.UnRegisterClass(TImagingDDS); +{$ENDIF} + TPicture.UnregisterGraphicClass(TImagingGraphic); + Classes.UnRegisterClass(TImagingGraphic); +end; + +function DataFormatToPixelFormat(Format: TImageFormat): TPixelFormat; +begin + case Format of +{$IFDEF COMPONENT_SET_VCL} + ifIndex8: Result := pf8bit; + ifR5G6B5: Result := pf16bit; + ifR8G8B8: Result := pf24bit; +{$ENDIF} + ifA8R8G8B8, + ifX8R8G8B8: Result := pf32bit; + else + Result := pfCustom; + end; +end; + +function PixelFormatToDataFormat(Format: TPixelFormat): TImageFormat; +begin + case Format of + pf8bit: Result := ifIndex8; + pf15bit: Result := ifA1R5G5B5; + pf16bit: Result := ifR5G6B5; + pf24bit: Result := ifR8G8B8; + pf32bit: Result := ifA8R8G8B8; + else + Result := ifUnknown; + end; +end; + +procedure ConvertDataToBitmap(const Data: TImageData; Bitmap: TBitmap); +var + I, LineBytes: LongInt; + PF: TPixelFormat; + Info: TImageFormatInfo; + WorkData: TImageData; +{$IFDEF COMPONENT_SET_VCL} + LogPalette: TMaxLogPalette; +{$ENDIF} +{$IFDEF COMPONENT_SET_LCL} + RawImage: TRawImage; + ImgHandle, ImgMaskHandle: HBitmap; +{$ENDIF} +begin + PF := DataFormatToPixelFormat(Data.Format); + GetImageFormatInfo(Data.Format, Info); + + if (PF = pf8bit) and PaletteHasAlpha(Data.Palette, Info.PaletteEntries) then + begin + // Some indexed images may have valid alpha data, dont lose it! + // (e.g. transparent 8bit PNG or GIF images) + PF := pfCustom; + end; + + if PF = pfCustom then + begin + // Convert from formats not supported by Graphics unit + Imaging.InitImage(WorkData); + Imaging.CloneImage(Data, WorkData); + if Info.IsFloatingPoint or Info.HasAlphaChannel or Info.IsSpecial then + Imaging.ConvertImage(WorkData, ifA8R8G8B8) + else + begin +{$IFDEF COMPONENT_SET_VCL} + if Info.IsIndexed or Info.HasGrayChannel then + Imaging.ConvertImage(WorkData, ifIndex8) + else if Info.UsePixelFormat then + Imaging.ConvertImage(WorkData, ifR5G6B5) + else + Imaging.ConvertImage(WorkData, ifR8G8B8); +{$ELSE} + Imaging.ConvertImage(WorkData, ifA8R8G8B8); +{$ENDIF} + end; + + PF := DataFormatToPixelFormat(WorkData.Format); + GetImageFormatInfo(WorkData.Format, Info); + end + else + WorkData := Data; + + if PF = pfCustom then + RaiseImaging(SBadFormatDataToBitmap, [ImageToStr(WorkData)]); + + LineBytes := WorkData.Width * Info.BytesPerPixel; + +{$IFDEF COMPONENT_SET_VCL} + Bitmap.Width := WorkData.Width; + Bitmap.Height := WorkData.Height; + Bitmap.PixelFormat := PF; + + if (PF = pf8bit) and (WorkData.Palette <> nil) then + begin + // Copy palette, this must be done before copying bits + FillChar(LogPalette, SizeOf(LogPalette), 0); + LogPalette.palVersion := $300; + LogPalette.palNumEntries := Info.PaletteEntries; + for I := 0 to Info.PaletteEntries - 1 do + with LogPalette do + begin + palPalEntry[I].peRed := WorkData.Palette[I].R; + palPalEntry[I].peGreen := WorkData.Palette[I].G; + palPalEntry[I].peBlue := WorkData.Palette[I].B; + end; + Bitmap.Palette := CreatePalette(PLogPalette(@LogPalette)^); + end; + // Copy scanlines + for I := 0 to WorkData.Height - 1 do + Move(PByteArray(WorkData.Bits)[I * LineBytes], Bitmap.Scanline[I]^, LineBytes); + + // Delphi 2009 and newer support alpha transparency fro TBitmap +{$IF Defined(DELPHI) and (CompilerVersion >= 20.0)} + if Bitmap.PixelFormat = pf32bit then + Bitmap.AlphaFormat := afDefined; +{$IFEND} + +{$ENDIF} +{$IFDEF COMPONENT_SET_LCL} + // Create 32bit raw image from image data + FillChar(RawImage, SizeOf(RawImage), 0); + with RawImage.Description do + begin + Width := WorkData.Width; + Height := WorkData.Height; + BitsPerPixel := 32; + Format := ricfRGBA; + LineEnd := rileDWordBoundary; + BitOrder := riboBitsInOrder; + ByteOrder := riboLSBFirst; + LineOrder := riloTopToBottom; + AlphaPrec := 8; + RedPrec := 8; + GreenPrec := 8; + BluePrec := 8; + AlphaShift := 24; + RedShift := 16; + GreenShift := 8; + BlueShift := 0; + Depth := 32; // Must be 32 for alpha blending (and for working in MacOSX Carbon) + end; + RawImage.Data := WorkData.Bits; + RawImage.DataSize := WorkData.Size; + + // Create bitmap from raw image + if RawImage_CreateBitmaps(RawImage, ImgHandle, ImgMaskHandle) then + begin + Bitmap.Handle := ImgHandle; + Bitmap.MaskHandle := ImgMaskHandle; + end; +{$ENDIF} + if WorkData.Bits <> Data.Bits then + Imaging.FreeImage(WorkData); +end; + +procedure ConvertBitmapToData(Bitmap: TBitmap; var Data: TImageData); +var + I, LineBytes: LongInt; + Format: TImageFormat; + Info: TImageFormatInfo; +{$IFDEF COMPONENT_SET_VCL} + Colors: Word; + LogPalette: TMaxLogPalette; +{$ENDIF} +{$IFDEF COMPONENT_SET_LCL} + RawImage: TRawImage; + LineLazBytes: LongInt; +{$ENDIF} +begin +{$IFDEF COMPONENT_SET_LCL} + // In the current Lazarus 0.9.10 Bitmap.PixelFormat property is useless. + // We cannot change bitmap's format by changing it (it will just release + // old image but not convert it to new format) nor we can determine bitmaps's + // current format (it is usually set to pfDevice). So bitmap's format is obtained + // trough RawImage api and cannot be changed to mirror some Imaging format + // (so formats with no coresponding Imaging format cannot be saved now). + + if RawImage_DescriptionFromBitmap(Bitmap.Handle, RawImage.Description) then + case RawImage.Description.BitsPerPixel of + 8: Format := ifIndex8; + 16: + if RawImage.Description.Depth = 15 then + Format := ifA1R5G5B5 + else + Format := ifR5G6B5; + 24: Format := ifR8G8B8; + 32: Format := ifA8R8G8B8; + 48: Format := ifR16G16B16; + 64: Format := ifA16R16G16B16; + else + Format := ifUnknown; + end; +{$ELSE} + Format := PixelFormatToDataFormat(Bitmap.PixelFormat); + if Format = ifUnknown then + begin + // Convert from formats not supported by Imaging (1/4 bit) + if Bitmap.PixelFormat < pf8bit then + Bitmap.PixelFormat := pf8bit + else + Bitmap.PixelFormat := pf32bit; + Format := PixelFormatToDataFormat(Bitmap.PixelFormat); + end; +{$ENDIF} + + if Format = ifUnknown then + RaiseImaging(SBadFormatBitmapToData, []); + + Imaging.NewImage(Bitmap.Width, Bitmap.Height, Format, Data); + GetImageFormatInfo(Data.Format, Info); + LineBytes := Data.Width * Info.BytesPerPixel; + +{$IFDEF COMPONENT_SET_VCL} + if (Format = ifIndex8) and (GetObject(Bitmap.Palette, SizeOf(Colors), + @Colors) <> 0) then + begin + // Copy palette + GetPaletteEntries(Bitmap.Palette, 0, Colors, LogPalette.palPalEntry); + if Colors > Info.PaletteEntries then + Colors := Info.PaletteEntries; + for I := 0 to Colors - 1 do + with LogPalette do + begin + Data.Palette[I].A := $FF; + Data.Palette[I].R := palPalEntry[I].peRed; + Data.Palette[I].G := palPalEntry[I].peGreen; + Data.Palette[I].B := palPalEntry[I].peBlue; + end; + end; + // Copy scanlines + for I := 0 to Data.Height - 1 do + Move(Bitmap.ScanLine[I]^, PByteArray(Data.Bits)[I * LineBytes], LineBytes); +{$ENDIF} +{$IFDEF COMPONENT_SET_LCL} + // Get raw image from bitmap (mask handle must be 0 or expect violations) + if RawImage_FromBitmap(RawImage, Bitmap.Handle, 0, nil) then + begin + LineLazBytes := GetBytesPerLine(Data.Width, RawImage.Description.BitsPerPixel, + RawImage.Description.LineEnd); + // Copy scanlines + for I := 0 to Data.Height - 1 do + begin + Move(PByteArray(RawImage.Data)[I * LineLazBytes], + PByteArray(Data.Bits)[I * LineBytes], LineBytes); + end; + // May need to swap RB order, depends on wifget set + if RawImage.Description.BlueShift > RawImage.Description.RedShift then + SwapChannels(Data, ChannelRed, ChannelBlue); + + RawImage.FreeData; + end; +{$ENDIF} +end; + +procedure ConvertImageToBitmap(Image: TBaseImage; Bitmap: TBitmap); +begin + ConvertDataToBitmap(Image.ImageDataPointer^, Bitmap); +end; + +procedure ConvertBitmapToImage(Bitmap: TBitmap; Image: TBaseImage); +begin + ConvertBitmapToData(Bitmap, Image.ImageDataPointer^); +end; + +{$IFDEF MSWINDOWS} +procedure DisplayImageDataOnDC(DC: HDC; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); +var + OldMode: Integer; + BitmapInfo: Windows.TBitmapInfo; + Bmp: TBitmap; +begin + if TestImage(ImageData) then + begin + Assert(ImageData.Format in [ifA8R8G8B8, ifX8R8G8B8], SBadFormatDisplay); + OldMode := Windows.SetStretchBltMode(DC, COLORONCOLOR); + + FillChar(BitmapInfo, SizeOf(BitmapInfo), 0); + with BitmapInfo.bmiHeader do + begin + biSize := SizeOf(TBitmapInfoHeader); + biPlanes := 1; + biBitCount := 32; + biCompression := BI_RGB; + biWidth := ImageData.Width; + biHeight := -ImageData.Height; + biSizeImage := ImageData.Size; + biXPelsPerMeter := 0; + biYPelsPerMeter := 0; + biClrUsed := 0; + biClrImportant := 0; + end; + + try + with SrcRect, ImageData do + if Windows.StretchDIBits(DC, DstRect.Left, DstRect.Top, + DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top, Left, + Top, Right - Left, Bottom - Top, Bits, BitmapInfo, DIB_RGB_COLORS, SRCCOPY) <> Height then + begin + // StretchDIBits may fail on some ocassions (error 487, http://support.microsoft.com/kb/269585). + // This fallback is slow but works every time. Thanks to Sergey Galezdinov for the fix. + Bmp := TBitmap.Create; + try + ConvertDataToBitmap(ImageData, Bmp); + StretchBlt(DC, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left, DstRect.Bottom - DstRect.Top, + Bmp.Canvas.Handle, 0, 0, Width, Height, SRCCOPY); + finally + Bmp.Free; + end; + end; + finally + Windows.SetStretchBltMode(DC, OldMode); + end; + end; +end; +{$ENDIF} + +procedure DisplayImageData(DstCanvas: TCanvas; const DstRect: TRect; const ImageData: TImageData; const SrcRect: TRect); +{$IF Defined(DCC) or Defined(LCLWIN32)} // Delphi or LCL Win32 +begin + DisplayImageDataOnDC(DstCanvas.Handle, DstRect, ImageData, SrcRect); +end; +{$ELSEIF Defined(LCLGTK2)} + type + TDeviceContext = TGtk2DeviceContext; + + procedure GDKDrawBitmap(Dest: HDC; DstX, DstY: Integer; SrcX, SrcY, + SrcWidth, SrcHeight: Integer; ImageData: TImageData); + var + P: TPoint; + begin + P := TDeviceContext(Dest).Offset; + Inc(DstX, P.X); + Inc(DstY, P.Y); + gdk_draw_rgb_32_image(TDeviceContext(Dest).Drawable, TDeviceContext(Dest).GC, + DstX, DstY, SrcWidth, SrcHeight, GDK_RGB_DITHER_NONE, + @PLongWordArray(ImageData.Bits)[SrcY * ImageData.Width + SrcX], ImageData.Width * 4); + end; + +var + DisplayImage: TImageData; + NewWidth, NewHeight: Integer; + SrcBounds, DstBounds, DstClip: TRect; +begin + if TestImage(ImageData) then + begin + Assert(ImageData.Format in [ifA8R8G8B8, ifX8R8G8B8], SBadFormatDisplay); + InitImage(DisplayImage); + + SrcBounds := RectToBounds(SrcRect); + DstBounds := RectToBounds(DstRect); + WidgetSet.GetClipBox(DstCanvas.Handle, @DstClip); + + ClipStretchBounds(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom, + DstBounds.Left, DstBounds.Top, DstBounds.Right, DstBounds.Bottom, ImageData.Width, + ImageData.Height, DstClip); + + NewWidth := DstBounds.Right; + NewHeight := DstBounds.Bottom; + + if (NewWidth > 0) and (NewHeight > 0) then + begin + if (SrcBounds.Right = NewWidth) and (SrcBounds.Bottom = NewHeight) then + try + CloneImage(ImageData, DisplayImage); + // Swap R-B channels for GTK display compatability! + SwapChannels(DisplayImage, ChannelRed, ChannelBlue); + GDKDrawBitmap(DstCanvas.Handle, DstBounds.Left, DstBounds.Top, + SrcBounds.Left, SrcBounds.Top, NewWidth, NewHeight, DisplayImage); + finally + FreeImage(DisplayImage); + end + else + try + // Create new image with desired dimensions + NewImage(NewWidth, NewHeight, ImageData.Format, DisplayImage); + // Stretch pixels from old image to new one TResizeFilter = (rfNearest, rfBilinear, rfBicubic); + StretchRect(ImageData, SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, + SrcBounds.Bottom, DisplayImage, 0, 0, NewWidth, NewHeight, rfNearest); + // Swap R-B channels for GTK display compatability! + SwapChannels(DisplayImage, ChannelRed, ChannelBlue); + GDKDrawBitmap(DstCanvas.Handle, DstBounds.Left, DstBounds.Top, 0, 0, + NewWidth, NewHeight, DisplayImage); + finally + FreeImage(DisplayImage); + end + end; + end; +end; +{$ELSE} +begin + raise Exception.Create(SUnsupportedLCLWidgetSet); +end; +{$IFEND} + +procedure DisplayImage(DstCanvas: TCanvas; DstX, DstY: LongInt; Image: TBaseImage); +begin + DisplayImageData(DstCanvas, BoundsToRect(DstX, DstY, Image.Width, Image.Height), + Image.ImageDataPointer^, Image.BoundsRect); +end; + +procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage); +begin + DisplayImageData(DstCanvas, DstRect, Image.ImageDataPointer^, Image.BoundsRect); +end; + +procedure DisplayImage(DstCanvas: TCanvas; const DstRect: TRect; Image: TBaseImage; const SrcRect: TRect); +begin + DisplayImageData(DstCanvas, DstRect, Image.ImageDataPointer^, SrcRect); +end; + + +{ TImagingGraphic class implementation } + +constructor TImagingGraphic.Create; +begin + inherited Create; + PixelFormat := pf24Bit; +end; + +procedure TImagingGraphic.LoadFromStream(Stream: TStream); +begin + ReadDataFromStream(Stream); +end; + +procedure TImagingGraphic.ReadDataFromStream(Stream: TStream); +var + Image: TSingleImage; +begin + Image := TSingleImage.Create; + try + Image.LoadFromStream(Stream); + Assign(Image); + finally + Image.Free; + end; +end; + +procedure TImagingGraphic.AssignTo(Dest: TPersistent); +var + Arr: TDynImageDataArray; +begin + if Dest is TSingleImage then + begin + AssignToImage(TSingleImage(Dest)) + end + else if Dest is TMultiImage then + begin + SetLength(Arr, 1); + AssignToImageData(Arr[0]); + TMultiImage(Dest).CreateFromArray(Arr); + Imaging.FreeImagesInArray(Arr); + end + else + inherited AssignTo(Dest); +end; + +procedure TImagingGraphic.Assign(Source: TPersistent); +begin + if Source is TBaseImage then + AssignFromImage(TBaseImage(Source)) + else + inherited Assign(Source); +end; + +procedure TImagingGraphic.AssignFromImage(Image: TBaseImage); +begin + if (Image <> nil) and Image.Valid then + AssignFromImageData(Image.ImageDataPointer^); +end; + +procedure TImagingGraphic.AssignToImage(Image: TBaseImage); +begin + if (Image <> nil) and (Image.ImageDataPointer <> nil) then + AssignToImageData(Image.ImageDataPointer^); +end; + +procedure TImagingGraphic.AssignFromImageData(const ImageData: TImageData); +begin + if Imaging.TestImage(ImageData) then + ConvertDataToBitmap(ImageData, Self); +end; + +procedure TImagingGraphic.AssignToImageData(var ImageData: TImageData); +begin + Imaging.FreeImage(ImageData); + ConvertBitmapToData(Self, ImageData); +end; + + +{ TImagingGraphicForSave class implementation } + +constructor TImagingGraphicForSave.Create; +begin + inherited Create; + FDefaultFileExt := GetFileFormat.Extensions[0]; + FSavingFormat := ifUnknown; + GetFileFormat.CheckOptionsValidity; +end; + +procedure TImagingGraphicForSave.WriteDataToStream(Stream: TStream); +var + Image: TSingleImage; +begin + if FDefaultFileExt <> '' then + begin + Image := TSingleImage.Create; + try + Image.Assign(Self); + if FSavingFormat <> ifUnknown then + Image.Format := FSavingFormat; + Image.SaveToStream(FDefaultFileExt, Stream); + finally + Image.Free; + end; + end; +end; + +procedure TImagingGraphicForSave.SaveToStream(Stream: TStream); +begin + WriteDataToStream(Stream); +end; + +{$IFDEF COMPONENT_SET_LCL} +class function TImagingGraphicForSave.GetFileExtensions: string; +begin + Result := StringReplace(GetFileFormat.Extensions.CommaText, ',', ';', [rfReplaceAll]); +end; + +function TImagingGraphicForSave.GetMimeType: string; +begin + Result := 'image/' + FDefaultFileExt; +end; +{$ENDIF} + +{$IFNDEF DONT_LINK_BITMAP} + +{ TImagingBitmap class implementation } + +constructor TImagingBitmap.Create; +begin + inherited Create; + FUseRLE := (GetFileFormat as TBitmapFileFormat).UseRLE; +end; + +class function TImagingBitmap.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TBitmapFileFormat); +end; + +procedure TImagingBitmap.SaveToStream(Stream: TStream); +begin + Imaging.PushOptions; + Imaging.SetOption(ImagingBitmapRLE, Ord(FUseRLE)); + inherited SaveToStream(Stream); + Imaging.PopOptions; +end; +{$ENDIF} + +{$IFNDEF DONT_LINK_JPEG} + +{ TImagingJpeg class implementation } + +constructor TImagingJpeg.Create; +begin + inherited Create; + FQuality := (GetFileFormat as TJpegFileFormat).Quality; + FProgressive := (GetFileFormat as TJpegFileFormat).Progressive; +end; + +class function TImagingJpeg.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TJpegFileFormat); +end; + +{$IFDEF COMPONENT_SET_LCL} +function TImagingJpeg.GetMimeType: string; +begin + Result := 'image/jpeg'; +end; +{$ENDIF} + +procedure TImagingJpeg.SaveToStream(Stream: TStream); +begin + Imaging.PushOptions; + Imaging.SetOption(ImagingJpegQuality, FQuality); + Imaging.SetOption(ImagingJpegProgressive, Ord(FProgressive)); + inherited SaveToStream(Stream); + Imaging.PopOptions; +end; + +{$ENDIF} + +{$IFNDEF DONT_LINK_PNG} + +{ TImagingPNG class implementation } + +constructor TImagingPNG.Create; +begin + inherited Create; + FPreFilter := (GetFileFormat as TPNGFileFormat).PreFilter; + FCompressLevel := (GetFileFormat as TPNGFileFormat).CompressLevel; +end; + +class function TImagingPNG.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TPNGFileFormat); +end; + +procedure TImagingPNG.SaveToStream(Stream: TStream); +begin + Imaging.PushOptions; + Imaging.SetOption(ImagingPNGPreFilter, FPreFilter); + Imaging.SetOption(ImagingPNGCompressLevel, FCompressLevel); + inherited SaveToStream(Stream); + Imaging.PopOptions; +end; +{$ENDIF} + +{$IFNDEF DONT_LINK_GIF} + +{ TImagingGIF class implementation} + +class function TImagingGIF.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TGIFFileFormat); +end; + +{$ENDIF} + +{$IFNDEF DONT_LINK_TARGA} + +{ TImagingTarga class implementation } + +constructor TImagingTarga.Create; +begin + inherited Create; + FUseRLE := (GetFileFormat as TTargaFileFormat).UseRLE; +end; + +class function TImagingTarga.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TTargaFileFormat); +end; + +procedure TImagingTarga.SaveToStream(Stream: TStream); +begin + Imaging.PushOptions; + Imaging.SetOption(ImagingTargaRLE, Ord(FUseRLE)); + inherited SaveToStream(Stream); + Imaging.PopOptions; +end; +{$ENDIF} + +{$IFNDEF DONT_LINK_DDS} + +{ TImagingDDS class implementation } + +constructor TImagingDDS.Create; +begin + inherited Create; + FCompression := dcNone; +end; + +class function TImagingDDS.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TDDSFileFormat); +end; + +procedure TImagingDDS.SaveToStream(Stream: TStream); +begin + case FCompression of + dcNone: FSavingFormat := ifUnknown; + dcDXT1: FSavingFormat := ifDXT1; + dcDXT3: FSavingFormat := ifDXT3; + dcDXT5: FSavingFormat := ifDXT5; + end; + Imaging.PushOptions; + Imaging.SetOption(ImagingDDSSaveCubeMap, Ord(False)); + Imaging.SetOption(ImagingDDSSaveVolume, Ord(False)); + Imaging.SetOption(ImagingDDSSaveMipMapCount, 1); + Imaging.SetOption(ImagingDDSSaveDepth, 1); + inherited SaveToStream(Stream); + Imaging.PopOptions; +end; +{$ENDIF} + +{$IFNDEF DONT_LINK_MNG} + +{ TImagingMNG class implementation } + +constructor TImagingMNG.Create; +begin + inherited Create; + FLossyCompression := (GetFileFormat as TMNGFileFormat).LossyCompression; + FLossyAlpha := (GetFileFormat as TMNGFileFormat).LossyAlpha; + FPreFilter := (GetFileFormat as TMNGFileFormat).PreFilter; + FCompressLevel := (GetFileFormat as TMNGFileFormat).CompressLevel; + FQuality := (GetFileFormat as TMNGFileFormat).Quality; + FProgressive := (GetFileFormat as TMNGFileFormat).Progressive; +end; + +class function TImagingMNG.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TMNGFileFormat); +end; + +{$IFDEF COMPONENT_SET_LCL} +function TImagingMNG.GetMimeType: string; +begin + Result := 'video/mng'; +end; +{$ENDIF} + +procedure TImagingMNG.SaveToStream(Stream: TStream); +begin + Imaging.PushOptions; + Imaging.SetOption(ImagingMNGLossyCompression, Ord(FLossyCompression)); + Imaging.SetOption(ImagingMNGLossyAlpha, Ord(FLossyAlpha)); + Imaging.SetOption(ImagingMNGPreFilter, FPreFilter); + Imaging.SetOption(ImagingMNGCompressLevel, FCompressLevel); + Imaging.SetOption(ImagingMNGQuality, FQuality); + Imaging.SetOption(ImagingMNGProgressive, Ord(FProgressive)); + inherited SaveToStream(Stream); + Imaging.PopOptions; +end; +{$ENDIF} + +{$IFNDEF DONT_LINK_JNG} + +{ TImagingJNG class implementation } + +constructor TImagingJNG.Create; +begin + inherited Create; + FLossyAlpha := (GetFileFormat as TJNGFileFormat).LossyAlpha; + FAlphaPreFilter := (GetFileFormat as TJNGFileFormat).PreFilter; + FAlphaCompressLevel := (GetFileFormat as TJNGFileFormat).CompressLevel; + FQuality := (GetFileFormat as TJNGFileFormat).Quality; + FProgressive := (GetFileFormat as TJNGFileFormat).Progressive; +end; + +class function TImagingJNG.GetFileFormat: TImageFileFormat; +begin + Result := FindImageFileFormatByClass(TJNGFileFormat); +end; + +procedure TImagingJNG.SaveToStream(Stream: TStream); +begin + Imaging.PushOptions; + Imaging.SetOption(ImagingJNGLossyALpha, Ord(FLossyAlpha)); + Imaging.SetOption(ImagingJNGAlphaPreFilter, FAlphaPreFilter); + Imaging.SetOption(ImagingJNGAlphaCompressLevel, FAlphaCompressLevel); + Imaging.SetOption(ImagingJNGQuality, FQuality); + Imaging.SetOption(ImagingJNGProgressive, Ord(FProgressive)); + inherited SaveToStream(Stream); + Imaging.PopOptions; +end; +{$ENDIF} + +initialization + RegisterTypes; +finalization + UnRegisterTypes; + +{$IFEND} // {$IF not Defined(COMPONENT_SET_LCL) and not Defined(COMPONENT_SET_VCL)} + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 --------------------------------------------------- + - Fixed bug in ConvertBitmapToData causing images from GTK2 bitmaps + to have swapped RB channels. + - LCL: Removed GTK1 support (deprecated). + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Transparency of 8bit images (like loaded from 8bit PNG or GIF) is + kept intact during conversion to TBitmap in ConvertDataToBitmap + (32bit bitmap is created). + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Setting AlphaFormat property of TBitmap in ConvertDataToBitmap + when using Delphi 2009+. + - Fixed garbled LCL TBitmaps created by ConvertDataToBitmap + in Mac OS X (Carbon). + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - Added some more IFDEFs for Lazarus widget sets. + - Removed CLX code. + - GTK version of Unix DisplayImageData only used with LCL GTK so the + the rest of the unit can be used with Qt or other LCL interfaces. + - Fallback mechanism for DisplayImageDataOnDC, it may fail on occasions. + - Changed file format conditional compilation to reflect changes + in LINK symbols. + - Lazarus 0.9.26 compatibility changes. + + -- 0.24.1 Changes/Bug Fixes --------------------------------- + - Fixed wrong IFDEF causing that Imaging wouldn't compile in Lazarus + with GTK2 target. + - Added commnets with code for Lazarus rev. 11861+ regarding + RawImage interface. Replace current code with that in comments + if you use Lazarus from SVN. New RawImage interface will be used by + default after next Lazarus release. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added TImagingGIF. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Uses only high level interface now (except for saving options). + - Slightly changed class hierarchy. TImagingGraphic is now only for loading + and base class for savers is new TImagingGraphicForSave. Also + TImagingGraphic is now registered with all supported file formats + by TPicture's format support. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - added DisplayImage procedures (thanks to Paul Michell, modified) + - removed RegisterTypes and UnRegisterTypes from interface section, + they are called automatically + - added procedures: ConvertImageToBitmap and ConvertBitmapToImage + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - LCL data to bitmap conversion didn´t work in Linux, fixed + - added MNG file format + - added JNG file format + + -- 0.15 Changes/Bug Fixes ----------------------------------- + - made it LCL compatible + - made it CLX compatible + - added all initial stuff +} + +end. diff --git a/src/lib/vampimg/ImagingDds.pas b/src/lib/vampimg/ImagingDds.pas new file mode 100644 index 0000000..9410495 --- /dev/null +++ b/src/lib/vampimg/ImagingDds.pas @@ -0,0 +1,1144 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader/saver for DirectDraw Surface images.} +unit ImagingDds; + +{$I ImagingOptions.inc} + +interface + +uses + ImagingTypes, Imaging, ImagingUtility, ImagingFormats; + +type + { Class for loading and saving Microsoft DirectDraw surfaces. + It can load/save all D3D formats which have coresponding + TImageFormat. It supports plain textures, cube textures and + volume textures, all of these can have mipmaps. It can also + load some formats which have no exact TImageFormat, but can be easily + converted to one (bump map formats, etc.). + You can get some information about last loaded DDS file by calling + GetOption with ImagingDDSLoadedXXX options and you can set some + saving options by calling SetOption with ImagingDDSSaveXXX or you can + simply use properties of this class. + Note that when saving cube maps and volumes input image array must contain + at least number of images to build cube/volume based on current + Depth and MipMapCount settings.} + TDDSFileFormat = class(TImageFileFormat) + private + FLoadedCubeMap: LongBool; + FLoadedVolume: LongBool; + FLoadedMipMapCount: LongInt; + FLoadedDepth: LongInt; + FSaveCubeMap: LongBool; + FSaveVolume: LongBool; + FSaveMipMapCount: LongInt; + FSaveDepth: LongInt; + procedure ComputeSubDimensions(Idx, Width, Height, MipMaps, Depth: LongInt; + IsCubeMap, IsVolume: Boolean; var CurWidth, CurHeight: LongInt); + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + procedure CheckOptionsValidity; override; + published + { True if last loaded DDS file was cube map.} + property LoadedCubeMap: LongBool read FLoadedCubeMap write FLoadedCubeMap; + { True if last loaded DDS file was volume texture.} + property LoadedVolume: LongBool read FLoadedVolume write FLoadedVolume; + { Number of mipmap levels of last loaded DDS image.} + property LoadedMipMapCount: LongInt read FLoadedMipMapCount write FLoadedMipMapCount; + { Depth (slices of volume texture or faces of cube map) of last loaded DDS image.} + property LoadedDepth: LongInt read FLoadedDepth write FLoadedDepth; + { True if next DDS file to be saved should be stored as cube map.} + property SaveCubeMap: LongBool read FSaveCubeMap write FSaveCubeMap; + { True if next DDS file to be saved should be stored as volume texture.} + property SaveVolume: LongBool read FSaveVolume write FSaveVolume; + { Sets the number of mipmaps which should be stored in the next saved DDS file. + Only applies to cube maps and volumes, ordinary 2D textures save all + levels present in input.} + property SaveMipMapCount: LongInt read FSaveMipMapCount write FSaveMipMapCount; + { Sets the depth (slices of volume texture or faces of cube map) + of the next saved DDS file.} + property SaveDepth: LongInt read FSaveDepth write FSaveDepth; + end; + +const + { DDS related metadata Ids } + + { DXGI format of textures stored in DDS files with DX10 extension. Type is + Enum (value corresponding to DXGI_FORMAT enum from DX SDK).} + SMetaDdsDxgiFormat = 'DdsDxgiFormat'; + { Number of mipmaps for each main image in DDS file.} + SMetaDdsMipMapCount = 'DdsMipMapCount'; + { Texture array size stored in DDS file (DX10 extension).} + SMetaDdsArraySize = 'DdsArraySize'; + +implementation + +const + SDDSFormatName = 'DirectDraw Surface'; + SDDSMasks = '*.dds'; + DDSSupportedFormats: TImageFormats = [ifR8G8B8, ifA8R8G8B8, ifX8R8G8B8, + ifA1R5G5B5, ifA4R4G4B4, ifX1R5G5B5, ifX4R4G4B4, ifR5G6B5, ifA16B16G16R16, + ifR32F, ifA32B32G32R32F, ifR16F, ifA16B16G16R16F, ifR3G3B2, ifGray8, ifA8Gray8, + ifGray16, ifDXT1, ifDXT3, ifDXT5, ifATI1N, ifATI2N]; + +const + { Four character codes.} + DDSMagic = LongWord(Byte('D') or (Byte('D') shl 8) or (Byte('S') shl 16) or + (Byte(' ') shl 24)); + FOURCC_DXT1 = LongWord(Byte('D') or (Byte('X') shl 8) or (Byte('T') shl 16) or + (Byte('1') shl 24)); + FOURCC_DXT3 = LongWord(Byte('D') or (Byte('X') shl 8) or (Byte('T') shl 16) or + (Byte('3') shl 24)); + FOURCC_DXT5 = LongWord(Byte('D') or (Byte('X') shl 8) or (Byte('T') shl 16) or + (Byte('5') shl 24)); + FOURCC_ATI1 = LongWord(Byte('A') or (Byte('T') shl 8) or (Byte('I') shl 16) or + (Byte('1') shl 24)); + FOURCC_ATI2 = LongWord(Byte('A') or (Byte('T') shl 8) or (Byte('I') shl 16) or + (Byte('2') shl 24)); + FOURCC_DX10 = LongWord(Byte('D') or (Byte('X') shl 8) or (Byte('1') shl 16) or + (Byte('0') shl 24)); + + { Some D3DFORMAT values used in DDS files as FourCC value.} + D3DFMT_A16B16G16R16 = 36; + D3DFMT_R32F = 114; + D3DFMT_A32B32G32R32F = 116; + D3DFMT_R16F = 111; + D3DFMT_A16B16G16R16F = 113; + + { Constans used by TDDSurfaceDesc2.Flags.} + DDSD_CAPS = $00000001; + DDSD_HEIGHT = $00000002; + DDSD_WIDTH = $00000004; + DDSD_PITCH = $00000008; + DDSD_PIXELFORMAT = $00001000; + DDSD_MIPMAPCOUNT = $00020000; + DDSD_LINEARSIZE = $00080000; + DDSD_DEPTH = $00800000; + + { Constans used by TDDSPixelFormat.Flags.} + DDPF_ALPHAPIXELS = $00000001; // used by formats which contain alpha + DDPF_FOURCC = $00000004; // used by DXT and large ARGB formats + DDPF_RGB = $00000040; // used by RGB formats + DDPF_LUMINANCE = $00020000; // used by formats like D3DFMT_L16 + DDPF_BUMPLUMINANCE = $00040000; // used by mixed signed-unsigned formats + DDPF_BUMPDUDV = $00080000; // used by signed formats + + { Constans used by TDDSCaps.Caps1.} + DDSCAPS_COMPLEX = $00000008; + DDSCAPS_TEXTURE = $00001000; + DDSCAPS_MIPMAP = $00400000; + + { Constans used by TDDSCaps.Caps2.} + DDSCAPS2_CUBEMAP = $00000200; + DDSCAPS2_POSITIVEX = $00000400; + DDSCAPS2_NEGATIVEX = $00000800; + DDSCAPS2_POSITIVEY = $00001000; + DDSCAPS2_NEGATIVEY = $00002000; + DDSCAPS2_POSITIVEZ = $00004000; + DDSCAPS2_NEGATIVEZ = $00008000; + DDSCAPS2_VOLUME = $00200000; + + { Flags for TDDSurfaceDesc2.Flags used when saving DDS file.} + DDS_SAVE_FLAGS = DDSD_CAPS or DDSD_PIXELFORMAT or DDSD_WIDTH or + DDSD_HEIGHT or DDSD_LINEARSIZE; + +type + { Stores the pixel format information.} + TDDPixelFormat = packed record + Size: LongWord; // Size of the structure = 32 bytes + Flags: LongWord; // Flags to indicate valid fields + FourCC: LongWord; // Four-char code for compressed textures (DXT) + BitCount: LongWord; // Bits per pixel if uncomp. usually 16,24 or 32 + RedMask: LongWord; // Bit mask for the Red component + GreenMask: LongWord; // Bit mask for the Green component + BlueMask: LongWord; // Bit mask for the Blue component + AlphaMask: LongWord; // Bit mask for the Alpha component + end; + + { Specifies capabilities of surface.} + TDDSCaps = packed record + Caps1: LongWord; // Should always include DDSCAPS_TEXTURE + Caps2: LongWord; // For cubic environment maps + Reserved: array[0..1] of LongWord; // Reserved + end; + + { Record describing DDS file contents.} + TDDSurfaceDesc2 = packed record + Size: LongWord; // Size of the structure = 124 Bytes + Flags: LongWord; // Flags to indicate valid fields + Height: LongWord; // Height of the main image in pixels + Width: LongWord; // Width of the main image in pixels + PitchOrLinearSize: LongWord; // For uncomp formats number of bytes per + // scanline. For comp it is the size in + // bytes of the main image + Depth: LongWord; // Only for volume text depth of the volume + MipMaps: LongInt; // Total number of levels in the mipmap chain + Reserved1: array[0..10] of LongWord; // Reserved + PixelFormat: TDDPixelFormat; // Format of the pixel data + Caps: TDDSCaps; // Capabilities + Reserved2: LongWord; // Reserved + end; + + { DDS file header.} + TDDSFileHeader = packed record + Magic: LongWord; // File format magic + Desc: TDDSurfaceDesc2; // Surface description + end; + + { Resoirce types for D3D 10+ } + TD3D10ResourceDimension = ( + D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, + D3D10_RESOURCE_DIMENSION_BUFFER = 1, + D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, + D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, + D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4 + ); + + { Texture formats for D3D 10+ } + TDXGIFormat = ( + DXGI_FORMAT_UNKNOWN = 0, + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + DXGI_FORMAT_R11G11B10_FLOAT = 26, + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + DXGI_FORMAT_R1_UNORM = 66, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_AYUV = 100, + DXGI_FORMAT_Y410 = 101, + DXGI_FORMAT_Y416 = 102, + DXGI_FORMAT_NV12 = 103, + DXGI_FORMAT_P010 = 104, + DXGI_FORMAT_P016 = 105, + DXGI_FORMAT_420_OPAQUE = 106, + DXGI_FORMAT_YUY2 = 107, + DXGI_FORMAT_Y210 = 108, + DXGI_FORMAT_Y216 = 109, + DXGI_FORMAT_NV11 = 110, + DXGI_FORMAT_AI44 = 111, + DXGI_FORMAT_IA44 = 112, + DXGI_FORMAT_P8 = 113, + DXGI_FORMAT_A8P8 = 114, + DXGI_FORMAT_B4G4R4A4_UNORM = 115 + ); + + { DX10 extension header for DDS file format } + TDX10Header = packed record + DXGIFormat: TDXGIFormat; + ResourceDimension: TD3D10ResourceDimension; + MiscFlags: LongWord; + ArraySize: LongWord; + Reserved: LongWord; + end; + +{ TDDSFileFormat class implementation } + +procedure TDDSFileFormat.Define; +begin + inherited; + FName := SDDSFormatName; + FFeatures := [ffLoad, ffSave, ffMultiImage]; + FSupportedFormats := DDSSupportedFormats; + + FSaveCubeMap := False; + FSaveVolume := False; + FSaveMipMapCount := 1; + FSaveDepth := 1; + + AddMasks(SDDSMasks); + + RegisterOption(ImagingDDSLoadedCubeMap, @FLoadedCubeMap); + RegisterOption(ImagingDDSLoadedVolume, @FLoadedVolume); + RegisterOption(ImagingDDSLoadedMipMapCount, @FLoadedMipMapCount); + RegisterOption(ImagingDDSLoadedDepth, @FLoadedDepth); + RegisterOption(ImagingDDSSaveCubeMap, @FSaveCubeMap); + RegisterOption(ImagingDDSSaveVolume, @FSaveVolume); + RegisterOption(ImagingDDSSaveMipMapCount, @FSaveMipMapCount); + RegisterOption(ImagingDDSSaveDepth, @FSaveDepth); +end; + +procedure TDDSFileFormat.CheckOptionsValidity; +begin + if FSaveCubeMap then + FSaveVolume := False; + if FSaveVolume then + FSaveCubeMap := False; + if FSaveDepth < 1 then + FSaveDepth := 1; + if FSaveMipMapCount < 1 then + FSaveMipMapCount := 1; +end; + +procedure TDDSFileFormat.ComputeSubDimensions(Idx, Width, Height, MipMaps, Depth: LongInt; + IsCubeMap, IsVolume: Boolean; var CurWidth, CurHeight: LongInt); +var + I, Last, Shift: LongInt; +begin + CurWidth := Width; + CurHeight := Height; + if MipMaps > 1 then + begin + if not IsVolume then + begin + if IsCubeMap then + begin + // Cube maps are stored like this + // Face 0 mimap 0 + // Face 0 mipmap 1 + // ... + // Face 1 mipmap 0 + // Face 1 mipmap 1 + // ... + + // Modify index so later in for loop we iterate less times + Idx := Idx - ((Idx div MipMaps) * MipMaps); + end; + for I := 0 to Idx - 1 do + begin + CurWidth := ClampInt(CurWidth shr 1, 1, CurWidth); + CurHeight := ClampInt(CurHeight shr 1, 1, CurHeight); + end; + end + else + begin + // Volume textures are stored in DDS files like this: + // Slice 0 mipmap 0 + // Slice 1 mipmap 0 + // Slice 2 mipmap 0 + // Slice 3 mipmap 0 + // Slice 0 mipmap 1 + // Slice 1 mipmap 1 + // Slice 0 mipmap 2 + // Slice 0 mipmap 3 ... + Shift := 0; + Last := Depth; + while Idx > Last - 1 do + begin + CurWidth := ClampInt(CurWidth shr 1, 1, CurWidth); + CurHeight := ClampInt(CurHeight shr 1, 1, CurHeight); + if (CurWidth = 1) and (CurHeight = 1) then + Break; + Inc(Shift); + Inc(Last, ClampInt(Depth shr Shift, 1, Depth)); + end; + end; + end; +end; + +function TDDSFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Hdr: TDDSFileHeader; + HdrDX10: TDX10Header; + SrcFormat: TImageFormat; + FmtInfo: TImageFormatInfo; + NeedsSwapChannels: Boolean; + CurrentWidth, CurrentHeight, ImageCount, LoadSize, I, + PitchOrLinear, MainImageLinearSize: Integer; + Data: PByte; + UseAsPitch: Boolean; + UseAsLinear: Boolean; + + function MasksEqual(const DDPF: TDDPixelFormat; PF: PPixelFormatInfo): Boolean; + begin + Result := (DDPF.AlphaMask = PF.ABitMask) and + (DDPF.RedMask = PF.RBitMask) and (DDPF.GreenMask = PF.GBitMask) and + (DDPF.BlueMask = PF.BBitMask); + end; + + function FindFourCCFormat(FourCC: LongWord): TImageFormat; + begin + // Handle FourCC and large ARGB formats + case FourCC of + D3DFMT_A16B16G16R16: Result := ifA16B16G16R16; + D3DFMT_R32F: Result := ifR32F; + D3DFMT_A32B32G32R32F: Result := ifA32B32G32R32F; + D3DFMT_R16F: Result := ifR16F; + D3DFMT_A16B16G16R16F: Result := ifA16B16G16R16F; + FOURCC_DXT1: Result := ifDXT1; + FOURCC_DXT3: Result := ifDXT3; + FOURCC_DXT5: Result := ifDXT5; + FOURCC_ATI1: Result := ifATI1N; + FOURCC_ATI2: Result := ifATI2N; + else + Result := ifUnknown; + end; + end; + + function FindDX10Format(DXGIFormat: TDXGIFormat; var NeedsSwapChannels: Boolean): TImageFormat; + begin + Result := ifUnknown; + NeedsSwapChannels := False; + + case DXGIFormat of + DXGI_FORMAT_UNKNOWN: ; + DXGI_FORMAT_R32G32B32A32_TYPELESS, DXGI_FORMAT_R32G32B32A32_FLOAT: + Result := ifA32B32G32R32F; + DXGI_FORMAT_R32G32B32A32_UINT: ; + DXGI_FORMAT_R32G32B32A32_SINT: ; + DXGI_FORMAT_R32G32B32_TYPELESS, DXGI_FORMAT_R32G32B32_FLOAT: + Result := ifB32G32R32F; + DXGI_FORMAT_R32G32B32_UINT: ; + DXGI_FORMAT_R32G32B32_SINT: ; + DXGI_FORMAT_R16G16B16A16_FLOAT: + Result := ifA16B16G16R16F; + DXGI_FORMAT_R16G16B16A16_TYPELESS, DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SINT: + Result := ifA16B16G16R16; + DXGI_FORMAT_R32G32_TYPELESS: ; + DXGI_FORMAT_R32G32_FLOAT: ; + DXGI_FORMAT_R32G32_UINT: ; + DXGI_FORMAT_R32G32_SINT: ; + DXGI_FORMAT_R32G8X24_TYPELESS: ; + DXGI_FORMAT_D32_FLOAT_S8X24_UINT: ; + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: ; + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: ; + DXGI_FORMAT_R10G10B10A2_TYPELESS: ; + DXGI_FORMAT_R10G10B10A2_UNORM: ; + DXGI_FORMAT_R10G10B10A2_UINT: ; + DXGI_FORMAT_R11G11B10_FLOAT: ; + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SNORM,DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + begin + Result := ifA8R8G8B8; + NeedsSwapChannels := True; + end; + DXGI_FORMAT_R16G16_TYPELESS: ; + DXGI_FORMAT_R16G16_FLOAT: ; + DXGI_FORMAT_R16G16_UNORM: ; + DXGI_FORMAT_R16G16_UINT: ; + DXGI_FORMAT_R16G16_SNORM: ; + DXGI_FORMAT_R16G16_SINT: ; + DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_SINT: + Result := ifGray32; + DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_R32_FLOAT: + Result := ifR32F; + DXGI_FORMAT_R24G8_TYPELESS: ; + DXGI_FORMAT_D24_UNORM_S8_UINT: ; + DXGI_FORMAT_R24_UNORM_X8_TYPELESS: ; + DXGI_FORMAT_X24_TYPELESS_G8_UINT: ; + DXGI_FORMAT_R8G8_TYPELESS, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SINT: + Result := ifA8Gray8; + DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_SNORM, DXGI_FORMAT_R16_SINT: + Result := ifGray16; + DXGI_FORMAT_R16_FLOAT: + Result := ifR16F; + DXGI_FORMAT_R8_TYPELESS, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_A8_UNORM: + Result := ifGray8; + DXGI_FORMAT_R1_UNORM: ; + DXGI_FORMAT_R9G9B9E5_SHAREDEXP: ; + DXGI_FORMAT_R8G8_B8G8_UNORM: ; + DXGI_FORMAT_G8R8_G8B8_UNORM: ; + DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB: + Result := ifDXT1; + DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB: + Result := ifDXT3; + DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB: + Result := ifDXT5; + DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM: + Result := ifATI1N; + DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM: + Result := ifATI2N; + DXGI_FORMAT_B5G6R5_UNORM: + Result := ifR5G6B5; + DXGI_FORMAT_B5G5R5A1_UNORM: + Result := ifA1R5G5B5; + DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_TYPELESS: + Result := ifA8R8G8B8; + DXGI_FORMAT_B8G8R8X8_UNORM, DXGI_FORMAT_B8G8R8X8_TYPELESS: + Result := ifX8R8G8B8; + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: ; + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: ; + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: ; + DXGI_FORMAT_BC6H_TYPELESS: ; + DXGI_FORMAT_BC6H_UF16: ; + DXGI_FORMAT_BC6H_SF16: ; + DXGI_FORMAT_BC7_TYPELESS: ; + DXGI_FORMAT_BC7_UNORM: ; + DXGI_FORMAT_BC7_UNORM_SRGB: ; + DXGI_FORMAT_P8: ; + DXGI_FORMAT_A8P8: ; + DXGI_FORMAT_B4G4R4A4_UNORM: + Result := ifA4R4G4B4; + end; + end; + +begin + Result := False; + ImageCount := 1; + FLoadedMipMapCount := 1; + FLoadedDepth := 1; + FLoadedVolume := False; + FLoadedCubeMap := False; + ZeroMemory(@HdrDX10, SizeOf(HdrDX10)); + + with GetIO, Hdr, Hdr.Desc.PixelFormat do + begin + Read(Handle, @Hdr, SizeOf(Hdr)); + + SrcFormat := ifUnknown; + NeedsSwapChannels := False; + + // Get image data format + if (Flags and DDPF_FOURCC) = DDPF_FOURCC then + begin + if FourCC = FOURCC_DX10 then + begin + Read(Handle, @HdrDX10, SizeOf(HdrDX10)); + SrcFormat := FindDX10Format(HdrDX10.DXGIFormat, NeedsSwapChannels); + FMetadata.SetMetaItem(SMetaDdsDxgiFormat, HdrDX10.DXGIFormat); + FMetadata.SetMetaItem(SMetaDdsArraySize, HdrDX10.ArraySize); + end + else + SrcFormat := FindFourCCFormat(FourCC); + end + else if (Flags and DDPF_RGB) = DDPF_RGB then + begin + // Handle RGB formats + if (Flags and DDPF_ALPHAPIXELS) = DDPF_ALPHAPIXELS then + begin + // Handle RGB with alpha formats + case BitCount of + 16: + begin + if MasksEqual(Desc.PixelFormat, GetFormatInfo(ifA4R4G4B4).PixelFormat) then + SrcFormat := ifA4R4G4B4; + if MasksEqual(Desc.PixelFormat, GetFormatInfo(ifA1R5G5B5).PixelFormat) then + SrcFormat := ifA1R5G5B5; + end; + 32: + begin + SrcFormat := ifA8R8G8B8; + if BlueMask = $00FF0000 then + NeedsSwapChannels := True; + end; + end; + end + else + begin + // Handle RGB without alpha formats + case BitCount of + 8: + if MasksEqual(Desc.PixelFormat, + GetFormatInfo(ifR3G3B2).PixelFormat) then + SrcFormat := ifR3G3B2; + 16: + begin + if MasksEqual(Desc.PixelFormat, + GetFormatInfo(ifX4R4G4B4).PixelFormat) then + SrcFormat := ifX4R4G4B4; + if MasksEqual(Desc.PixelFormat, + GetFormatInfo(ifX1R5G5B5).PixelFormat) then + SrcFormat := ifX1R5G5B5; + if MasksEqual(Desc.PixelFormat, + GetFormatInfo(ifR5G6B5).PixelFormat) then + SrcFormat := ifR5G6B5; + end; + 24: SrcFormat := ifR8G8B8; + 32: + begin + SrcFormat := ifX8R8G8B8; + if BlueMask = $00FF0000 then + NeedsSwapChannels := True; + end; + end; + end; + end + else if (Flags and DDPF_LUMINANCE) = DDPF_LUMINANCE then + begin + // Handle luminance formats + if (Flags and DDPF_ALPHAPIXELS) = DDPF_ALPHAPIXELS then + begin + // Handle luminance with alpha formats + if BitCount = 16 then + SrcFormat := ifA8Gray8; + end + else + begin + // Handle luminance without alpha formats + case BitCount of + 8: SrcFormat := ifGray8; + 16: SrcFormat := ifGray16; + end; + end; + end + else if (Flags and DDPF_BUMPLUMINANCE) = DDPF_BUMPLUMINANCE then + begin + // Handle mixed bump-luminance formats like D3DFMT_X8L8V8U8 + case BitCount of + 32: + if BlueMask = $00FF0000 then + begin + SrcFormat := ifX8R8G8B8; // D3DFMT_X8L8V8U8 + NeedsSwapChannels := True; + end; + end; + end + else if (Flags and DDPF_BUMPDUDV) = DDPF_BUMPDUDV then + begin + // Handle bumpmap formats like D3DFMT_Q8W8V8U8 + case BitCount of + 16: SrcFormat := ifA8Gray8; // D3DFMT_V8U8 + 32: + if AlphaMask = $FF000000 then + begin + SrcFormat := ifA8R8G8B8; // D3DFMT_Q8W8V8U8 + NeedsSwapChannels := True; + end; + 64: SrcFormat := ifA16B16G16R16; // D3DFMT_Q16W16V16U16 + end; + end; + + // If DDS format is not supported we will exit + if SrcFormat = ifUnknown then + Exit; + + // File contains mipmaps for each subimage. + { Some DDS writers ignore setting proper Caps and Flags so + this check is not usable: + if ((Desc.Caps.Caps1 and DDSCAPS_MIPMAP) = DDSCAPS_MIPMAP) and + ((Desc.Flags and DDSD_MIPMAPCOUNT) = DDSD_MIPMAPCOUNT) then} + if Desc.MipMaps > 1 then + begin + FLoadedMipMapCount := Desc.MipMaps; + FMetadata.SetMetaItem(SMetaDdsMipMapCount, Desc.MipMaps); + ImageCount := Desc.MipMaps; + end; + + // File stores volume texture + if ((Desc.Caps.Caps2 and DDSCAPS2_VOLUME) = DDSCAPS2_VOLUME) and + ((Desc.Flags and DDSD_DEPTH) = DDSD_DEPTH) then + begin + FLoadedVolume := True; + FLoadedDepth := Desc.Depth; + ImageCount := GetVolumeLevelCount(Desc.Depth, ImageCount); + end; + + // File stores cube texture + if (Desc.Caps.Caps2 and DDSCAPS2_CUBEMAP) = DDSCAPS2_CUBEMAP then + begin + FLoadedCubeMap := True; + I := 0; + if (Desc.Caps.Caps2 and DDSCAPS2_POSITIVEX) = DDSCAPS2_POSITIVEX then Inc(I); + if (Desc.Caps.Caps2 and DDSCAPS2_POSITIVEY) = DDSCAPS2_POSITIVEY then Inc(I); + if (Desc.Caps.Caps2 and DDSCAPS2_POSITIVEZ) = DDSCAPS2_POSITIVEZ then Inc(I); + if (Desc.Caps.Caps2 and DDSCAPS2_NEGATIVEX) = DDSCAPS2_NEGATIVEX then Inc(I); + if (Desc.Caps.Caps2 and DDSCAPS2_NEGATIVEY) = DDSCAPS2_NEGATIVEY then Inc(I); + if (Desc.Caps.Caps2 and DDSCAPS2_NEGATIVEZ) = DDSCAPS2_NEGATIVEZ then Inc(I); + FLoadedDepth := I; + ImageCount := ImageCount * I; + end; + + // Allocate and load all images in file + FmtInfo := GetFormatInfo(SrcFormat); + SetLength(Images, ImageCount); + + // Compute the pitch or get if from file if present + UseAsPitch := (Desc.Flags and DDSD_PITCH) = DDSD_PITCH; + UseAsLinear := (Desc.Flags and DDSD_LINEARSIZE) = DDSD_LINEARSIZE; + // Use linear as default if none is set + if not UseAsPitch and not UseAsLinear then + UseAsLinear := True; + // Main image pitch or linear size + PitchOrLinear := Desc.PitchOrLinearSize; + + // Check: some writers just write garbage to pitch/linear size fields and flags + MainImageLinearSize := FmtInfo.GetPixelsSize(SrcFormat, Desc.Width, Desc.Height); + if UseAsLinear and ((PitchOrLinear < MainImageLinearSize) or + (PitchOrLinear * Integer(Desc.Height) = MainImageLinearSize)) then + begin + // Explicitly set linear size + PitchOrLinear := MainImageLinearSize; + end; + + for I := 0 to ImageCount - 1 do + begin + // Compute dimensions of surrent subimage based on texture type and + // number of mipmaps + ComputeSubDimensions(I, Desc.Width, Desc.Height, Desc.MipMaps, Desc.Depth, + FLoadedCubeMap, FLoadedVolume, CurrentWidth, CurrentHeight); + NewImage(CurrentWidth, CurrentHeight, SrcFormat, Images[I]); + + if (I > 0) or (PitchOrLinear = 0) then + begin + // Compute pitch or linear size for mipmap levels, or even for main image + // since some formats do not fill pitch nor size + if UseAsLinear then + PitchOrLinear := FmtInfo.GetPixelsSize(SrcFormat, CurrentWidth, CurrentHeight) + else + PitchOrLinear := (CurrentWidth * FmtInfo.BytesPerPixel + 3) div 4 * 4; // must be DWORD aligned + end; + + if UseAsLinear then + LoadSize := PitchOrLinear + else + LoadSize := CurrentHeight * PitchOrLinear; + + if UseAsLinear or (LoadSize = Images[I].Size) then + begin + // If DDS does not use Pitch we can simply copy data + Read(Handle, Images[I].Bits, LoadSize) + end + else + begin + // If DDS uses Pitch we must load aligned scanlines + // and then remove padding + GetMem(Data, LoadSize); + try + Read(Handle, Data, LoadSize); + RemovePadBytes(Data, Images[I].Bits, CurrentWidth, CurrentHeight, + FmtInfo.BytesPerPixel, PitchOrLinear); + finally + FreeMem(Data); + end; + end; + + if NeedsSwapChannels then + SwapChannels(Images[I], ChannelRed, ChannelBlue); + end; + Result := True; + end; +end; + +function TDDSFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +var + Hdr: TDDSFileHeader; + MainImage, ImageToSave: TImageData; + I, MainIdx, Len, ImageCount: LongInt; + J: LongWord; + FmtInfo: TImageFormatInfo; + MustBeFreed: Boolean; + Is2DTexture, IsCubeMap, IsVolume: Boolean; + MipMapCount, CurrentWidth, CurrentHeight: LongInt; + NeedsResize: Boolean; + NeedsConvert: Boolean; +begin + Result := False; + FillChar(Hdr, Sizeof(Hdr), 0); + + MainIdx := FFirstIdx; + Len := FLastIdx - MainIdx + 1; + // Some DDS saving rules: + // 2D textures: Len is used as mipmap count (FSaveMipMapCount not used!). + // Cube maps: FSaveDepth * FSaveMipMapCount images are used, if Len is + // smaller than this file is saved as regular 2D texture. + // Volume maps: GetVolumeLevelCount(FSaveDepth, FSaveMipMapCount) images are + // used, if Len is smaller than this file is + // saved as regular 2D texture. + + IsCubeMap := FSaveCubeMap; + IsVolume := FSaveVolume; + MipMapCount := FSaveMipMapCount; + + if IsCubeMap then + begin + // Check if we have enough images on Input to save cube map + if Len < FSaveDepth * FSaveMipMapCount then + IsCubeMap := False; + end + else if IsVolume then + begin + // Check if we have enough images on Input to save volume texture + if Len < GetVolumeLevelCount(FSaveDepth, FSaveMipMapCount) then + IsVolume := False; + end; + + Is2DTexture := not IsCubeMap and not IsVolume; + if Is2DTexture then + begin + // Get number of mipmaps used with 2D texture + MipMapCount := Min(Len, GetNumMipMapLevels(Images[MainIdx].Width, Images[MainIdx].Height)); + end; + + // we create compatible main image and fill headers + if MakeCompatible(Images[MainIdx], MainImage, MustBeFreed) then + with GetIO, MainImage, Hdr do + try + FmtInfo := GetFormatInfo(Format); + Magic := DDSMagic; + Desc.Size := SizeOf(Desc); + Desc.Width := Width; + Desc.Height := Height; + Desc.Flags := DDS_SAVE_FLAGS; + Desc.Caps.Caps1 := DDSCAPS_TEXTURE; + Desc.PixelFormat.Size := SizeOf(Desc.PixelFormat); + Desc.PitchOrLinearSize := MainImage.Size; + ImageCount := MipMapCount; + + if MipMapCount > 1 then + begin + // Set proper flags if we have some mipmaps to be saved + Desc.Flags := Desc.Flags or DDSD_MIPMAPCOUNT; + Desc.Caps.Caps1 := Desc.Caps.Caps1 or DDSCAPS_MIPMAP or DDSCAPS_COMPLEX; + Desc.MipMaps := MipMapCount; + end; + + if IsCubeMap then + begin + // Set proper cube map flags - number of stored faces is taken + // from FSaveDepth + Desc.Caps.Caps1 := Desc.Caps.Caps1 or DDSCAPS_COMPLEX; + Desc.Caps.Caps2 := Desc.Caps.Caps2 or DDSCAPS2_CUBEMAP; + J := DDSCAPS2_POSITIVEX; + for I := 0 to FSaveDepth - 1 do + begin + Desc.Caps.Caps2 := Desc.Caps.Caps2 or J; + J := J shl 1; + end; + ImageCount := FSaveDepth * FSaveMipMapCount; + end + else if IsVolume then + begin + // Set proper flags for volume texture + Desc.Flags := Desc.Flags or DDSD_DEPTH; + Desc.Caps.Caps1 := Desc.Caps.Caps1 or DDSCAPS_COMPLEX; + Desc.Caps.Caps2 := Desc.Caps.Caps2 or DDSCAPS2_VOLUME; + Desc.Depth := FSaveDepth; + ImageCount := GetVolumeLevelCount(FSaveDepth, FSaveMipMapCount); + end; + + // Now we set DDS pixel format for main image + if FmtInfo.IsSpecial or FmtInfo.IsFloatingPoint or + (FmtInfo.BytesPerPixel > 4) then + begin + Desc.PixelFormat.Flags := DDPF_FOURCC; + case Format of + ifA16B16G16R16: Desc.PixelFormat.FourCC := D3DFMT_A16B16G16R16; + ifR32F: Desc.PixelFormat.FourCC := D3DFMT_R32F; + ifA32B32G32R32F: Desc.PixelFormat.FourCC := D3DFMT_A32B32G32R32F; + ifR16F: Desc.PixelFormat.FourCC := D3DFMT_R16F; + ifA16B16G16R16F: Desc.PixelFormat.FourCC := D3DFMT_A16B16G16R16F; + ifDXT1: Desc.PixelFormat.FourCC := FOURCC_DXT1; + ifDXT3: Desc.PixelFormat.FourCC := FOURCC_DXT3; + ifDXT5: Desc.PixelFormat.FourCC := FOURCC_DXT5; + ifATI1N: Desc.PixelFormat.FourCC := FOURCC_ATI1; + ifATI2N: Desc.PixelFormat.FourCC := FOURCC_ATI2; + end; + end + else if FmtInfo.HasGrayChannel then + begin + Desc.PixelFormat.Flags := DDPF_LUMINANCE; + Desc.PixelFormat.BitCount := FmtInfo.BytesPerPixel * 8; + case Format of + ifGray8: Desc.PixelFormat.RedMask := 255; + ifGray16: Desc.PixelFormat.RedMask := 65535; + ifA8Gray8: + begin + Desc.PixelFormat.Flags := Desc.PixelFormat.Flags or DDPF_ALPHAPIXELS; + Desc.PixelFormat.RedMask := 255; + Desc.PixelFormat.AlphaMask := 65280; + end; + end; + end + else + begin + Desc.PixelFormat.Flags := DDPF_RGB; + Desc.PixelFormat.BitCount := FmtInfo.BytesPerPixel * 8; + if FmtInfo.HasAlphaChannel then + begin + Desc.PixelFormat.Flags := Desc.PixelFormat.Flags or DDPF_ALPHAPIXELS; + Desc.PixelFormat.AlphaMask := $FF000000; + end; + if FmtInfo.BytesPerPixel > 2 then + begin + Desc.PixelFormat.RedMask := $00FF0000; + Desc.PixelFormat.GreenMask := $0000FF00; + Desc.PixelFormat.BlueMask := $000000FF; + end + else + begin + Desc.PixelFormat.AlphaMask := FmtInfo.PixelFormat.ABitMask; + Desc.PixelFormat.RedMask := FmtInfo.PixelFormat.RBitMask; + Desc.PixelFormat.GreenMask := FmtInfo.PixelFormat.GBitMask; + Desc.PixelFormat.BlueMask := FmtInfo.PixelFormat.BBitMask; + end; + end; + + // Header and main image are written to output + Write(Handle, @Hdr, SizeOf(Hdr)); + Write(Handle, MainImage.Bits, MainImage.Size); + + // Write the rest of the images and convert them to + // the same format as main image if necessary and ensure proper mipmap + // simensions too. + for I := MainIdx + 1 to MainIdx + ImageCount - 1 do + begin + // Get proper dimensions for this level + ComputeSubDimensions(I, Desc.Width, Desc.Height, Desc.MipMaps, Desc.Depth, + IsCubeMap, IsVolume, CurrentWidth, CurrentHeight); + + // Check if input image for this level has the right size and format + NeedsResize := not ((Images[I].Width = CurrentWidth) and (Images[I].Height = CurrentHeight)); + NeedsConvert := not (Images[I].Format = Format); + + if NeedsResize or NeedsConvert then + begin + // Input image must be resized or converted to different format + // to become valid mipmap level + InitImage(ImageToSave); + CloneImage(Images[I], ImageToSave); + if NeedsConvert then + ConvertImage(ImageToSave, Format); + if NeedsResize then + ResizeImage(ImageToSave, CurrentWidth, CurrentHeight, rfBilinear); + end + else + // Input image can be used without any changes + ImageToSave := Images[I]; + + // Write level data and release temp image if necessary + Write(Handle, ImageToSave.Bits, ImageToSave.Size); + if Images[I].Bits <> ImageToSave.Bits then + FreeImage(ImageToSave); + end; + + Result := True; + finally + if MustBeFreed then + FreeImage(MainImage); + end; +end; + +procedure TDDSFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if Info.IsIndexed or Info.IsSpecial then + // convert indexed and unsupported special formatd to A8R8G8B8 + ConvFormat := ifA8R8G8B8 + else if Info.IsFloatingPoint then + begin + if Info.Format = ifA16R16G16B16F then + // only swap channels here + ConvFormat := ifA16B16G16R16F + else + // convert other floating point formats to A32B32G32R32F + ConvFormat := ifA32B32G32R32F + end + else if Info.HasGrayChannel then + begin + if Info.HasAlphaChannel then + // convert grayscale with alpha to A8Gray8 + ConvFormat := ifA8Gray8 + else if Info.BytesPerPixel = 1 then + // convert 8bit grayscale to Gray8 + ConvFormat := ifGray8 + else + // convert 16-64bit grayscales to Gray16 + ConvFormat := ifGray16; + end + else if Info.BytesPerPixel > 4 then + ConvFormat := ifA16B16G16R16 + else if Info.HasAlphaChannel then + // convert the other images with alpha channel to A8R8G8B8 + ConvFormat := ifA8R8G8B8 + else + // convert the other formats to X8R8G8B8 + ConvFormat := ifX8R8G8B8; + + ConvertImage(Image, ConvFormat); +end; + +function TDDSFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Hdr: TDDSFileHeader; + ReadCount: LongInt; +begin + Result := False; + if Handle <> nil then + with GetIO do + begin + ReadCount := Read(Handle, @Hdr, SizeOf(Hdr)); + Seek(Handle, -ReadCount, smFromCurrent); + Result := (Hdr.Magic = DDSMagic) and (ReadCount = SizeOf(Hdr)) and + ((Hdr.Desc.Caps.Caps1 and DDSCAPS_TEXTURE) = DDSCAPS_TEXTURE); + end; +end; + +initialization + RegisterImageFileFormat(TDDSFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 ---------------------------------------------------- + - Texture and D3D specific info stored in DDS is now available as metadata + (loading). + - Added support for loading DDS files with DX10 extension + (http://msdn.microsoft.com/en-us/library/windows/desktop/bb943991(v=vs.85).aspx) + and few compatibility fixes. + + -- 0.25.0 Changes/Bug Fixes --------------------------------- + - Added support for 3Dc ATI1/2 formats. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Saved DDS with mipmaps now correctly defineds COMPLEX flag. + - Fixed loading of RGB DDS files that use pitch and have mipmaps - + mipmaps were loaded wrongly. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Changed saving behaviour a bit: mipmaps are inlcuded automatically for + 2D textures if input image array has more than 1 image (no need to + set SaveMipMapCount manually). + - Mipmap levels are now saved with proper dimensions when saving DDS files. + - Made some changes to not be so strict when loading DDS files. + Many programs seem to save them in non-standard format + (by MS DDS File Reference). + - Added missing ifX8R8G8B8 to SupportedFormats, MakeCompatible failed + when image was converted to this format (inside). + - MakeCompatible method moved to base class, put ConvertToSupported here. + GetSupportedFormats removed, it is now set in constructor. + - Fixed bug that sometimes saved non-standard DDS files and another + one that caused crash when these files were loaded. + - Changed extensions to filename masks. + - Changed SaveData, LoadData, and MakeCompatible methods according + to changes in base class in Imaging unit. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - added support for half-float image formats + - change in LoadData to allow support for more images + in one stream loading + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - fixed bug in TestFormat which does not recognize many DDS files + - changed pitch/linearsize handling in DDS loading code to + load DDS files produced by NVidia's Photoshop plugin +} + +end. diff --git a/src/lib/vampimg/ImagingExtras.pas b/src/lib/vampimg/ImagingExtras.pas new file mode 100644 index 0000000..d32f0f9 --- /dev/null +++ b/src/lib/vampimg/ImagingExtras.pas @@ -0,0 +1,153 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This is helper unit that registers all image file formats in Extras package + to Imaging core loading and saving functions. Just put this unit in your uses + clause instead of adding every unit that provides new file format support. + Also new constants for SetOption/GetOption functions for new file formats + are located here.} +unit ImagingExtras; + +{$I ImagingOptions.inc} + +{$DEFINE DONT_LINK_JPEG2000} // link support for JPEG2000 images +{$DEFINE DONT_LINK_TIFF} // link support for TIFF images +//{$DEFINE DONT_LINK_PSD} // link support for PSD images +//{$DEFINE DONT_LINK_PCX} // link support for PCX images +//{$DEFINE DONT_LINK_XPM} // link support for XPM images +//{$IFNDEF FULL_FEATURE_SET} + {$DEFINE DONT_LINK_ELDER} // link support for Elder Imagery images +//{$ENDIF} + +{$IF not ( + (Defined(DCC) and Defined(CPUX86) and not Defined(MACOS)) or + (Defined(FPC) and not Defined(MSDOS) and + ((Defined(CPUX86) and (Defined(LINUX) or Defined(WIN32) or Defined(MACOS)) or + (Defined(CPUX64) and Defined(LINUX))))) + )} + // JPEG2000 only for 32bit Windows/Linux/OSX and for 64bit Unix with FPC + {$DEFINE DONT_LINK_JPEG2000} +{$IFEND} + +{$IF not (Defined(DCC) and Defined(CPUX86) and not Defined(MACOS))} + {$DEFINE DONT_LINK_TIFF} // Only for Delphi now +{$IFEND} + +interface + +const + { Those are new options for GetOption/SetOption interface. } + + { Controls JPEG 2000 lossy compression quality. It is number in range 1..100. + 1 means small/ugly file, 100 means large/nice file. Default is 80.} + ImagingJpeg2000Quality = 55; + { Controls whether JPEG 2000 image is saved with full file headers or just + as code stream. Default value is False (0).} + ImagingJpeg2000CodeStreamOnly = 56; + { Specifies JPEG 2000 image compression type. If True (1), saved JPEG 2000 files + will be losslessly compressed. Otherwise lossy compression is used. + Default value is False (0).} + ImagingJpeg2000LosslessCompression = 57; + { Specifies compression scheme used when saving TIFF images. Supported values + are 0 (Uncompressed), 1 (LZW), 2 (PackBits RLE), 3 (Deflate - ZLib), 4 (JPEG), + 5 (CCITT Group 4 fax encoding - for binary images only). + Default is 1 (LZW). Note that not all images can be stored with + JPEG compression - these images will be saved with default compression if + JPEG is set.} + ImagingTiffCompression = 65; + { Controls compression quality when selected TIFF compression is Jpeg. + It is number in range 1..100. 1 means small/ugly file, + 100 means large/nice file. Accessible trough ImagingTiffJpegQuality option.} + ImagingTiffJpegQuality = 66; + { When activated (True = 1) existing TIFF files are not overwritten when saving but + new images are instead appended thus producing multipage TIFFs. + Default value is False (0).} + ImagingTiffAppendMode = 67; + { If enabled image data is saved as layer of PSD file. This is required + to get proper transparency when opened in Photoshop for images with + alpha data (will be opened with one layer, RGB color channels, and transparency). + If you don't need this Photoshop compatibility turn this option off as you'll get + smaller file (will be opened in PS as background raster with RGBA channels). + Default value is True (1). } + ImagingPSDSaveAsLayer = 70; + +implementation + +uses +{$IFNDEF DONT_LINK_JPEG2000} + ImagingJpeg2000, +{$ENDIF} +{$IFNDEF DONT_LINK_TIFF} + ImagingLibTiffDelphi, +{$ENDIF} +{$IFNDEF DONT_LINK_PSD} + ImagingPsd, +{$ENDIF} +{$IFNDEF DONT_LINK_PCX} + ImagingPcx, +{$ENDIF} +{$IFNDEF DONT_LINK_XPM} + ImagingXpm, +{$ENDIF} +{$IFNDEF DONT_LINK_ELDER} + ElderImagery, +{$ENDIF} + Imaging; + +{ + File Notes: + + -- TODOS ----------------------------------------------------- + - nothing now + + -- 0.77 ----------------------------------------------------- + - Added ImagingTiffAppendMode option. + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Added Group 4 Fax encoding as compression for TIFF files. + - Added ImagingTiffJpegQuality option. + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Allowed JPEG2000 for Mac OS X x86 + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - ElderImagery formats are disabled by default, TIFF enabled. + - Changed _LINK_ symbols according to changes in ImagingOptions.inc. + + -- 0.24.1 Changes/Bug Fixes --------------------------------- + - Allowed JPEG2000 for x86_64 CPUS in Linux + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Better IF conditional to disable JPEG2000 on unsupported platforms. + - Added PSD and TIFF related stuff. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Created with initial stuff. + +} + +end. diff --git a/src/lib/vampimg/ImagingFormats.pas b/src/lib/vampimg/ImagingFormats.pas new file mode 100644 index 0000000..b42b4ac --- /dev/null +++ b/src/lib/vampimg/ImagingFormats.pas @@ -0,0 +1,4516 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit manages information about all image data formats and contains + low level format conversion, manipulation, and other related functions.} +unit ImagingFormats; + +{$I ImagingOptions.inc} + +interface + +uses + ImagingTypes, Imaging, ImagingUtility; + +type + TImageFormatInfoArray = array[TImageFormat] of PImageFormatInfo; + PImageFormatInfoArray = ^TImageFormatInfoArray; + + +{ Additional image manipulation functions (usually used internally by Imaging unit) } + +type + { Color reduction operations.} + TReduceColorsAction = (raCreateHistogram, raUpdateHistogram, raMakeColorMap, + raMapImage); + TReduceColorsActions = set of TReduceColorsAction; +const + AllReduceColorsActions = [raCreateHistogram, raUpdateHistogram, + raMakeColorMap, raMapImage]; +{ Reduces the number of colors of source. Src is bits of source image + (ARGB or floating point) and Dst is in some indexed format. MaxColors + is the number of colors to which reduce and DstPal is palette to which + the resulting colors are written and it must be allocated to at least + MaxColors entries. ChannelMask is 'anded' with every pixel's channel value + when creating color histogram. If $FF is used all 8bits of color channels + are used which can be slow for large images with many colors so you can + use lower masks to speed it up.} +procedure ReduceColorsMedianCut(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; MaxColors: LongInt; ChannelMask: Byte; + DstPal: PPalette32; Actions: TReduceColorsActions = AllReduceColorsActions); +{ Stretches rectangle in source image to rectangle in destination image + using nearest neighbor filtering. It is fast but results look blocky + because there is no interpolation used. SrcImage and DstImage must be + in the same data format. Works for all data formats except special formats.} +procedure StretchNearest(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt); +type + { Built-in sampling filters.} + TSamplingFilter = (sfNearest, sfLinear, sfCosine, sfHermite, sfQuadratic, + sfGaussian, sfSpline, sfLanczos, sfMitchell, sfCatmullRom); + { Type of custom sampling function} + TFilterFunction = function(Value: Single): Single; +const + { Default resampling filter used for bicubic resizing.} + DefaultCubicFilter = sfCatmullRom; +var + { Built-in filter functions.} + SamplingFilterFunctions: array[TSamplingFilter] of TFilterFunction; + { Default radii of built-in filter functions.} + SamplingFilterRadii: array[TSamplingFilter] of Single; + +{ Stretches rectangle in source image to rectangle in destination image + with resampling. One of built-in resampling filters defined by + Filter is used. Set WrapEdges to True for seamlessly tileable images. + SrcImage and DstImage must be in the same data format. + Works for all data formats except special and indexed formats.} +procedure StretchResample(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt; Filter: TSamplingFilter; WrapEdges: Boolean = False); overload; +{ Stretches rectangle in source image to rectangle in destination image + with resampling. You can use custom sampling function and filter radius. + Set WrapEdges to True for seamlessly tileable images. SrcImage and DstImage + must be in the same data format. + Works for all data formats except special and indexed formats.} +procedure StretchResample(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt; Filter: TFilterFunction; Radius: Single; + WrapEdges: Boolean = False); overload; +{ Helper for functions that create mipmap levels. BiggerLevel is + valid image and SmallerLevel is empty zeroed image. SmallerLevel is created + with Width and Height dimensions and it is filled with pixels of BiggerLevel + using resampling filter specified by ImagingMipMapFilter option. + Uses StretchNearest and StretchResample internally so the same image data format + limitations apply.} +procedure FillMipMapLevel(const BiggerLevel: TImageData; Width, Height: LongInt; + var SmallerLevel: TImageData); + + +{ Various helper & support functions } + +{ Copies Src pixel to Dest pixel. It is faster than System.Move procedure.} +procedure CopyPixel(Src, Dest: Pointer; BytesPerPixel: LongInt); {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Compares Src pixel and Dest pixel. It is faster than SysUtils.CompareMem function.} +function ComparePixels(PixelA, PixelB: Pointer; BytesPerPixel: LongInt): Boolean; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Translates pixel color in SrcFormat to DstFormat.} +procedure TranslatePixel(SrcPixel, DstPixel: Pointer; SrcFormat, + DstFormat: TImageFormat; SrcPalette, DstPalette: PPalette32); +{ Clamps floating point pixel channel values to [0.0, 1.0] range.} +procedure ClampFloatPixel(var PixF: TColorFPRec); {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Helper function that converts pixel in any format to 32bit ARGB pixel. + For common formats it's faster than calling GetPixel32 etc.} +procedure ConvertToPixel32(SrcPix: PByte; DestPix: PColor32Rec; + const SrcInfo: TImageFormatInfo; SrcPalette: PPalette32 = nil); {$IFDEF USE_INLINE}inline;{$ENDIF} + +{ Adds padding bytes at the ends of scanlines. Bpp is the number of bytes per + pixel of source and WidthBytes is the number of bytes per scanlines of dest.} +procedure AddPadBytes(DataIn: Pointer; DataOut: Pointer; Width, Height, + Bpp, WidthBytes: LongInt); +{ Removes padding from image with scanlines that have aligned sizes. Bpp is + the number of bytes per pixel of dest and WidthBytes is the number of bytes + per scanlines of source.} +procedure RemovePadBytes(DataIn: Pointer; DataOut: Pointer; Width, Height, + Bpp, WidthBytes: LongInt); + +{ Converts 1bit image data to 8bit. Used mostly by file loaders for formats + supporting 1bit images. Scaling of pixel values to 8bits is optional + (indexed formats don't need this).} +procedure Convert1To8(DataIn, DataOut: PByte; Width, Height, + WidthBytes: LongInt; ScaleTo8Bits: Boolean); +{ Converts 2bit image data to 8bit. Used mostly by file loaders for formats + supporting 2bit images. Scaling of pixel values to 8bits is optional + (indexed formats don't need this).} +procedure Convert2To8(DataIn, DataOut: PByte; Width, Height, + WidthBytes: LongInt; ScaleTo8Bits: Boolean); +{ Converts 4bit image data to 8bit. Used mostly by file loaders for formats + supporting 4bit images. Scaling of pixel values to 8bits is optional + (indexed formats don't need this).} +procedure Convert4To8(DataIn, DataOut: PByte; Width, Height, + WidthBytes: LongInt; ScaleTo8Bits: Boolean); + +{ Helper function for image file loaders. Some 15 bit images (targas, bitmaps) + may contain 1 bit alpha but there is no indication of it. This function checks + all 16 bit(should be X1R5G5B5 or A1R5G5B5 format) pixels and some of them have + alpha bit set it returns True, otherwise False.} +function Has16BitImageAlpha(NumPixels: LongInt; Data: PWord): Boolean; +{ Helper function for image file loaders. This function checks is similar + to Has16BitImageAlpha but works with A8R8G8B8/X8R8G8B8 format.} +function Has32BitImageAlpha(NumPixels: LongInt; Data: PLongWord): Boolean; +{ Checks if there is any relevant alpha data (any entry has alpha <> 255) + in the given palette.} +function PaletteHasAlpha(Palette: PPalette32; PaletteEntries: Integer): Boolean; + +{ Provides indexed access to each line of pixels. Does not work with special + format images.} +function GetScanLine(ImageBits: Pointer; const FormatInfo: TImageFormatInfo; + LineWidth, Index: LongInt): Pointer; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns True if Format is valid image data format identifier.} +function IsImageFormatValid(Format: TImageFormat): Boolean; + +{ Converts 16bit half floating point value to 32bit Single.} +function HalfToFloat(Half: THalfFloat): Single; +{ Converts 32bit Single to 16bit half floating point.} +function FloatToHalf(Float: Single): THalfFloat; + +{ Converts half float color value to single-precision floating point color.} +function ColorHalfToFloat(ColorHF: TColorHFRec): TColorFPRec; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Converts single-precision floating point color to half float color.} +function ColorFloatToHalf(ColorFP: TColorFPRec): TColorHFRec; {$IFDEF USE_INLINE}inline;{$ENDIF} + +{ Makes image PalEntries x 1 big where each pixel has color of one pal entry.} +procedure VisualizePalette(Pal: PPalette32; Entries: Integer; out PalImage: TImageData); + +type + TPointRec = record + Pos: LongInt; + Weight: Single; + end; + TCluster = array of TPointRec; + TMappingTable = array of TCluster; + +{ Helper function for resampling.} +function BuildMappingTable(DstLow, DstHigh, SrcLow, SrcHigh, SrcImageWidth: LongInt; + Filter: TFilterFunction; Radius: Single; WrapEdges: Boolean): TMappingTable; +{ Helper function for resampling.} +procedure FindExtremes(const Map: TMappingTable; var MinPos, MaxPos: LongInt); + + +{ Pixel readers/writers for different image formats } + +{ Returns pixel of image in any ARGB format. Channel values are scaled to 16 bits.} +procedure ChannelGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Pix: TColor64Rec); +{ Sets pixel of image in any ARGB format. Channel values must be scaled to 16 bits.} +procedure ChannelSetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + const Pix: TColor64Rec); + +{ Returns pixel of image in any grayscale format. Gray value is scaled to 64 bits + and alpha to 16 bits.} +procedure GrayGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Gray: TColor64Rec; var Alpha: Word); +{ Sets pixel of image in any grayscale format. Gray value must be scaled to 64 bits + and alpha to 16 bits.} +procedure GraySetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + const Gray: TColor64Rec; Alpha: Word); + +{ Returns pixel of image in any floating point format. Channel values are + in range <0.0, 1.0>.} +procedure FloatGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Pix: TColorFPRec); +{ Sets pixel of image in any floating point format. Channel values must be + in range <0.0, 1.0>.} +procedure FloatSetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + const Pix: TColorFPRec); + +{ Returns pixel of image in any indexed format. Returned value is index to + the palette.} +procedure IndexGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Index: LongWord); +{ Sets pixel of image in any indexed format. Index is index to the palette.} +procedure IndexSetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + Index: LongWord); + + +{ Pixel readers/writers for 32bit and FP colors} + +{ Function for getting pixel colors. Native pixel is read from Image and + then translated to 32 bit ARGB.} +function GetPixel32Generic(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32): TColor32Rec; +{ Procedure for setting pixel colors. Input 32 bit ARGB color is translated to + native format and then written to Image.} +procedure SetPixel32Generic(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32; const Color: TColor32Rec); +{ Function for getting pixel colors. Native pixel is read from Image and + then translated to FP ARGB.} +function GetPixelFPGeneric(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32): TColorFPRec; +{ Procedure for setting pixel colors. Input FP ARGB color is translated to + native format and then written to Image.} +procedure SetPixelFPGeneric(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32; const Color: TColorFPRec); + + +{ Image format conversion functions } + +{ Converts any ARGB format to any ARGB format.} +procedure ChannelToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any ARGB format to any grayscale format.} +procedure ChannelToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any ARGB format to any floating point format.} +procedure ChannelToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any ARGB format to any indexed format.} +procedure ChannelToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; DstPal: PPalette32); + +{ Converts any grayscale format to any grayscale format.} +procedure GrayToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any grayscale format to any ARGB format.} +procedure GrayToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any grayscale format to any floating point format.} +procedure GrayToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any grayscale format to any indexed format.} +procedure GrayToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; DstPal: PPalette32); + +{ Converts any floating point format to any floating point format.} +procedure FloatToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any floating point format to any ARGB format.} +procedure FloatToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any floating point format to any grayscale format.} +procedure FloatToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +{ Converts any floating point format to any indexed format.} +procedure FloatToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; DstPal: PPalette32); + +{ Converts any indexed format to any indexed format.} +procedure IndexToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal, DstPal: PPalette32); +{ Converts any indexed format to any ARGB format.} +procedure IndexToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal: PPalette32); +{ Converts any indexed format to any grayscale format.} +procedure IndexToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal: PPalette32); +{ Converts any indexed format to any floating point format.} +procedure IndexToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal: PPalette32); + + +{ Color constructor functions } + +{ Constructs TColor24Rec color.} +function Color24(R, G, B: Byte): TColor24Rec; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Constructs TColor32Rec color.} +function Color32(A, R, G, B: Byte): TColor32Rec; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Constructs TColor48Rec color.} +function Color48(R, G, B: Word): TColor48Rec; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Constructs TColor64Rec color.} +function Color64(A, R, G, B: Word): TColor64Rec; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Constructs TColorFPRec color.} +function ColorFP(A, R, G, B: Single): TColorFPRec; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Constructs TColorHFRec color.} +function ColorHF(A, R, G, B: THalfFloat): TColorHFRec; {$IFDEF USE_INLINE}inline;{$ENDIF} + + +{ Special formats conversion functions } + +{ Converts image to/from/between special image formats (dxtc, ...).} +procedure ConvertSpecial(var Image: TImageData; SrcInfo, + DstInfo: PImageFormatInfo); + + +{ Inits all image format information. Called internally on startup.} +procedure InitImageFormats(var Infos: TImageFormatInfoArray); + +const + // Grayscale conversion channel weights + GrayConv: TColorFPRec = (B: 0.114; G: 0.587; R: 0.299; A: 0.0); + + // Contants for converting integer colors to floating point + OneDiv8Bit: Single = 1.0 / 255.0; + OneDiv16Bit: Single = 1.0 / 65535.0; + +implementation + +{ TImageFormatInfo member functions } + +{ Returns size in bytes of image in given standard format where + Size = Width * Height * Bpp.} +function GetStdPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; forward; +{ Checks if Width and Height are valid for given standard format.} +procedure CheckStdDimensions(Format: TImageFormat; var Width, Height: LongInt); forward; +{ Returns size in bytes of image in given DXT format.} +function GetDXTPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; forward; +{ Checks if Width and Height are valid for given DXT format. If they are + not valid, they are changed to pass the check.} +procedure CheckDXTDimensions(Format: TImageFormat; var Width, Height: LongInt); forward; +{ Returns size in bytes of image in BTC format.} +function GetBTCPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; forward; +{ Returns size in bytes of image in binary format (1bit image).} +function GetBinaryPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; forward; + +function GetBCPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; forward; +procedure CheckBCDimensions(Format: TImageFormat; var Width, Height: LongInt); forward; + + +{ Optimized pixel readers/writers for 32bit and FP colors to be stored in TImageFormatInfo } + +function GetPixel32ifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColor32Rec; forward; +procedure SetPixel32ifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColor32Rec); forward; +function GetPixelFPifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColorFPRec; forward; +procedure SetPixelFPifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColorFPRec); forward; + +function GetPixel32Channel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColor32Rec; forward; +procedure SetPixel32Channel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColor32Rec); forward; +function GetPixelFPChannel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColorFPRec; forward; +procedure SetPixelFPChannel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColorFPRec); forward; + +function GetPixelFPFloat32(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColorFPRec; forward; +procedure SetPixelFPFloat32(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColorFPRec); forward; + +var + PFR3G3B2: TPixelFormatInfo; + PFX5R1G1B1: TPixelFormatInfo; + PFR5G6B5: TPixelFormatInfo; + PFA1R5G5B5: TPixelFormatInfo; + PFA4R4G4B4: TPixelFormatInfo; + PFX1R5G5B5: TPixelFormatInfo; + PFX4R4G4B4: TPixelFormatInfo; + FInfos: PImageFormatInfoArray; + +var + // Free Pascal generates hundreds of warnings here +{$WARNINGS OFF} + + // indexed formats + Index8Info: TImageFormatInfo = ( + Format: ifIndex8; + Name: 'Index8'; + BytesPerPixel: 1; + ChannelCount: 1; + PaletteEntries: 256; + HasAlphaChannel: True; + IsIndexed: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + // grayscale formats + Gray8Info: TImageFormatInfo = ( + Format: ifGray8; + Name: 'Gray8'; + BytesPerPixel: 1; + ChannelCount: 1; + HasGrayChannel: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Channel8Bit; + GetPixelFP: GetPixelFPChannel8Bit; + SetPixel32: SetPixel32Channel8Bit; + SetPixelFP: SetPixelFPChannel8Bit); + + A8Gray8Info: TImageFormatInfo = ( + Format: ifA8Gray8; + Name: 'A8Gray8'; + BytesPerPixel: 2; + ChannelCount: 2; + HasGrayChannel: True; + HasAlphaChannel: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Channel8Bit; + GetPixelFP: GetPixelFPChannel8Bit; + SetPixel32: SetPixel32Channel8Bit; + SetPixelFP: SetPixelFPChannel8Bit); + + Gray16Info: TImageFormatInfo = ( + Format: ifGray16; + Name: 'Gray16'; + BytesPerPixel: 2; + ChannelCount: 1; + HasGrayChannel: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + Gray32Info: TImageFormatInfo = ( + Format: ifGray32; + Name: 'Gray32'; + BytesPerPixel: 4; + ChannelCount: 1; + HasGrayChannel: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + Gray64Info: TImageFormatInfo = ( + Format: ifGray64; + Name: 'Gray64'; + BytesPerPixel: 8; + ChannelCount: 1; + HasGrayChannel: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + A16Gray16Info: TImageFormatInfo = ( + Format: ifA16Gray16; + Name: 'A16Gray16'; + BytesPerPixel: 4; + ChannelCount: 2; + HasGrayChannel: True; + HasAlphaChannel: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + // ARGB formats + X5R1G1B1Info: TImageFormatInfo = ( + Format: ifX5R1G1B1; + Name: 'X5R1G1B1'; + BytesPerPixel: 1; + ChannelCount: 3; + UsePixelFormat: True; + PixelFormat: @PFX5R1G1B1; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + R3G3B2Info: TImageFormatInfo = ( + Format: ifR3G3B2; + Name: 'R3G3B2'; + BytesPerPixel: 1; + ChannelCount: 3; + UsePixelFormat: True; + PixelFormat: @PFR3G3B2; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + R5G6B5Info: TImageFormatInfo = ( + Format: ifR5G6B5; + Name: 'R5G6B5'; + BytesPerPixel: 2; + ChannelCount: 3; + UsePixelFormat: True; + PixelFormat: @PFR5G6B5; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + A1R5G5B5Info: TImageFormatInfo = ( + Format: ifA1R5G5B5; + Name: 'A1R5G5B5'; + BytesPerPixel: 2; + ChannelCount: 4; + HasAlphaChannel: True; + UsePixelFormat: True; + PixelFormat: @PFA1R5G5B5; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + A4R4G4B4Info: TImageFormatInfo = ( + Format: ifA4R4G4B4; + Name: 'A4R4G4B4'; + BytesPerPixel: 2; + ChannelCount: 4; + HasAlphaChannel: True; + UsePixelFormat: True; + PixelFormat: @PFA4R4G4B4; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + X1R5G5B5Info: TImageFormatInfo = ( + Format: ifX1R5G5B5; + Name: 'X1R5G5B5'; + BytesPerPixel: 2; + ChannelCount: 3; + UsePixelFormat: True; + PixelFormat: @PFX1R5G5B5; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + X4R4G4B4Info: TImageFormatInfo = ( + Format: ifX4R4G4B4; + Name: 'X4R4G4B4'; + BytesPerPixel: 2; + ChannelCount: 3; + UsePixelFormat: True; + PixelFormat: @PFX4R4G4B4; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + R8G8B8Info: TImageFormatInfo = ( + Format: ifR8G8B8; + Name: 'R8G8B8'; + BytesPerPixel: 3; + ChannelCount: 3; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Channel8Bit; + GetPixelFP: GetPixelFPChannel8Bit; + SetPixel32: SetPixel32Channel8Bit; + SetPixelFP: SetPixelFPChannel8Bit); + + A8R8G8B8Info: TImageFormatInfo = ( + Format: ifA8R8G8B8; + Name: 'A8R8G8B8'; + BytesPerPixel: 4; + ChannelCount: 4; + HasAlphaChannel: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32ifA8R8G8B8; + GetPixelFP: GetPixelFPifA8R8G8B8; + SetPixel32: SetPixel32ifA8R8G8B8; + SetPixelFP: SetPixelFPifA8R8G8B8); + + X8R8G8B8Info: TImageFormatInfo = ( + Format: ifX8R8G8B8; + Name: 'X8R8G8B8'; + BytesPerPixel: 4; + ChannelCount: 3; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Channel8Bit; + GetPixelFP: GetPixelFPChannel8Bit; + SetPixel32: SetPixel32Channel8Bit; + SetPixelFP: SetPixelFPChannel8Bit); + + R16G16B16Info: TImageFormatInfo = ( + Format: ifR16G16B16; + Name: 'R16G16B16'; + BytesPerPixel: 6; + ChannelCount: 3; + RBSwapFormat: ifB16G16R16; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + A16R16G16B16Info: TImageFormatInfo = ( + Format: ifA16R16G16B16; + Name: 'A16R16G16B16'; + BytesPerPixel: 8; + ChannelCount: 4; + HasAlphaChannel: True; + RBSwapFormat: ifA16B16G16R16; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + B16G16R16Info: TImageFormatInfo = ( + Format: ifB16G16R16; + Name: 'B16G16R16'; + BytesPerPixel: 6; + ChannelCount: 3; + IsRBSwapped: True; + RBSwapFormat: ifR16G16B16; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + A16B16G16R16Info: TImageFormatInfo = ( + Format: ifA16B16G16R16; + Name: 'A16B16G16R16'; + BytesPerPixel: 8; + ChannelCount: 4; + HasAlphaChannel: True; + IsRBSwapped: True; + RBSwapFormat: ifA16R16G16B16; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + // floating point formats + R32FInfo: TImageFormatInfo = ( + Format: ifR32F; + Name: 'R32F'; + BytesPerPixel: 4; + ChannelCount: 1; + IsFloatingPoint: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPFloat32; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPFloat32); + + A32R32G32B32FInfo: TImageFormatInfo = ( + Format: ifA32R32G32B32F; + Name: 'A32R32G32B32F'; + BytesPerPixel: 16; + ChannelCount: 4; + HasAlphaChannel: True; + IsFloatingPoint: True; + RBSwapFormat: ifA32B32G32R32F; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPFloat32; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPFloat32); + + A32B32G32R32FInfo: TImageFormatInfo = ( + Format: ifA32B32G32R32F; + Name: 'A32B32G32R32F'; + BytesPerPixel: 16; + ChannelCount: 4; + HasAlphaChannel: True; + IsFloatingPoint: True; + IsRBSwapped: True; + RBSwapFormat: ifA32R32G32B32F; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPFloat32; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPFloat32); + + R16FInfo: TImageFormatInfo = ( + Format: ifR16F; + Name: 'R16F'; + BytesPerPixel: 2; + ChannelCount: 1; + IsFloatingPoint: True; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + A16R16G16B16FInfo: TImageFormatInfo = ( + Format: ifA16R16G16B16F; + Name: 'A16R16G16B16F'; + BytesPerPixel: 8; + ChannelCount: 4; + HasAlphaChannel: True; + IsFloatingPoint: True; + RBSwapFormat: ifA16B16G16R16F; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + A16B16G16R16FInfo: TImageFormatInfo = ( + Format: ifA16B16G16R16F; + Name: 'A16B16G16R16F'; + BytesPerPixel: 8; + ChannelCount: 4; + HasAlphaChannel: True; + IsFloatingPoint: True; + IsRBSwapped: True; + RBSwapFormat: ifA16R16G16B16F; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPGeneric; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPGeneric); + + R32G32B32FInfo: TImageFormatInfo = ( + Format: ifR32G32B32F; + Name: 'R32G32B32F'; + BytesPerPixel: 12; + ChannelCount: 3; + IsFloatingPoint: True; + RBSwapFormat: ifB32G32R32F; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPFloat32; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPFloat32); + + B32G32R32FInfo: TImageFormatInfo = ( + Format: ifB32G32R32F; + Name: 'B32G32R32F'; + BytesPerPixel: 12; + ChannelCount: 3; + IsFloatingPoint: True; + IsRBSwapped: True; + RBSwapFormat: ifR32G32B32F; + GetPixelsSize: GetStdPixelsSize; + CheckDimensions: CheckStdDimensions; + GetPixel32: GetPixel32Generic; + GetPixelFP: GetPixelFPFloat32; + SetPixel32: SetPixel32Generic; + SetPixelFP: SetPixelFPFloat32); + + // special formats + DXT1Info: TImageFormatInfo = ( + Format: ifDXT1; + Name: 'DXT1'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + GetPixelsSize: GetDXTPixelsSize; + CheckDimensions: CheckDXTDimensions; + SpecialNearestFormat: ifA8R8G8B8); + + DXT3Info: TImageFormatInfo = ( + Format: ifDXT3; + Name: 'DXT3'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + GetPixelsSize: GetDXTPixelsSize; + CheckDimensions: CheckDXTDimensions; + SpecialNearestFormat: ifA8R8G8B8); + + DXT5Info: TImageFormatInfo = ( + Format: ifDXT5; + Name: 'DXT5'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + GetPixelsSize: GetDXTPixelsSize; + CheckDimensions: CheckDXTDimensions; + SpecialNearestFormat: ifA8R8G8B8); + + BTCInfo: TImageFormatInfo = ( + Format: ifBTC; + Name: 'BTC'; + ChannelCount: 1; + HasAlphaChannel: False; + IsSpecial: True; + GetPixelsSize: GetBTCPixelsSize; + CheckDimensions: CheckDXTDimensions; + SpecialNearestFormat: ifGray8); + + ATI1NInfo: TImageFormatInfo = ( + Format: ifATI1N; + Name: 'ATI1N'; + ChannelCount: 1; + HasAlphaChannel: False; + IsSpecial: True; + GetPixelsSize: GetDXTPixelsSize; + CheckDimensions: CheckDXTDimensions; + SpecialNearestFormat: ifGray8); + + ATI2NInfo: TImageFormatInfo = ( + Format: ifATI2N; + Name: 'ATI2N'; + ChannelCount: 2; + HasAlphaChannel: False; + IsSpecial: True; + GetPixelsSize: GetDXTPixelsSize; + CheckDimensions: CheckDXTDimensions; + SpecialNearestFormat: ifA8R8G8B8); + + BinaryInfo: TImageFormatInfo = ( + Format: ifBinary; + Name: 'Binary'; + ChannelCount: 1; + HasAlphaChannel: False; + IsSpecial: True; + GetPixelsSize: GetBinaryPixelsSize; + CheckDimensions: CheckStdDimensions; + SpecialNearestFormat: ifGray8); + + {ETC1Info: TImageFormatInfo = ( + Format: ifETC1; + Name: 'ETC1'; + ChannelCount: 3; + HasAlphaChannel: False; + IsSpecial: True; + IsPasstrough: True; + GetPixelsSize: GetBCPixelsSize; + CheckDimensions: CheckBCDimensions; + SpecialNearestFormat: ifR8G8B8); + + ETC2RGBInfo: TImageFormatInfo = ( + Format: ifETC2RGB; + Name: 'ETC2RGB'; + ChannelCount: 3; + HasAlphaChannel: False; + IsSpecial: True; + IsPasstrough: True; + GetPixelsSize: GetBCPixelsSize; + CheckDimensions: CheckBCDimensions; + SpecialNearestFormat: ifR8G8B8); + + ETC2RGBAInfo: TImageFormatInfo = ( + Format: ifETC2RGBA; + Name: 'ETC2RGBA'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + IsPasstrough: True; + GetPixelsSize: GetBCPixelsSize; + CheckDimensions: CheckBCDimensions; + SpecialNearestFormat: ifA8R8G8B8); + + ETC2PAInfo: TImageFormatInfo = ( + Format: ifETC2PA; + Name: 'ETC2PA'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + IsPasstrough: True; + GetPixelsSize: GetBCPixelsSize; + CheckDimensions: CheckBCDimensions; + SpecialNearestFormat: ifA8R8G8B8); + + DXBC6Info: TImageFormatInfo = ( + Format: ifDXBC6; + Name: 'DXBC6'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + IsPasstrough: True; + GetPixelsSize: GetBCPixelsSize; + CheckDimensions: CheckBCDimensions; + SpecialNearestFormat: ifA8R8G8B8); + + DXBC7Info: TImageFormatInfo = ( + Format: ifDXBC6; + Name: 'DXBC7'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + IsPasstrough: True; + GetPixelsSize: GetBCPixelsSize; + CheckDimensions: CheckBCDimensions; + SpecialNearestFormat: ifA8R8G8B8); } + + {PVRTCInfo: TImageFormatInfo = ( + Format: ifPVRTC; + Name: 'PVRTC'; + ChannelCount: 4; + HasAlphaChannel: True; + IsSpecial: True; + IsPasstrough: True; + GetPixelsSize: GetBCPixelsSize; + CheckDimensions: CheckBCDimensions; + SpecialNearestFormat: ifA8R8G8B8);} + +{$WARNINGS ON} + +function PixelFormat(ABitCount, RBitCount, GBitCount, BBitCount: Byte): TPixelFormatInfo; forward; + +procedure InitImageFormats(var Infos: TImageFormatInfoArray); +begin + FInfos := @Infos; + + Infos[ifDefault] := @A8R8G8B8Info; + // indexed formats + Infos[ifIndex8] := @Index8Info; + // grayscale formats + Infos[ifGray8] := @Gray8Info; + Infos[ifA8Gray8] := @A8Gray8Info; + Infos[ifGray16] := @Gray16Info; + Infos[ifGray32] := @Gray32Info; + Infos[ifGray64] := @Gray64Info; + Infos[ifA16Gray16] := @A16Gray16Info; + // ARGB formats + Infos[ifX5R1G1B1] := @X5R1G1B1Info; + Infos[ifR3G3B2] := @R3G3B2Info; + Infos[ifR5G6B5] := @R5G6B5Info; + Infos[ifA1R5G5B5] := @A1R5G5B5Info; + Infos[ifA4R4G4B4] := @A4R4G4B4Info; + Infos[ifX1R5G5B5] := @X1R5G5B5Info; + Infos[ifX4R4G4B4] := @X4R4G4B4Info; + Infos[ifR8G8B8] := @R8G8B8Info; + Infos[ifA8R8G8B8] := @A8R8G8B8Info; + Infos[ifX8R8G8B8] := @X8R8G8B8Info; + Infos[ifR16G16B16] := @R16G16B16Info; + Infos[ifA16R16G16B16] := @A16R16G16B16Info; + Infos[ifB16G16R16] := @B16G16R16Info; + Infos[ifA16B16G16R16] := @A16B16G16R16Info; + // floating point formats + Infos[ifR32F] := @R32FInfo; + Infos[ifA32R32G32B32F] := @A32R32G32B32FInfo; + Infos[ifA32B32G32R32F] := @A32B32G32R32FInfo; + Infos[ifR16F] := @R16FInfo; + Infos[ifA16R16G16B16F] := @A16R16G16B16FInfo; + Infos[ifA16B16G16R16F] := @A16B16G16R16FInfo; + Infos[ifR32G32B32F] := @R32G32B32FInfo; + Infos[ifB32G32R32F] := @B32G32R32FInfo; + // special formats + Infos[ifDXT1] := @DXT1Info; + Infos[ifDXT3] := @DXT3Info; + Infos[ifDXT5] := @DXT5Info; + Infos[ifBTC] := @BTCInfo; + Infos[ifATI1N] := @ATI1NInfo; + Infos[ifATI2N] := @ATI2NInfo; + Infos[ifBinary] := @BinaryInfo; + + PFR3G3B2 := PixelFormat(0, 3, 3, 2); + PFX5R1G1B1 := PixelFormat(0, 1, 1, 1); + PFR5G6B5 := PixelFormat(0, 5, 6, 5); + PFA1R5G5B5 := PixelFormat(1, 5, 5, 5); + PFA4R4G4B4 := PixelFormat(4, 4, 4, 4); + PFX1R5G5B5 := PixelFormat(0, 5, 5, 5); + PFX4R4G4B4 := PixelFormat(0, 4, 4, 4); +end; + + +{ Internal unit helper functions } + +function PixelFormat(ABitCount, RBitCount, GBitCount, BBitCount: Byte): TPixelFormatInfo; +begin + Result.ABitMask := ((1 shl ABitCount) - 1) shl (RBitCount + GBitCount + + BBitCount); + Result.RBitMask := ((1 shl RBitCount) - 1) shl (GBitCount + BBitCount); + Result.GBitMask := ((1 shl GBitCount) - 1) shl (BBitCount); + Result.BBitMask := (1 shl BBitCount) - 1; + Result.ABitCount := ABitCount; + Result.RBitCount := RBitCount; + Result.GBitCount := GBitCount; + Result.BBitCount := BBitCount; + Result.AShift := RBitCount + GBitCount + BBitCount; + Result.RShift := GBitCount + BBitCount; + Result.GShift := BBitCount; + Result.BShift := 0; + Result.ARecDiv := Max(1, Pow2Int(Result.ABitCount) - 1); + Result.RRecDiv := Max(1, Pow2Int(Result.RBitCount) - 1); + Result.GRecDiv := Max(1, Pow2Int(Result.GBitCount) - 1); + Result.BRecDiv := Max(1, Pow2Int(Result.BBitCount) - 1); +end; + +function PixelFormatMask(ABitMask, RBitMask, GBitMask, BBitMask: LongWord): TPixelFormatInfo; + + function GetBitCount(B: LongWord): LongWord; + var + I: LongWord; + begin + I := 0; + while (I < 31) and (((1 shl I) and B) = 0) do + Inc(I); + Result := 0; + while ((1 shl I) and B) <> 0 do + begin + Inc(I); + Inc(Result); + end; + end; + +begin + Result := PixelFormat(GetBitCount(ABitMask), GetBitCount(RBitMask), + GetBitCount(GBitMask), GetBitCount(BBitMask)); +end; + +function PFSetARGB(const PF: TPixelFormatInfo; A, R, G, B: Byte): TColor32; +{$IFDEF USE_INLINE}inline;{$ENDIF} +begin + with PF do + Result := + (A shl ABitCount shr 8 shl AShift) or + (R shl RBitCount shr 8 shl RShift) or + (G shl GBitCount shr 8 shl GShift) or + (B shl BBitCount shr 8 shl BShift); +end; + +procedure PFGetARGB(const PF: TPixelFormatInfo; Color: LongWord; + var A, R, G, B: Byte); {$IFDEF USE_INLINE}inline;{$ENDIF} +begin + with PF do + begin + A := (Color and ABitMask shr AShift) * 255 div ARecDiv; + R := (Color and RBitMask shr RShift) * 255 div RRecDiv; + G := (Color and GBitMask shr GShift) * 255 div GRecDiv; + B := (Color and BBitMask shl BShift) * 255 div BRecDiv; + end; +end; + +function PFSetColor(const PF: TPixelFormatInfo; ARGB: TColor32): LongWord; +{$IFDEF USE_INLINE}inline;{$ENDIF} +begin + with PF do + Result := + (Byte(ARGB shr 24) shl ABitCount shr 8 shl AShift) or + (Byte(ARGB shr 16) shl RBitCount shr 8 shl RShift) or + (Byte(ARGB shr 8) shl GBitCount shr 8 shl GShift) or + (Byte(ARGB) shl BBitCount shr 8 shl BShift); +end; + +function PFGetColor(const PF: TPixelFormatInfo; Color: LongWord): TColor32; +{$IFDEF USE_INLINE}inline;{$ENDIF} +begin + //with PF, TColor32Rec(Result) do + begin + TColor32Rec(Result).A := (Color and PF.ABitMask shr PF.AShift) * 255 div PF.ARecDiv; + TColor32Rec(Result).R := (Color and PF.RBitMask shr PF.RShift) * 255 div PF.RRecDiv; + TColor32Rec(Result).G := (Color and PF.GBitMask shr PF.GShift) * 255 div PF.GRecDiv; + TColor32Rec(Result).B := (Color and PF.BBitMask shl PF.BShift) * 255 div PF.BRecDiv; + end; +end; + + +{ Color constructor functions } + + +function Color24(R, G, B: Byte): TColor24Rec; +begin + Result.R := R; + Result.G := G; + Result.B := B; +end; + +function Color32(A, R, G, B: Byte): TColor32Rec; +begin + Result.A := A; + Result.R := R; + Result.G := G; + Result.B := B; +end; + +function Color48(R, G, B: Word): TColor48Rec; +begin + Result.R := R; + Result.G := G; + Result.B := B; +end; + +function Color64(A, R, G, B: Word): TColor64Rec; +begin + Result.A := A; + Result.R := R; + Result.G := G; + Result.B := B; +end; + +function ColorFP(A, R, G, B: Single): TColorFPRec; +begin + Result.A := A; + Result.R := R; + Result.G := G; + Result.B := B; +end; + +function ColorHF(A, R, G, B: THalfFloat): TColorHFRec; +begin + Result.A := A; + Result.R := R; + Result.G := G; + Result.B := B; +end; + + +{ Additional image manipulation functions (usually used internally by Imaging unit) } + +const + MaxPossibleColors = 4096; + HashSize = 32768; + AlphaWeight = 1024; + RedWeight = 612; + GreenWeight = 1202; + BlueWeight = 234; + +type + PColorBin = ^TColorBin; + TColorBin = record + Color: TColor32Rec; + Number: LongInt; + Next: PColorBin; + end; + + THashTable = array[0..HashSize - 1] of PColorBin; + + TColorBox = record + AMin, AMax, + RMin, RMax, + GMin, GMax, + BMin, BMax: LongInt; + Total: LongInt; + Represented: TColor32Rec; + List: PColorBin; + end; + +var + Table: THashTable; + Box: array[0..MaxPossibleColors - 1] of TColorBox; + Boxes: LongInt; + BoxesCreated: Boolean = False; + +procedure ReduceColorsMedianCut(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; MaxColors: LongInt; ChannelMask: Byte; + DstPal: PPalette32; Actions: TReduceColorsActions); + + procedure CreateHistogram (Src: PByte; SrcInfo: PImageFormatInfo; + ChannelMask: Byte); + var + A, R, G, B: Byte; + I, Addr: LongInt; + PC: PColorBin; + Col: TColor32Rec; + begin + for I := 0 to NumPixels - 1 do + begin + Col := GetPixel32Generic(Src, SrcInfo, nil); + A := Col.A and ChannelMask; + R := Col.R and ChannelMask; + G := Col.G and ChannelMask; + B := Col.B and ChannelMask; + + Addr := (A + 11 * B + 59 * R + 119 * G) mod HashSize; + PC := Table[Addr]; + + while (PC <> nil) and ((PC.Color.R <> R) or (PC.Color.G <> G) or + (PC.Color.B <> B) or (PC.Color.A <> A)) do + PC := PC.Next; + + if PC = nil then + begin + New(PC); + PC.Color.R := R; + PC.Color.G := G; + PC.Color.B := B; + PC.Color.A := A; + PC.Number := 1; + PC.Next := Table[Addr]; + Table[Addr] := PC; + end + else + Inc(PC^.Number); + Inc(Src, SrcInfo.BytesPerPixel); + end; + end; + + procedure InitBox (var Box : TColorBox); + begin + Box.AMin := 256; + Box.RMin := 256; + Box.GMin := 256; + Box.BMin := 256; + Box.AMax := -1; + Box.RMax := -1; + Box.GMax := -1; + Box.BMax := -1; + Box.Total := 0; + Box.List := nil; + end; + + procedure ChangeBox (var Box: TColorBox; const C: TColorBin); + begin + with C.Color do + begin + if A < Box.AMin then Box.AMin := A; + if A > Box.AMax then Box.AMax := A; + if B < Box.BMin then Box.BMin := B; + if B > Box.BMax then Box.BMax := B; + if G < Box.GMin then Box.GMin := G; + if G > Box.GMax then Box.GMax := G; + if R < Box.RMin then Box.RMin := R; + if R > Box.RMax then Box.RMax := R; + end; + Inc(Box.Total, C.Number); + end; + + procedure MakeColormap; + var + I, J: LongInt; + CP, Pom: PColorBin; + Cut, LargestIdx, Largest, Size, S: LongInt; + CutA, CutR, CutG, CutB: Boolean; + SumA, SumR, SumG, SumB: LongInt; + Temp: TColorBox; + begin + I := 0; + Boxes := 1; + LargestIdx := 0; + while (I < HashSize) and (Table[I] = nil) do + Inc(i); + if I < HashSize then + begin + // put all colors into Box[0] + InitBox(Box[0]); + repeat + CP := Table[I]; + while CP.Next <> nil do + begin + ChangeBox(Box[0], CP^); + CP := CP.Next; + end; + ChangeBox(Box[0], CP^); + CP.Next := Box[0].List; + Box[0].List := Table[I]; + Table[I] := nil; + repeat + Inc(I) + until (I = HashSize) or (Table[I] <> nil); + until I = HashSize; + // now all colors are in Box[0] + repeat + // cut one color box + Largest := 0; + for I := 0 to Boxes - 1 do + with Box[I] do + begin + Size := (AMax - AMin) * AlphaWeight; + S := (RMax - RMin) * RedWeight; + if S > Size then + Size := S; + S := (GMax - GMin) * GreenWeight; + if S > Size then + Size := S; + S := (BMax - BMin) * BlueWeight; + if S > Size then + Size := S; + if Size > Largest then + begin + Largest := Size; + LargestIdx := I; + end; + end; + if Largest > 0 then + begin + // cutting Box[LargestIdx] into Box[LargestIdx] and Box[Boxes] + CutR := False; + CutG := False; + CutB := False; + CutA := False; + with Box[LargestIdx] do + begin + if (AMax - AMin) * AlphaWeight = Largest then + begin + Cut := (AMax + AMin) shr 1; + CutA := True; + end + else + if (RMax - RMin) * RedWeight = Largest then + begin + Cut := (RMax + RMin) shr 1; + CutR := True; + end + else + if (GMax - GMin) * GreenWeight = Largest then + begin + Cut := (GMax + GMin) shr 1; + CutG := True; + end + else + begin + Cut := (BMax + BMin) shr 1; + CutB := True; + end; + CP := List; + end; + InitBox(Box[LargestIdx]); + InitBox(Box[Boxes]); + repeat + // distribute one color + Pom := CP.Next; + with CP.Color do + begin + if (CutA and (A <= Cut)) or (CutR and (R <= Cut)) or + (CutG and (G <= Cut)) or (CutB and (B <= Cut)) then + I := LargestIdx + else + I := Boxes; + end; + CP.Next := Box[i].List; + Box[i].List := CP; + ChangeBox(Box[i], CP^); + CP := Pom; + until CP = nil; + Inc(Boxes); + end; + until (Boxes = MaxColors) or (Largest = 0); + // compute box representation + for I := 0 to Boxes - 1 do + begin + SumR := 0; + SumG := 0; + SumB := 0; + SumA := 0; + repeat + CP := Box[I].List; + Inc(SumR, CP.Color.R * CP.Number); + Inc(SumG, CP.Color.G * CP.Number); + Inc(SumB, CP.Color.B * CP.Number); + Inc(SumA, CP.Color.A * CP.Number); + Box[I].List := CP.Next; + Dispose(CP); + until Box[I].List = nil; + with Box[I] do + begin + Represented.A := SumA div Total; + Represented.R := SumR div Total; + Represented.G := SumG div Total; + Represented.B := SumB div Total; + AMin := AMin and ChannelMask; + RMin := RMin and ChannelMask; + GMin := GMin and ChannelMask; + BMin := BMin and ChannelMask; + AMax := (AMax and ChannelMask) + (not ChannelMask); + RMax := (RMax and ChannelMask) + (not ChannelMask); + GMax := (GMax and ChannelMask) + (not ChannelMask); + BMax := (BMax and ChannelMask) + (not ChannelMask); + end; + end; + // sort color boxes + for I := 0 to Boxes - 2 do + begin + Largest := 0; + for J := I to Boxes - 1 do + if Box[J].Total > Largest then + begin + Largest := Box[J].Total; + LargestIdx := J; + end; + if LargestIdx <> I then + begin + Temp := Box[I]; + Box[I] := Box[LargestIdx]; + Box[LargestIdx] := Temp; + end; + end; + end; + end; + + procedure FillOutputPalette; + var + I: LongInt; + begin + FillChar(DstPal^, SizeOf(TColor32Rec) * MaxColors, $FF); + for I := 0 to MaxColors - 1 do + begin + if I < Boxes then + with Box[I].Represented do + begin + DstPal[I].A := A; + DstPal[I].R := R; + DstPal[I].G := G; + DstPal[I].B := B; + end + else + DstPal[I].Color := $FF000000; + end; + end; + + function MapColor(const Col: TColor32Rec) : LongInt; + var + I: LongInt; + begin + I := 0; + with Col do + while (I < Boxes) and ((Box[I].AMin > A) or (Box[I].AMax < A) or + (Box[I].RMin > R) or (Box[I].RMax < R) or (Box[I].GMin > G) or + (Box[I].GMax < G) or (Box[I].BMin > B) or (Box[I].BMax < B)) do + Inc(I); + if I = Boxes then + MapColor := 0 + else + MapColor := I; + end; + + procedure MapImage(Src, Dst: PByte; SrcInfo, DstInfo: PImageFormatInfo); + var + I: LongInt; + Col: TColor32Rec; + begin + for I := 0 to NumPixels - 1 do + begin + Col := GetPixel32Generic(Src, SrcInfo, nil); + IndexSetDstPixel(Dst, DstInfo, MapColor(Col)); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; + end; + +begin + MaxColors := ClampInt(MaxColors, 2, MaxPossibleColors); + + if (raUpdateHistogram in Actions) or (raMapImage in Actions) then + begin + Assert(not SrcInfo.IsSpecial); + Assert(not SrcInfo.IsIndexed); + end; + + if raCreateHistogram in Actions then + FillChar(Table, SizeOf(Table), 0); + + if raUpdateHistogram in Actions then + CreateHistogram(Src, SrcInfo, ChannelMask); + + if raMakeColorMap in Actions then + begin + MakeColorMap; + FillOutputPalette; + end; + + if raMapImage in Actions then + MapImage(Src, Dst, SrcInfo, DstInfo); +end; + +procedure StretchNearest(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt); +var + Info: TImageFormatInfo; + ScaleX, ScaleY, X, Y, Xp, Yp: LongInt; + DstPixel, SrcLine: PByte; +begin + GetImageFormatInfo(SrcImage.Format, Info); + Assert(SrcImage.Format = DstImage.Format); + Assert(not Info.IsSpecial); + // Use integers instead of floats for source image pixel coords + // Xp and Yp coords must be shifted right to get read source image coords + ScaleX := (SrcWidth shl 16) div DstWidth; + ScaleY := (SrcHeight shl 16) div DstHeight; + Yp := 0; + for Y := 0 to DstHeight - 1 do + begin + Xp := 0; + SrcLine := @PByteArray(SrcImage.Bits)[((SrcY + Yp shr 16) * SrcImage.Width + SrcX) * Info.BytesPerPixel]; + DstPixel := @PByteArray(DstImage.Bits)[((DstY + Y) * DstImage.Width + DstX) * Info.BytesPerPixel]; + for X := 0 to DstWidth - 1 do + begin + case Info.BytesPerPixel of + 1: PByte(DstPixel)^ := PByteArray(SrcLine)[Xp shr 16]; + 2: PWord(DstPixel)^ := PWordArray(SrcLine)[Xp shr 16]; + 3: PColor24Rec(DstPixel)^ := PPalette24(SrcLine)[Xp shr 16]; + 4: PColor32(DstPixel)^ := PLongWordArray(SrcLine)[Xp shr 16]; + 6: PColor48Rec(DstPixel)^ := PColor48RecArray(SrcLine)[Xp shr 16]; + 8: PColor64(DstPixel)^ := PInt64Array(SrcLine)[Xp shr 16]; + 16: PColorFPRec(DstPixel)^ := PColorFPRecArray(SrcLine)[Xp shr 16]; + end; + Inc(DstPixel, Info.BytesPerPixel); + Inc(Xp, ScaleX); + end; + Inc(Yp, ScaleY); + end; +end; + +{ Filter function for nearest filtering. Also known as box filter.} +function FilterNearest(Value: Single): Single; +begin + if (Value > -0.5) and (Value <= 0.5) then + Result := 1 + else + Result := 0; +end; + +{ Filter function for linear filtering. Also known as triangle or Bartlett filter.} +function FilterLinear(Value: Single): Single; +begin + if Value < 0.0 then + Value := -Value; + if Value < 1.0 then + Result := 1.0 - Value + else + Result := 0.0; +end; + +{ Cosine filter.} +function FilterCosine(Value: Single): Single; +begin + Result := 0; + if Abs(Value) < 1 then + Result := (Cos(Value * Pi) + 1) / 2; +end; + +{ f(t) = 2|t|^3 - 3|t|^2 + 1, -1 <= t <= 1 } +function FilterHermite(Value: Single): Single; +begin + if Value < 0.0 then + Value := -Value; + if Value < 1 then + Result := (2 * Value - 3) * Sqr(Value) + 1 + else + Result := 0; +end; + +{ Quadratic filter. Also known as Bell.} +function FilterQuadratic(Value: Single): Single; +begin + if Value < 0.0 then + Value := -Value; + if Value < 0.5 then + Result := 0.75 - Sqr(Value) + else + if Value < 1.5 then + begin + Value := Value - 1.5; + Result := 0.5 * Sqr(Value); + end + else + Result := 0.0; +end; + +{ Gaussian filter.} +function FilterGaussian(Value: Single): Single; +begin + Result := Exp(-2.0 * Sqr(Value)) * Sqrt(2.0 / Pi); +end; + +{ 4th order (cubic) b-spline filter.} +function FilterSpline(Value: Single): Single; +var + Temp: Single; +begin + if Value < 0.0 then + Value := -Value; + if Value < 1.0 then + begin + Temp := Sqr(Value); + Result := 0.5 * Temp * Value - Temp + 2.0 / 3.0; + end + else + if Value < 2.0 then + begin + Value := 2.0 - Value; + Result := Sqr(Value) * Value / 6.0; + end + else + Result := 0.0; +end; + +{ Lanczos-windowed sinc filter.} +function FilterLanczos(Value: Single): Single; + + function SinC(Value: Single): Single; + begin + if Value <> 0.0 then + begin + Value := Value * Pi; + Result := Sin(Value) / Value; + end + else + Result := 1.0; + end; + +begin + if Value < 0.0 then + Value := -Value; + if Value < 3.0 then + Result := SinC(Value) * SinC(Value / 3.0) + else + Result := 0.0; +end; + +{ Micthell cubic filter.} +function FilterMitchell(Value: Single): Single; +const + B = 1.0 / 3.0; + C = 1.0 / 3.0; +var + Temp: Single; +begin + if Value < 0.0 then + Value := -Value; + Temp := Sqr(Value); + if Value < 1.0 then + begin + Value := (((12.0 - 9.0 * B - 6.0 * C) * (Value * Temp)) + + ((-18.0 + 12.0 * B + 6.0 * C) * Temp) + + (6.0 - 2.0 * B)); + Result := Value / 6.0; + end + else + if Value < 2.0 then + begin + Value := (((-B - 6.0 * C) * (Value * Temp)) + + ((6.0 * B + 30.0 * C) * Temp) + + ((-12.0 * B - 48.0 * C) * Value) + + (8.0 * B + 24.0 * C)); + Result := Value / 6.0; + end + else + Result := 0.0; +end; + +{ CatmullRom spline filter.} +function FilterCatmullRom(Value: Single): Single; +begin + if Value < 0.0 then + Value := -Value; + if Value < 1.0 then + Result := 0.5 * (2.0 + Sqr(Value) * (-5.0 + 3.0 * Value)) + else + if Value < 2.0 then + Result := 0.5 * (4.0 + Value * (-8.0 + Value * (5.0 - Value))) + else + Result := 0.0; +end; + +procedure StretchResample(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt; Filter: TSamplingFilter; WrapEdges: Boolean); +begin + // Calls the other function with filter function and radius defined by Filter + StretchResample(SrcImage, SrcX, SrcY, SrcWidth, SrcHeight, DstImage, DstX, DstY, + DstWidth, DstHeight, SamplingFilterFunctions[Filter], SamplingFilterRadii[Filter], + WrapEdges); +end; + +var + FullEdge: Boolean = True; + +{ The following resampling code is modified and extended code from Graphics32 + library by Alex A. Denisov.} +function BuildMappingTable(DstLow, DstHigh, SrcLow, SrcHigh, SrcImageWidth: LongInt; + Filter: TFilterFunction; Radius: Single; WrapEdges: Boolean): TMappingTable; +var + I, J, K, N: LongInt; + Left, Right, SrcWidth, DstWidth: LongInt; + Weight, Scale, Center, Count: Single; +begin + Result := nil; + K := 0; + SrcWidth := SrcHigh - SrcLow; + DstWidth := DstHigh - DstLow; + + // Check some special cases + if SrcWidth = 1 then + begin + SetLength(Result, DstWidth); + for I := 0 to DstWidth - 1 do + begin + SetLength(Result[I], 1); + Result[I][0].Pos := 0; + Result[I][0].Weight := 1.0; + end; + Exit; + end + else + if (SrcWidth = 0) or (DstWidth = 0) then + Exit; + + if FullEdge then + Scale := DstWidth / SrcWidth + else + Scale := (DstWidth - 1) / (SrcWidth - 1); + + SetLength(Result, DstWidth); + + // Pre-calculate filter contributions for a row or column + if Scale = 0.0 then + begin + Assert(Length(Result) = 1); + SetLength(Result[0], 1); + Result[0][0].Pos := (SrcLow + SrcHigh) div 2; + Result[0][0].Weight := 1.0; + end + else if Scale < 1.0 then + begin + // Sub-sampling - scales from bigger to smaller + Radius := Radius / Scale; + for I := 0 to DstWidth - 1 do + begin + if FullEdge then + Center := SrcLow - 0.5 + (I + 0.5) / Scale + else + Center := SrcLow + I / Scale; + Left := Floor(Center - Radius); + Right := Ceil(Center + Radius); + Count := -1.0; + for J := Left to Right do + begin + Weight := Filter((Center - J) * Scale) * Scale; + if Weight <> 0.0 then + begin + Count := Count + Weight; + K := Length(Result[I]); + SetLength(Result[I], K + 1); + Result[I][K].Pos := ClampInt(J, SrcLow, SrcHigh - 1); + Result[I][K].Weight := Weight; + end; + end; + if Length(Result[I]) = 0 then + begin + SetLength(Result[I], 1); + Result[I][0].Pos := Floor(Center); + Result[I][0].Weight := 1.0; + end + else if Count <> 0.0 then + Result[I][K div 2].Weight := Result[I][K div 2].Weight - Count; + end; + end + else // if Scale > 1.0 then + begin + // Super-sampling - scales from smaller to bigger + Scale := 1.0 / Scale; + for I := 0 to DstWidth - 1 do + begin + if FullEdge then + Center := SrcLow - 0.5 + (I + 0.5) * Scale + else + Center := SrcLow + I * Scale; + Left := Floor(Center - Radius); + Right := Ceil(Center + Radius); + Count := -1.0; + for J := Left to Right do + begin + Weight := Filter(Center - J); + if Weight <> 0.0 then + begin + Count := Count + Weight; + K := Length(Result[I]); + SetLength(Result[I], K + 1); + + if WrapEdges then + begin + if J < 0 then + N := SrcImageWidth + J + else if J >= SrcImageWidth then + N := J - SrcImageWidth + else + N := ClampInt(J, SrcLow, SrcHigh - 1); + end + else + N := ClampInt(J, SrcLow, SrcHigh - 1); + + Result[I][K].Pos := N; + Result[I][K].Weight := Weight; + end; + end; + if Count <> 0.0 then + Result[I][K div 2].Weight := Result[I][K div 2].Weight - Count; + end; + end; +end; + +procedure FindExtremes(const Map: TMappingTable; var MinPos, MaxPos: LongInt); +var + I, J: LongInt; +begin + if Length(Map) > 0 then + begin + MinPos := Map[0][0].Pos; + MaxPos := MinPos; + for I := 0 to Length(Map) - 1 do + for J := 0 to Length(Map[I]) - 1 do + begin + if MinPos > Map[I][J].Pos then + MinPos := Map[I][J].Pos; + if MaxPos < Map[I][J].Pos then + MaxPos := Map[I][J].Pos; + end; + end; +end; + +procedure StretchResample(const SrcImage: TImageData; SrcX, SrcY, SrcWidth, + SrcHeight: LongInt; var DstImage: TImageData; DstX, DstY, DstWidth, + DstHeight: LongInt; Filter: TFilterFunction; Radius: Single; WrapEdges: Boolean); +const + Channel8BitMax: Single = 255.0; +var + MapX, MapY: TMappingTable; + I, J, X, Y: LongInt; + XMinimum, XMaximum: LongInt; + LineBufferFP: array of TColorFPRec; + ClusterX, ClusterY: TCluster; + Weight, AccumA, AccumR, AccumG, AccumB: Single; + DstLine: PByte; + SrcFloat: TColorFPRec; + Info: TImageFormatInfo; + BytesPerChannel: LongInt; +begin + GetImageFormatInfo(SrcImage.Format, Info); + Assert(SrcImage.Format = DstImage.Format); + Assert(not Info.IsSpecial and not Info.IsIndexed); + BytesPerChannel := Info.BytesPerPixel div Info.ChannelCount; + + // Create horizontal and vertical mapping tables + MapX := BuildMappingTable(DstX, DstX + DstWidth, SrcX, SrcX + SrcWidth, + SrcImage.Width, Filter, Radius, WrapEdges); + MapY := BuildMappingTable(DstY, DstY + DstHeight, SrcY, SrcY + SrcHeight, + SrcImage.Height, Filter, Radius, WrapEdges); + + if (MapX = nil) or (MapY = nil) then + Exit; + + ClusterX := nil; + ClusterY := nil; + + try + // Find min and max X coords of pixels that will contribute to target image + FindExtremes(MapX, XMinimum, XMaximum); + + SetLength(LineBufferFP, XMaximum - XMinimum + 1); + // Following code works for the rest of data formats + for J := 0 to DstHeight - 1 do + begin + // First for each pixel in the current line sample vertically + // and store results in LineBuffer. Then sample horizontally + // using values in LineBuffer. + ClusterY := MapY[J]; + for X := XMinimum to XMaximum do + begin + // Clear accumulators + AccumA := 0; + AccumR := 0; + AccumG := 0; + AccumB := 0; + // For each pixel in line compute weighted sum of pixels + // in source column that will contribute to this pixel + for Y := 0 to Length(ClusterY) - 1 do + begin + // Accumulate this pixel's weighted value + Weight := ClusterY[Y].Weight; + SrcFloat := Info.GetPixelFP(@PByteArray(SrcImage.Bits)[(ClusterY[Y].Pos * SrcImage.Width + X) * Info.BytesPerPixel], @Info, nil); + AccumB := AccumB + SrcFloat.B * Weight; + AccumG := AccumG + SrcFloat.G * Weight; + AccumR := AccumR + SrcFloat.R * Weight; + AccumA := AccumA + SrcFloat.A * Weight; + end; + // Store accumulated value for this pixel in buffer + with LineBufferFP[X - XMinimum] do + begin + A := AccumA; + R := AccumR; + G := AccumG; + B := AccumB; + end; + end; + + DstLine := @PByteArray(DstImage.Bits)[((J + DstY) * DstImage.Width + DstX) * Info.BytesPerPixel]; + // Now compute final colors for targte pixels in the current row + // by sampling horizontally + for I := 0 to DstWidth - 1 do + begin + ClusterX := MapX[I]; + // Clear accumulator + AccumA := 0; + AccumR := 0; + AccumG := 0; + AccumB := 0; + // Compute weighted sum of values (which are already + // computed weighted sums of pixels in source columns stored in LineBuffer) + // that will contribute to the current target pixel + for X := 0 to Length(ClusterX) - 1 do + begin + Weight := ClusterX[X].Weight; + with LineBufferFP[ClusterX[X].Pos - XMinimum] do + begin + AccumB := AccumB + B * Weight; + AccumG := AccumG + G * Weight; + AccumR := AccumR + R * Weight; + AccumA := AccumA + A * Weight; + end; + end; + + // Now compute final color to be written to dest image + SrcFloat.A := AccumA; + SrcFloat.R := AccumR; + SrcFloat.G := AccumG; + SrcFloat.B := AccumB; + + Info.SetPixelFP(DstLine, @Info, nil, SrcFloat); + Inc(DstLine, Info.BytesPerPixel); + end; + end; + + finally + MapX := nil; + MapY := nil; + end; +end; + +procedure FillMipMapLevel(const BiggerLevel: TImageData; Width, Height: LongInt; + var SmallerLevel: TImageData); +var + Filter: TSamplingFilter; + Info: TImageFormatInfo; + CompatibleCopy: TImageData; +begin + Assert(TestImage(BiggerLevel)); + Filter := TSamplingFilter(GetOption(ImagingMipMapFilter)); + + // If we have special format image we must create copy to allow pixel access + GetImageFormatInfo(BiggerLevel.Format, Info); + if Info.IsSpecial then + begin + InitImage(CompatibleCopy); + CloneImage(BiggerLevel, CompatibleCopy); + ConvertImage(CompatibleCopy, ifDefault); + end + else + CompatibleCopy := BiggerLevel; + + // Create new smaller image + NewImage(Width, Height, CompatibleCopy.Format, SmallerLevel); + GetImageFormatInfo(CompatibleCopy.Format, Info); + // If input is indexed we must copy its palette + if Info.IsIndexed then + CopyPalette(CompatibleCopy.Palette, SmallerLevel.Palette, 0, 0, Info.PaletteEntries); + + if (Filter = sfNearest) or Info.IsIndexed then + begin + StretchNearest(CompatibleCopy, 0, 0, CompatibleCopy.Width, CompatibleCopy.Height, + SmallerLevel, 0, 0, Width, Height); + end + else + begin + StretchResample(CompatibleCopy, 0, 0, CompatibleCopy.Width, CompatibleCopy.Height, + SmallerLevel, 0, 0, Width, Height, Filter); + end; + + // Free copy and convert result to special format if necessary + if CompatibleCopy.Format <> BiggerLevel.Format then + begin + ConvertImage(SmallerLevel, BiggerLevel.Format); + FreeImage(CompatibleCopy); + end; +end; + + +{ Various format support functions } + +procedure CopyPixel(Src, Dest: Pointer; BytesPerPixel: LongInt); +begin + case BytesPerPixel of + 1: PByte(Dest)^ := PByte(Src)^; + 2: PWord(Dest)^ := PWord(Src)^; + 3: PColor24Rec(Dest)^ := PColor24Rec(Src)^; + 4: PLongWord(Dest)^ := PLongWord(Src)^; + 6: PColor48Rec(Dest)^ := PColor48Rec(Src)^; + 8: PInt64(Dest)^ := PInt64(Src)^; + 12: PColor96FPRec(Dest)^ := PColor96FPRec(Src)^; + 16: PColorFPRec(Dest)^ := PColorFPRec(Src)^; + end; +end; + +function ComparePixels(PixelA, PixelB: Pointer; BytesPerPixel: LongInt): Boolean; +begin + case BytesPerPixel of + 1: Result := PByte(PixelA)^ = PByte(PixelB)^; + 2: Result := PWord(PixelA)^ = PWord(PixelB)^; + 3: Result := (PWord(PixelA)^ = PWord(PixelB)^) and (PColor24Rec(PixelA).R = PColor24Rec(PixelB).R); + 4: Result := PLongWord(PixelA)^ = PLongWord(PixelB)^; + 6: Result := (PLongWord(PixelA)^ = PLongWord(PixelB)^) and (PColor48Rec(PixelA).R = PColor48Rec(PixelB).R); + 8: Result := PInt64(PixelA)^ = PInt64(PixelB)^; + 12: Result := (PFloatHelper(PixelA).Data = PFloatHelper(PixelB).Data) and + (PFloatHelper(PixelA).Data32 = PFloatHelper(PixelB).Data32); + 16: Result := (PFloatHelper(PixelA).Data = PFloatHelper(PixelB).Data) and + (PFloatHelper(PixelA).Data64 = PFloatHelper(PixelB).Data64); + else + Result := False; + end; +end; + +procedure TranslatePixel(SrcPixel, DstPixel: Pointer; SrcFormat, + DstFormat: TImageFormat; SrcPalette, DstPalette: PPalette32); +var + SrcInfo, DstInfo: PImageFormatInfo; + PixFP: TColorFPRec; +begin + SrcInfo := FInfos[SrcFormat]; + DstInfo := FInfos[DstFormat]; + + PixFP := GetPixelFPGeneric(SrcPixel, SrcInfo, SrcPalette); + SetPixelFPGeneric(DstPixel, DstInfo, DstPalette, PixFP); +end; + +procedure ClampFloatPixel(var PixF: TColorFPRec); +begin + if PixF.A > 1.0 then + PixF.A := 1.0; + if PixF.R > 1.0 then + PixF.R := 1.0; + if PixF.G > 1.0 then + PixF.G := 1.0; + if PixF.B > 1.0 then + PixF.B := 1.0; + + if PixF.A < 0.0 then + PixF.A := 0.0; + if PixF.R < 0.0 then + PixF.R := 0.0; + if PixF.G < 0.0 then + PixF.G := 0.0; + if PixF.B < 0.0 then + PixF.B := 0.0; +end; + +procedure ConvertToPixel32(SrcPix: PByte; DestPix: PColor32Rec; + const SrcInfo: TImageFormatInfo; SrcPalette: PPalette32); +begin + case SrcInfo.Format of + ifIndex8: + begin + DestPix^ := SrcPalette[SrcPix^]; + end; + ifGray8: + begin + DestPix.R := SrcPix^; + DestPix.G := SrcPix^; + DestPix.B := SrcPix^; + DestPix.A := 255; + end; + ifA8Gray8: + begin + DestPix.R := SrcPix^; + DestPix.G := SrcPix^; + DestPix.B := SrcPix^; + DestPix.A := PWordRec(SrcPix).High; + end; + ifGray16: + begin + DestPix.R := PWord(SrcPix)^ shr 8; + DestPix.G := DestPix.R; + DestPix.B := DestPix.R; + DestPix.A := 255; + end; + ifR8G8B8: + begin + DestPix.Color24Rec := PColor24Rec(SrcPix)^; + DestPix.A := 255; + end; + ifA8R8G8B8: + begin + DestPix^ := PColor32Rec(SrcPix)^; + end; + ifR16G16B16: + begin + DestPix.R := PColor48Rec(SrcPix).R shr 8; + DestPix.G := PColor48Rec(SrcPix).G shr 8; + DestPix.B := PColor48Rec(SrcPix).B shr 8; + DestPix.A := 255; + end; + ifA16R16G16B16: + begin + DestPix.R := PColor64Rec(SrcPix).R shr 8; + DestPix.G := PColor64Rec(SrcPix).G shr 8; + DestPix.B := PColor64Rec(SrcPix).B shr 8; + DestPix.A := PColor64Rec(SrcPix).A shr 8; + end; + else + DestPix^ := SrcInfo.GetPixel32(SrcPix, @SrcInfo, SrcPalette); + end; +end; + +procedure AddPadBytes(DataIn: Pointer; DataOut: Pointer; Width, Height, + Bpp, WidthBytes: LongInt); +var + I, W: LongInt; +begin + W := Width * Bpp; + for I := 0 to Height - 1 do + Move(PByteArray(DataIn)[I * W], PByteArray(DataOut)[I * WidthBytes], W); +end; + +procedure RemovePadBytes(DataIn: Pointer; DataOut: Pointer; Width, Height, + Bpp, WidthBytes: LongInt); +var + I, W: LongInt; +begin + W := Width * Bpp; + for I := 0 to Height - 1 do + Move(PByteArray(DataIn)[I * WidthBytes], PByteArray(DataOut)[I * W], W); +end; + +procedure Convert1To8(DataIn, DataOut: PByte; Width, Height, + WidthBytes: LongInt; ScaleTo8Bits: Boolean); +const + Mask1: array[0..7] of Byte = ($80, $40, $20, $10, $08, $04, $02, $01); + Shift1: array[0..7] of Byte = (7, 6, 5, 4, 3, 2, 1, 0); + Scaling: Byte = 255; +var + X, Y: LongInt; + InArray: PByteArray absolute DataIn; +begin + for Y := 0 to Height - 1 do + for X := 0 to Width - 1 do + begin + DataOut^ := (InArray[Y * WidthBytes + X shr 3] and Mask1[X and 7]) shr Shift1[X and 7]; + if ScaleTo8Bits then + DataOut^ := DataOut^ * Scaling; + Inc(DataOut); + end; +end; + +procedure Convert2To8(DataIn, DataOut: PByte; Width, Height, + WidthBytes: LongInt; ScaleTo8Bits: Boolean); +const + Mask2: array[0..3] of Byte = ($C0, $30, $0C, $03); + Shift2: array[0..3] of Byte = (6, 4, 2, 0); + Scaling: Byte = 85; +var + X, Y: LongInt; + InArray: PByteArray absolute DataIn; +begin + for Y := 0 to Height - 1 do + for X := 0 to Width - 1 do + begin + DataOut^ := (InArray[Y * WidthBytes + X shr 2] and Mask2[X and 3]) shr Shift2[X and 3]; + if ScaleTo8Bits then + DataOut^ := DataOut^ * Scaling; + Inc(DataOut); + end; +end; + +procedure Convert4To8(DataIn, DataOut: PByte; Width, Height, + WidthBytes: LongInt; ScaleTo8Bits: Boolean); +const + Mask4: array[0..1] of Byte = ($F0, $0F); + Shift4: array[0..1] of Byte = (4, 0); + Scaling: Byte = 17; +var + X, Y: LongInt; + InArray: PByteArray absolute DataIn; +begin + for Y := 0 to Height - 1 do + for X := 0 to Width - 1 do + begin + DataOut^ := (InArray[Y * WidthBytes + X shr 1] and Mask4[X and 1]) shr Shift4[X and 1]; + if ScaleTo8Bits then + DataOut^ := DataOut^ * Scaling; + Inc(DataOut); + end; +end; + +function Has16BitImageAlpha(NumPixels: LongInt; Data: PWord): Boolean; +var + I: LongInt; +begin + Result := False; + for I := 0 to NumPixels - 1 do + begin + if Data^ >= 1 shl 15 then + begin + Result := True; + Exit; + end; + Inc(Data); + end; +end; + +function Has32BitImageAlpha(NumPixels: LongInt; Data: PLongWord): Boolean; +var + I: LongInt; +begin + Result := False; + for I := 0 to NumPixels - 1 do + begin + if Data^ >= 1 shl 24 then + begin + Result := True; + Exit; + end; + Inc(Data); + end; +end; + +function PaletteHasAlpha(Palette: PPalette32; PaletteEntries: Integer): Boolean; +var + I: Integer; +begin + for I := 0 to PaletteEntries - 1 do + begin + if Palette[I].A <> 255 then + begin + Result := True; + Exit; + end; + end; + Result := False; +end; + +function GetScanLine(ImageBits: Pointer; const FormatInfo: TImageFormatInfo; + LineWidth, Index: LongInt): Pointer; +var + LineBytes: LongInt; +begin + Assert(not FormatInfo.IsSpecial); + LineBytes := FormatInfo.GetPixelsSize(FormatInfo.Format, LineWidth, 1); + Result := @PByteArray(ImageBits)[Index * LineBytes]; +end; + +function IsImageFormatValid(Format: TImageFormat): Boolean; +begin + Result := FInfos[Format] <> nil; +end; + +const + HalfMin: Single = 5.96046448e-08; // Smallest positive half + HalfMinNorm: Single = 6.10351562e-05; // Smallest positive normalized half + HalfMax: Single = 65504.0; // Largest positive half + HalfEpsilon: Single = 0.00097656; // Smallest positive e for which half (1.0 + e) != half (1.0) + HalfNaN: THalfFloat = 65535; + HalfPosInf: THalfFloat = 31744; + HalfNegInf: THalfFloat = 64512; + + +{ + Half/Float conversions inspired by half class from OpenEXR library. + + Float (Pascal Single type) is an IEEE 754 single-precision + floating point number. + + Bit layout of Single: + + 31 (msb) + | + | 30 23 + | | | + | | | 22 0 (lsb) + | | | | | + X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX + s e m + + Bit layout of half: + + 15 (msb) + | + | 14 10 + | | | + | | | 9 0 (lsb) + | | | | | + X XXXXX XXXXXXXXXX + s e m + + S is the sign-bit, e is the exponent and m is the significand (mantissa). +} + +function HalfToFloat(Half: THalfFloat): Single; +var + Dst, Sign, Mantissa: LongWord; + Exp: LongInt; +begin + // Extract sign, exponent, and mantissa from half number + Sign := Half shr 15; + Exp := (Half and $7C00) shr 10; + Mantissa := Half and 1023; + + if (Exp > 0) and (Exp < 31) then + begin + // Common normalized number + Exp := Exp + (127 - 15); + Mantissa := Mantissa shl 13; + Dst := (Sign shl 31) or (LongWord(Exp) shl 23) or Mantissa; + // Result := Power(-1, Sign) * Power(2, Exp - 15) * (1 + Mantissa / 1024); + end + else if (Exp = 0) and (Mantissa = 0) then + begin + // Zero - preserve sign + Dst := Sign shl 31; + end + else if (Exp = 0) and (Mantissa <> 0) then + begin + // Denormalized number - renormalize it + while (Mantissa and $00000400) = 0 do + begin + Mantissa := Mantissa shl 1; + Dec(Exp); + end; + Inc(Exp); + Mantissa := Mantissa and not $00000400; + // Now assemble normalized number + Exp := Exp + (127 - 15); + Mantissa := Mantissa shl 13; + Dst := (Sign shl 31) or (LongWord(Exp) shl 23) or Mantissa; + // Result := Power(-1, Sign) * Power(2, -14) * (Mantissa / 1024); + end + else if (Exp = 31) and (Mantissa = 0) then + begin + // +/- infinity + Dst := (Sign shl 31) or $7F800000; + end + else //if (Exp = 31) and (Mantisa <> 0) then + begin + // Not a number - preserve sign and mantissa + Dst := (Sign shl 31) or $7F800000 or (Mantissa shl 13); + end; + + // Reinterpret LongWord as Single + Result := PSingle(@Dst)^; +end; + +function FloatToHalf(Float: Single): THalfFloat; +var + Src: LongWord; + Sign, Exp, Mantissa: LongInt; +begin + Src := PLongWord(@Float)^; + // Extract sign, exponent, and mantissa from Single number + Sign := Src shr 31; + Exp := LongInt((Src and $7F800000) shr 23) - 127 + 15; + Mantissa := Src and $007FFFFF; + + if (Exp > 0) and (Exp < 30) then + begin + // Simple case - round the significand and combine it with the sign and exponent + Result := (Sign shl 15) or (Exp shl 10) or ((Mantissa + $00001000) shr 13); + end + else if Src = 0 then + begin + // Input float is zero - return zero + Result := 0; + end + else + begin + // Difficult case - lengthy conversion + if Exp <= 0 then + begin + if Exp < -10 then + begin + // Input float's value is less than HalfMin, return zero + Result := 0; + end + else + begin + // Float is a normalized Single whose magnitude is less than HalfNormMin. + // We convert it to denormalized half. + Mantissa := (Mantissa or $00800000) shr (1 - Exp); + // Round to nearest + if (Mantissa and $00001000) > 0 then + Mantissa := Mantissa + $00002000; + // Assemble Sign and Mantissa (Exp is zero to get denormalized number) + Result := (Sign shl 15) or (Mantissa shr 13); + end; + end + else if Exp = 255 - 127 + 15 then + begin + if Mantissa = 0 then + begin + // Input float is infinity, create infinity half with original sign + Result := (Sign shl 15) or $7C00; + end + else + begin + // Input float is NaN, create half NaN with original sign and mantissa + Result := (Sign shl 15) or $7C00 or (Mantissa shr 13); + end; + end + else + begin + // Exp is > 0 so input float is normalized Single + + // Round to nearest + if (Mantissa and $00001000) > 0 then + begin + Mantissa := Mantissa + $00002000; + if (Mantissa and $00800000) > 0 then + begin + Mantissa := 0; + Exp := Exp + 1; + end; + end; + + if Exp > 30 then + begin + // Exponent overflow - return infinity half + Result := (Sign shl 15) or $7C00; + end + else + // Assemble normalized half + Result := (Sign shl 15) or (Exp shl 10) or (Mantissa shr 13); + end; + end; +end; + +function ColorHalfToFloat(ColorHF: TColorHFRec): TColorFPRec; +begin + Result.A := HalfToFloat(ColorHF.A); + Result.R := HalfToFloat(ColorHF.R); + Result.G := HalfToFloat(ColorHF.G); + Result.B := HalfToFloat(ColorHF.B); +end; + +function ColorFloatToHalf(ColorFP: TColorFPRec): TColorHFRec; +begin + Result.A := FloatToHalf(ColorFP.A); + Result.R := FloatToHalf(ColorFP.R); + Result.G := FloatToHalf(ColorFP.G); + Result.B := FloatToHalf(ColorFP.B); +end; + +procedure VisualizePalette(Pal: PPalette32; Entries: Integer; out PalImage: TImageData); +var + I: Integer; + Pix: PColor32; +begin + InitImage(PalImage); + NewImage(Entries, 1, ifA8R8G8B8, PalImage); + Pix := PalImage.Bits; + for I := 0 to Entries - 1 do + begin + Pix^ := Pal[I].Color; + Inc(Pix); + end; +end; + + +{ Pixel readers/writers for different image formats } + +procedure ChannelGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Pix: TColor64Rec); +var + A, R, G, B: Byte; +begin + A := 0; + R := 0; + G := 0; + B := 0; + FillChar(Pix, SizeOf(Pix), 0); + // returns 64 bit color value with 16 bits for each channel + case SrcInfo.BytesPerPixel of + 1: + begin + PFGetARGB(SrcInfo.PixelFormat^, Src^, A, R, G, B); + Pix.A := A shl 8; + Pix.R := R shl 8; + Pix.G := G shl 8; + Pix.B := B shl 8; + end; + 2: + begin + PFGetARGB(SrcInfo.PixelFormat^, PWord(Src)^, A, R, G, B); + Pix.A := A shl 8; + Pix.R := R shl 8; + Pix.G := G shl 8; + Pix.B := B shl 8; + end; + 3: + with Pix do + begin + R := MulDiv(PColor24Rec(Src).R, 65535, 255); + G := MulDiv(PColor24Rec(Src).G, 65535, 255); + B := MulDiv(PColor24Rec(Src).B, 65535, 255); + end; + 4: + with Pix do + begin + A := MulDiv(PColor32Rec(Src).A, 65535, 255); + R := MulDiv(PColor32Rec(Src).R, 65535, 255); + G := MulDiv(PColor32Rec(Src).G, 65535, 255); + B := MulDiv(PColor32Rec(Src).B, 65535, 255); + end; + 6: + with Pix do + begin + R := PColor48Rec(Src).R; + G := PColor48Rec(Src).G; + B := PColor48Rec(Src).B; + end; + 8: Pix.Color := PColor64(Src)^; + end; + // if src has no alpha, we set it to max (otherwise we would have to + // test if dest has alpha or not in each ChannelToXXX function) + if not SrcInfo.HasAlphaChannel then + Pix.A := 65535; + + if SrcInfo.IsRBSwapped then + SwapValues(Pix.R, Pix.B); +end; + +procedure ChannelSetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + const Pix: TColor64Rec); +var + PixW: TColor64Rec; +begin + PixW := Pix; + if DstInfo.IsRBSwapped then + SwapValues(PixW.R, PixW.B); + // Pix contains 64 bit color value with 16 bit for each channel + case DstInfo.BytesPerPixel of + 1: Dst^ := PFSetARGB(DstInfo.PixelFormat^, PixW.A shr 8, + PixW.R shr 8, PixW.G shr 8, PixW.B shr 8); + 2: PWord(Dst)^ := PFSetARGB(DstInfo.PixelFormat^, PixW.A shr 8, + PixW.R shr 8, PixW.G shr 8, PixW.B shr 8); + 3: + with PColor24Rec(Dst)^ do + begin + R := MulDiv(PixW.R, 255, 65535); + G := MulDiv(PixW.G, 255, 65535); + B := MulDiv(PixW.B, 255, 65535); + end; + 4: + with PColor32Rec(Dst)^ do + begin + A := MulDiv(PixW.A, 255, 65535); + R := MulDiv(PixW.R, 255, 65535); + G := MulDiv(PixW.G, 255, 65535); + B := MulDiv(PixW.B, 255, 65535); + end; + 6: + with PColor48Rec(Dst)^ do + begin + R := PixW.R; + G := PixW.G; + B := PixW.B; + end; + 8: PColor64(Dst)^ := PixW.Color; + end; +end; + +procedure GrayGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Gray: TColor64Rec; var Alpha: Word); +begin + FillChar(Gray, SizeOf(Gray), 0); + // Source alpha is scaled to 16 bits and stored in Alpha, + // grayscale value is scaled to 64 bits and stored in Gray + case SrcInfo.BytesPerPixel of + 1: Gray.A := MulDiv(Src^, 65535, 255); + 2: + if SrcInfo.HasAlphaChannel then + with PWordRec(Src)^ do + begin + Alpha := MulDiv(High, 65535, 255); + Gray.A := MulDiv(Low, 65535, 255); + end + else + Gray.A := PWord(Src)^; + 4: + if SrcInfo.HasAlphaChannel then + with PLongWordRec(Src)^ do + begin + Alpha := High; + Gray.A := Low; + end + else + with PLongWordRec(Src)^ do + begin + Gray.A := High; + Gray.R := Low; + end; + 8: Gray.Color := PColor64(Src)^; + end; + // if src has no alpha, we set it to max (otherwise we would have to + // test if dest has alpha or not in each GrayToXXX function) + if not SrcInfo.HasAlphaChannel then + Alpha := 65535; +end; + +procedure GraySetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + const Gray: TColor64Rec; Alpha: Word); +begin + // Gray contains grayscale value scaled to 64 bits, Alpha contains + // alpha value scaled to 16 bits + case DstInfo.BytesPerPixel of + 1: Dst^ := MulDiv(Gray.A, 255, 65535); + 2: + if DstInfo.HasAlphaChannel then + with PWordRec(Dst)^ do + begin + High := MulDiv(Alpha, 255, 65535); + Low := MulDiv(Gray.A, 255, 65535); + end + else + PWord(Dst)^ := Gray.A; + 4: + if DstInfo.HasAlphaChannel then + with PLongWordRec(Dst)^ do + begin + High := Alpha; + Low := Gray.A; + end + else + with PLongWordRec(Dst)^ do + begin + High := Gray.A; + Low := Gray.R; + end; + 8: PColor64(Dst)^ := Gray.Color; + end; +end; + +procedure FloatGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Pix: TColorFPRec); +var + PixHF: TColorHFRec; +begin + Assert(SrcInfo.BytesPerPixel in [2, 4, 8, 12, 16]); + + if SrcInfo.BytesPerPixel in [4, 12, 16] then + begin + // IEEE 754 single-precision channels + FillChar(Pix, SizeOf(Pix), 0); + case SrcInfo.BytesPerPixel of + 4: Pix.R := PSingle(Src)^; + 12: Pix.Color96Rec := PColor96FPRec(Src)^; + 16: Pix := PColorFPRec(Src)^; + end; + end + else + begin + // Half float channels + FillChar(PixHF, SizeOf(PixHF), 0); + case SrcInfo.BytesPerPixel of + 2: PixHF.R := PHalfFloat(Src)^; + 8: PixHF := PColorHFRec(Src)^; + end; + Pix := ColorHalfToFloat(PixHF); + end; + + // If src has no alpha, we set it to max (otherwise we would have to + // test if dest has alpha or not in each FloatToXXX function) + if not SrcInfo.HasAlphaChannel then + Pix.A := 1.0; + if SrcInfo.IsRBSwapped then + SwapValues(Pix.R, Pix.B); +end; + +procedure FloatSetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + const Pix: TColorFPRec); +var + PixW: TColorFPRec; + PixHF: TColorHFRec; +begin + Assert(DstInfo.BytesPerPixel in [2, 4, 8, 12, 16]); + + PixW := Pix; + if DstInfo.IsRBSwapped then + SwapValues(PixW.R, PixW.B); + + if DstInfo.BytesPerPixel in [4, 12, 16] then + begin + case DstInfo.BytesPerPixel of + 4: PSingle(Dst)^ := PixW.R; + 12: PColor96FPRec(Dst)^:= PixW.Color96Rec; + 16: PColorFPRec(Dst)^ := PixW; + end; + end + else + begin + PixHF := ColorFloatToHalf(PixW); + case DstInfo.BytesPerPixel of + 2: PHalfFloat(Dst)^ := PixHF.R; + 8: PColorHFRec(Dst)^ := PixHF; + end; + end; +end; + +procedure IndexGetSrcPixel(Src: PByte; SrcInfo: PImageFormatInfo; + var Index: LongWord); +begin + case SrcInfo.BytesPerPixel of + 1: Index := Src^; + end; +end; + +procedure IndexSetDstPixel(Dst: PByte; DstInfo: PImageFormatInfo; + Index: LongWord); +begin + case DstInfo.BytesPerPixel of + 1: Dst^ := Byte(Index); + 2: PWord(Dst)^ := Word(Index); + 4: PLongWord(Dst)^ := Index; + end; +end; + + +{ Pixel readers/writers for 32bit and FP colors} + +function GetPixel32Generic(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColor32Rec; +var + Pix64: TColor64Rec; + PixF: TColorFPRec; + Alpha: Word; + Index: LongWord; +begin + if Info.Format = ifA8R8G8B8 then + begin + Result := PColor32Rec(Bits)^ + end + else if Info.Format = ifR8G8B8 then + begin + PColor24Rec(@Result)^ := PColor24Rec(Bits)^; + Result.A := $FF; + end + else if Info.IsFloatingPoint then + begin + FloatGetSrcPixel(Bits, Info, PixF); + Result.A := ClampToByte(Round(PixF.A * 255.0)); + Result.R := ClampToByte(Round(PixF.R * 255.0)); + Result.G := ClampToByte(Round(PixF.G * 255.0)); + Result.B := ClampToByte(Round(PixF.B * 255.0)); + end + else if Info.HasGrayChannel then + begin + GrayGetSrcPixel(Bits, Info, Pix64, Alpha); + Result.A := MulDiv(Alpha, 255, 65535); + Result.R := MulDiv(Pix64.A, 255, 65535); + Result.G := MulDiv(Pix64.A, 255, 65535); + Result.B := MulDiv(Pix64.A, 255, 65535); + end + else if Info.IsIndexed then + begin + IndexGetSrcPixel(Bits, Info, Index); + Result := Palette[Index]; + end + else + begin + ChannelGetSrcPixel(Bits, Info, Pix64); + Result.A := MulDiv(Pix64.A, 255, 65535); + Result.R := MulDiv(Pix64.R, 255, 65535); + Result.G := MulDiv(Pix64.G, 255, 65535); + Result.B := MulDiv(Pix64.B, 255, 65535); + end; +end; + +procedure SetPixel32Generic(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColor32Rec); +var + Pix64: TColor64Rec; + PixF: TColorFPRec; + Alpha: Word; + Index: LongWord; +begin + if Info.Format = ifA8R8G8B8 then + begin + PColor32Rec(Bits)^ := Color + end + else if Info.Format = ifR8G8B8 then + begin + PColor24Rec(Bits)^ := Color.Color24Rec; + end + else if Info.IsFloatingPoint then + begin + PixF.A := Color.A * OneDiv8Bit; + PixF.R := Color.R * OneDiv8Bit; + PixF.G := Color.G * OneDiv8Bit; + PixF.B := Color.B * OneDiv8Bit; + FloatSetDstPixel(Bits, Info, PixF); + end + else if Info.HasGrayChannel then + begin + Alpha := MulDiv(Color.A, 65535, 255); + Pix64.Color := 0; + Pix64.A := MulDiv(Round(GrayConv.R * Color.R + GrayConv.G * Color.G + + GrayConv.B * Color.B), 65535, 255); + GraySetDstPixel(Bits, Info, Pix64, Alpha); + end + else if Info.IsIndexed then + begin + Index := FindColor(Palette, Info.PaletteEntries, Color.Color); + IndexSetDstPixel(Bits, Info, Index); + end + else + begin + Pix64.A := MulDiv(Color.A, 65535, 255); + Pix64.R := MulDiv(Color.R, 65535, 255); + Pix64.G := MulDiv(Color.G, 65535, 255); + Pix64.B := MulDiv(Color.B, 65535, 255); + ChannelSetDstPixel(Bits, Info, Pix64); + end; +end; + +function GetPixelFPGeneric(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColorFPRec; +var + Pix32: TColor32Rec; + Pix64: TColor64Rec; + Alpha: Word; + Index: LongWord; +begin + if Info.IsFloatingPoint then + begin + FloatGetSrcPixel(Bits, Info, Result); + end + else if Info.HasGrayChannel then + begin + GrayGetSrcPixel(Bits, Info, Pix64, Alpha); + Result.A := Alpha * OneDiv16Bit; + Result.R := Pix64.A * OneDiv16Bit; + Result.G := Pix64.A * OneDiv16Bit; + Result.B := Pix64.A * OneDiv16Bit; + end + else if Info.IsIndexed then + begin + IndexGetSrcPixel(Bits, Info, Index); + Pix32 := Palette[Index]; + Result.A := Pix32.A * OneDiv8Bit; + Result.R := Pix32.R * OneDiv8Bit; + Result.G := Pix32.G * OneDiv8Bit; + Result.B := Pix32.B * OneDiv8Bit; + end + else + begin + ChannelGetSrcPixel(Bits, Info, Pix64); + Result.A := Pix64.A * OneDiv16Bit; + Result.R := Pix64.R * OneDiv16Bit; + Result.G := Pix64.G * OneDiv16Bit; + Result.B := Pix64.B * OneDiv16Bit; + end; +end; + +procedure SetPixelFPGeneric(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColorFPRec); +var + Pix32: TColor32Rec; + Pix64: TColor64Rec; + Alpha: Word; + Index: LongWord; +begin + if Info.IsFloatingPoint then + begin + FloatSetDstPixel(Bits, Info, Color); + end + else if Info.HasGrayChannel then + begin + Alpha := ClampToWord(Round(Color.A * 65535.0)); + Pix64.Color := 0; + Pix64.A := ClampToWord(Round((GrayConv.R * Color.R + GrayConv.G * Color.G + + GrayConv.B * Color.B) * 65535.0)); + GraySetDstPixel(Bits, Info, Pix64, Alpha); + end + else if Info.IsIndexed then + begin + Pix32.A := ClampToByte(Round(Color.A * 255.0)); + Pix32.R := ClampToByte(Round(Color.R * 255.0)); + Pix32.G := ClampToByte(Round(Color.G * 255.0)); + Pix32.B := ClampToByte(Round(Color.B * 255.0)); + Index := FindColor(Palette, Info.PaletteEntries, Pix32.Color); + IndexSetDstPixel(Bits, Info, Index); + end + else + begin + Pix64.A := ClampToWord(Round(Color.A * 65535.0)); + Pix64.R := ClampToWord(Round(Color.R * 65535.0)); + Pix64.G := ClampToWord(Round(Color.G * 65535.0)); + Pix64.B := ClampToWord(Round(Color.B * 65535.0)); + ChannelSetDstPixel(Bits, Info, Pix64); + end; +end; + + +{ Image format conversion functions } + +procedure ChannelToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + Pix64: TColor64Rec; +begin + // two most common conversions (RGB->ARGB and ARGB->RGB for 24/32 bit + // images) are made separately from general ARGB conversion to + // make them faster + if (SrcInfo.BytesPerPixel = 3) and (DstInfo.BytesPerPixel = 4) then + for I := 0 to NumPixels - 1 do + begin + PColor24Rec(Dst)^ := PColor24Rec(Src)^; + if DstInfo.HasAlphaChannel then + PColor32Rec(Dst).A := 255; + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end + else + if (SrcInfo.BytesPerPixel = 4) and (DstInfo.BytesPerPixel = 3) then + for I := 0 to NumPixels - 1 do + begin + PColor24Rec(Dst)^ := PColor24Rec(Src)^; + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end + else + for I := 0 to NumPixels - 1 do + begin + // general ARGB conversion + ChannelGetSrcPixel(Src, SrcInfo, Pix64); + ChannelSetDstPixel(Dst, DstInfo, Pix64); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure ChannelToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + Pix64: TColor64Rec; + Alpha: Word; +begin + // two most common conversions (R8G8B8->Gray8 nad A8R8G8B8->Gray8) + // are made separately from general conversions to make them faster + if (SrcInfo.BytesPerPixel in [3, 4]) and (DstInfo.Format = ifGray8) then + for I := 0 to NumPixels - 1 do + begin + Dst^ := Round(GrayConv.R * PColor24Rec(Src).R + GrayConv.G * PColor24Rec(Src).G + + GrayConv.B * PColor24Rec(Src).B); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end + else + for I := 0 to NumPixels - 1 do + begin + ChannelGetSrcPixel(Src, SrcInfo, Pix64); + + // alpha is saved from source pixel to Alpha, + // Gray value is computed and set to highest word of Pix64 so + // Pix64.Color contains grayscale value scaled to 64 bits + Alpha := Pix64.A; + with GrayConv do + Pix64.A := Round(R * Pix64.R + G * Pix64.G + B * Pix64.B); + + GraySetDstPixel(Dst, DstInfo, Pix64, Alpha); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure ChannelToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + Pix64: TColor64Rec; + PixF: TColorFPRec; +begin + for I := 0 to NumPixels - 1 do + begin + ChannelGetSrcPixel(Src, SrcInfo, Pix64); + + // floating point channel values are scaled to 1.0 + PixF.A := Pix64.A * OneDiv16Bit; + PixF.R := Pix64.R * OneDiv16Bit; + PixF.G := Pix64.G * OneDiv16Bit; + PixF.B := Pix64.B * OneDiv16Bit; + + FloatSetDstPixel(Dst, DstInfo, PixF); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure ChannelToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; DstPal: PPalette32); +begin + ReduceColorsMedianCut(NumPixels, Src, Dst, SrcInfo, DstInfo, DstInfo.PaletteEntries, + GetOption(ImagingColorReductionMask), DstPal); +end; + +procedure GrayToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + Gray: TColor64Rec; + Alpha: Word; +begin + // two most common conversions (Gray8->Gray16 nad Gray16->Gray8) + // are made separately from general conversions to make them faster + if (SrcInfo.Format = ifGray8) and (DstInfo.Format = ifGray16) then + begin + for I := 0 to NumPixels - 1 do + PWordArray(Dst)[I] := PByteArray(Src)[I] shl 8; + end + else + begin + if (DstInfo.Format = ifGray8) and (SrcInfo.Format = ifGray16) then + begin + for I := 0 to NumPixels - 1 do + PByteArray(Dst)[I] := PWordArray(Src)[I] shr 8; + end + else + for I := 0 to NumPixels - 1 do + begin + // general grayscale conversion + GrayGetSrcPixel(Src, SrcInfo, Gray, Alpha); + GraySetDstPixel(Dst, DstInfo, Gray, Alpha); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; + end; +end; + +procedure GrayToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + Pix64: TColor64Rec; + Alpha: Word; +begin + // two most common conversions (Gray8->R8G8B8 nad Gray8->A8R8G8B8) + // are made separately from general conversions to make them faster + if (DstInfo.BytesPerPixel in [3, 4]) and (SrcInfo.Format = ifGray8) then + for I := 0 to NumPixels - 1 do + begin + PColor24Rec(Dst).R := Src^; + PColor24Rec(Dst).G := Src^; + PColor24Rec(Dst).B := Src^; + if DstInfo.HasAlphaChannel then + PColor32Rec(Dst).A := $FF; + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end + else + for I := 0 to NumPixels - 1 do + begin + GrayGetSrcPixel(Src, SrcInfo, Pix64, Alpha); + + // most significant word of grayscale value is used for + // each channel and alpha channel is set to Alpha + Pix64.R := Pix64.A; + Pix64.G := Pix64.A; + Pix64.B := Pix64.A; + Pix64.A := Alpha; + + ChannelSetDstPixel(Dst, DstInfo, Pix64); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure GrayToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + Gray: TColor64Rec; + PixF: TColorFPRec; + Alpha: Word; +begin + for I := 0 to NumPixels - 1 do + begin + GrayGetSrcPixel(Src, SrcInfo, Gray, Alpha); + // most significant word of grayscale value is used for + // each channel and alpha channel is set to Alpha + // then all is scaled to 0..1 + PixF.R := Gray.A * OneDiv16Bit; + PixF.G := Gray.A * OneDiv16Bit; + PixF.B := Gray.A * OneDiv16Bit; + PixF.A := Alpha * OneDiv16Bit; + + FloatSetDstPixel(Dst, DstInfo, PixF); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure GrayToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; DstPal: PPalette32); +var + I: LongInt; + Idx: LongWord; + Gray: TColor64Rec; + Alpha, Shift: Word; +begin + FillGrayscalePalette(DstPal, DstInfo.PaletteEntries); + Shift := Log2Int(DstInfo.PaletteEntries); + // most common conversion (Gray8->Index8) + // is made separately from general conversions to make it faster + if (SrcInfo.Format = ifGray8) and (DstInfo.Format = ifIndex8) then + for I := 0 to NumPixels - 1 do + begin + Dst^ := Src^; + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end + else + for I := 0 to NumPixels - 1 do + begin + // gray value is read from src and index to precomputed + // grayscale palette is computed and written to dst + // (we assume here that there will be no more than 65536 palette + // entries in dst format, gray value is shifted so the highest + // gray value match the highest possible index in palette) + GrayGetSrcPixel(Src, SrcInfo, Gray, Alpha); + Idx := Gray.A shr (16 - Shift); + IndexSetDstPixel(Dst, DstInfo, Idx); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure FloatToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + PixF: TColorFPRec; +begin + for I := 0 to NumPixels - 1 do + begin + // general floating point conversion + FloatGetSrcPixel(Src, SrcInfo, PixF); + FloatSetDstPixel(Dst, DstInfo, PixF); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure FloatToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + Pix64: TColor64Rec; + PixF: TColorFPRec; +begin + for I := 0 to NumPixels - 1 do + begin + FloatGetSrcPixel(Src, SrcInfo, PixF); + ClampFloatPixel(PixF); + + // floating point channel values are scaled to 1.0 + Pix64.A := ClampToWord(Round(PixF.A * 65535)); + Pix64.R := ClampToWord(Round(PixF.R * 65535)); + Pix64.G := ClampToWord(Round(PixF.G * 65535)); + Pix64.B := ClampToWord(Round(PixF.B * 65535)); + + ChannelSetDstPixel(Dst, DstInfo, Pix64); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure FloatToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo); +var + I: LongInt; + PixF: TColorFPRec; + Gray: TColor64Rec; + Alpha: Word; +begin + for I := 0 to NumPixels - 1 do + begin + FloatGetSrcPixel(Src, SrcInfo, PixF); + ClampFloatPixel(PixF); + + // alpha is saved from source pixel to Alpha, + // Gray value is computed and set to highest word of Pix64 so + // Pix64.Color contains grayscale value scaled to 64 bits + Alpha := ClampToWord(Round(PixF.A * 65535.0)); + Gray.A := ClampToWord(Round((GrayConv.R * PixF.R + GrayConv.G * PixF.G + + GrayConv.B * PixF.B) * 65535.0)); + + GraySetDstPixel(Dst, DstInfo, Gray, Alpha); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure FloatToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; DstPal: PPalette32); +begin + ReduceColorsMedianCut(NumPixels, Src, Dst, SrcInfo, DstInfo, DstInfo.PaletteEntries, + GetOption(ImagingColorReductionMask), DstPal); +end; + +procedure IndexToIndex(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal, DstPal: PPalette32); +var + I: LongInt; +begin + // there is only one indexed format now, so it is just a copy + for I := 0 to NumPixels - 1 do + begin + Dst^ := Src^; + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; + for I := 0 to SrcInfo.PaletteEntries - 1 do + DstPal[I] := SrcPal[I]; +end; + +procedure IndexToChannel(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal: PPalette32); +var + I: LongInt; + Pix64: TColor64Rec; + Idx: LongWord; +begin + // two most common conversions (Index8->R8G8B8 nad Index8->A8R8G8B8) + // are made separately from general conversions to make them faster + if (SrcInfo.Format = ifIndex8) and (DstInfo.Format in [ifR8G8B8, ifA8R8G8B8]) then + for I := 0 to NumPixels - 1 do + begin + with PColor24Rec(Dst)^ do + begin + R := SrcPal[Src^].R; + G := SrcPal[Src^].G; + B := SrcPal[Src^].B; + end; + if DstInfo.Format = ifA8R8G8B8 then + PColor32Rec(Dst).A := SrcPal[Src^].A; + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end + else + for I := 0 to NumPixels - 1 do + begin + // index to palette is read from source and color + // is retrieved from palette entry. Color is then + // scaled to 16bits and written to dest + IndexGetSrcPixel(Src, SrcInfo, Idx); + with Pix64 do + begin + A := SrcPal[Idx].A shl 8; + R := SrcPal[Idx].R shl 8; + G := SrcPal[Idx].G shl 8; + B := SrcPal[Idx].B shl 8; + end; + ChannelSetDstPixel(Dst, DstInfo, Pix64); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure IndexToGray(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal: PPalette32); +var + I: LongInt; + Gray: TColor64Rec; + Alpha: Word; + Idx: LongWord; +begin + // most common conversion (Index8->Gray8) + // is made separately from general conversions to make it faster + if (SrcInfo.Format = ifIndex8) and (DstInfo.Format = ifGray8) then + begin + for I := 0 to NumPixels - 1 do + begin + Dst^ := Round(GrayConv.R * SrcPal[Src^].R + GrayConv.G * SrcPal[Src^].G + + GrayConv.B * SrcPal[Src^].B); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end + end + else + for I := 0 to NumPixels - 1 do + begin + // index to palette is read from source and color + // is retrieved from palette entry. Color is then + // transformed to grayscale and assigned to the highest + // byte of Gray value + IndexGetSrcPixel(Src, SrcInfo, Idx); + Alpha := SrcPal[Idx].A shl 8; + Gray.A := MulDiv(Round(GrayConv.R * SrcPal[Idx].R + GrayConv.G * SrcPal[Idx].G + + GrayConv.B * SrcPal[Idx].B), 65535, 255); + GraySetDstPixel(Dst, DstInfo, Gray, Alpha); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + +procedure IndexToFloat(NumPixels: LongInt; Src, Dst: PByte; SrcInfo, + DstInfo: PImageFormatInfo; SrcPal: PPalette32); +var + I: LongInt; + Idx: LongWord; + PixF: TColorFPRec; +begin + for I := 0 to NumPixels - 1 do + begin + // index to palette is read from source and color + // is retrieved from palette entry. Color is then + // scaled to 0..1 and written to dest + IndexGetSrcPixel(Src, SrcInfo, Idx); + with PixF do + begin + A := SrcPal[Idx].A * OneDiv8Bit; + R := SrcPal[Idx].R * OneDiv8Bit; + G := SrcPal[Idx].G * OneDiv8Bit; + B := SrcPal[Idx].B * OneDiv8Bit; + end; + FloatSetDstPixel(Dst, DstInfo, PixF); + Inc(Src, SrcInfo.BytesPerPixel); + Inc(Dst, DstInfo.BytesPerPixel); + end; +end; + + +{ Special formats conversion functions } + +type + // DXT RGB color block + TDXTColorBlock = packed record + Color0, Color1: Word; + Mask: LongWord; + end; + PDXTColorBlock = ^TDXTColorBlock; + + // DXT explicit alpha for a block + TDXTAlphaBlockExp = packed record + Alphas: array[0..3] of Word; + end; + PDXTAlphaBlockExp = ^TDXTAlphaBlockExp; + + // DXT interpolated alpha for a block + TDXTAlphaBlockInt = packed record + Alphas: array[0..7] of Byte; + end; + PDXTAlphaBlockInt = ^TDXTAlphaBlockInt; + + TPixelInfo = record + Color: Word; + Alpha: Byte; + Orig: TColor32Rec; + end; + + TPixelBlock = array[0..15] of TPixelInfo; + +function DecodeCol(Color: Word): TColor32Rec; +{$IFDEF USE_INLINE} inline; {$ENDIF} +begin + Result.A := $FF; +{ Result.R := ((Color and $F800) shr 11) shl 3; + Result.G := ((Color and $07E0) shr 5) shl 2; + Result.B := (Color and $001F) shl 3;} + // this color expansion is slower but gives better results + Result.R := (Color shr 11) * 255 div 31; + Result.G := ((Color shr 5) and $3F) * 255 div 63; + Result.B := (Color and $1F) * 255 div 31; +end; + +procedure DecodeDXT1(SrcBits, DestBits: PByte; Width, Height: LongInt); +var + Sel, X, Y, I, J, K: LongInt; + Block: TDXTColorBlock; + Colors: array[0..3] of TColor32Rec; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + Block := PDXTColorBlock(SrcBits)^; + Inc(SrcBits, SizeOf(Block)); + // we read and decode endpoint colors + Colors[0] := DecodeCol(Block.Color0); + Colors[1] := DecodeCol(Block.Color1); + // and interpolate between them + if Block.Color0 > Block.Color1 then + begin + // interpolation for block without alpha + Colors[2].A := $FF; + Colors[2].R := (Colors[0].R shl 1 + Colors[1].R + 1) div 3; + Colors[2].G := (Colors[0].G shl 1 + Colors[1].G + 1) div 3; + Colors[2].B := (Colors[0].B shl 1 + Colors[1].B + 1) div 3; + Colors[3].A := $FF; + Colors[3].R := (Colors[0].R + Colors[1].R shl 1 + 1) div 3; + Colors[3].G := (Colors[0].G + Colors[1].G shl 1 + 1) div 3; + Colors[3].B := (Colors[0].B + Colors[1].B shl 1 + 1) div 3; + end + else + begin + // interpolation for block with alpha + Colors[2].A := $FF; + Colors[2].R := (Colors[0].R + Colors[1].R) shr 1; + Colors[2].G := (Colors[0].G + Colors[1].G) shr 1; + Colors[2].B := (Colors[0].B + Colors[1].B) shr 1; + Colors[3].A := 0; + Colors[3].R := (Colors[0].R + Colors[1].R shl 1 + 1) div 3; + Colors[3].G := (Colors[0].G + Colors[1].G shl 1 + 1) div 3; + Colors[3].B := (Colors[0].B + Colors[1].B shl 1 + 1) div 3; + end; + + // we distribute the dxt block colors across the 4x4 block of the + // destination image accroding to the dxt block mask + K := 0; + for J := 0 to 3 do + for I := 0 to 3 do + begin + Sel := (Block.Mask and (3 shl (K shl 1))) shr (K shl 1); + if ((X shl 2 + I) < Width) and ((Y shl 2 + J) < Height) then + PPalette32(DestBits)[(Y shl 2 + J) * Width + X shl 2 + I] := + Colors[Sel]; + Inc(K); + end; + end; +end; + +procedure DecodeDXT3(SrcBits, DestBits: PByte; Width, Height: LongInt); +var + Sel, X, Y, I, J, K: LongInt; + Block: TDXTColorBlock; + AlphaBlock: TDXTAlphaBlockExp; + Colors: array[0..3] of TColor32Rec; + AWord: Word; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + AlphaBlock := PDXTAlphaBlockExp(SrcBits)^; + Inc(SrcBits, SizeOf(AlphaBlock)); + Block := PDXTColorBlock(SrcBits)^; + Inc(SrcBits, SizeOf(Block)); + // we read and decode endpoint colors + Colors[0] := DecodeCol(Block.Color0); + Colors[1] := DecodeCol(Block.Color1); + // and interpolate between them + Colors[2].R := (Colors[0].R shl 1 + Colors[1].R + 1) div 3; + Colors[2].G := (Colors[0].G shl 1 + Colors[1].G + 1) div 3; + Colors[2].B := (Colors[0].B shl 1 + Colors[1].B + 1) div 3; + Colors[3].R := (Colors[0].R + Colors[1].R shl 1 + 1) div 3; + Colors[3].G := (Colors[0].G + Colors[1].G shl 1 + 1) div 3; + Colors[3].B := (Colors[0].B + Colors[1].B shl 1 + 1) div 3; + + // we distribute the dxt block colors and alphas + // across the 4x4 block of the destination image + // accroding to the dxt block mask and alpha block + K := 0; + for J := 0 to 3 do + begin + AWord := AlphaBlock.Alphas[J]; + for I := 0 to 3 do + begin + Sel := (Block.Mask and (3 shl (K shl 1))) shr (K shl 1); + if (X shl 2 + I < Width) and (Y shl 2 + J < Height) then + begin + Colors[Sel].A := AWord and $0F; + Colors[Sel].A := Colors[Sel].A or (Colors[Sel].A shl 4); + PPalette32(DestBits)[(Y shl 2 + J) * Width + X shl 2 + I] := + Colors[Sel]; + end; + Inc(K); + AWord := AWord shr 4; + end; + end; + end; +end; + +procedure GetInterpolatedAlphas(var AlphaBlock: TDXTAlphaBlockInt); +begin + with AlphaBlock do + if Alphas[0] > Alphas[1] then + begin + // Interpolation of six alphas + Alphas[2] := (6 * Alphas[0] + 1 * Alphas[1] + 3) div 7; + Alphas[3] := (5 * Alphas[0] + 2 * Alphas[1] + 3) div 7; + Alphas[4] := (4 * Alphas[0] + 3 * Alphas[1] + 3) div 7; + Alphas[5] := (3 * Alphas[0] + 4 * Alphas[1] + 3) div 7; + Alphas[6] := (2 * Alphas[0] + 5 * Alphas[1] + 3) div 7; + Alphas[7] := (1 * Alphas[0] + 6 * Alphas[1] + 3) div 7; + end + else + begin + // Interpolation of four alphas, two alphas are set directly + Alphas[2] := (4 * Alphas[0] + 1 * Alphas[1] + 2) div 5; + Alphas[3] := (3 * Alphas[0] + 2 * Alphas[1] + 2) div 5; + Alphas[4] := (2 * Alphas[0] + 3 * Alphas[1] + 2) div 5; + Alphas[5] := (1 * Alphas[0] + 4 * Alphas[1] + 2) div 5; + Alphas[6] := 0; + Alphas[7] := $FF; + end; +end; + +procedure DecodeDXT5(SrcBits, DestBits: PByte; Width, Height: LongInt); +var + Sel, X, Y, I, J, K: LongInt; + Block: TDXTColorBlock; + AlphaBlock: TDXTAlphaBlockInt; + Colors: array[0..3] of TColor32Rec; + AMask: array[0..1] of LongWord; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + AlphaBlock := PDXTAlphaBlockInt(SrcBits)^; + Inc(SrcBits, SizeOf(AlphaBlock)); + Block := PDXTColorBlock(SrcBits)^; + Inc(SrcBits, SizeOf(Block)); + // we read and decode endpoint colors + Colors[0] := DecodeCol(Block.Color0); + Colors[1] := DecodeCol(Block.Color1); + // and interpolate between them + Colors[2].R := (Colors[0].R shl 1 + Colors[1].R + 1) div 3; + Colors[2].G := (Colors[0].G shl 1 + Colors[1].G + 1) div 3; + Colors[2].B := (Colors[0].B shl 1 + Colors[1].B + 1) div 3; + Colors[3].R := (Colors[0].R + Colors[1].R shl 1 + 1) div 3; + Colors[3].G := (Colors[0].G + Colors[1].G shl 1 + 1) div 3; + Colors[3].B := (Colors[0].B + Colors[1].B shl 1 + 1) div 3; + // 6 bit alpha mask is copied into two long words for + // easier usage + AMask[0] := PLongWord(@AlphaBlock.Alphas[2])^ and $00FFFFFF; + AMask[1] := PLongWord(@AlphaBlock.Alphas[5])^ and $00FFFFFF; + // alpha interpolation between two endpoint alphas + GetInterpolatedAlphas(AlphaBlock); + + // we distribute the dxt block colors and alphas + // across the 4x4 block of the destination image + // accroding to the dxt block mask and alpha block mask + K := 0; + for J := 0 to 3 do + for I := 0 to 3 do + begin + Sel := (Block.Mask and (3 shl (K shl 1))) shr (K shl 1); + if ((X shl 2 + I) < Width) and ((Y shl 2 + J) < Height) then + begin + Colors[Sel].A := AlphaBlock.Alphas[AMask[J shr 1] and 7]; + PPalette32(DestBits)[(Y shl 2 + J) * Width + (X shl 2 + I)] := + Colors[Sel]; + end; + Inc(K); + AMask[J shr 1] := AMask[J shr 1] shr 3; + end; + end; +end; + +procedure GetBlock(var Block: TPixelBlock; SrcBits: Pointer; XPos, YPos, + Width, Height: LongInt); +var + X, Y, I: LongInt; + Src: PColor32Rec; +begin + I := 0; + // 4x4 pixel block is filled with information about every + // pixel in the block: alpha, original color, 565 color + for Y := 0 to 3 do + for X := 0 to 3 do + begin + Src := @PPalette32(SrcBits)[(YPos shl 2 + Y) * Width + XPos shl 2 + X]; + Block[I].Color := ((Src.R shr 3) shl 11) or ((Src.G shr 2) shl 5) or + (Src.B shr 3); + Block[I].Alpha := Src.A; + Block[I].Orig := Src^; + Inc(I); + end; +end; + +function ColorDistance(const C1, C2: TColor32Rec): LongInt; +{$IFDEF USE_INLINE} inline;{$ENDIF} +begin + Result := (C1.R - C2.R) * (C1.R - C2.R) + + (C1.G - C2.G) * (C1.G - C2.G) + (C1.B - C2.B) * (C1.B - C2.B); +end; + +procedure GetEndpoints(const Block: TPixelBlock; var Ep0, Ep1: Word); +var + I, J, Farthest, Dist: LongInt; + Colors: array[0..15] of TColor32Rec; +begin + // we choose two colors from the pixel block which has the + // largest distance between them + for I := 0 to 15 do + Colors[I] := Block[I].Orig; + Farthest := -1; + for I := 0 to 15 do + for J := I + 1 to 15 do + begin + Dist := ColorDistance(Colors[I], Colors[J]); + if Dist > Farthest then + begin + Farthest := Dist; + Ep0 := Block[I].Color; + Ep1 := Block[J].Color; + end; + end; +end; + +procedure GetAlphaEndpoints(const Block: TPixelBlock; var Min, Max: Byte); +var + I: LongInt; +begin + Min := 255; + Max := 0; + // we choose the lowest and the highest alpha values + for I := 0 to 15 do + begin + if Block[I].Alpha < Min then + Min := Block[I].Alpha; + if Block[I].Alpha > Max then + Max := Block[I].Alpha; + end; +end; + +procedure FixEndpoints(var Ep0, Ep1: Word; HasAlpha: Boolean); +var + Temp: Word; +begin + // if dxt block has alpha information, Ep0 must be smaller + // than Ep1, if the block has no alpha Ep1 must be smaller + if HasAlpha then + begin + if Ep0 > Ep1 then + begin + Temp := Ep0; + Ep0 := Ep1; + Ep1 := Temp; + end; + end + else + if Ep0 < Ep1 then + begin + Temp := Ep0; + Ep0 := Ep1; + Ep1 := Temp; + end; +end; + +function GetColorMask(Ep0, Ep1: Word; NumCols: LongInt; + const Block: TPixelBlock): LongWord; +var + I, J, Closest, Dist: LongInt; + Colors: array[0..3] of TColor32Rec; + Mask: array[0..15] of Byte; +begin + FillChar(Mask, sizeof(Mask), 0); + // we decode endpoint colors + Colors[0] := DecodeCol(Ep0); + Colors[1] := DecodeCol(Ep1); + // and interpolate colors between (3 for DXT1 with alpha, 4 for the others) + if NumCols = 3 then + begin + Colors[2].R := (Colors[0].R + Colors[1].R) shr 1; + Colors[2].G := (Colors[0].G + Colors[1].G) shr 1; + Colors[2].B := (Colors[0].B + Colors[1].B) shr 1; + Colors[3].R := (Colors[0].R + Colors[1].R) shr 1; + Colors[3].G := (Colors[0].G + Colors[1].G) shr 1; + Colors[3].B := (Colors[0].B + Colors[1].B) shr 1; + end + else + begin + Colors[2].R := (Colors[0].R shl 1 + Colors[1].R + 1) div 3; + Colors[2].G := (Colors[0].G shl 1 + Colors[1].G + 1) div 3; + Colors[2].B := (Colors[0].B shl 1 + Colors[1].B + 1) div 3; + Colors[3].R := (Colors[0].R + Colors[1].R shl 1 + 1) div 3; + Colors[3].G := (Colors[0].G + Colors[1].G shl 1 + 1) div 3; + Colors[3].B := (Colors[0].B + Colors[1].B shl 1 + 1) div 3; + end; + + for I := 0 to 15 do + begin + // this is only for DXT1 with alpha + if (Block[I].Alpha < 128) and (NumCols = 3) then + begin + Mask[I] := 3; + Continue; + end; + // for each of the 16 input pixels the nearest color in the + // 4 dxt colors is found + Closest := MaxInt; + for J := 0 to NumCols - 1 do + begin + Dist := ColorDistance(Block[I].Orig, Colors[J]); + if Dist < Closest then + begin + Closest := Dist; + Mask[I] := J; + end; + end; + end; + + Result := 0; + for I := 0 to 15 do + Result := Result or (Mask[I] shl (I shl 1)); +end; + +procedure GetAlphaMask(Ep0, Ep1: Byte; var Block: TPixelBlock; Mask: PByteArray); +var + Alphas: array[0..7] of Byte; + M: array[0..15] of Byte; + I, J, Closest, Dist: LongInt; +begin + FillChar(M, sizeof(M), 0); + Alphas[0] := Ep0; + Alphas[1] := Ep1; + // interpolation between two given alpha endpoints + // (I use 6 interpolated values mode) + Alphas[2] := (6 * Alphas[0] + 1 * Alphas[1] + 3) div 7; + Alphas[3] := (5 * Alphas[0] + 2 * Alphas[1] + 3) div 7; + Alphas[4] := (4 * Alphas[0] + 3 * Alphas[1] + 3) div 7; + Alphas[5] := (3 * Alphas[0] + 4 * Alphas[1] + 3) div 7; + Alphas[6] := (2 * Alphas[0] + 5 * Alphas[1] + 3) div 7; + Alphas[7] := (1 * Alphas[0] + 6 * Alphas[1] + 3) div 7; + + // the closest interpolated values for each of the input alpha + // is found + for I := 0 to 15 do + begin + Closest := MaxInt; + for J := 0 to 7 do + begin + Dist := Abs(Alphas[J] - Block[I].Alpha); + if Dist < Closest then + begin + Closest := Dist; + M[I] := J; + end; + end; + end; + + Mask[0] := M[0] or (M[1] shl 3) or ((M[2] and 3) shl 6); + Mask[1] := ((M[2] and 4) shr 2) or (M[3] shl 1) or (M[4] shl 4) or + ((M[5] and 1) shl 7); + Mask[2] := ((M[5] and 6) shr 1) or (M[6] shl 2) or (M[7] shl 5); + Mask[3] := M[8] or (M[9] shl 3) or ((M[10] and 3) shl 6); + Mask[4] := ((M[10] and 4) shr 2) or (M[11] shl 1) or (M[12] shl 4) or + ((M[13] and 1) shl 7); + Mask[5] := ((M[13] and 6) shr 1) or (M[14] shl 2) or (M[15] shl 5); +end; + + +procedure EncodeDXT1(SrcBits: PByte; DestBits: PByte; Width, Height: LongInt); +var + X, Y, I: LongInt; + HasAlpha: Boolean; + Block: TDXTColorBlock; + Pixels: TPixelBlock; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + GetBlock(Pixels, SrcBits, X, Y, Width, Height); + HasAlpha := False; + for I := 0 to 15 do + if Pixels[I].Alpha < 128 then + begin + HasAlpha := True; + Break; + end; + GetEndpoints(Pixels, Block.Color0, Block.Color1); + FixEndpoints(Block.Color0, Block.Color1, HasAlpha); + if HasAlpha then + Block.Mask := GetColorMask(Block.Color0, Block.Color1, 3, Pixels) + else + Block.Mask := GetColorMask(Block.Color0, Block.Color1, 4, Pixels); + PDXTColorBlock(DestBits)^ := Block; + Inc(DestBits, SizeOf(Block)); + end; +end; + +procedure EncodeDXT3(SrcBits: Pointer; DestBits: PByte; Width, Height: LongInt); +var + X, Y, I: LongInt; + Block: TDXTColorBlock; + AlphaBlock: TDXTAlphaBlockExp; + Pixels: TPixelBlock; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + GetBlock(Pixels, SrcBits, X, Y, Width, Height); + for I := 0 to 7 do + PByteArray(@AlphaBlock.Alphas)[I] := + (Pixels[I shl 1].Alpha shr 4) or ((Pixels[I shl 1 + 1].Alpha shr 4) shl 4); + GetEndpoints(Pixels, Block.Color0, Block.Color1); + FixEndpoints(Block.Color0, Block.Color1, False); + Block.Mask := GetColorMask(Block.Color0, Block.Color1, 4, Pixels); + PDXTAlphaBlockExp(DestBits)^ := AlphaBlock; + Inc(DestBits, SizeOf(AlphaBlock)); + PDXTColorBlock(DestBits)^ := Block; + Inc(DestBits, SizeOf(Block)); + end; +end; + +procedure EncodeDXT5(SrcBits: Pointer; DestBits: PByte; Width, Height: LongInt); +var + X, Y: LongInt; + Block: TDXTColorBlock; + AlphaBlock: TDXTAlphaBlockInt; + Pixels: TPixelBlock; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + GetBlock(Pixels, SrcBits, X, Y, Width, Height); + GetEndpoints(Pixels, Block.Color0, Block.Color1); + FixEndpoints(Block.Color0, Block.Color1, False); + Block.Mask := GetColorMask(Block.Color0, Block.Color1, 4, Pixels); + GetAlphaEndPoints(Pixels, AlphaBlock.Alphas[1], AlphaBlock.Alphas[0]); + GetAlphaMask(AlphaBlock.Alphas[0], AlphaBlock.Alphas[1], Pixels, + PByteArray(@AlphaBlock.Alphas[2])); + PDXTAlphaBlockInt(DestBits)^ := AlphaBlock; + Inc(DestBits, SizeOf(AlphaBlock)); + PDXTColorBlock(DestBits)^ := Block; + Inc(DestBits, SizeOf(Block)); + end; +end; + +type + TBTCBlock = packed record + MLower, MUpper: Byte; + BitField: Word; + end; + PBTCBlock = ^TBTCBlock; + +procedure EncodeBTC(SrcBits: Pointer; DestBits: PByte; Width, Height: Integer); +var + X, Y, I, J: Integer; + Block: TBTCBlock; + M, MLower, MUpper, K: Integer; + Pixels: array[0..15] of Byte; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + M := 0; + MLower := 0; + MUpper := 0; + FillChar(Block, SizeOf(Block), 0); + K := 0; + + // Store 4x4 pixels and compute average, lower, and upper intensity levels + for I := 0 to 3 do + for J := 0 to 3 do + begin + Pixels[K] := PByteArray(SrcBits)[(Y shl 2 + I) * Width + X shl 2 + J]; + Inc(M, Pixels[K]); + Inc(K); + end; + + M := M div 16; + K := 0; + + // Now compute upper and lower levels, number of upper pixels, + // and update bit field (1 when pixel is above avg. level M) + for I := 0 to 15 do + begin + if Pixels[I] > M then + begin + Inc(MUpper, Pixels[I]); + Inc(K); + Block.BitField := Block.BitField or (1 shl I); + end + else + Inc(MLower, Pixels[I]); + end; + + // Scale levels and save them to block + if K > 0 then + Block.MUpper := ClampToByte(MUpper div K) + else + Block.MUpper := 0; + Block.MLower := ClampToByte(MLower div (16 - K)); + + // Finally save block to dest data + PBTCBlock(DestBits)^ := Block; + Inc(DestBits, SizeOf(Block)); + end; +end; + +procedure GetOneChannelBlock(var Block: TPixelBlock; SrcBits: Pointer; XPos, YPos, + Width, Height, BytesPP, ChannelIdx: Integer); +var + X, Y, I: Integer; + Src: PByte; +begin + I := 0; + // 4x4 pixel block is filled with information about every pixel in the block, + // but only one channel value is stored in Alpha field + for Y := 0 to 3 do + for X := 0 to 3 do + begin + Src := @PByteArray(SrcBits)[(YPos * 4 + Y) * Width * BytesPP + + (XPos * 4 + X) * BytesPP + ChannelIdx]; + Block[I].Alpha := Src^; + Inc(I); + end; +end; + +procedure EncodeATI1N(SrcBits: Pointer; DestBits: PByte; Width, Height: Integer); +var + X, Y: Integer; + AlphaBlock: TDXTAlphaBlockInt; + Pixels: TPixelBlock; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + // Encode one channel + GetOneChannelBlock(Pixels, SrcBits, X, Y, Width, Height, 1, 0); + GetAlphaEndPoints(Pixels, AlphaBlock.Alphas[1], AlphaBlock.Alphas[0]); + GetAlphaMask(AlphaBlock.Alphas[0], AlphaBlock.Alphas[1], Pixels, + PByteArray(@AlphaBlock.Alphas[2])); + PDXTAlphaBlockInt(DestBits)^ := AlphaBlock; + Inc(DestBits, SizeOf(AlphaBlock)); + end; +end; + +procedure EncodeATI2N(SrcBits: Pointer; DestBits: PByte; Width, Height: Integer); +var + X, Y: Integer; + AlphaBlock: TDXTAlphaBlockInt; + Pixels: TPixelBlock; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + // Encode Red/X channel + GetOneChannelBlock(Pixels, SrcBits, X, Y, Width, Height, 4, ChannelRed); + GetAlphaEndPoints(Pixels, AlphaBlock.Alphas[1], AlphaBlock.Alphas[0]); + GetAlphaMask(AlphaBlock.Alphas[0], AlphaBlock.Alphas[1], Pixels, + PByteArray(@AlphaBlock.Alphas[2])); + PDXTAlphaBlockInt(DestBits)^ := AlphaBlock; + Inc(DestBits, SizeOf(AlphaBlock)); + // Encode Green/Y channel + GetOneChannelBlock(Pixels, SrcBits, X, Y, Width, Height, 4, ChannelGreen); + GetAlphaEndPoints(Pixels, AlphaBlock.Alphas[1], AlphaBlock.Alphas[0]); + GetAlphaMask(AlphaBlock.Alphas[0], AlphaBlock.Alphas[1], Pixels, + PByteArray(@AlphaBlock.Alphas[2])); + PDXTAlphaBlockInt(DestBits)^ := AlphaBlock; + Inc(DestBits, SizeOf(AlphaBlock)); + end; +end; + +procedure EncodeBinary(SrcBits: Pointer; DestBits: PByte; Width, Height: Integer); +var + Src: PByte absolute SrcBits; + Bitmap: PByteArray absolute DestBits; + X, Y, WidthBytes: Integer; + PixelTresholded, Treshold: Byte; +begin + Treshold := ClampToByte(GetOption(ImagingBinaryTreshold)); + WidthBytes := (Width + 7) div 8; + + for Y := 0 to Height - 1 do + for X := 0 to Width - 1 do + begin + if Src^ > Treshold then + PixelTresholded := 255 + else + PixelTresholded := 0; + + Bitmap[Y * WidthBytes + X div 8] := Bitmap[Y * WidthBytes + X div 8] or // OR current value of byte with following: + (PixelTresholded and 1) // To make 1 from 255, 0 remains 0 + shl (7 - (X mod 8)); // Put current bit to proper place in byte + + Inc(Src); + end; +end; + +procedure DecodeBTC(SrcBits, DestBits: PByte; Width, Height: Integer); +var + X, Y, I, J, K: Integer; + Block: TBTCBlock; + Dest: PByte; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + Block := PBTCBlock(SrcBits)^; + Inc(SrcBits, SizeOf(Block)); + K := 0; + + // Just write MUpper when there is '1' in bit field and MLower + // when there is '0' + for I := 0 to 3 do + for J := 0 to 3 do + begin + Dest := @PByteArray(DestBits)[(Y shl 2 + I) * Width + X shl 2 + J]; + if Block.BitField and (1 shl K) <> 0 then + Dest^ := Block.MUpper + else + Dest^ := Block.MLower; + Inc(K); + end; + end; +end; + +procedure DecodeATI1N(SrcBits, DestBits: PByte; Width, Height: Integer); +var + X, Y, I, J: Integer; + AlphaBlock: TDXTAlphaBlockInt; + AMask: array[0..1] of LongWord; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + AlphaBlock := PDXTAlphaBlockInt(SrcBits)^; + Inc(SrcBits, SizeOf(AlphaBlock)); + // 6 bit alpha mask is copied into two long words for + // easier usage + AMask[0] := PLongWord(@AlphaBlock.Alphas[2])^ and $00FFFFFF; + AMask[1] := PLongWord(@AlphaBlock.Alphas[5])^ and $00FFFFFF; + // alpha interpolation between two endpoint alphas + GetInterpolatedAlphas(AlphaBlock); + + // we distribute the dxt block alphas + // across the 4x4 block of the destination image + for J := 0 to 3 do + for I := 0 to 3 do + begin + PByteArray(DestBits)[(Y shl 2 + J) * Width + (X shl 2 + I)] := + AlphaBlock.Alphas[AMask[J shr 1] and 7]; + AMask[J shr 1] := AMask[J shr 1] shr 3; + end; + end; +end; + +procedure DecodeATI2N(SrcBits, DestBits: PByte; Width, Height: Integer); +var + X, Y, I, J: Integer; + Color: TColor32Rec; + AlphaBlock1, AlphaBlock2: TDXTAlphaBlockInt; + AMask1: array[0..1] of LongWord; + AMask2: array[0..1] of LongWord; +begin + for Y := 0 to Height div 4 - 1 do + for X := 0 to Width div 4 - 1 do + begin + // Read the first alpha block and get masks + AlphaBlock1 := PDXTAlphaBlockInt(SrcBits)^; + Inc(SrcBits, SizeOf(AlphaBlock1)); + AMask1[0] := PLongWord(@AlphaBlock1.Alphas[2])^ and $00FFFFFF; + AMask1[1] := PLongWord(@AlphaBlock1.Alphas[5])^ and $00FFFFFF; + // Read the secind alpha block and get masks + AlphaBlock2 := PDXTAlphaBlockInt(SrcBits)^; + Inc(SrcBits, SizeOf(AlphaBlock2)); + AMask2[0] := PLongWord(@AlphaBlock2.Alphas[2])^ and $00FFFFFF; + AMask2[1] := PLongWord(@AlphaBlock2.Alphas[5])^ and $00FFFFFF; + // alpha interpolation between two endpoint alphas + GetInterpolatedAlphas(AlphaBlock1); + GetInterpolatedAlphas(AlphaBlock2); + + Color.A := $FF; + Color.B := 0; + + // Distribute alpha block values across 4x4 pixel block, + // first alpha block represents Red channel, second is Green. + for J := 0 to 3 do + for I := 0 to 3 do + begin + Color.R := AlphaBlock1.Alphas[AMask1[J shr 1] and 7]; + Color.G := AlphaBlock2.Alphas[AMask2[J shr 1] and 7]; + PColor32RecArray(DestBits)[(Y shl 2 + J) * Width + (X shl 2 + I)] := Color; + AMask1[J shr 1] := AMask1[J shr 1] shr 3; + AMask2[J shr 1] := AMask2[J shr 1] shr 3; + end; + end; +end; + +procedure DecodeBinary(SrcBits, DestBits: PByte; Width, Height: Integer); {$IFDEF USE_INLINE}inline;{$ENDIF} +begin + Convert1To8(SrcBits, DestBits, Width, Height, (Width + 7) div 8, True); +end; + +procedure SpecialToUnSpecial(const SrcImage: TImageData; DestBits: Pointer; + SpecialFormat: TImageFormat); +begin + case SpecialFormat of + ifDXT1: DecodeDXT1(SrcImage.Bits, DestBits, SrcImage.Width, SrcImage.Height); + ifDXT3: DecodeDXT3(SrcImage.Bits, DestBits, SrcImage.Width, SrcImage.Height); + ifDXT5: DecodeDXT5(SrcImage.Bits, DestBits, SrcImage.Width, SrcImage.Height); + ifBTC: DecodeBTC (SrcImage.Bits, DestBits, SrcImage.Width, SrcImage.Height); + ifATI1N: DecodeATI1N(SrcImage.Bits, DestBits, SrcImage.Width, SrcImage.Height); + ifATI2N: DecodeATI2N(SrcImage.Bits, DestBits, SrcImage.Width, SrcImage.Height); + ifBinary: DecodeBinary(SrcImage.Bits, DestBits, SrcImage.Width, SrcImage.Height); + end; +end; + +procedure UnSpecialToSpecial(SrcBits: Pointer; const DestImage: TImageData; + SpecialFormat: TImageFormat); +begin + case SpecialFormat of + ifDXT1: EncodeDXT1(SrcBits, DestImage.Bits, DestImage.Width, DestImage.Height); + ifDXT3: EncodeDXT3(SrcBits, DestImage.Bits, DestImage.Width, DestImage.Height); + ifDXT5: EncodeDXT5(SrcBits, DestImage.Bits, DestImage.Width, DestImage.Height); + ifBTC: EncodeBTC (SrcBits, DestImage.Bits, DestImage.Width, DestImage.Height); + ifATI1N: EncodeATI1N(SrcBits, DestImage.Bits, DestImage.Width, DestImage.Height); + ifATI2N: EncodeATI2N(SrcBits, DestImage.Bits, DestImage.Width, DestImage.Height); + ifBinary: EncodeBinary(SrcBits, DestImage.Bits, DestImage.Width, DestImage.Height); + end; +end; + +procedure ConvertSpecial(var Image: TImageData; + SrcInfo, DstInfo: PImageFormatInfo); +var + WorkImage: TImageData; + + procedure CheckSize(var Img: TImageData; Info: PImageFormatInfo); + var + Width, Height: Integer; + begin + Width := Img.Width; + Height := Img.Height; + DstInfo.CheckDimensions(Info.Format, Width, Height); + ResizeImage(Img, Width, Height, rfNearest); + end; + +begin + if SrcInfo.IsSpecial and DstInfo.IsSpecial then + begin + // Convert source to nearest 'normal' format + InitImage(WorkImage); + NewImage(Image.Width, Image.Height, SrcInfo.SpecialNearestFormat, WorkImage); + SpecialToUnSpecial(Image, WorkImage.Bits, SrcInfo.Format); + FreeImage(Image); + // Make sure output of SpecialToUnSpecial is the same as input of + // UnSpecialToSpecial + if SrcInfo.SpecialNearestFormat <> DstInfo.SpecialNearestFormat then + ConvertImage(WorkImage, DstInfo.SpecialNearestFormat); + // Convert work image to dest special format + CheckSize(WorkImage, DstInfo); + NewImage(WorkImage.Width, WorkImage.Height, DstInfo.Format, Image); + UnSpecialToSpecial(WorkImage.Bits, Image, DstInfo.Format); + FreeImage(WorkImage); + end + else if SrcInfo.IsSpecial and not DstInfo.IsSpecial then + begin + // Convert source to nearest 'normal' format + InitImage(WorkImage); + NewImage(Image.Width, Image.Height, SrcInfo.SpecialNearestFormat, WorkImage); + SpecialToUnSpecial(Image, WorkImage.Bits, SrcInfo.Format); + FreeImage(Image); + // Now convert to dest format + ConvertImage(WorkImage, DstInfo.Format); + Image := WorkImage; + end + else if not SrcInfo.IsSpecial and DstInfo.IsSpecial then + begin + // Convert source to nearest format + WorkImage := Image; + ConvertImage(WorkImage, DstInfo.SpecialNearestFormat); + // Now convert from nearest to dest + CheckSize(WorkImage, DstInfo); + InitImage(Image); + NewImage(WorkImage.Width, WorkImage.Height, DstInfo.Format, Image); + UnSpecialToSpecial(WorkImage.Bits, Image, DstInfo.Format); + FreeImage(WorkImage); + end; +end; + +function GetStdPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; +begin + if FInfos[Format] <> nil then + Result := Width * Height * FInfos[Format].BytesPerPixel + else + Result := 0; +end; + +procedure CheckStdDimensions(Format: TImageFormat; var Width, Height: LongInt); +begin +end; + +function GetDXTPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; +begin + // DXT can be used only for images with dimensions that are + // multiples of four + CheckDXTDimensions(Format, Width, Height); + Result := Width * Height; + if Format in [ifDXT1, ifATI1N] then + Result := Result div 2; +end; + +procedure CheckDXTDimensions(Format: TImageFormat; var Width, Height: LongInt); +begin + // DXT image dimensions must be multiples of four + Width := (Width + 3) and not 3; // div 4 * 4; + Height := (Height + 3) and not 3; // div 4 * 4; +end; + +function GetBTCPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; +begin + // BTC can be used only for images with dimensions that are + // multiples of four + CheckDXTDimensions(Format, Width, Height); + Result := Width * Height div 4; // 2bits/pixel +end; + +function GetBCPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; +begin + raise ENotImplemented.Create(); +end; + +procedure CheckBCDimensions(Format: TImageFormat; var Width, Height: LongInt); +begin + raise ENotImplemented.Create(); +end; + +function GetBinaryPixelsSize(Format: TImageFormat; Width, Height: LongInt): LongInt; +begin + // Binary images are aligned on BYTE boundary + Result := ((Width + 7) div 8) * Height; // 1bit/pixel +end; + +{ Optimized pixel readers/writers for 32bit and FP colors to be stored in TImageFormatInfo } + +function GetPixel32ifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColor32Rec; +begin + Result.Color := PLongWord(Bits)^; +end; + +procedure SetPixel32ifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColor32Rec); +begin + PLongWord(Bits)^ := Color.Color; +end; + +function GetPixelFPifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColorFPRec; +begin + Result.A := PColor32Rec(Bits).A * OneDiv8Bit; + Result.R := PColor32Rec(Bits).R * OneDiv8Bit; + Result.G := PColor32Rec(Bits).G * OneDiv8Bit; + Result.B := PColor32Rec(Bits).B * OneDiv8Bit; +end; + +procedure SetPixelFPifA8R8G8B8(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColorFPRec); +begin + PColor32Rec(Bits).A := ClampToByte(Round(Color.A * 255.0)); + PColor32Rec(Bits).R := ClampToByte(Round(Color.R * 255.0)); + PColor32Rec(Bits).G := ClampToByte(Round(Color.G * 255.0)); + PColor32Rec(Bits).B := ClampToByte(Round(Color.B * 255.0)); +end; + +function GetPixel32Channel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColor32Rec; +begin + Result.A := 0; + Result.R := 0; + Result.G := 0; + Result.B := 0; + case Info.Format of + ifR8G8B8, ifX8R8G8B8: + begin + Result.A := $FF; + PColor24Rec(@Result)^ := PColor24Rec(Bits)^; + end; + ifGray8, ifA8Gray8: + begin + if Info.HasAlphaChannel then + Result.A := PWordRec(Bits).High + else + Result.A := $FF; + Result.R := PWordRec(Bits).Low; + Result.G := PWordRec(Bits).Low; + Result.B := PWordRec(Bits).Low; + end; + end; +end; + +procedure SetPixel32Channel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColor32Rec); +begin + case Info.Format of + ifR8G8B8, ifX8R8G8B8: + begin + PColor24Rec(Bits)^ := PColor24Rec(@Color)^; + end; + ifGray8, ifA8Gray8: + begin + if Info.HasAlphaChannel then + PWordRec(Bits).High := Color.A; + PWordRec(Bits).Low := Round(GrayConv.R * Color.R + GrayConv.G * Color.G + + GrayConv.B * Color.B); + end; + end; +end; + +function GetPixelFPChannel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColorFPRec; +begin + Result.A := 0; + Result.R := 0; + Result.G := 0; + Result.B := 0; + case Info.Format of + ifR8G8B8, ifX8R8G8B8: + begin + Result.A := 1.0; + Result.R := PColor24Rec(Bits).R * OneDiv8Bit; + Result.G := PColor24Rec(Bits).G * OneDiv8Bit; + Result.B := PColor24Rec(Bits).B * OneDiv8Bit; + end; + ifGray8, ifA8Gray8: + begin + if Info.HasAlphaChannel then + Result.A := PWordRec(Bits).High * OneDiv8Bit + else + Result.A := 1.0; + Result.R := PWordRec(Bits).Low * OneDiv8Bit; + Result.G := PWordRec(Bits).Low * OneDiv8Bit; + Result.B := PWordRec(Bits).Low * OneDiv8Bit; + end; + end; +end; + +procedure SetPixelFPChannel8Bit(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColorFPRec); +begin + case Info.Format of + ifR8G8B8, ifX8R8G8B8: + begin + PColor24Rec(Bits).R := ClampToByte(Round(Color.R * 255.0)); + PColor24Rec(Bits).G := ClampToByte(Round(Color.G * 255.0)); + PColor24Rec(Bits).B := ClampToByte(Round(Color.B * 255.0)); + end; + ifGray8, ifA8Gray8: + begin + if Info.HasAlphaChannel then + PWordRec(Bits).High := ClampToByte(Round(Color.A * 255.0)); + PWordRec(Bits).Low := ClampToByte(Round((GrayConv.R * Color.R + GrayConv.G * Color.G + + GrayConv.B * Color.B) * 255.0)); + end; + end; +end; + +function GetPixelFPFloat32(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32): TColorFPRec; +begin + case Info.Format of + ifA32R32G32B32F, ifA32B32G32R32F: + begin + Result := PColorFPRec(Bits)^; + end; + ifR32G32B32F, ifB32G32R32F: + begin + Result.A := 1.0; + Result.Color96Rec := PColor96FPRec(Bits)^; + end; + ifR32F: + begin + Result.A := 1.0; + Result.R := PSingle(Bits)^; + Result.G := 0.0; + Result.B := 0.0; + end; + end; + if Info.IsRBSwapped then + SwapValues(Result.R, Result.B); +end; + +procedure SetPixelFPFloat32(Bits: Pointer; Info: PImageFormatInfo; Palette: PPalette32; const Color: TColorFPRec); +begin + case Info.Format of + ifA32R32G32B32F, ifA32B32G32R32F: + begin + PColorFPRec(Bits)^ := Color; + end; + ifR32G32B32F, ifB32G32R32F: + begin + PColor96FPRec(Bits)^ := Color.Color96Rec; + end; + ifR32F: + begin + PSingle(Bits)^ := Color.R; + end; + end; + if Info.IsRBSwapped then + SwapValues(PColor96FPRec(Bits).R, PColor96FPRec(Bits).B); +end; + +initialization + // Initialize default sampling filter function pointers and radii + SamplingFilterFunctions[sfNearest] := FilterNearest; + SamplingFilterFunctions[sfLinear] := FilterLinear; + SamplingFilterFunctions[sfCosine] := FilterCosine; + SamplingFilterFunctions[sfHermite] := FilterHermite; + SamplingFilterFunctions[sfQuadratic] := FilterQuadratic; + SamplingFilterFunctions[sfGaussian] := FilterGaussian; + SamplingFilterFunctions[sfSpline] := FilterSpline; + SamplingFilterFunctions[sfLanczos] := FilterLanczos; + SamplingFilterFunctions[sfMitchell] := FilterMitchell; + SamplingFilterFunctions[sfCatmullRom] := FilterCatmullRom; + SamplingFilterRadii[sfNearest] := 1.0; + SamplingFilterRadii[sfLinear] := 1.0; + SamplingFilterRadii[sfCosine] := 1.0; + SamplingFilterRadii[sfHermite] := 1.0; + SamplingFilterRadii[sfQuadratic] := 1.5; + SamplingFilterRadii[sfGaussian] := 1.25; + SamplingFilterRadii[sfSpline] := 2.0; + SamplingFilterRadii[sfLanczos] := 3.0; + SamplingFilterRadii[sfMitchell] := 2.0; + SamplingFilterRadii[sfCatmullRom] := 2.0; + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77 Changes/Bug Fixes ------------------------------------- + - NOT YET: Added support for Passtrough image data formats. + - Added ConvertToPixel32 helper function. + + -- 0.26.5 Changes/Bug Fixes ----------------------------------- + - Removed optimized codepatch for few data formats from StretchResample + function. It was quite buggy and not so much faster anyway. + - Added PaletteHasAlpha function. + - Added support functions for ifBinary data format. + - Added optional pixel scaling to Convert1To8, Convert2To8, + abd Convert4To8 functions. + + -- 0.26.3 Changes/Bug Fixes ----------------------------------- + - Filtered resampling ~10% faster now. + - Fixed DXT3 alpha encoding. + - ifIndex8 format now has HasAlphaChannel=True. + + -- 0.25.0 Changes/Bug Fixes ----------------------------------- + - Made some resampling stuff public so that it can be used in canvas class. + - Added some color constructors. + - Added VisualizePalette helper function. + - Fixed ConvertSpecial, not very readable before and error when + converting special->special. + + -- 0.24.3 Changes/Bug Fixes ----------------------------------- + - Some refactorings a changes to DXT based formats. + - Added ifATI1N and ifATI2N image data formats support structures and functions. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added ifBTC image format support structures and functions. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - FillMipMapLevel now works well with indexed and special formats too. + - Moved Convert1To8 and Convert4To8 functions from ImagingBitmaps here + and created new Convert2To8 function. They are now used by more than one + file format loader. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - StretchResample now uses pixel get/set functions stored in + TImageFormatInfo so it is much faster for formats that override + them with optimized ones + - added pixel set/get functions optimized for various image formats + (to be stored in TImageFormatInfo) + - bug in ConvertSpecial caused problems when converting DXTC images + to bitmaps in ImagingCoponents + - bug in StretchRect caused that it didn't work with ifR32F and + ifR16F formats + - removed leftover code in FillMipMapLevel which disabled + filtered resizing of images witch ChannelSize <> 8bits + - added half float converting functions and support for half based + image formats where needed + - added TranslatePixel and IsImageFormatValid functions + - fixed possible range overflows when converting from FP to integer images + - added pixel set/get functions: GetPixel32Generic, GetPixelFPGeneric, + SetPixel32Generic, SetPixelFPGeneric + - fixed occasional range overflows in StretchResample + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - added StretchNearest, StretchResample and some sampling functions + - added ChannelCount values to TImageFormatInfo constants + - added resolution validity check to GetDXTPixelsSize + + -- 0.15 Changes/Bug Fixes ----------------------------------- + - added RBSwapFormat values to some TImageFromatInfo definitions + - fixed bug in ConvertSpecial (causing DXT images to convert only to 32bit) + - added CopyPixel, ComparePixels helper functions + + -- 0.13 Changes/Bug Fixes ----------------------------------- + - replaced pixel format conversions for colors not to be + darkened when converting from low bit counts + - ReduceColorsMedianCut was updated to support creating one + optimal palette for more images and it is somewhat faster + now too + - there was ugly bug in DXTC dimensions checking +} + +end. diff --git a/src/lib/vampimg/ImagingGif.pas b/src/lib/vampimg/ImagingGif.pas new file mode 100644 index 0000000..a38e33a --- /dev/null +++ b/src/lib/vampimg/ImagingGif.pas @@ -0,0 +1,1291 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader/saver for GIF images.} +unit ImagingGif; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, Classes, Imaging, ImagingTypes, ImagingIO, ImagingUtility; + +type + { GIF (Graphics Interchange Format) loader/saver class. GIF was + (and is still used) popular format for storing images supporting + multiple images per file and single color transparency. + Pixel format is 8 bit indexed where each image frame can have + its own color palette. GIF uses lossless LZW compression + (patent expired few years ago). + Imaging can load and save all GIFs with all frames and supports + transparency. Imaging can load just raw ifIndex8 frames or + also animate them in ifA8R8G8B8 format. See ImagingGIFLoadAnimated option.} + TGIFFileFormat = class(TImageFileFormat) + private + FLoadAnimated: LongBool; + function InterlaceStep(Y, Height: Integer; var Pass: Integer): Integer; + procedure LZWDecompress(Stream: TStream; Handle: TImagingHandle; + Width, Height: Integer; Interlaced: Boolean; Data: Pointer); + procedure LZWCompress(const IO: TIOFunctions; Handle: TImagingHandle; + Width, Height, BitCount: Integer; Interlaced: Boolean; Data: Pointer); + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + published + property LoadAnimated: LongBool read FLoadAnimated write FLoadAnimated; + end; + +implementation + +const + SGIFFormatName = 'Graphics Interchange Format'; + SGIFMasks = '*.gif'; + GIFSupportedFormats: TImageFormats = [ifIndex8]; + GIFDefaultLoadAnimated = True; + +type + TGIFVersion = (gv87, gv89); + TDisposalMethod = (dmNoRemoval, dmLeave, dmRestoreBackground, + dmRestorePrevious, dmReserved4, dmReserved5, dmReserved6, dmReserved7); + +const + GIFSignature: TChar3 = 'GIF'; + GIFVersions: array[TGIFVersion] of TChar3 = ('87a', '89a'); + GIFDefaultDelay = 65; + + // Masks for accessing fields in PackedFields of TGIFHeader + GIFGlobalColorTable = $80; + GIFColorResolution = $70; + GIFColorTableSorted = $08; + GIFColorTableSize = $07; + + // Masks for accessing fields in PackedFields of TImageDescriptor + GIFLocalColorTable = $80; + GIFInterlaced = $40; + GIFLocalTableSorted = $20; + + // Block identifiers + GIFPlainText: Byte = $01; + GIFGraphicControlExtension: Byte = $F9; + GIFCommentExtension: Byte = $FE; + GIFApplicationExtension: Byte = $FF; + GIFImageDescriptor: Byte = Ord(','); + GIFExtensionIntroducer: Byte = Ord('!'); + GIFTrailer: Byte = Ord(';'); + GIFBlockTerminator: Byte = $00; + + // Masks for accessing fields in PackedFields of TGraphicControlExtension + GIFTransparent = $01; + GIFUserInput = $02; + GIFDisposalMethod = $1C; + +const + // Netscape sub block types + GIFAppLoopExtension = 1; + GIFAppBufferExtension = 2; + +type + TGIFHeader = packed record + // File header part + Signature: TChar3; // Header Signature (always "GIF") + Version: TChar3; // GIF format version("87a" or "89a") + // Logical Screen Descriptor part + ScreenWidth: Word; // Width of Display Screen in Pixels + ScreenHeight: Word; // Height of Display Screen in Pixels + PackedFields: Byte; // Screen and color map information + BackgroundColorIndex: Byte; // Background color index (in global color table) + AspectRatio: Byte; // Pixel aspect ratio, ratio = (AspectRatio + 15) / 64 + end; + + TImageDescriptor = packed record + //Separator: Byte; // leave that out since we always read one bye ahead + Left: Word; // X position of image with respect to logical screen + Top: Word; // Y position + Width: Word; + Height: Word; + PackedFields: Byte; + end; + +const + // GIF extension labels + GIFExtTypeGraphic = $F9; + GIFExtTypePlainText = $01; + GIFExtTypeApplication = $FF; + GIFExtTypeComment = $FE; + +type + TGraphicControlExtension = packed record + BlockSize: Byte; + PackedFields: Byte; + DelayTime: Word; + TransparentColorIndex: Byte; + Terminator: Byte; + end; + +type + TGIFIdentifierCode = array[0..7] of AnsiChar; + TGIFAuthenticationCode = array[0..2] of AnsiChar; + TGIFApplicationRec = packed record + Identifier: TGIFIdentifierCode; + Authentication: TGIFAuthenticationCode; + end; + +const + CodeTableSize = 4096; + HashTableSize = 17777; + +type + TReadContext = record + Inx: Integer; + Size: Integer; + Buf: array [0..255 + 4] of Byte; + CodeSize: Integer; + ReadMask: Integer; + end; + PReadContext = ^TReadContext; + + TWriteContext = record + Inx: Integer; + CodeSize: Integer; + Buf: array [0..255 + 4] of Byte; + end; + PWriteContext = ^TWriteContext; + + TOutputContext = record + W: Integer; + H: Integer; + X: Integer; + Y: Integer; + BitsPerPixel: Integer; + Pass: Integer; + Interlace: Boolean; + LineIdent: Integer; + Data: Pointer; + CurrLineData: Pointer; + end; + + TImageDict = record + Tail: Word; + Index: Word; + Col: Byte; + end; + PImageDict = ^TImageDict; + + PIntCodeTable = ^TIntCodeTable; + TIntCodeTable = array [0..CodeTableSize - 1] of Word; + + TDictTable = array [0..CodeTableSize - 1] of TImageDict; + PDictTable = ^TDictTable; + +resourcestring + SGIFDecodingError = 'Error when decoding GIF LZW data'; + +{ + TGIFFileFormat implementation +} + +procedure TGIFFileFormat.Define; +begin + inherited; + FName := SGIFFormatName; + FFeatures := [ffLoad, ffSave, ffMultiImage]; + FSupportedFormats := GIFSupportedFormats; + FLoadAnimated := GIFDefaultLoadAnimated; + + AddMasks(SGIFMasks); + RegisterOption(ImagingGIFLoadAnimated, @FLoadAnimated); +end; + +function TGIFFileFormat.InterlaceStep(Y, Height: Integer; var Pass: Integer): Integer; +begin + Result := Y; + case Pass of + 0, 1: + Inc(Result, 8); + 2: + Inc(Result, 4); + 3: + Inc(Result, 2); + end; + if Result >= Height then + begin + if Pass = 0 then + begin + Pass := 1; + Result := 4; + if Result < Height then + Exit; + end; + if Pass = 1 then + begin + Pass := 2; + Result := 2; + if Result < Height then + Exit; + end; + if Pass = 2 then + begin + Pass := 3; + Result := 1; + end; + end; +end; + +{ GIF LZW decompresion code is from JVCL JvGIF.pas unit.} +procedure TGIFFileFormat.LZWDecompress(Stream: TStream; Handle: TImagingHandle; Width, Height: Integer; + Interlaced: Boolean; Data: Pointer); +var + MinCodeSize: Byte; + MaxCode, BitMask, InitCodeSize: Integer; + ClearCode, EndingCode, FirstFreeCode, FreeCode: Word; + I, OutCount, Code: Integer; + CurCode, OldCode, InCode, FinalChar: Word; + Prefix, Suffix, OutCode: PIntCodeTable; + ReadCtxt: TReadContext; + OutCtxt: TOutputContext; + TableFull: Boolean; + + function ReadCode(var Context: TReadContext): Integer; + var + RawCode: Integer; + ByteIndex: Integer; + Bytes: Byte; + BytesToLose: Integer; + begin + while (Context.Inx + Context.CodeSize > Context.Size) and + (Stream.Position < Stream.Size) do + begin + // Not enough bits in buffer - refill it - Not very efficient, but infrequently called + BytesToLose := Context.Inx shr 3; + // Note biggest Code Size is 12 bits. And this can at worst span 3 Bytes + Move(Context.Buf[Word(BytesToLose)], Context.Buf[0], 3); + Context.Inx := Context.Inx and 7; + Context.Size := Context.Size - (BytesToLose shl 3); + Stream.Read(Bytes, 1); + if Bytes > 0 then + Stream.Read(Context.Buf[Word(Context.Size shr 3)], Bytes); + Context.Size := Context.Size + (Bytes shl 3); + end; + ByteIndex := Context.Inx shr 3; + RawCode := Context.Buf[Word(ByteIndex)] + + (Word(Context.Buf[Word(ByteIndex + 1)]) shl 8); + if Context.CodeSize > 8 then + RawCode := RawCode + (Integer(Context.Buf[ByteIndex + 2]) shl 16); + RawCode := RawCode shr (Context.Inx and 7); + Context.Inx := Context.Inx + Byte(Context.CodeSize); + Result := RawCode and Context.ReadMask; + end; + + procedure Output(Value: Byte; var Context: TOutputContext); + var + P: PByte; + begin + if Context.Y >= Context.H then + Exit; + + // Only ifIndex8 supported + P := @PByteArray(Context.CurrLineData)[Context.X]; + P^ := Value; + + {case Context.BitsPerPixel of + 1: + begin + P := @PByteArray(Context.CurrLineData)[Context.X shr 3]; + if (Context.X and $07) <> 0 then + P^ := P^ or Word(Value shl (7 - (Word(Context.X and 7)))) + else + P^ := Byte(Value shl 7); + end; + 4: + begin + P := @PByteArray(Context.CurrLineData)[Context.X shr 1]; + if (Context.X and 1) <> 0 then + P^ := P^ or Value + else + P^ := Byte(Value shl 4); + end; + 8: + begin + P := @PByteArray(Context.CurrLineData)[Context.X]; + P^ := Value; + end; + end;} + Inc(Context.X); + + if Context.X < Context.W then + Exit; + Context.X := 0; + if Context.Interlace then + Context.Y := InterlaceStep(Context.Y, Context.H, Context.Pass) + else + Inc(Context.Y); + + Context.CurrLineData := @PByteArray(Context.Data)[Context.Y * Context.LineIdent]; + end; + +begin + OutCount := 0; + OldCode := 0; + FinalChar := 0; + TableFull := False; + GetMem(Prefix, SizeOf(TIntCodeTable)); + GetMem(Suffix, SizeOf(TIntCodeTable)); + GetMem(OutCode, SizeOf(TIntCodeTable) + SizeOf(Word)); + try + Stream.Read(MinCodeSize, 1); + if (MinCodeSize < 2) or (MinCodeSize > 9) then + RaiseImaging(SGIFDecodingError, []); + // Initial read context + ReadCtxt.Inx := 0; + ReadCtxt.Size := 0; + ReadCtxt.CodeSize := MinCodeSize + 1; + ReadCtxt.ReadMask := (1 shl ReadCtxt.CodeSize) - 1; + // Initialise pixel-output context + OutCtxt.X := 0; + OutCtxt.Y := 0; + OutCtxt.Pass := 0; + OutCtxt.W := Width; + OutCtxt.H := Height; + OutCtxt.BitsPerPixel := MinCodeSize; + OutCtxt.Interlace := Interlaced; + OutCtxt.LineIdent := Width; + OutCtxt.Data := Data; + OutCtxt.CurrLineData := Data; + BitMask := (1 shl OutCtxt.BitsPerPixel) - 1; + // 2 ^ MinCodeSize accounts for all colours in file + ClearCode := 1 shl MinCodeSize; + EndingCode := ClearCode + 1; + FreeCode := ClearCode + 2; + FirstFreeCode := FreeCode; + // 2^ (MinCodeSize + 1) includes clear and eoi Code and space too + InitCodeSize := ReadCtxt.CodeSize; + MaxCode := 1 shl ReadCtxt.CodeSize; + Code := ReadCode(ReadCtxt); + while (Code <> EndingCode) and (Code <> $FFFF) and + (OutCtxt.Y < OutCtxt.H) do + begin + if Code = ClearCode then + begin + ReadCtxt.CodeSize := InitCodeSize; + MaxCode := 1 shl ReadCtxt.CodeSize; + ReadCtxt.ReadMask := MaxCode - 1; + FreeCode := FirstFreeCode; + Code := ReadCode(ReadCtxt); + CurCode := Code; + OldCode := Code; + if Code = $FFFF then + Break; + FinalChar := (CurCode and BitMask); + Output(Byte(FinalChar), OutCtxt); + TableFull := False; + end + else + begin + CurCode := Code; + InCode := Code; + if CurCode >= FreeCode then + begin + CurCode := OldCode; + OutCode^[OutCount] := FinalChar; + Inc(OutCount); + end; + while CurCode > BitMask do + begin + if OutCount > CodeTableSize then + RaiseImaging(SGIFDecodingError, []); + OutCode^[OutCount] := Suffix^[CurCode]; + Inc(OutCount); + CurCode := Prefix^[CurCode]; + end; + + FinalChar := CurCode and BitMask; + OutCode^[OutCount] := FinalChar; + Inc(OutCount); + for I := OutCount - 1 downto 0 do + Output(Byte(OutCode^[I]), OutCtxt); + OutCount := 0; + // Update dictionary + if not TableFull then + begin + Prefix^[FreeCode] := OldCode; + Suffix^[FreeCode] := FinalChar; + // Advance to next free slot + Inc(FreeCode); + if FreeCode >= MaxCode then + begin + if ReadCtxt.CodeSize < 12 then + begin + Inc(ReadCtxt.CodeSize); + MaxCode := MaxCode shl 1; + ReadCtxt.ReadMask := (1 shl ReadCtxt.CodeSize) - 1; + end + else + TableFull := True; + end; + end; + OldCode := InCode; + end; + Code := ReadCode(ReadCtxt); + end; + if Code = $FFFF then + RaiseImaging(SGIFDecodingError, []); + finally + FreeMem(Prefix); + FreeMem(OutCode); + FreeMem(Suffix); + end; +end; + +{ GIF LZW compresion code is from JVCL JvGIF.pas unit.} +procedure TGIFFileFormat.LZWCompress(const IO: TIOFunctions; Handle: TImagingHandle; Width, Height, BitCount: Integer; + Interlaced: Boolean; Data: Pointer); +var + LineIdent: Integer; + MinCodeSize, Col: Byte; + InitCodeSize, X, Y: Integer; + Pass: Integer; + MaxCode: Integer; { 1 shl CodeSize } + ClearCode, EndingCode, LastCode, Tail: Integer; + I, HashValue: Integer; + LenString: Word; + Dict: PDictTable; + HashTable: TList; + PData: PByte; + WriteCtxt: TWriteContext; + + function InitHash(P: Integer): Integer; + begin + Result := (P + 3) * 301; + end; + + procedure WriteCode(Code: Integer; var Context: TWriteContext); + var + BufIndex: Integer; + Bytes: Byte; + begin + BufIndex := Context.Inx shr 3; + Code := Code shl (Context.Inx and 7); + Context.Buf[BufIndex] := Context.Buf[BufIndex] or Byte(Code); + Context.Buf[BufIndex + 1] := Byte(Code shr 8); + Context.Buf[BufIndex + 2] := Byte(Code shr 16); + Context.Inx := Context.Inx + Context.CodeSize; + if Context.Inx >= 255 * 8 then + begin + // Flush out full buffer + Bytes := 255; + IO.Write(Handle, @Bytes, 1); + IO.Write(Handle, @Context.Buf, Bytes); + Move(Context.Buf[255], Context.Buf[0], 2); + FillChar(Context.Buf[2], 255, 0); + Context.Inx := Context.Inx - (255 * 8); + end; + end; + + procedure FlushCode(var Context: TWriteContext); + var + Bytes: Byte; + begin + Bytes := (Context.Inx + 7) shr 3; + if Bytes > 0 then + begin + IO.Write(Handle, @Bytes, 1); + IO.Write(Handle, @Context.Buf, Bytes); + end; + // Data block terminator - a block of zero Size + Bytes := 0; + IO.Write(Handle, @Bytes, 1); + end; + +begin + LineIdent := Width; + Tail := 0; + HashValue := 0; + Col := 0; + HashTable := TList.Create; + GetMem(Dict, SizeOf(TDictTable)); + try + for I := 0 to HashTableSize - 1 do + HashTable.Add(nil); + + // Initialise encoder variables + InitCodeSize := BitCount + 1; + if InitCodeSize = 2 then + Inc(InitCodeSize); + MinCodeSize := InitCodeSize - 1; + IO.Write(Handle, @MinCodeSize, 1); + ClearCode := 1 shl MinCodeSize; + EndingCode := ClearCode + 1; + LastCode := EndingCode; + MaxCode := 1 shl InitCodeSize; + LenString := 0; + // Setup write context + WriteCtxt.Inx := 0; + WriteCtxt.CodeSize := InitCodeSize; + FillChar(WriteCtxt.Buf, SizeOf(WriteCtxt.Buf), 0); + WriteCode(ClearCode, WriteCtxt); + Y := 0; + Pass := 0; + + while Y < Height do + begin + PData := @PByteArray(Data)[Y * LineIdent]; + for X := 0 to Width - 1 do + begin + // Only ifIndex8 support + case BitCount of + 8: + begin + Col := PData^; + PData := @PByteArray(PData)[1]; + end; + {4: + begin + if X and 1 <> 0 then + begin + Col := PData^ and $0F; + PData := @PByteArray(PData)[1]; + end + else + Col := PData^ shr 4; + end; + 1: + begin + if X and 7 = 7 then + begin + Col := PData^ and 1; + PData := @PByteArray(PData)[1]; + end + else + Col := (PData^ shr (7 - (X and $07))) and $01; + end;} + end; + Inc(LenString); + if LenString = 1 then + begin + Tail := Col; + HashValue := InitHash(Col); + end + else + begin + HashValue := HashValue * (Col + LenString + 4); + I := HashValue mod HashTableSize; + HashValue := HashValue mod HashTableSize; + while (HashTable[I] <> nil) and + ((PImageDict(HashTable[I])^.Tail <> Tail) or + (PImageDict(HashTable[I])^.Col <> Col)) do + begin + Inc(I); + if I >= HashTableSize then + I := 0; + end; + if HashTable[I] <> nil then // Found in the strings table + Tail := PImageDict(HashTable[I])^.Index + else + begin + // Not found + WriteCode(Tail, WriteCtxt); + Inc(LastCode); + HashTable[I] := @Dict^[LastCode]; + PImageDict(HashTable[I])^.Index := LastCode; + PImageDict(HashTable[I])^.Tail := Tail; + PImageDict(HashTable[I])^.Col := Col; + Tail := Col; + HashValue := InitHash(Col); + LenString := 1; + if LastCode >= MaxCode then + begin + // Next Code will be written longer + MaxCode := MaxCode shl 1; + Inc(WriteCtxt.CodeSize); + end + else + if LastCode >= CodeTableSize - 2 then + begin + // Reset tables + WriteCode(Tail, WriteCtxt); + WriteCode(ClearCode, WriteCtxt); + LenString := 0; + LastCode := EndingCode; + WriteCtxt.CodeSize := InitCodeSize; + MaxCode := 1 shl InitCodeSize; + for I := 0 to HashTableSize - 1 do + HashTable[I] := nil; + end; + end; + end; + end; + if Interlaced then + Y := InterlaceStep(Y, Height, Pass) + else + Inc(Y); + end; + WriteCode(Tail, WriteCtxt); + WriteCode(EndingCode, WriteCtxt); + FlushCode(WriteCtxt); + finally + HashTable.Free; + FreeMem(Dict); + end; +end; + +function TGIFFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +type + TFrameInfo = record + Left, Top: Integer; + Width, Height: Integer; + Disposal: TDisposalMethod; + HasTransparency: Boolean; + HasLocalPal: Boolean; + TransIndex: Integer; + BackIndex: Integer; + end; +var + Header: TGIFHeader; + HasGlobalPal: Boolean; + GlobalPalLength: Integer; + GlobalPal: TPalette32Size256; + ScreenWidth, ScreenHeight, I, CachedIndex: Integer; + BlockID: Byte; + HasGraphicExt: Boolean; + GraphicExt: TGraphicControlExtension; + FrameInfos: array of TFrameInfo; + AppRead: Boolean; + CachedFrame: TImageData; + AnimFrames: TDynImageDataArray; + + function ReadBlockID: Byte; + begin + Result := GIFTrailer; + if GetIO.Read(Handle, @Result, SizeOf(Result)) < SizeOf(Result) then + Result := GIFTrailer; + end; + + procedure ReadExtensions; + var + BlockSize, BlockType, ExtType: Byte; + AppRec: TGIFApplicationRec; + LoopCount: SmallInt; + + procedure SkipBytes; + begin + with GetIO do + repeat + // Read block sizes and skip them + Read(Handle, @BlockSize, SizeOf(BlockSize)); + Seek(Handle, BlockSize, smFromCurrent); + until BlockSize = 0; + end; + + begin + HasGraphicExt := False; + AppRead := False; + + // Read extensions until image descriptor is found. Only graphic extension + // is stored now (for transparency), others are skipped. + while BlockID = GIFExtensionIntroducer do + with GetIO do + begin + Read(Handle, @ExtType, SizeOf(ExtType)); + + while ExtType in [GIFGraphicControlExtension, GIFCommentExtension, GIFApplicationExtension, GIFPlainText] do + begin + if ExtType = GIFGraphicControlExtension then + begin + HasGraphicExt := True; + Read(Handle, @GraphicExt, SizeOf(GraphicExt)); + end + else if (ExtType = GIFApplicationExtension) and not AppRead then + begin + Read(Handle, @BlockSize, SizeOf(BlockSize)); + if BlockSize >= SizeOf(AppRec) then + begin + Read(Handle, @AppRec, SizeOf(AppRec)); + if ((AppRec.Identifier = 'NETSCAPE') and (AppRec.Authentication = '2.0')) or + ((AppRec.Identifier = 'ANIMEXTS') and (AppRec.Authentication = '1.0')) then + begin + Read(Handle, @BlockSize, SizeOf(BlockSize)); + while BlockSize <> 0 do + begin + BlockType := ReadBlockID; + Dec(BlockSize); + + case BlockType of + GIFAppLoopExtension: + if (BlockSize >= SizeOf(LoopCount)) then + begin + // Read loop count + Read(Handle, @LoopCount, SizeOf(LoopCount)); + Dec(BlockSize, SizeOf(LoopCount)); + if LoopCount > 0 then + Inc(LoopCount); // Netscape extension is really "repeats" not "loops" + FMetadata.SetMetaItem(SMetaAnimationLoops, LoopCount); + end; + GIFAppBufferExtension: + begin + Dec(BlockSize, SizeOf(Word)); + Seek(Handle, SizeOf(Word), smFromCurrent); + end; + end; + end; + SkipBytes; + AppRead := True; + end + else + begin + // Revert all bytes reading + Seek(Handle, - SizeOf(AppRec) - SizeOf(BlockSize), smFromCurrent); + SkipBytes; + end; + end + else + begin + Seek(Handle, - BlockSize - SizeOf(BlockSize), smFromCurrent); + SkipBytes; + end; + end + else if ExtType in [GIFCommentExtension, GIFApplicationExtension, GIFPlainText] then + repeat + // Read block sizes and skip them + Read(Handle, @BlockSize, SizeOf(BlockSize)); + Seek(Handle, BlockSize, smFromCurrent); + until BlockSize = 0; + + // Read ID of following block + BlockID := ReadBlockID; + ExtType := BlockID; + end + end; + end; + + procedure CopyLZWData(Dest: TStream); + var + CodeSize, BlockSize: Byte; + InputSize: Integer; + Buff: array[Byte] of Byte; + begin + InputSize := ImagingIO.GetInputSize(GetIO, Handle); + // Copy codesize to stream + GetIO.Read(Handle, @CodeSize, 1); + Dest.Write(CodeSize, 1); + repeat + // Read and write data blocks, last is block term value of 0 + GetIO.Read(Handle, @BlockSize, 1); + Dest.Write(BlockSize, 1); + if BlockSize > 0 then + begin + GetIO.Read(Handle, @Buff[0], BlockSize); + Dest.Write(Buff[0], BlockSize); + end; + until (BlockSize = 0) or (GetIO.Tell(Handle) >= InputSize); + end; + + procedure ReadFrame; + var + ImageDesc: TImageDescriptor; + Interlaced: Boolean; + I, Idx, LocalPalLength: Integer; + LocalPal: TPalette32Size256; + LZWStream: TMemoryStream; + + procedure RemoveBadFrame; + begin + FreeImage(Images[Idx]); + SetLength(Images, Length(Images) - 1); + end; + + begin + Idx := Length(Images); + SetLength(Images, Idx + 1); + SetLength(FrameInfos, Idx + 1); + FillChar(LocalPal, SizeOf(LocalPal), 0); + + with GetIO do + begin + // Read and parse image descriptor + Read(Handle, @ImageDesc, SizeOf(ImageDesc)); + FrameInfos[Idx].HasLocalPal := (ImageDesc.PackedFields and GIFLocalColorTable) = GIFLocalColorTable; + Interlaced := (ImageDesc.PackedFields and GIFInterlaced) = GIFInterlaced; + LocalPalLength := ImageDesc.PackedFields and GIFColorTableSize; + LocalPalLength := 1 shl (LocalPalLength + 1); // Total pal length is 2^(n+1) + + // From Mozilla source + if (ImageDesc.Width = 0) or (ImageDesc.Width > Header.ScreenWidth) then + ImageDesc.Width := Header.ScreenWidth; + if (ImageDesc.Height = 0) or (ImageDesc.Height > Header.ScreenHeight) then + ImageDesc.Height := Header.ScreenHeight; + + FrameInfos[Idx].Left := ImageDesc.Left; + FrameInfos[Idx].Top := ImageDesc.Top; + FrameInfos[Idx].Width := ImageDesc.Width; + FrameInfos[Idx].Height := ImageDesc.Height; + FrameInfos[Idx].BackIndex := Header.BackgroundColorIndex; + + // Create new image for this frame which would be later pasted onto logical screen + NewImage(ImageDesc.Width, ImageDesc.Height, ifIndex8, Images[Idx]); + + // Load local palette if there is any + if FrameInfos[Idx].HasLocalPal then + for I := 0 to LocalPalLength - 1 do + begin + LocalPal[I].A := 255; + Read(Handle, @LocalPal[I].R, SizeOf(LocalPal[I].R)); + Read(Handle, @LocalPal[I].G, SizeOf(LocalPal[I].G)); + Read(Handle, @LocalPal[I].B, SizeOf(LocalPal[I].B)); + end; + + // Use local pal if present or global pal if present or create + // default pal if neither of them is present + if FrameInfos[Idx].HasLocalPal then + Move(LocalPal, Images[Idx].Palette^, SizeOf(LocalPal)) + else if HasGlobalPal then + Move(GlobalPal, Images[Idx].Palette^, SizeOf(GlobalPal)) + else + FillCustomPalette(Images[Idx].Palette, GlobalPalLength, 3, 3, 2); + + if (ImageDesc.Left <= Header.ScreenWidth + 1) and (ImageDesc.Top <= Header.ScreenHeight + 1) then + begin + // Resize the screen if needed to fit the frame + ScreenWidth := Max(ScreenWidth, ImageDesc.Width + ImageDesc.Left); + ScreenHeight := Max(ScreenHeight, ImageDesc.Height + ImageDesc.Top); + end + else + begin + // Remove frame outside logical screen + RemoveBadFrame; + Exit; + end; + + // If Grahic Control Extension is present make use of it + if HasGraphicExt then + begin + FrameInfos[Idx].HasTransparency := (GraphicExt.PackedFields and GIFTransparent) = GIFTransparent; + FrameInfos[Idx].Disposal := TDisposalMethod((GraphicExt.PackedFields and GIFDisposalMethod) shr 2); + if FrameInfos[Idx].HasTransparency then + begin + FrameInfos[Idx].TransIndex := GraphicExt.TransparentColorIndex; + Images[Idx].Palette[FrameInfos[Idx].TransIndex].A := 0; + end; + FMetadata.SetMetaItem(SMetaFrameDelay, Integer(GraphicExt.DelayTime * 10), Idx); + end + else + FrameInfos[Idx].HasTransparency := False; + + LZWStream := TMemoryStream.Create; + try + try + // Copy LZW data to temp stream, needed for correct decompression + CopyLZWData(LZWStream); + LZWStream.Position := 0; + // Data decompression finally + LZWDecompress(LZWStream, Handle, ImageDesc.Width, ImageDesc.Height, Interlaced, Images[Idx].Bits); + except + RemoveBadFrame; + Exit; + end; + finally + LZWStream.Free; + end; + end; + end; + + procedure CopyFrameTransparent32(const Image, Frame: TImageData; Left, Top: Integer); + var + X, Y: Integer; + Src: PByte; + Dst: PColor32; + begin + Src := Frame.Bits; + + // Copy all pixels from frame to log screen but ignore the transparent ones + for Y := 0 to Frame.Height - 1 do + begin + Dst := @PColor32RecArray(Image.Bits)[(Top + Y) * Image.Width + Left]; + for X := 0 to Frame.Width - 1 do + begin + if (Frame.Palette[Src^].A <> 0) then + Dst^ := Frame.Palette[Src^].Color; + Inc(Src); + Inc(Dst); + end; + end; + end; + + procedure AnimateFrame(Index: Integer; var AnimFrame: TImageData); + var + I, First, Last: Integer; + UseCache: Boolean; + BGColor: TColor32; + begin + // We may need to use raw frame 0 to n to correctly animate n-th frame + Last := Index; + First := Max(0, Last); + // See if we can use last animate frame as a basis for this one + // (so we don't have to use previous raw frames). + UseCache := TestImage(CachedFrame) and (CachedIndex = Index - 1) and (CachedIndex >= 0) and + (FrameInfos[CachedIndex].Disposal <> dmRestorePrevious); + + // Reuse or release cache + if UseCache then + CloneImage(CachedFrame, AnimFrame) + else + FreeImage(CachedFrame); + + // Default color for clearing of the screen + BGColor := Images[Index].Palette[FrameInfos[Index].BackIndex].Color; + + // Now prepare logical screen for drawing of raw frame at Index. + // We may need to use all previous raw frames to get the screen + // to proper state (according to their disposal methods). + + if not UseCache then + begin + if FrameInfos[Index].HasTransparency then + BGColor := Images[Index].Palette[FrameInfos[Index].TransIndex].Color; + // Clear whole screen + FillMemoryLongWord(AnimFrame.Bits, AnimFrame.Size, BGColor); + + // Try to maximize First so we don't have to use all 0 to n raw frames + while First > 0 do + begin + if (ScreenWidth = Images[First].Width) and (ScreenHeight = Images[First].Height) then + begin + if (FrameInfos[First].Disposal = dmRestoreBackground) and (First < Last) then + Break; + end; + Dec(First); + end; + + for I := First to Last - 1 do + begin + case FrameInfos[I].Disposal of + dmNoRemoval, dmLeave: + begin + // Copy previous raw frame onto screen + CopyFrameTransparent32(AnimFrame, Images[I], FrameInfos[I].Left, FrameInfos[I].Top); + end; + dmRestoreBackground: + if (I > First) then + begin + // Restore background color + FillRect(AnimFrame, FrameInfos[I].Left, FrameInfos[I].Top, + FrameInfos[I].Width, FrameInfos[I].Height, @BGColor); + end; + dmRestorePrevious: ; // Do nothing - previous state is already on screen + end; + end; + end + else if FrameInfos[CachedIndex].Disposal = dmRestoreBackground then + begin + // We have our cached result but also need to restore + // background in a place of cached frame + if FrameInfos[CachedIndex].HasTransparency then + BGColor := Images[CachedIndex].Palette[FrameInfos[CachedIndex].TransIndex].Color; + FillRect(AnimFrame, FrameInfos[CachedIndex].Left, FrameInfos[CachedIndex].Top, + FrameInfos[CachedIndex].Width, FrameInfos[CachedIndex].Height, @BGColor); + end; + + // Copy current raw frame to prepared screen + CopyFrameTransparent32(AnimFrame, Images[Index], FrameInfos[Index].Left, FrameInfos[Index].Top); + + // Cache animated result + CloneImage(AnimFrame, CachedFrame); + CachedIndex := Index; + end; + +begin + AppRead := False; + + SetLength(Images, 0); + FillChar(GlobalPal, SizeOf(GlobalPal), 0); + + with GetIO do + begin + // Read GIF header + Read(Handle, @Header, SizeOf(Header)); + ScreenWidth := Header.ScreenWidth; + ScreenHeight := Header.ScreenHeight; + HasGlobalPal := Header.PackedFields and GIFGlobalColorTable = GIFGlobalColorTable; // Bit 7 + GlobalPalLength := Header.PackedFields and GIFColorTableSize; // Bits 0-2 + GlobalPalLength := 1 shl (GlobalPalLength + 1); // Total pal length is 2^(n+1) + + // Read global palette from file if present + if HasGlobalPal then + begin + for I := 0 to GlobalPalLength - 1 do + begin + GlobalPal[I].A := 255; + Read(Handle, @GlobalPal[I].R, SizeOf(GlobalPal[I].R)); + Read(Handle, @GlobalPal[I].G, SizeOf(GlobalPal[I].G)); + Read(Handle, @GlobalPal[I].B, SizeOf(GlobalPal[I].B)); + end; + end; + + // Read ID of the first block + BlockID := ReadBlockID; + + // Now read all data blocks in the file until file trailer is reached + while BlockID <> GIFTrailer do + begin + // Read blocks until we find the one of known type + while not (BlockID in [GIFTrailer, GIFExtensionIntroducer, GIFImageDescriptor]) do + BlockID := ReadBlockID; + // Read supported and skip unsupported extensions + ReadExtensions; + // If image frame is found read it + if BlockID = GIFImageDescriptor then + ReadFrame; + // Read next block's ID + BlockID := ReadBlockID; + // If block ID is unknown set it to end-of-GIF marker + if not (BlockID in [GIFExtensionIntroducer, GIFTrailer, GIFImageDescriptor]) then + BlockID := GIFTrailer; + end; + + if FLoadAnimated then + begin + // Aniated frames will be stored in AnimFrames + SetLength(AnimFrames, Length(Images)); + InitImage(CachedFrame); + CachedIndex := -1; + + for I := 0 to High(Images) do + begin + // Create new logical screen + NewImage(ScreenWidth, ScreenHeight, ifA8R8G8B8, AnimFrames[I]); + // Animate frames to current log screen + AnimateFrame(I, AnimFrames[I]); + end; + + // Now release raw 8bit frames and put animated 32bit ones + // to output array + FreeImage(CachedFrame); + for I := 0 to High(AnimFrames) do + begin + FreeImage(Images[I]); + Images[I] := AnimFrames[I]; + end; + end; + + Result := True; + end; +end; + +function TGIFFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: Integer): Boolean; +var + Header: TGIFHeader; + ImageDesc: TImageDescriptor; + ImageToSave: TImageData; + MustBeFreed: Boolean; + I, J: Integer; + GraphicExt: TGraphicControlExtension; + + procedure FindMaxDimensions(var MaxWidth, MaxHeight: Word); + var + I: Integer; + begin + MaxWidth := Images[FFirstIdx].Width; + MaxHeight := Images[FFirstIdx].Height; + + for I := FFirstIdx + 1 to FLastIdx do + begin + MaxWidth := Iff(Images[I].Width > MaxWidth, Images[I].Width, MaxWidth); + MaxHeight := Iff(Images[I].Height > MaxWidth, Images[I].Height, MaxHeight); + end; + end; + + procedure SetFrameDelay(Idx: Integer; var Ext: TGraphicControlExtension); + begin + if FMetadata.HasMetaItemForSaving(SMetaFrameDelay, Idx) then + Ext.DelayTime := FMetadata.MetaItemsForSavingMulti[SMetaFrameDelay, Idx] div 10 + else + Ext.DelayTime := GIFDefaultDelay; + end; + + procedure SaveGlobalMetadata; + var + AppExt: TGIFApplicationRec; + BlockSize, LoopExtId: Byte; + Repeats: Word; + begin + if FMetadata.HasMetaItemForSaving(SMetaAnimationLoops) then + with GetIO do + begin + FillChar(AppExt, SizeOf(AppExt), 0); + AppExt.Identifier := 'NETSCAPE'; + AppExt.Authentication := '2.0'; + Repeats := FMetadata.MetaItemsForSaving[SMetaAnimationLoops]; + if Repeats > 0 then + Dec(Repeats); + LoopExtId := GIFAppLoopExtension; + + Write(Handle, @GIFExtensionIntroducer, SizeOf(GIFExtensionIntroducer)); + Write(Handle, @GIFApplicationExtension, SizeOf(GIFApplicationExtension)); + BlockSize := 11; + Write(Handle, @BlockSize, SizeOf(BlockSize)); + Write(Handle, @AppExt, SizeOf(AppExt)); + BlockSize := 3; + Write(Handle, @BlockSize, SizeOf(BlockSize)); + Write(Handle, @LoopExtId, SizeOf(LoopExtId)); + Write(Handle, @Repeats, SizeOf(Repeats)); + Write(Handle, @GIFBlockTerminator, SizeOf(GIFBlockTerminator)); + end; + end; + +begin + // Fill header with data, select size of largest image in array as + // logical screen size + FillChar(Header, Sizeof(Header), 0); + Header.Signature := GIFSignature; + Header.Version := GIFVersions[gv89]; + FindMaxDimensions(Header.ScreenWidth, Header.ScreenHeight); + Header.PackedFields := GIFColorResolution; // Color resolution is 256 + GetIO.Write(Handle, @Header, SizeOf(Header)); + + // Prepare default GC extension with delay + FillChar(GraphicExt, Sizeof(GraphicExt), 0); + GraphicExt.DelayTime := GIFDefaultDelay; + GraphicExt.BlockSize := 4; + + SaveGlobalMetadata; + + for I := FFirstIdx to FLastIdx do + begin + if MakeCompatible(Images[I], ImageToSave, MustBeFreed) then + with GetIO, ImageToSave do + try + // Write Graphic Control Extension with default delay + Write(Handle, @GIFExtensionIntroducer, SizeOf(GIFExtensionIntroducer)); + Write(Handle, @GIFGraphicControlExtension, SizeOf(GIFGraphicControlExtension)); + SetFrameDelay(I, GraphicExt); + Write(Handle, @GraphicExt, SizeOf(GraphicExt)); + // Write frame marker and fill and write image descriptor for this frame + Write(Handle, @GIFImageDescriptor, SizeOf(GIFImageDescriptor)); + FillChar(ImageDesc, Sizeof(ImageDesc), 0); + ImageDesc.Width := Width; + ImageDesc.Height := Height; + ImageDesc.PackedFields := GIFLocalColorTable or GIFColorTableSize; // Use lccal color table with 256 entries + Write(Handle, @ImageDesc, SizeOf(ImageDesc)); + + // Write local color table for each frame + for J := 0 to 255 do + begin + Write(Handle, @Palette[J].R, SizeOf(Palette[J].R)); + Write(Handle, @Palette[J].G, SizeOf(Palette[J].G)); + Write(Handle, @Palette[J].B, SizeOf(Palette[J].B)); + end; + + // Finally compress image data + LZWCompress(GetIO, Handle, Width, Height, 8, False, Bits); + + finally + if MustBeFreed then + FreeImage(ImageToSave); + end; + end; + + GetIO.Write(Handle, @GIFTrailer, SizeOf(GIFTrailer)); + Result := True; +end; + +procedure TGIFFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +begin + ConvertImage(Image, ifIndex8); +end; + +function TGIFFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Header: TGIFHeader; + ReadCount: Integer; +begin + Result := False; + if Handle <> nil then + begin + ReadCount := GetIO.Read(Handle, @Header, SizeOf(Header)); + GetIO.Seek(Handle, -ReadCount, smFromCurrent); + Result := (ReadCount >= SizeOf(Header)) and + (Header.Signature = GIFSignature) and + ((Header.Version = GIFVersions[gv87]) or (Header.Version = GIFVersions[gv89])); + end; +end; + +initialization + RegisterImageFileFormat(TGIFFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77 Changes/Bug Fixes ----------------------------------- + - Fixed crash when resaving GIF with animation metadata. + - Writes frame delays of GIF animations from metadata. + - Reads and writes looping of GIF animations stored into/from metadata. + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Reads frame delays from GIF animations into metadata. + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Fixed bug - loading of GIF with NETSCAPE app extensions + failed with Delphi 2009. + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - GIF loading and animation mostly rewritten, based on + modification by Sergey Galezdinov (ExtraGIF in Extras/Contrib). + + -- 0.25.0 Changes/Bug Fixes --------------------------------- + - Fixed loading of some rare GIFs, problems with LZW + decompression. + + -- 0.24.3 Changes/Bug Fixes --------------------------------- + - Better solution to transparency for some GIFs. Background not + transparent by default. + + -- 0.24.1 Changes/Bug Fixes --------------------------------- + - Made backround color transparent by default (alpha = 0). + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Fixed other loading bugs (local pal size, transparency). + - Added GIF saving. + - Fixed bug when loading multiframe GIFs and implemented few animation + features (disposal methods, ...). + - Loading of GIFs working. + - Unit created with initial stuff! +} + +end. diff --git a/src/lib/vampimg/ImagingIO.pas b/src/lib/vampimg/ImagingIO.pas new file mode 100644 index 0000000..32d2bc2 --- /dev/null +++ b/src/lib/vampimg/ImagingIO.pas @@ -0,0 +1,646 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains default IO functions for reading from/writting to + files, streams and memory.} +unit ImagingIO; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, Classes, ImagingTypes, Imaging, ImagingUtility; + +type + TMemoryIORec = record + Data: ImagingUtility.PByteArray; + Position: LongInt; + Size: LongInt; + end; + PMemoryIORec = ^TMemoryIORec; + +var + OriginalFileIO: TIOFunctions; + FileIO: TIOFunctions; + StreamIO: TIOFunctions; + MemoryIO: TIOFunctions; + +{ Helper function that returns size of input (from current position to the end) + represented by Handle (and opened and operated on by members of IOFunctions).} +function GetInputSize(IOFunctions: TIOFunctions; Handle: TImagingHandle): LongInt; +{ Helper function that initializes TMemoryIORec with given params.} +function PrepareMemIO(Data: Pointer; Size: LongInt): TMemoryIORec; +{ Reads one text line from input (CR+LF, CR, or LF as line delimiter).} +function ReadLine(IOFunctions: TIOFunctions; Handle: TImagingHandle; + out Line: AnsiString; FailOnControlChars: Boolean = False): Boolean; +{ Writes one text line to input with optional line delimiter.} +procedure WriteLine(IOFunctions: TIOFunctions; Handle: TImagingHandle; + const Line: AnsiString; const LineEnding: AnsiString = sLineBreak); + +implementation + +const + DefaultBufferSize = 16 * 1024; + +type + { Based on TaaBufferedStream + Copyright (c) Julian M Bucknall 1997, 1999 } + TBufferedStream = class + private + FBuffer: PByteArray; + FBufSize: Integer; + FBufStart: Integer; + FBufPos: Integer; + FBytesInBuf: Integer; + FSize: Integer; + FDirty: Boolean; + FStream: TStream; + function GetPosition: Integer; + function GetSize: Integer; + procedure ReadBuffer; + procedure WriteBuffer; + procedure SetPosition(const Value: Integer); + public + constructor Create(AStream: TStream); + destructor Destroy; override; + function Read(var Buffer; Count: Integer): Integer; + function Write(const Buffer; Count: Integer): Integer; + function Seek(Offset: Integer; Origin: Word): Integer; + procedure Commit; + property Stream: TStream read FStream; + property Position: Integer read GetPosition write SetPosition; + property Size: Integer read GetSize; + end; + +constructor TBufferedStream.Create(AStream: TStream); +begin + inherited Create; + FStream := AStream; + FBufSize := DefaultBufferSize; + GetMem(FBuffer, FBufSize); + FBufPos := 0; + FBytesInBuf := 0; + FBufStart := 0; + FDirty := False; + FSize := AStream.Size; +end; + +destructor TBufferedStream.Destroy; +begin + if FBuffer <> nil then + begin + Commit; + FreeMem(FBuffer); + end; + FStream.Position := Position; // Make sure source stream has right position + inherited Destroy; +end; + +function TBufferedStream.GetPosition: Integer; +begin + Result := FBufStart + FBufPos; +end; + +procedure TBufferedStream.SetPosition(const Value: Integer); +begin + Seek(Value, soFromCurrent); +end; + +function TBufferedStream.GetSize: Integer; +begin + Result := FSize; +end; + +procedure TBufferedStream.ReadBuffer; +var + SeekResult: Integer; +begin + SeekResult := FStream.Seek(FBufStart, 0); + if SeekResult = -1 then + raise Exception.Create('TBufferedStream.ReadBuffer: seek failed'); + FBytesInBuf := FStream.Read(FBuffer^, FBufSize); + if FBytesInBuf <= 0 then + raise Exception.Create('TBufferedStream.ReadBuffer: read failed'); +end; + +procedure TBufferedStream.WriteBuffer; +var + SeekResult: Integer; + BytesWritten: Integer; +begin + SeekResult := FStream.Seek(FBufStart, 0); + if SeekResult = -1 then + raise Exception.Create('TBufferedStream.WriteBuffer: seek failed'); + BytesWritten := FStream.Write(FBuffer^, FBytesInBuf); + if BytesWritten <> FBytesInBuf then + raise Exception.Create('TBufferedStream.WriteBuffer: write failed'); +end; + +procedure TBufferedStream.Commit; +begin + if FDirty then + begin + WriteBuffer; + FDirty := False; + end; +end; + +function TBufferedStream.Read(var Buffer; Count: Integer): Integer; +var + BufAsBytes : TByteArray absolute Buffer; + BufIdx, BytesToGo, BytesToRead: Integer; +begin + // Calculate the actual number of bytes we can read - this depends on + // the current position and size of the stream as well as the number + // of bytes requested. + BytesToGo := Count; + if FSize < (FBufStart + FBufPos + Count) then + BytesToGo := FSize - (FBufStart + FBufPos); + + if BytesToGo <= 0 then + begin + Result := 0; + Exit; + end; + // Remember to return the result of our calculation + Result := BytesToGo; + + BufIdx := 0; + if FBytesInBuf = 0 then + ReadBuffer; + // Calculate the number of bytes we can read prior to the loop + BytesToRead := FBytesInBuf - FBufPos; + if BytesToRead > BytesToGo then + BytesToRead := BytesToGo; + // Copy from the stream buffer to the caller's buffer + Move(FBuffer^[FBufPos], BufAsBytes[BufIdx], BytesToRead); + // Calculate the number of bytes still to read} + Dec(BytesToGo, BytesToRead); + + // while we have bytes to read, read them + while BytesToGo > 0 do + begin + Inc(BufIdx, BytesToRead); + // As we've exhausted this buffer-full, advance to the next, check + // to see whether we need to write the buffer out first + if FDirty then + begin + WriteBuffer; + FDirty := false; + end; + Inc(FBufStart, FBufSize); + FBufPos := 0; + ReadBuffer; + // Calculate the number of bytes we can read in this cycle + BytesToRead := FBytesInBuf; + if BytesToRead > BytesToGo then + BytesToRead := BytesToGo; + // Ccopy from the stream buffer to the caller's buffer + Move(FBuffer^, BufAsBytes[BufIdx], BytesToRead); + // Calculate the number of bytes still to read + Dec(BytesToGo, BytesToRead); + end; + // Remember our new position + Inc(FBufPos, BytesToRead); + if FBufPos = FBufSize then + begin + Inc(FBufStart, FBufSize); + FBufPos := 0; + FBytesInBuf := 0; + end; +end; + +function TBufferedStream.Seek(Offset: Integer; Origin: Word): Integer; +var + NewBufStart, NewPos: Integer; +begin + // Calculate the new position + case Origin of + soFromBeginning : NewPos := Offset; + soFromCurrent : NewPos := FBufStart + FBufPos + Offset; + soFromEnd : NewPos := FSize + Offset; + else + raise Exception.Create('TBufferedStream.Seek: invalid origin'); + end; + + if (NewPos < 0) or (NewPos > FSize) then + begin + //NewPos := ClampInt(NewPos, 0, FSize); don't do this - for writing + end; + // Calculate which page of the file we need to be at + NewBufStart := NewPos and not Pred(FBufSize); + // If the new page is different than the old, mark the buffer as being + // ready to be replenished, and if need be write out any dirty data + if NewBufStart <> FBufStart then + begin + if FDirty then + begin + WriteBuffer; + FDirty := False; + end; + FBufStart := NewBufStart; + FBytesInBuf := 0; + end; + // Save the new position + FBufPos := NewPos - NewBufStart; + Result := NewPos; +end; + +function TBufferedStream.Write(const Buffer; Count: Integer): Integer; +var + BufAsBytes: TByteArray absolute Buffer; + BufIdx, BytesToGo, BytesToWrite: Integer; +begin + // When we write to this stream we always assume that we can write the + // requested number of bytes: if we can't (eg, the disk is full) we'll + // get an exception somewhere eventually. + BytesToGo := Count; + // Remember to return the result of our calculation + Result := BytesToGo; + + BufIdx := 0; + if (FBytesInBuf = 0) and (FSize > FBufStart) then + ReadBuffer; + // Calculate the number of bytes we can write prior to the loop + BytesToWrite := FBufSize - FBufPos; + if BytesToWrite > BytesToGo then + BytesToWrite := BytesToGo; + // Copy from the caller's buffer to the stream buffer + Move(BufAsBytes[BufIdx], FBuffer^[FBufPos], BytesToWrite); + // Mark our stream buffer as requiring a save to the actual stream, + // note that this will suffice for the rest of the routine as well: no + // inner routine will turn off the dirty flag. + FDirty := True; + // Calculate the number of bytes still to write + Dec(BytesToGo, BytesToWrite); + + // While we have bytes to write, write them + while BytesToGo > 0 do + begin + Inc(BufIdx, BytesToWrite); + // As we've filled this buffer, write it out to the actual stream + // and advance to the next buffer, reading it if required + FBytesInBuf := FBufSize; + WriteBuffer; + Inc(FBufStart, FBufSize); + FBufPos := 0; + FBytesInBuf := 0; + if FSize > FBufStart then + ReadBuffer; + // Calculate the number of bytes we can write in this cycle + BytesToWrite := FBufSize; + if BytesToWrite > BytesToGo then + BytesToWrite := BytesToGo; + // Copy from the caller's buffer to our buffer + Move(BufAsBytes[BufIdx], FBuffer^, BytesToWrite); + // Calculate the number of bytes still to write + Dec(BytesToGo, BytesToWrite); + end; + // Remember our new position + Inc(FBufPos, BytesToWrite); + // Make sure the count of valid bytes is correct + if FBytesInBuf < FBufPos then + FBytesInBuf := FBufPos; + // Make sure the stream size is correct + if FSize < (FBufStart + FBytesInBuf) then + FSize := FBufStart + FBytesInBuf; + // If we're at the end of the buffer, write it out and advance to the + // start of the next page + if FBufPos = FBufSize then + begin + WriteBuffer; + FDirty := False; + Inc(FBufStart, FBufSize); + FBufPos := 0; + FBytesInBuf := 0; + end; +end; + +{ File IO functions } + +function FileOpen(FileName: PChar; Mode: TOpenMode): TImagingHandle; cdecl; +var + Stream: TStream; +begin + Stream := nil; + + case Mode of + omReadOnly: Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); + omCreate: Stream := TFileStream.Create(FileName, fmCreate); + omReadWrite: + begin + if FileExists(FileName) then + Stream := TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive) + else + Stream := TFileStream.Create(FileName, fmCreate); + end; + end; + + Assert(Stream <> nil); + Result := TBufferedStream.Create(Stream); +end; + +procedure FileClose(Handle: TImagingHandle); cdecl; +var + Stream: TStream; +begin + Stream := TBufferedStream(Handle).Stream; + TBufferedStream(Handle).Free; + Stream.Free; +end; + +function FileEof(Handle: TImagingHandle): Boolean; cdecl; +begin + Result := TBufferedStream(Handle).Position = TBufferedStream(Handle).Size; +end; + +function FileSeek(Handle: TImagingHandle; Offset: LongInt; Mode: TSeekMode): + LongInt; cdecl; +begin + Result := TBufferedStream(Handle).Seek(Offset, LongInt(Mode)); +end; + +function FileTell(Handle: TImagingHandle): LongInt; cdecl; +begin + Result := TBufferedStream(Handle).Position; +end; + +function FileRead(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): + LongInt; cdecl; +begin + Result := TBufferedStream(Handle).Read(Buffer^, Count); +end; + +function FileWrite(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): + LongInt; cdecl; +begin + Result := TBufferedStream(Handle).Write(Buffer^, Count); +end; + +{ Stream IO functions } + +function StreamOpen(FileName: PChar; Mode: TOpenMode): TImagingHandle; cdecl; +begin + Result := FileName; +end; + +procedure StreamClose(Handle: TImagingHandle); cdecl; +begin +end; + +function StreamEof(Handle: TImagingHandle): Boolean; cdecl; +begin + Result := TStream(Handle).Position = TStream(Handle).Size; +end; + +function StreamSeek(Handle: TImagingHandle; Offset: LongInt; Mode: TSeekMode): + LongInt; cdecl; +begin + Result := TStream(Handle).Seek(Offset, LongInt(Mode)); +end; + +function StreamTell(Handle: TImagingHandle): LongInt; cdecl; +begin + Result := TStream(Handle).Position; +end; + +function StreamRead(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): + LongInt; cdecl; +begin + Result := TStream(Handle).Read(Buffer^, Count); +end; + +function StreamWrite(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): + LongInt; cdecl; +begin + Result := TStream(Handle).Write(Buffer^, Count); +end; + +{ Memory IO functions } + +function MemoryOpen(FileName: PChar; Mode: TOpenMode): TImagingHandle; cdecl; +begin + Result := FileName; +end; + +procedure MemoryClose(Handle: TImagingHandle); cdecl; +begin +end; + +function MemoryEof(Handle: TImagingHandle): Boolean; cdecl; +begin + Result := PMemoryIORec(Handle).Position = PMemoryIORec(Handle).Size; +end; + +function MemorySeek(Handle: TImagingHandle; Offset: LongInt; Mode: TSeekMode): + LongInt; cdecl; +begin + Result := PMemoryIORec(Handle).Position; + case Mode of + smFromBeginning: Result := Offset; + smFromCurrent: Result := PMemoryIORec(Handle).Position + Offset; + smFromEnd: Result := PMemoryIORec(Handle).Size + Offset; + end; + //Result := ClampInt(Result, 0, PMemoryIORec(Handle).Size); don't do this - some file formats use it + PMemoryIORec(Handle).Position := Result; +end; + +function MemoryTell(Handle: TImagingHandle): LongInt; cdecl; +begin + Result := PMemoryIORec(Handle).Position; +end; + +function MemoryRead(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): + LongInt; cdecl; +var + Rec: PMemoryIORec; +begin + Rec := PMemoryIORec(Handle); + Result := Count; + if Rec.Position + Count > Rec.Size then + Result := Rec.Size - Rec.Position; + Move(Rec.Data[Rec.Position], Buffer^, Result); + Rec.Position := Rec.Position + Result; +end; + +function MemoryWrite(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): + LongInt; cdecl; +var + Rec: PMemoryIORec; +begin + Rec := PMemoryIORec(Handle); + Result := Count; + if Rec.Position + Count > Rec.Size then + Result := Rec.Size - Rec.Position; + Move(Buffer^, Rec.Data[Rec.Position], Result); + Rec.Position := Rec.Position + Result; +end; + +{ Helper IO functions } + +function GetInputSize(IOFunctions: TIOFunctions; Handle: TImagingHandle): LongInt; +var + OldPos: Int64; +begin + OldPos := IOFunctions.Tell(Handle); + IOFunctions.Seek(Handle, 0, smFromEnd); + Result := IOFunctions.Tell(Handle); + IOFunctions.Seek(Handle, OldPos, smFromBeginning); +end; + +function PrepareMemIO(Data: Pointer; Size: LongInt): TMemoryIORec; +begin + Result.Data := Data; + Result.Position := 0; + Result.Size := Size; +end; + +function ReadLine(IOFunctions: TIOFunctions; Handle: TImagingHandle; + out Line: AnsiString; FailOnControlChars: Boolean): Boolean; +const + MaxLine = 1024; +var + EolPos, Pos: Integer; + C: AnsiChar; + EolReached: Boolean; + Endings: set of AnsiChar; +begin + Line := ''; + Pos := 0; + EolPos := 0; + EolReached := False; + Endings := [#10, #13]; + Result := True; + + while not IOFunctions.Eof(Handle) do + begin + IOFunctions.Read(Handle, @C, SizeOf(C)); + + if FailOnControlChars and (Byte(C) < $20) then + begin + Break; + end; + + if not (C in Endings) then + begin + if EolReached then + begin + IOFunctions.Seek(Handle, EolPos, smFromBeginning); + Exit; + end + else + begin + SetLength(Line, Length(Line) + 1); + Line[Length(Line)] := C; + end; + end + else if not EolReached then + begin + EolReached := True; + EolPos := IOFunctions.Tell(Handle); + end; + + Inc(Pos); + if Pos >= MaxLine then + begin + Break; + end; + end; + + Result := False; + IOFunctions.Seek(Handle, -Pos, smFromCurrent); +end; + +procedure WriteLine(IOFunctions: TIOFunctions; Handle: TImagingHandle; + const Line: AnsiString; const LineEnding: AnsiString); +var + ToWrite: AnsiString; +begin + ToWrite := Line + LineEnding; + IOFunctions.Write(Handle, @ToWrite[1], Length(ToWrite)); +end; + +initialization + OriginalFileIO.Open := FileOpen; + OriginalFileIO.Close := FileClose; + OriginalFileIO.Eof := FileEof; + OriginalFileIO.Seek := FileSeek; + OriginalFileIO.Tell := FileTell; + OriginalFileIO.Read := FileRead; + OriginalFileIO.Write := FileWrite; + + StreamIO.Open := StreamOpen; + StreamIO.Close := StreamClose; + StreamIO.Eof := StreamEof; + StreamIO.Seek := StreamSeek; + StreamIO.Tell := StreamTell; + StreamIO.Read := StreamRead; + StreamIO.Write := StreamWrite; + + MemoryIO.Open := MemoryOpen; + MemoryIO.Close := MemoryClose; + MemoryIO.Eof := MemoryEof; + MemoryIO.Seek := MemorySeek; + MemoryIO.Tell := MemoryTell; + MemoryIO.Read := MemoryRead; + MemoryIO.Write := MemoryWrite; + + ResetFileIO; + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 --------------------------------------------------- + - Updated IO Open functions according to changes in ImagingTypes. + - Added ReadLine and WriteLine functions. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added merge between buffered read-only and write-only file + stream adapters - TIFF saving needed both reading and writing. + - Fixed bug causing wrong value of TBufferedWriteFile.Size + (needed to add buffer pos to size). + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Removed TMemoryIORec.Written, use Position to get proper memory + position (Written didn't take Seeks into account). + - Added TBufferedReadFile and TBufferedWriteFile classes for + buffered file reading/writting. File IO functions now use these + classes resulting in performance increase mainly in file formats + that read/write many small chunks. + - Added fmShareDenyWrite to FileOpenRead. You can now read + files opened for reading by Imaging from other apps. + - Added GetInputSize and PrepareMemIO helper functions. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - changed behaviour of MemorySeek to act as TStream + based Seeks +} +end. diff --git a/src/lib/vampimg/ImagingJpeg.pas b/src/lib/vampimg/ImagingJpeg.pas new file mode 100644 index 0000000..ef9a5e7 --- /dev/null +++ b/src/lib/vampimg/ImagingJpeg.pas @@ -0,0 +1,768 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader/saver for Jpeg images.} +unit ImagingJpeg; + +{$I ImagingOptions.inc} + +{ You can choose which Pascal JpegLib implementation will be used. + IMJPEGLIB is version bundled with Imaging which works with all supported + compilers and platforms. + PASJPEG is original JpegLib translation or version modified for FPC + (and shipped with it). You can use PASJPEG if this version is already + linked with another part of your program and you don't want to have + two quite large almost the same libraries linked to your exe. + This is the case with Lazarus applications for example.} + +{$DEFINE IMJPEGLIB} +{ $DEFINE PASJPEG} + +{ Automatically use FPC's PasJpeg when compiling with Lazarus. But not when + WINDOWS is defined. See http://galfar.vevb.net/imaging/smf/index.php/topic,90.0.html. + Fixed in FPC revision 13963: http://bugs.freepascal.org/view.php?id=14928 } +{$IF Defined(LCL) and not Defined(WINDOWS)} + {$UNDEF IMJPEGLIB} + {$DEFINE PASJPEG} +{$IFEND} + +{ We usually want to skip the rest of the corrupted file when loading JEPG files + instead of getting exception. JpegLib's error handler can only be + exited using setjmp/longjmp ("non-local goto") functions to get error + recovery when loading corrupted JPEG files. This is implemented in assembler + and currently available only for 32bit Delphi targets and FPC.} +{$DEFINE ErrorJmpRecovery} +{$IF Defined(DCC) and not Defined(CPUX86)} + {$UNDEF ErrorJmpRecovery} +{$IFEND} + +interface + +uses + SysUtils, ImagingTypes, Imaging, ImagingColors, +{$IF Defined(IMJPEGLIB)} + imjpeglib, imjmorecfg, imjcomapi, imjdapimin, imjdeferr, imjerror, + imjdapistd, imjcapimin, imjcapistd, imjdmarker, imjcparam, +{$ELSEIF Defined(PASJPEG)} + jpeglib, jmorecfg, jcomapi, jdapimin, jdeferr, jerror, + jdapistd, jcapimin, jcapistd, jdmarker, jcparam, +{$IFEND} + ImagingUtility; + +{$IF Defined(FPC) and Defined(PASJPEG)} + { When using FPC's pasjpeg in FPC the channel order is BGR instead of RGB} + {$DEFINE RGBSWAPPED} +{$IFEND} + +type + { Class for loading/saving Jpeg images. Supports load/save of + 8 bit grayscale and 24 bit RGB images. Jpegs can be saved with optional + progressive encoding. + Based on IJG's JpegLib so doesn't support alpha channels and lossless + coding.} + TJpegFileFormat = class(TImageFileFormat) + private + FGrayScale: Boolean; + protected + FQuality: LongInt; + FProgressive: LongBool; + procedure SetJpegIO(const JpegIO: TIOFunctions); virtual; + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + procedure CheckOptionsValidity; override; + published + { Controls Jpeg save compression quality. It is number in range 1..100. + 1 means small/ugly file, 100 means large/nice file. Accessible trough + ImagingJpegQuality option.} + property Quality: LongInt read FQuality write FQuality; + { If True Jpeg images are saved in progressive format. Accessible trough + ImagingJpegProgressive option.} + property Progressive: LongBool read FProgressive write FProgressive; + end; + +implementation + +const + SJpegFormatName = 'Joint Photographic Experts Group Image'; + SJpegMasks = '*.jpg,*.jpeg,*.jfif,*.jpe,*.jif'; + JpegSupportedFormats: TImageFormats = [ifR8G8B8, ifGray8]; + JpegDefaultQuality = 90; + JpegDefaultProgressive = False; + +const + { Jpeg file identifiers.} + JpegMagic: TChar2 = #$FF#$D8; + BufferSize = 16384; + +resourcestring + SJpegError = 'JPEG Error'; + +type + TJpegContext = record + case Byte of + 0: (common: jpeg_common_struct); + 1: (d: jpeg_decompress_struct); + 2: (c: jpeg_compress_struct); + end; + + TSourceMgr = record + Pub: jpeg_source_mgr; + Input: TImagingHandle; + Buffer: JOCTETPTR; + StartOfFile: Boolean; + end; + PSourceMgr = ^TSourceMgr; + + TDestMgr = record + Pub: jpeg_destination_mgr; + Output: TImagingHandle; + Buffer: JOCTETPTR; + end; + PDestMgr = ^TDestMgr; + +var + JIO: TIOFunctions; + JpegErrorMgr: jpeg_error_mgr; + +{ Intenal unit jpeglib support functions } + +{$IFDEF ErrorJmpRecovery} + {$IFDEF DCC} + type + jmp_buf = record + EBX, + ESI, + EDI, + ESP, + EBP, + EIP: LongWord; + end; + pjmp_buf = ^jmp_buf; + + { JmpLib SetJmp/LongJmp Library + (C)Copyright 2003, 2004 Will DeWitt Jr. } + function SetJmp(out jmpb: jmp_buf): Integer; + asm + { -> EAX jmpb } + { <- EAX Result } + MOV EDX, [ESP] // Fetch return address (EIP) + // Save task state + MOV [EAX+jmp_buf.&EBX], EBX + MOV [EAX+jmp_buf.&ESI], ESI + MOV [EAX+jmp_buf.&EDI], EDI + MOV [EAX+jmp_buf.&ESP], ESP + MOV [EAX+jmp_buf.&EBP], EBP + MOV [EAX+jmp_buf.&EIP], EDX + + SUB EAX, EAX + @@1: + end; + + procedure LongJmp(const jmpb: jmp_buf; retval: Integer); + asm + { -> EAX jmpb } + { EDX retval } + { <- EAX Result } + XCHG EDX, EAX + + MOV ECX, [EDX+jmp_buf.&EIP] + // Restore task state + MOV EBX, [EDX+jmp_buf.&EBX] + MOV ESI, [EDX+jmp_buf.&ESI] + MOV EDI, [EDX+jmp_buf.&EDI] + MOV ESP, [EDX+jmp_buf.&ESP] + MOV EBP, [EDX+jmp_buf.&EBP] + MOV [ESP], ECX // Restore return address (EIP) + + TEST EAX, EAX // Ensure retval is <> 0 + JNZ @@1 + MOV EAX, 1 + @@1: + end; + {$ENDIF} + +type + TJmpBuf = jmp_buf; + TErrorClientData = record + JmpBuf: TJmpBuf; + ScanlineReadReached: Boolean; + end; + PErrorClientData = ^TErrorClientData; +{$ENDIF} + +procedure JpegError(CInfo: j_common_ptr); + + procedure RaiseError; + var + Buffer: AnsiString; + begin + // Create the message and raise exception + CInfo.err.format_message(CInfo, Buffer); + // Warning: you can get "Invalid argument index in format" exception when + // using FPC (see http://bugs.freepascal.org/view.php?id=21229). + // Fixed in FPC 2.7.1 + {$IF Defined(FPC) and (FPC_FULLVERSION <= 20701)} + raise EImagingError.CreateFmt(SJPEGError + ' %d', [CInfo.err.msg_code]); + {$ELSE} + raise EImagingError.CreateFmt(SJPEGError + ' %d: ' + string(Buffer), [CInfo.err.msg_code]); + {$IFEND} + end; + +begin +{$IFDEF ErrorJmpRecovery} + // Only recovers on loads and when header is sucessfully loaded + // (error occurs when reading scanlines) + if (CInfo.client_data <> nil) and + PErrorClientData(CInfo.client_data).ScanlineReadReached then + begin + // Non-local jump to error handler in TJpegFileFormat.LoadData + longjmp(PErrorClientData(CInfo.client_data).JmpBuf, 1) + end + else + RaiseError; +{$ELSE} + RaiseError; +{$ENDIF} +end; + +procedure OutputMessage(CurInfo: j_common_ptr); +begin +end; + +procedure ReleaseContext(var jc: TJpegContext); +begin + if jc.common.err = nil then + Exit; + jpeg_destroy(@jc.common); + jpeg_destroy_decompress(@jc.d); + jpeg_destroy_compress(@jc.c); + jc.common.err := nil; +end; + +procedure InitSource(cinfo: j_decompress_ptr); +begin + PSourceMgr(cinfo.src).StartOfFile := True; +end; + +function FillInputBuffer(cinfo: j_decompress_ptr): Boolean; +var + NBytes: LongInt; + Src: PSourceMgr; +begin + Src := PSourceMgr(cinfo.src); + NBytes := JIO.Read(Src.Input, Src.Buffer, BufferSize); + + if NBytes <= 0 then + begin + PByteArray(Src.Buffer)[0] := $FF; + PByteArray(Src.Buffer)[1] := JPEG_EOI; + NBytes := 2; + end; + Src.Pub.next_input_byte := Src.Buffer; + Src.Pub.bytes_in_buffer := NBytes; + Src.StartOfFile := False; + Result := True; +end; + +procedure SkipInputData(cinfo: j_decompress_ptr; num_bytes: LongInt); +var + Src: PSourceMgr; +begin + Src := PSourceMgr(cinfo.src); + if num_bytes > 0 then + begin + while num_bytes > Src.Pub.bytes_in_buffer do + begin + Dec(num_bytes, Src.Pub.bytes_in_buffer); + FillInputBuffer(cinfo); + end; + Src.Pub.next_input_byte := @PByteArray(Src.Pub.next_input_byte)[num_bytes]; + //Inc(LongInt(Src.Pub.next_input_byte), num_bytes); + Dec(Src.Pub.bytes_in_buffer, num_bytes); + end; +end; + +procedure TermSource(cinfo: j_decompress_ptr); +var + Src: PSourceMgr; +begin + Src := PSourceMgr(cinfo.src); + // Move stream position back just after EOI marker so that more that one + // JPEG images can be loaded from one stream + JIO.Seek(Src.Input, -Src.Pub.bytes_in_buffer, smFromCurrent); +end; + +procedure JpegStdioSrc(var cinfo: jpeg_decompress_struct; Handle: + TImagingHandle); +var + Src: PSourceMgr; +begin + if cinfo.src = nil then + begin + cinfo.src := cinfo.mem.alloc_small(j_common_ptr(@cinfo), JPOOL_PERMANENT, + SizeOf(TSourceMgr)); + Src := PSourceMgr(cinfo.src); + Src.Buffer := cinfo.mem.alloc_small(j_common_ptr(@cinfo), JPOOL_PERMANENT, + BufferSize * SizeOf(JOCTET)); + end; + Src := PSourceMgr(cinfo.src); + Src.Pub.init_source := InitSource; + Src.Pub.fill_input_buffer := FillInputBuffer; + Src.Pub.skip_input_data := SkipInputData; + Src.Pub.resync_to_restart := jpeg_resync_to_restart; + Src.Pub.term_source := TermSource; + Src.Input := Handle; + Src.Pub.bytes_in_buffer := 0; + Src.Pub.next_input_byte := nil; +end; + +procedure InitDest(cinfo: j_compress_ptr); +var + Dest: PDestMgr; +begin + Dest := PDestMgr(cinfo.dest); + Dest.Pub.next_output_byte := Dest.Buffer; + Dest.Pub.free_in_buffer := BufferSize; +end; + +function EmptyOutput(cinfo: j_compress_ptr): Boolean; +var + Dest: PDestMgr; +begin + Dest := PDestMgr(cinfo.dest); + JIO.Write(Dest.Output, Dest.Buffer, BufferSize); + Dest.Pub.next_output_byte := Dest.Buffer; + Dest.Pub.free_in_buffer := BufferSize; + Result := True; +end; + +procedure TermDest(cinfo: j_compress_ptr); +var + Dest: PDestMgr; + DataCount: LongInt; +begin + Dest := PDestMgr(cinfo.dest); + DataCount := BufferSize - Dest.Pub.free_in_buffer; + if DataCount > 0 then + JIO.Write(Dest.Output, Dest.Buffer, DataCount); +end; + +procedure JpegStdioDest(var cinfo: jpeg_compress_struct; Handle: + TImagingHandle); +var + Dest: PDestMgr; +begin + if cinfo.dest = nil then + cinfo.dest := cinfo.mem.alloc_small(j_common_ptr(@cinfo), + JPOOL_PERMANENT, SizeOf(TDestMgr)); + Dest := PDestMgr(cinfo.dest); + Dest.Buffer := cinfo.mem.alloc_small(j_common_ptr(@cinfo), JPOOL_IMAGE, + BufferSize * SIZEOF(JOCTET)); + Dest.Pub.init_destination := InitDest; + Dest.Pub.empty_output_buffer := EmptyOutput; + Dest.Pub.term_destination := TermDest; + Dest.Output := Handle; +end; + +procedure SetupErrorMgr(var jc: TJpegContext); +begin + // Set standard error handlers and then override some + jc.common.err := jpeg_std_error(JpegErrorMgr); + jc.common.err.error_exit := JpegError; + jc.common.err.output_message := OutputMessage; +end; + +procedure InitDecompressor(Handle: TImagingHandle; var jc: TJpegContext); +begin + jpeg_CreateDecompress(@jc.d, JPEG_LIB_VERSION, sizeof(jc.d)); + JpegStdioSrc(jc.d, Handle); + jpeg_read_header(@jc.d, True); + jc.d.scale_num := 1; + jc.d.scale_denom := 1; + jc.d.do_block_smoothing := True; + if jc.d.out_color_space = JCS_GRAYSCALE then + begin + jc.d.quantize_colors := True; + jc.d.desired_number_of_colors := 256; + end; +end; + +procedure InitCompressor(Handle: TImagingHandle; var jc: TJpegContext; + Saver: TJpegFileFormat); +begin + jpeg_CreateCompress(@jc.c, JPEG_LIB_VERSION, sizeof(jc.c)); + JpegStdioDest(jc.c, Handle); + if Saver.FGrayScale then + jc.c.in_color_space := JCS_GRAYSCALE + else + jc.c.in_color_space := JCS_RGB; + jpeg_set_defaults(@jc.c); + jpeg_set_quality(@jc.c, Saver.FQuality, True); + if Saver.FProgressive then + jpeg_simple_progression(@jc.c); +end; + +{ TJpegFileFormat class implementation } + +procedure TJpegFileFormat.Define; +begin + FName := SJpegFormatName; + FFeatures := [ffLoad, ffSave]; + FSupportedFormats := JpegSupportedFormats; + + FQuality := JpegDefaultQuality; + FProgressive := JpegDefaultProgressive; + + AddMasks(SJpegMasks); + RegisterOption(ImagingJpegQuality, @FQuality); + RegisterOption(ImagingJpegProgressive, @FProgressive); +end; + +procedure TJpegFileFormat.CheckOptionsValidity; +begin + // Check if option values are valid + if not (FQuality in [1..100]) then + FQuality := JpegDefaultQuality; +end; + +function TJpegFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + PtrInc, LinesPerCall, LinesRead, I: Integer; + Dest: PByte; + jc: TJpegContext; + Info: TImageFormatInfo; + Col32: PColor32Rec; + NeedsRedBlueSwap: Boolean; + Pix: PColor24Rec; +{$IFDEF ErrorJmpRecovery} + ErrorClient: TErrorClientData; +{$ENDIF} + + procedure LoadMetaData; + var + XDensity, YDensity: Single; + ResUnit: TResolutionUnit; + begin + // Density unit: 0 - undef, 1 - inch, 2 - cm + if jc.d.saw_JFIF_marker and (jc.d.density_unit > 0) and + (jc.d.X_density > 0) and (jc.d.Y_density > 0) then + begin + XDensity := jc.d.X_density; + YDensity := jc.d.Y_density; + ResUnit := ruDpi; + if jc.d.density_unit = 2 then + ResUnit := ruDpcm; + FMetadata.SetPhysicalPixelSize(ResUnit, XDensity, YDensity); + end; + end; + +begin + // Copy IO functions to global var used in JpegLib callbacks + Result := False; + SetJpegIO(GetIO); + SetLength(Images, 1); + + with JIO, Images[0] do + try + ZeroMemory(@jc, SizeOf(jc)); + SetupErrorMgr(jc); + {$IFDEF ErrorJmpRecovery} + ZeroMemory(@ErrorClient, SizeOf(ErrorClient)); + jc.common.client_data := @ErrorClient; + if setjmp(ErrorClient.JmpBuf) <> 0 then + begin + Result := True; + Exit; + end; + {$ENDIF} + InitDecompressor(Handle, jc); + + case jc.d.out_color_space of + JCS_GRAYSCALE: Format := ifGray8; + JCS_RGB: Format := ifR8G8B8; + JCS_CMYK: Format := ifA8R8G8B8; + else + Exit; + end; + + NewImage(jc.d.image_width, jc.d.image_height, Format, Images[0]); + jpeg_start_decompress(@jc.d); + GetImageFormatInfo(Format, Info); + PtrInc := Width * Info.BytesPerPixel; + LinesPerCall := 1; + Dest := Bits; + + // If Jpeg's colorspace is RGB and not YCbCr we need to swap + // R and B to get Imaging's native order + NeedsRedBlueSwap := jc.d.jpeg_color_space = JCS_RGB; + {$IFDEF RGBSWAPPED} + // Force R-B swap for FPC's PasJpeg + NeedsRedBlueSwap := True; + {$ENDIF} + + {$IFDEF ErrorJmpRecovery} + ErrorClient.ScanlineReadReached := True; + {$ENDIF} + + while jc.d.output_scanline < jc.d.output_height do + begin + LinesRead := jpeg_read_scanlines(@jc.d, @Dest, LinesPerCall); + if NeedsRedBlueSwap and (Format = ifR8G8B8) then + begin + Pix := PColor24Rec(Dest); + for I := 0 to Width - 1 do + begin + SwapValues(Pix.R, Pix.B); + Inc(Pix); + end; + end; + Inc(Dest, PtrInc * LinesRead); + end; + + if jc.d.out_color_space = JCS_CMYK then + begin + Col32 := Bits; + // Translate from CMYK to RGB + for I := 0 to Width * Height - 1 do + begin + CMYKToRGB(255 - Col32.B, 255 - Col32.G, 255 - Col32.R, 255 - Col32.A, + Col32.R, Col32.G, Col32.B); + Col32.A := 255; + Inc(Col32); + end; + end; + + // Store supported metadata + LoadMetaData; + + jpeg_finish_output(@jc.d); + jpeg_finish_decompress(@jc.d); + Result := True; + finally + ReleaseContext(jc); + end; +end; + +function TJpegFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +var + PtrInc, LinesWritten: LongInt; + Src, Line: PByte; + jc: TJpegContext; + ImageToSave: TImageData; + Info: TImageFormatInfo; + MustBeFreed: Boolean; +{$IFDEF RGBSWAPPED} + I: LongInt; + Pix: PColor24Rec; +{$ENDIF} + + procedure SaveMetaData; + var + XRes, YRes: Single; + begin + if FMetadata.GetPhysicalPixelSize(ruDpcm, XRes, YRes, True) then + begin + jc.c.density_unit := 2; // Dots per cm + jc.c.X_density := Round(XRes); + jc.c.Y_density := Round(YRes) + end; + end; + +begin + Result := False; + // Copy IO functions to global var used in JpegLib callbacks + SetJpegIO(GetIO); + + // Makes image to save compatible with Jpeg saving capabilities + if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then + with JIO, ImageToSave do + try + ZeroMemory(@jc, SizeOf(jc)); + SetupErrorMgr(jc); + + GetImageFormatInfo(Format, Info); + FGrayScale := Format = ifGray8; + InitCompressor(Handle, jc, Self); + jc.c.image_width := Width; + jc.c.image_height := Height; + if FGrayScale then + begin + jc.c.input_components := 1; + jc.c.in_color_space := JCS_GRAYSCALE; + end + else + begin + jc.c.input_components := 3; + jc.c.in_color_space := JCS_RGB; + end; + + PtrInc := Width * Info.BytesPerPixel; + Src := Bits; + + {$IFDEF RGBSWAPPED} + GetMem(Line, PtrInc); + {$ENDIF} + + // Save supported metadata + SaveMetaData; + + jpeg_start_compress(@jc.c, True); + while (jc.c.next_scanline < jc.c.image_height) do + begin + {$IFDEF RGBSWAPPED} + if Format = ifR8G8B8 then + begin + Move(Src^, Line^, PtrInc); + Pix := PColor24Rec(Line); + for I := 0 to Width - 1 do + begin + SwapValues(Pix.R, Pix.B); + Inc(Pix, 1); + end; + end; + {$ELSE} + Line := Src; + {$ENDIF} + + LinesWritten := jpeg_write_scanlines(@jc.c, @Line, 1); + Inc(Src, PtrInc * LinesWritten); + end; + + jpeg_finish_compress(@jc.c); + Result := True; + finally + ReleaseContext(jc); + if MustBeFreed then + FreeImage(ImageToSave); + {$IFDEF RGBSWAPPED} + FreeMem(Line); + {$ENDIF} + end; +end; + +procedure TJpegFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +begin + if Info.HasGrayChannel then + ConvertImage(Image, ifGray8) + else + ConvertImage(Image, ifR8G8B8); +end; + +function TJpegFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + ReadCount: LongInt; + ID: array[0..9] of AnsiChar; +begin + Result := False; + if Handle <> nil then + with GetIO do + begin + FillChar(ID, SizeOf(ID), 0); + ReadCount := Read(Handle, @ID, SizeOf(ID)); + Seek(Handle, -ReadCount, smFromCurrent); + Result := (ReadCount = SizeOf(ID)) and + CompareMem(@ID, @JpegMagic, SizeOf(JpegMagic)); + end; +end; + +procedure TJpegFileFormat.SetJpegIO(const JpegIO: TIOFunctions); +begin + JIO := JpegIO; +end; + +initialization + RegisterImageFileFormat(TJpegFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 --------------------------------------------------- + - Able to read corrupted JPEG files - loads partial image + and skips the corrupted parts (FPC and x86 Delphi). + - Fixed reading of physical resolution metadata, could cause + "divided by zero" later on for some files. + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Fixed loading of some JPEGs with certain APPN markers (bug in JpegLib). + - Fixed swapped Red-Blue order when loading Jpegs with + jc.d.jpeg_color_space = JCS_RGB. + - Added loading and saving of physical pixel size metadata. + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Changed the Jpeg error manager, messages were not properly formated. + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - Fixed wrong color space setting in InitCompressor. + - Fixed problem with progressive Jpegs in FPC (modified JpegLib, + can't use FPC's PasJpeg in Windows). + + -- 0.25.0 Changes/Bug Fixes --------------------------------- + - FPC's PasJpeg wasn't really used in last version, fixed. + + -- 0.24.1 Changes/Bug Fixes --------------------------------- + - Fixed loading of CMYK jpeg images. Could cause heap corruption + and loaded image looked wrong. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Removed JFIF/EXIF detection from TestFormat. Found JPEGs + with different headers (Lavc) which weren't recognized. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - MakeCompatible method moved to base class, put ConvertToSupported here. + GetSupportedFormats removed, it is now set in constructor. + - Made public properties for options registered to SetOption/GetOption + functions. + - Changed extensions to filename masks. + - Changed SaveData, LoadData, and MakeCompatible methods according + to changes in base class in Imaging unit. + - Changes in TestFormat, now reads JFIF and EXIF signatures too. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - input position is now set correctly to the end of the image + after loading is done. Loading of sequence of JPEG files stored in + single stream works now + - when loading and saving images in FPC with PASJPEG read and + blue channels are swapped to have the same chanel order as IMJPEGLIB + - you can now choose between IMJPEGLIB and PASJPEG implementations + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - added SetJpegIO method which is used by JNG image format +} +end. diff --git a/src/lib/vampimg/ImagingNetworkGraphics.pas b/src/lib/vampimg/ImagingNetworkGraphics.pas new file mode 100644 index 0000000..364cbcf --- /dev/null +++ b/src/lib/vampimg/ImagingNetworkGraphics.pas @@ -0,0 +1,2695 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loaders/savers for Network Graphics image + file formats PNG, MNG, and JNG.} +unit ImagingNetworkGraphics; + +interface + +{$I ImagingOptions.inc} + +{ If MNG support is enabled we must make sure PNG and JNG are enabled too.} +{$IFNDEF DONT_LINK_MNG} + {$UNDEF DONT_LINK_PNG} + {$UNDEF DONT_LINK_JNG} +{$ENDIF} + +uses + Types, SysUtils, Classes, ImagingTypes, Imaging, ImagingUtility, ImagingFormats, dzlib; + +type + { Basic class for Network Graphics file formats loaders/savers.} + TNetworkGraphicsFileFormat = class(TImageFileFormat) + protected + FSignature: TChar8; + FPreFilter: LongInt; + FCompressLevel: LongInt; + FLossyCompression: LongBool; + FLossyAlpha: LongBool; + FQuality: LongInt; + FProgressive: LongBool; + FZLibStategy: Integer; + function GetSupportedFormats: TImageFormats; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + procedure Define; override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + procedure CheckOptionsValidity; override; + published + { Sets precompression filter used when saving images with lossless compression. + Allowed values are: 0 (none), 1 (sub), 2 (up), 3 (average), 4 (paeth), + 5 (use 0 for indexed/gray images and 4 for RGB/ARGB images), + 6 (adaptive filtering - use best filter for each scanline - very slow). + Note that filters 3 and 4 are much slower than filters 1 and 2. + Default value is 5.} + property PreFilter: LongInt read FPreFilter write FPreFilter; + { Sets ZLib compression level used when saving images with lossless compression. + Allowed values are in range 0 (no compresstion) to 9 (best compression). + Default value is 5.} + property CompressLevel: LongInt read FCompressLevel write FCompressLevel; + { Specifies whether MNG animation frames are saved with lossy or lossless + compression. Lossless frames are saved as PNG images and lossy frames are + saved as JNG images. Allowed values are 0 (False) and 1 (True). + Default value is 0.} + property LossyCompression: LongBool read FLossyCompression write FLossyCompression; + { Defines whether alpha channel of lossy MNG frames or JNG images + is lossy compressed too. Allowed values are 0 (False) and 1 (True). + Default value is 0.} + property LossyAlpha: LongBool read FLossyAlpha write FLossyAlpha; + { Specifies compression quality used when saving lossy MNG frames or JNG images. + For details look at ImagingJpegQuality option.} + property Quality: LongInt read FQuality write FQuality; + { Specifies whether images are saved in progressive format when saving lossy + MNG frames or JNG images. For details look at ImagingJpegProgressive.} + property Progressive: LongBool read FProgressive write FProgressive; + end; + + { Class for loading Portable Network Graphics Images. + Loads all types of this image format (all images in png test suite) + and saves all types with bitcount >= 8 (non-interlaced only). + Compression level and filtering can be set by options interface. + + Supported ancillary chunks (loading): + tRNS, bKGD + (for indexed images transparency contains alpha values for palette, + RGB/Gray images with transparency are converted to formats with alpha + and pixels with transparent color are replaced with background color + with alpha = 0).} + TPNGFileFormat = class(TNetworkGraphicsFileFormat) + private + FLoadAnimated: LongBool; + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + published + property LoadAnimated: LongBool read FLoadAnimated write FLoadAnimated; + end; + +{$IFNDEF DONT_LINK_MNG} + { Class for loading Multiple Network Graphics files. + This format has complex animation capabilities but Imaging only + extracts frames. Individual frames are stored as standard PNG or JNG + images. Loads all types of these frames stored in IHDR-IEND and + JHDR-IEND streams (Note that there are MNG chunks + like BASI which define images but does not contain image data itself, + those are ignored). + Imaging saves MNG files as MNG-VLC (very low complexity) so it is basicaly + an array of image frames without MNG animation chunks. Frames can be saved + as lossless PNG or lossy JNG images (look at TPNGFileFormat and + TJNGFileFormat for info). Every frame can be in different data format. + + Many frame compression settings can be modified by options interface.} + TMNGFileFormat = class(TNetworkGraphicsFileFormat) + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + end; +{$ENDIF} + +{$IFNDEF DONT_LINK_JNG} + { Class for loading JPEG Network Graphics Images. + Loads all types of this image format (all images in jng test suite) + and saves all types except 12 bit JPEGs. + Alpha channel in JNG images is stored separately from color/gray data and + can be lossy (as JPEG image) or lossless (as PNG image) compressed. + Type of alpha compression, compression level and quality, + and filtering can be set by options interface. + + Supported ancillary chunks (loading): + tRNS, bKGD + (Images with transparency are converted to formats with alpha + and pixels with transparent color are replaced with background color + with alpha = 0).} + TJNGFileFormat = class(TNetworkGraphicsFileFormat) + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + end; +{$ENDIF} + + +implementation + +uses +{$IFNDEF DONT_LINK_JNG} + ImagingJpeg, ImagingIO, +{$ENDIF} + ImagingCanvases; + +const + NGDefaultPreFilter = 5; + NGDefaultCompressLevel = 5; + NGDefaultLossyAlpha = False; + NGDefaultLossyCompression = False; + NGDefaultProgressive = False; + NGDefaultQuality = 90; + NGLosslessFormats: TImageFormats = [ifIndex8, ifGray8, ifA8Gray8, ifGray16, + ifA16Gray16, ifR8G8B8, ifA8R8G8B8, ifR16G16B16, ifA16R16G16B16, ifB16G16R16, + ifA16B16G16R16, ifBinary]; + NGLossyFormats: TImageFormats = [ifGray8, ifA8Gray8, ifR8G8B8, ifA8R8G8B8]; + PNGDefaultLoadAnimated = True; + NGDefaultZLibStartegy = 1; // Z_FILTERED + + SPNGFormatName = 'Portable Network Graphics'; + SPNGMasks = '*.png'; + SMNGFormatName = 'Multiple Network Graphics'; + SMNGMasks = '*.mng'; + SJNGFormatName = 'JPEG Network Graphics'; + SJNGMasks = '*.jng'; + +resourcestring + SErrorLoadingChunk = 'Error when reading %s chunk data. File may be corrupted.'; + +type + { Chunk header.} + TChunkHeader = packed record + DataSize: LongWord; + ChunkID: TChar4; + end; + + { IHDR chunk format - PNG header.} + TIHDR = packed record + Width: LongWord; // Image width + Height: LongWord; // Image height + BitDepth: Byte; // Bits per pixel or bits per sample (for truecolor) + ColorType: Byte; // 0 = grayscale, 2 = truecolor, 3 = palette, + // 4 = gray + alpha, 6 = truecolor + alpha + Compression: Byte; // Compression type: 0 = ZLib + Filter: Byte; // Used precompress filter + Interlacing: Byte; // Used interlacing: 0 = no int, 1 = Adam7 + end; + PIHDR = ^TIHDR; + + { MHDR chunk format - MNG header.} + TMHDR = packed record + FrameWidth: LongWord; // Frame width + FrameHeight: LongWord; // Frame height + TicksPerSecond: LongWord; // FPS of animation + NominalLayerCount: LongWord; // Number of layers in file + NominalFrameCount: LongWord; // Number of frames in file + NominalPlayTime: LongWord; // Play time of animation in ticks + SimplicityProfile: LongWord; // Defines which MNG features are used in this file + end; + PMHDR = ^TMHDR; + + { JHDR chunk format - JNG header.} + TJHDR = packed record + Width: LongWord; // Image width + Height: LongWord; // Image height + ColorType: Byte; // 8 = grayscale (Y), 10 = color (YCbCr), + // 12 = gray + alpha (Y-alpha), 14 = color + alpha (YCbCr-alpha) + SampleDepth: Byte; // 8, 12 or 20 (8 and 12 samples together) bit + Compression: Byte; // Compression type: 8 = Huffman coding + Interlacing: Byte; // 0 = single scan, 8 = progressive + AlphaSampleDepth: Byte; // 0, 1, 2, 4, 8, 16 if alpha compression is 0 (PNG) + // 8 if alpha compression is 8 (JNG) + AlphaCompression: Byte; // 0 = PNG graysscale IDAT, 8 = grayscale 8-bit JPEG + AlphaFilter: Byte; // 0 = PNG filter or no filter (JPEG) + AlphaInterlacing: Byte; // 0 = non interlaced + end; + PJHDR = ^TJHDR; + + { acTL chunk format - APNG animation control.} + TacTL = packed record + NumFrames: LongWord; // Number of frames + NumPlay: LongWord; // Number of times to loop the animation (0 = inf) + end; + PacTL =^TacTL; + + { fcTL chunk format - APNG frame control.} + TfcTL = packed record + SeqNumber: LongWord; // Sequence number of the animation chunk, starting from 0 + Width: LongWord; // Width of the following frame + Height: LongWord; // Height of the following frame + XOffset: LongWord; // X position at which to render the following frame + YOffset: LongWord; // Y position at which to render the following frame + DelayNumer: Word; // Frame delay fraction numerator + DelayDenom: Word; // Frame delay fraction denominator + DisposeOp: Byte; // Type of frame area disposal to be done after rendering this frame + BlendOp: Byte; // Type of frame area rendering for this frame + end; + PfcTL = ^TfcTL; + + { pHYs chunk format - encodes the absolute or relative dimensions of pixels.} + TpHYs = packed record + PixelsPerUnitX: LongWord; + PixelsPerUnitY: LongWord; + UnitSpecifier: Byte; + end; + PpHYs = ^TpHYs; + +const + { PNG file identifier.} + PNGSignature: TChar8 = #$89'PNG'#$0D#$0A#$1A#$0A; + { MNG file identifier.} + MNGSignature: TChar8 = #$8A'MNG'#$0D#$0A#$1A#$0A; + { JNG file identifier.} + JNGSignature: TChar8 = #$8B'JNG'#$0D#$0A#$1A#$0A; + + { Constants for chunk identifiers and signature identifiers. + They are in big-endian format.} + IHDRChunk: TChar4 = 'IHDR'; + IENDChunk: TChar4 = 'IEND'; + MHDRChunk: TChar4 = 'MHDR'; + MENDChunk: TChar4 = 'MEND'; + JHDRChunk: TChar4 = 'JHDR'; + IDATChunk: TChar4 = 'IDAT'; + JDATChunk: TChar4 = 'JDAT'; + JDAAChunk: TChar4 = 'JDAA'; + JSEPChunk: TChar4 = 'JSEP'; + PLTEChunk: TChar4 = 'PLTE'; + BACKChunk: TChar4 = 'BACK'; + DEFIChunk: TChar4 = 'DEFI'; + TERMChunk: TChar4 = 'TERM'; + tRNSChunk: TChar4 = 'tRNS'; + bKGDChunk: TChar4 = 'bKGD'; + gAMAChunk: TChar4 = 'gAMA'; + acTLChunk: TChar4 = 'acTL'; + fcTLChunk: TChar4 = 'fcTL'; + fdATChunk: TChar4 = 'fdAT'; + pHYsChunk: TChar4 = 'pHYs'; + + { APNG frame dispose operations.} + DisposeOpNone = 0; + DisposeOpBackground = 1; + DisposeOpPrevious = 2; + + { APNG frame blending modes} + BlendOpSource = 0; + BlendOpOver = 1; + + { Interlace start and offsets.} + RowStart: array[0..6] of LongInt = (0, 0, 4, 0, 2, 0, 1); + ColumnStart: array[0..6] of LongInt = (0, 4, 0, 2, 0, 1, 0); + RowIncrement: array[0..6] of LongInt = (8, 8, 8, 4, 4, 2, 2); + ColumnIncrement: array[0..6] of LongInt = (8, 8, 4, 4, 2, 2, 1); + +type + { Helper class that holds information about MNG frame in PNG or JNG format.} + TFrameInfo = class + public + Index: Integer; + FrameWidth, FrameHeight: LongInt; + IsJpegFrame: Boolean; + IHDR: TIHDR; + JHDR: TJHDR; + fcTL: TfcTL; + pHYs: TpHYs; + Palette: PPalette24; + PaletteEntries: LongInt; + Transparency: Pointer; + TransparencySize: LongInt; + Background: Pointer; + BackgroundSize: LongInt; + IDATMemory: TMemoryStream; + JDATMemory: TMemoryStream; + JDAAMemory: TMemoryStream; + constructor Create(AIndex: Integer); + destructor Destroy; override; + procedure AssignSharedProps(Source: TFrameInfo); + end; + + { Defines type of Network Graphics file.} + TNGFileType = (ngPNG, ngAPNG, ngMNG, ngJNG); + + TNGFileHandler = class + public + FileFormat: TNetworkGraphicsFileFormat; + FileType: TNGFileType; + Frames: array of TFrameInfo; + MHDR: TMHDR; // Main header for MNG files + acTL: TacTL; // Global anim control for APNG files + GlobalPalette: PPalette24; + GlobalPaletteEntries: LongInt; + GlobalTransparency: Pointer; + GlobalTransparencySize: LongInt; + constructor Create(AFileFormat: TNetworkGraphicsFileFormat); + destructor Destroy; override; + procedure Clear; + function GetLastFrame: TFrameInfo; + function AddFrameInfo: TFrameInfo; + procedure LoadMetaData; + end; + + { Network Graphics file parser and frame converter.} + TNGFileLoader = class(TNGFileHandler) + public + function LoadFile(Handle: TImagingHandle): Boolean; + procedure LoadImageFromPNGFrame(FrameWidth, FrameHeight: LongInt; const IHDR: TIHDR; IDATStream: TMemoryStream; var Image: TImageData); +{$IFNDEF DONT_LINK_JNG} + procedure LoadImageFromJNGFrame(FrameWidth, FrameHeight: LongInt; const JHDR: TJHDR; IDATStream, JDATStream, JDAAStream: TMemoryStream; var Image: TImageData); +{$ENDIF} + procedure ApplyFrameSettings(Frame: TFrameInfo; var Image: TImageData); + end; + + TNGFileSaver = class(TNGFileHandler) + public + PreFilter: LongInt; + CompressLevel: LongInt; + LossyAlpha: Boolean; + Quality: LongInt; + Progressive: Boolean; + ZLibStrategy: Integer; + function SaveFile(Handle: TImagingHandle): Boolean; + procedure AddFrame(const Image: TImageData; IsJpegFrame: Boolean); + procedure StoreImageToPNGFrame(const IHDR: TIHDR; Bits: Pointer; FmtInfo: TImageFormatInfo; IDATStream: TMemoryStream); +{$IFNDEF DONT_LINK_JNG} + procedure StoreImageToJNGFrame(const JHDR: TJHDR; const Image: TImageData; IDATStream, JDATStream, JDAAStream: TMemoryStream); +{$ENDIF} + procedure SetFileOptions; + end; + +{$IFNDEF DONT_LINK_JNG} + TCustomIOJpegFileFormat = class(TJpegFileFormat) + protected + FCustomIO: TIOFunctions; + procedure SetJpegIO(const JpegIO: TIOFunctions); override; + procedure SetCustomIO(const CustomIO: TIOFunctions); + end; +{$ENDIF} + + TAPNGAnimator = class + public + class procedure Animate(var Images: TDynImageDataArray; const acTL: TacTL; const SrcFrames: array of TFrameInfo); + end; + +{ Helper routines } + +function PaethPredictor(A, B, C: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +var + P, PA, PB, PC: LongInt; +begin + P := A + B - C; + PA := Abs(P - A); + PB := Abs(P - B); + PC := Abs(P - C); + if (PA <= PB) and (PA <= PC) then + Result := A + else + if PB <= PC then + Result := B + else + Result := C; +end; + +procedure SwapRGB(Line: PByte; Width, SampleDepth, BytesPerPixel: LongInt); +var + I: LongInt; + Tmp: Word; +begin + case SampleDepth of + 8: + for I := 0 to Width - 1 do + with PColor24Rec(Line)^ do + begin + Tmp := R; + R := B; + B := Tmp; + Inc(Line, BytesPerPixel); + end; + 16: + for I := 0 to Width - 1 do + with PColor48Rec(Line)^ do + begin + Tmp := R; + R := B; + B := Tmp; + Inc(Line, BytesPerPixel); + end; + end; + end; + +{$IFNDEF DONT_LINK_JNG} + +{ TCustomIOJpegFileFormat class implementation } + +procedure TCustomIOJpegFileFormat.SetCustomIO(const CustomIO: TIOFunctions); +begin + FCustomIO := CustomIO; +end; + +procedure TCustomIOJpegFileFormat.SetJpegIO(const JpegIO: TIOFunctions); +begin + inherited SetJpegIO(FCustomIO); +end; + +{$ENDIF} + +{ TFrameInfo class implementation } + +constructor TFrameInfo.Create(AIndex: Integer); +begin + Index := AIndex; + IDATMemory := TMemoryStream.Create; + JDATMemory := TMemoryStream.Create; + JDAAMemory := TMemoryStream.Create; +end; + +destructor TFrameInfo.Destroy; +begin + FreeMem(Palette); + FreeMem(Transparency); + FreeMem(Background); + IDATMemory.Free; + JDATMemory.Free; + JDAAMemory.Free; + inherited Destroy; +end; + +procedure TFrameInfo.AssignSharedProps(Source: TFrameInfo); +begin + IHDR := Source.IHDR; + JHDR := Source.JHDR; + PaletteEntries := Source.PaletteEntries; + GetMem(Palette, PaletteEntries * SizeOf(TColor24Rec)); + Move(Source.Palette^, Palette^, PaletteEntries * SizeOf(TColor24Rec)); + TransparencySize := Source.TransparencySize; + GetMem(Transparency, TransparencySize); + Move(Source.Transparency^, Transparency^, TransparencySize); +end; + +{ TNGFileHandler class implementation} + +destructor TNGFileHandler.Destroy; +begin + Clear; + inherited Destroy; +end; + +procedure TNGFileHandler.Clear; +var + I: LongInt; +begin + for I := 0 to Length(Frames) - 1 do + Frames[I].Free; + SetLength(Frames, 0); + FreeMemNil(GlobalPalette); + GlobalPaletteEntries := 0; + FreeMemNil(GlobalTransparency); + GlobalTransparencySize := 0; +end; + +constructor TNGFileHandler.Create(AFileFormat: TNetworkGraphicsFileFormat); +begin + FileFormat := AFileFormat; +end; + +function TNGFileHandler.GetLastFrame: TFrameInfo; +var + Len: LongInt; +begin + Len := Length(Frames); + if Len > 0 then + Result := Frames[Len - 1] + else + Result := nil; +end; + +procedure TNGFileHandler.LoadMetaData; +var + I: Integer; + Delay, Denom: Integer; +begin + if FileType = ngAPNG then + begin + // Num plays of APNG animation + FileFormat.FMetadata.SetMetaItem(SMetaAnimationLoops, acTL.NumPlay); + end; + + for I := 0 to High(Frames) do + begin + if Frames[I].pHYs.UnitSpecifier = 1 then + begin + // Store physical pixel dimensions, in PNG stored as pixels per meter DPM + FileFormat.FMetadata.SetPhysicalPixelSize(ruDpm, Frames[I].pHYs.PixelsPerUnitX, + Frames[I].pHYs.PixelsPerUnitY); + end; + if FileType = ngAPNG then + begin + // Store frame delay of APNG file frame + Denom := Frames[I].fcTL.DelayDenom; + if Denom = 0 then + Denom := 100; + Delay := Round(1000 * (Frames[I].fcTL.DelayNumer / Denom)); + FileFormat.FMetadata.SetMetaItem(SMetaFrameDelay, Delay, I); + end; + end; +end; + +function TNGFileHandler.AddFrameInfo: TFrameInfo; +var + Len: LongInt; +begin + Len := Length(Frames); + SetLength(Frames, Len + 1); + Result := TFrameInfo.Create(Len); + Frames[Len] := Result; +end; + +{ TNGFileLoader class implementation} + +function TNGFileLoader.LoadFile(Handle: TImagingHandle): Boolean; +var + Sig: TChar8; + Chunk: TChunkHeader; + ChunkData: Pointer; + ChunkCrc: LongWord; + + procedure ReadChunk; + begin + GetIO.Read(Handle, @Chunk, SizeOf(Chunk)); + Chunk.DataSize := SwapEndianLongWord(Chunk.DataSize); + end; + + procedure ReadChunkData; + var + ReadBytes: LongWord; + begin + FreeMemNil(ChunkData); + GetMem(ChunkData, Chunk.DataSize); + ReadBytes := GetIO.Read(Handle, ChunkData, Chunk.DataSize); + GetIO.Read(Handle, @ChunkCrc, SizeOf(ChunkCrc)); + if ReadBytes <> Chunk.DataSize then + RaiseImaging(SErrorLoadingChunk, [string(Chunk.ChunkID)]); + end; + + procedure SkipChunkData; + begin + GetIO.Seek(Handle, Chunk.DataSize + SizeOf(ChunkCrc), smFromCurrent); + end; + + procedure StartNewPNGImage; + var + Frame: TFrameInfo; + begin + ReadChunkData; + + if Chunk.ChunkID = fcTLChunk then + begin + if (Length(Frames) = 1) and (Frames[0].IDATMemory.Size = 0) then + begin + // First fcTL chunk maybe for first IDAT frame which is alredy created + Frame := Frames[0]; + end + else + begin + // Subsequent APNG frames with data in fdAT + Frame := AddFrameInfo; + // Copy some shared props from first frame (IHDR is the same for all APNG frames, palette etc) + Frame.AssignSharedProps(Frames[0]); + end; + Frame.fcTL := PfcTL(ChunkData)^; + SwapEndianLongWord(@Frame.fcTL, 5); + Frame.fcTL.DelayNumer := SwapEndianWord(Frame.fcTL.DelayNumer); + Frame.fcTL.DelayDenom := SwapEndianWord(Frame.fcTL.DelayDenom); + Frame.FrameWidth := Frame.fcTL.Width; + Frame.FrameHeight := Frame.fcTL.Height; + end + else + begin + // This is frame defined by IHDR chunk + Frame := AddFrameInfo; + Frame.IHDR := PIHDR(ChunkData)^; + SwapEndianLongWord(@Frame.IHDR, 2); + Frame.FrameWidth := Frame.IHDR.Width; + Frame.FrameHeight := Frame.IHDR.Height; + end; + Frame.IsJpegFrame := False; + end; + + procedure StartNewJNGImage; + var + Frame: TFrameInfo; + begin + ReadChunkData; + Frame := AddFrameInfo; + Frame.IsJpegFrame := True; + Frame.JHDR := PJHDR(ChunkData)^; + SwapEndianLongWord(@Frame.JHDR, 2); + Frame.FrameWidth := Frame.JHDR.Width; + Frame.FrameHeight := Frame.JHDR.Height; + end; + + procedure AppendIDAT; + begin + ReadChunkData; + // Append current IDAT/fdAT chunk to storage stream + if Chunk.ChunkID = IDATChunk then + GetLastFrame.IDATMemory.Write(ChunkData^, Chunk.DataSize) + else if Chunk.ChunkID = fdATChunk then + GetLastFrame.IDATMemory.Write(PByteArray(ChunkData)[4], Chunk.DataSize - SizeOf(LongWord)); + end; + + procedure AppendJDAT; + begin + ReadChunkData; + // Append current JDAT chunk to storage stream + GetLastFrame.JDATMemory.Write(ChunkData^, Chunk.DataSize); + end; + + procedure AppendJDAA; + begin + ReadChunkData; + // Append current JDAA chunk to storage stream + GetLastFrame.JDAAMemory.Write(ChunkData^, Chunk.DataSize); + end; + + procedure LoadPLTE; + begin + ReadChunkData; + if GetLastFrame = nil then + begin + // Load global palette + GetMem(GlobalPalette, Chunk.DataSize); + Move(ChunkData^, GlobalPalette^, Chunk.DataSize); + GlobalPaletteEntries := Chunk.DataSize div 3; + end + else if GetLastFrame.Palette = nil then + begin + if (Chunk.DataSize = 0) and (GlobalPalette <> nil) then + begin + // Use global palette + GetMem(GetLastFrame.Palette, GlobalPaletteEntries * SizeOf(TColor24Rec)); + Move(GlobalPalette^, GetLastFrame.Palette^, GlobalPaletteEntries * SizeOf(TColor24Rec)); + GetLastFrame.PaletteEntries := GlobalPaletteEntries; + end + else + begin + // Load pal from PLTE chunk + GetMem(GetLastFrame.Palette, Chunk.DataSize); + Move(ChunkData^, GetLastFrame.Palette^, Chunk.DataSize); + GetLastFrame.PaletteEntries := Chunk.DataSize div 3; + end; + end; + end; + + procedure LoadtRNS; + begin + ReadChunkData; + if GetLastFrame = nil then + begin + // Load global transparency + GetMem(GlobalTransparency, Chunk.DataSize); + Move(ChunkData^, GlobalTransparency^, Chunk.DataSize); + GlobalTransparencySize := Chunk.DataSize; + end + else if GetLastFrame.Transparency = nil then + begin + if (Chunk.DataSize = 0) and (GlobalTransparency <> nil) then + begin + // Use global transparency + GetMem(GetLastFrame.Transparency, GlobalTransparencySize); + Move(GlobalTransparency^, GetLastFrame.Transparency^, Chunk.DataSize); + GetLastFrame.TransparencySize := GlobalTransparencySize; + end + else + begin + // Load pal from tRNS chunk + GetMem(GetLastFrame.Transparency, Chunk.DataSize); + Move(ChunkData^, GetLastFrame.Transparency^, Chunk.DataSize); + GetLastFrame.TransparencySize := Chunk.DataSize; + end; + end; + end; + + procedure LoadbKGD; + begin + ReadChunkData; + if GetLastFrame.Background = nil then + begin + GetMem(GetLastFrame.Background, Chunk.DataSize); + Move(ChunkData^, GetLastFrame.Background^, Chunk.DataSize); + GetLastFrame.BackgroundSize := Chunk.DataSize; + end; + end; + + procedure HandleacTL; + begin + FileType := ngAPNG; + ReadChunkData; + acTL := PacTL(ChunkData)^; + SwapEndianLongWord(@acTL, SizeOf(acTL) div SizeOf(LongWord)); + end; + + procedure LoadpHYs; + begin + ReadChunkData; + with GetLastFrame do + begin + pHYs := PpHYs(ChunkData)^; + SwapEndianLongWord(@pHYs, SizeOf(pHYs) div SizeOf(LongWord)); + end; + end; + +begin + Result := False; + Clear; + ChunkData := nil; + with GetIO do + try + Read(Handle, @Sig, SizeOf(Sig)); + // Set file type according to the signature + if Sig = PNGSignature then FileType := ngPNG + else if Sig = MNGSignature then FileType := ngMNG + else if Sig = JNGSignature then FileType := ngJNG + else Exit; + + if FileType = ngMNG then + begin + // Store MNG header if present + ReadChunk; + ReadChunkData; + MHDR := PMHDR(ChunkData)^; + SwapEndianLongWord(@MHDR, SizeOf(MHDR) div SizeOf(LongWord)); + end; + + // Read chunks until ending chunk or EOF is reached + repeat + ReadChunk; + if (Chunk.ChunkID = IHDRChunk) or (Chunk.ChunkID = fcTLChunk) then StartNewPNGImage + else if Chunk.ChunkID = JHDRChunk then StartNewJNGImage + else if (Chunk.ChunkID = IDATChunk) or (Chunk.ChunkID = fdATChunk) then AppendIDAT + else if Chunk.ChunkID = JDATChunk then AppendJDAT + else if Chunk.ChunkID = JDAAChunk then AppendJDAA + else if Chunk.ChunkID = PLTEChunk then LoadPLTE + else if Chunk.ChunkID = tRNSChunk then LoadtRNS + else if Chunk.ChunkID = bKGDChunk then LoadbKGD + else if Chunk.ChunkID = acTLChunk then HandleacTL + else if Chunk.ChunkID = pHYsChunk then LoadpHYs + else SkipChunkData; + until Eof(Handle) or (Chunk.ChunkID = MENDChunk) or + ((FileType <> ngMNG) and (Chunk.ChunkID = IENDChunk)); + + Result := True; + finally + FreeMemNil(ChunkData); + end; +end; + +procedure TNGFileLoader.LoadImageFromPNGFrame(FrameWidth, FrameHeight: LongInt; const IHDR: TIHDR; + IDATStream: TMemoryStream; var Image: TImageData); +type + TGetPixelFunc = function(Line: PByteArray; X: LongInt): Byte; +var + LineBuffer: array[Boolean] of PByteArray; + ActLine: Boolean; + Data, TotalBuffer, ZeroLine, PrevLine: Pointer; + BitCount, TotalSize, TotalPos, BytesPerPixel, I, Pass, + SrcDataSize, BytesPerLine, InterlaceLineBytes, InterlaceWidth: LongInt; + Info: TImageFormatInfo; + + procedure DecodeAdam7; + const + BitTable: array[1..8] of LongInt = ($1, $3, 0, $F, 0, 0, 0, $FF); + StartBit: array[1..8] of LongInt = (7, 6, 0, 4, 0, 0, 0, 0); + var + Src, Dst, Dst2: PByte; + CurBit, Col: LongInt; + begin + Src := @LineBuffer[ActLine][1]; + Col := ColumnStart[Pass]; + with Image do + case BitCount of + 1, 2, 4: + begin + Dst := @PByteArray(Data)[I * BytesPerLine]; + repeat + CurBit := StartBit[BitCount]; + repeat + Dst2 := @PByteArray(Dst)[(BitCount * Col) shr 3]; + Dst2^ := Dst2^ or ((Src^ shr CurBit) and BitTable[BitCount]) + shl (StartBit[BitCount] - (Col * BitCount mod 8)); + Inc(Col, ColumnIncrement[Pass]); + Dec(CurBit, BitCount); + until CurBit < 0; + Inc(Src); + until Col >= Width; + end; + else + begin + Dst := @PByteArray(Data)[I * BytesPerLine + Col * BytesPerPixel]; + repeat + CopyPixel(Src, Dst, BytesPerPixel); + Inc(Dst, BytesPerPixel); + Inc(Src, BytesPerPixel); + Inc(Dst, ColumnIncrement[Pass] * BytesPerPixel - BytesPerPixel); + Inc(Col, ColumnIncrement[Pass]); + until Col >= Width; + end; + end; + end; + + procedure FilterScanline(Filter: Byte; BytesPerPixel: LongInt; Line, PrevLine, Target: PByteArray; + BytesPerLine: LongInt); + var + I: LongInt; + begin + case Filter of + 0: + begin + // No filter + Move(Line^, Target^, BytesPerLine); + end; + 1: + begin + // Sub filter + Move(Line^, Target^, BytesPerPixel); + for I := BytesPerPixel to BytesPerLine - 1 do + Target[I] := (Line[I] + Target[I - BytesPerPixel]) and $FF; + end; + 2: + begin + // Up filter + for I := 0 to BytesPerLine - 1 do + Target[I] := (Line[I] + PrevLine[I]) and $FF; + end; + 3: + begin + // Average filter + for I := 0 to BytesPerPixel - 1 do + Target[I] := (Line[I] + PrevLine[I] shr 1) and $FF; + for I := BytesPerPixel to BytesPerLine - 1 do + Target[I] := (Line[I] + (Target[I - BytesPerPixel] + PrevLine[I]) shr 1) and $FF; + end; + 4: + begin + // Paeth filter + for I := 0 to BytesPerPixel - 1 do + Target[I] := (Line[I] + PaethPredictor(0, PrevLine[I], 0)) and $FF; + for I := BytesPerPixel to BytesPerLine - 1 do + Target[I] := (Line[I] + PaethPredictor(Target[I - BytesPerPixel], PrevLine[I], PrevLine[I - BytesPerPixel])) and $FF; + end; + end; + end; + + procedure TransformLOCOToRGB(Data: PByte; NumPixels, BytesPerPixel: LongInt); + var + I: LongInt; + begin + for I := 0 to NumPixels - 1 do + begin + if IHDR.BitDepth = 8 then + begin + PColor32Rec(Data).R := Byte(PColor32Rec(Data).R + PColor32Rec(Data).G); + PColor32Rec(Data).B := Byte(PColor32Rec(Data).B + PColor32Rec(Data).G); + end + else + begin + PColor64Rec(Data).R := Word(PColor64Rec(Data).R + PColor64Rec(Data).G); + PColor64Rec(Data).B := Word(PColor64Rec(Data).B + PColor64Rec(Data).G); + end; + Inc(Data, BytesPerPixel); + end; + end; + + function CheckBinaryPalette: Boolean; + begin + with GetLastFrame do + Result := (PaletteEntries = 2) and + (Palette[0].R = 0) and (Palette[0].G = 0) and (Palette[0].B = 0) and + (Palette[1].R = 255) and (Palette[1].G = 255) and (Palette[1].B = 255); + end; + +begin + Image.Width := FrameWidth; + Image.Height := FrameHeight; + Image.Format := ifUnknown; + + case IHDR.ColorType of + 0: + begin + // Gray scale image + case IHDR.BitDepth of + 1: Image.Format := ifBinary; + 2, 4, 8: Image.Format := ifGray8; + 16: Image.Format := ifGray16; + end; + BitCount := IHDR.BitDepth; + end; + 2: + begin + // RGB image + case IHDR.BitDepth of + 8: Image.Format := ifR8G8B8; + 16: Image.Format := ifR16G16B16; + end; + BitCount := IHDR.BitDepth * 3; + end; + 3: + begin + // Indexed image + if (IHDR.BitDepth = 1) and CheckBinaryPalette then + Image.Format := ifBinary + else + Image.Format := ifIndex8; + BitCount := IHDR.BitDepth; + end; + 4: + begin + // Grayscale + alpha image + case IHDR.BitDepth of + 8: Image.Format := ifA8Gray8; + 16: Image.Format := ifA16Gray16; + end; + BitCount := IHDR.BitDepth * 2; + end; + 6: + begin + // ARGB image + case IHDR.BitDepth of + 8: Image.Format := ifA8R8G8B8; + 16: Image.Format := ifA16R16G16B16; + end; + BitCount := IHDR.BitDepth * 4; + end; + end; + + GetImageFormatInfo(Image.Format, Info); + BytesPerPixel := (BitCount + 7) div 8; + + LineBuffer[True] := nil; + LineBuffer[False] := nil; + TotalBuffer := nil; + ZeroLine := nil; + ActLine := True; + + // Start decoding + with Image do + try + BytesPerLine := (Width * BitCount + 7) div 8; + SrcDataSize := Height * BytesPerLine; + GetMem(Data, SrcDataSize); + FillChar(Data^, SrcDataSize, 0); + GetMem(ZeroLine, BytesPerLine); + FillChar(ZeroLine^, BytesPerLine, 0); + + if IHDR.Interlacing = 1 then + begin + // Decode interlaced images + TotalPos := 0; + DecompressBuf(IDATStream.Memory, IDATStream.Size, 0, + Pointer(TotalBuffer), TotalSize); + GetMem(LineBuffer[True], BytesPerLine + 1); + GetMem(LineBuffer[False], BytesPerLine + 1); + for Pass := 0 to 6 do + begin + // Prepare next interlace run + if Width <= ColumnStart[Pass] then + Continue; + InterlaceWidth := (Width + ColumnIncrement[Pass] - 1 - + ColumnStart[Pass]) div ColumnIncrement[Pass]; + InterlaceLineBytes := (InterlaceWidth * BitCount + 7) shr 3; + I := RowStart[Pass]; + FillChar(LineBuffer[True][0], BytesPerLine + 1, 0); + FillChar(LineBuffer[False][0], BytesPerLine + 1, 0); + while I < Height do + begin + // Copy line from decompressed data to working buffer + Move(PByteArray(TotalBuffer)[TotalPos], + LineBuffer[ActLine][0], InterlaceLineBytes + 1); + Inc(TotalPos, InterlaceLineBytes + 1); + // Swap red and blue channels if necessary + if (IHDR.ColorType in [2, 6]) then + SwapRGB(@LineBuffer[ActLine][1], InterlaceWidth, IHDR.BitDepth, BytesPerPixel); + // Reverse-filter current scanline + FilterScanline(LineBuffer[ActLine][0], BytesPerPixel, + @LineBuffer[ActLine][1], @LineBuffer[not ActLine][1], + @LineBuffer[ActLine][1], InterlaceLineBytes); + // Decode Adam7 interlacing + DecodeAdam7; + ActLine := not ActLine; + // Continue with next row in interlaced order + Inc(I, RowIncrement[Pass]); + end; + end; + end + else + begin + // Decode non-interlaced images + PrevLine := ZeroLine; + DecompressBuf(IDATStream.Memory, IDATStream.Size, SrcDataSize + Height, + Pointer(TotalBuffer), TotalSize); + for I := 0 to Height - 1 do + begin + // Swap red and blue channels if necessary + if IHDR.ColorType in [2, 6] then + SwapRGB(@PByteArray(TotalBuffer)[I * (BytesPerLine + 1) + 1], Width, + IHDR.BitDepth, BytesPerPixel); + // reverse-filter current scanline + FilterScanline(PByteArray(TotalBuffer)[I * (BytesPerLine + 1)], + BytesPerPixel, @PByteArray(TotalBuffer)[I * (BytesPerLine + 1) + 1], + PrevLine, @PByteArray(Data)[I * BytesPerLine], BytesPerLine); + PrevLine := @PByteArray(Data)[I * BytesPerLine]; + end; + end; + + Size := Info.GetPixelsSize(Info.Format, Width, Height); + + if Size <> SrcDataSize then + begin + // If source data size is different from size of image in assigned + // format we must convert it (it is in 1/2/4 bit count) + GetMem(Bits, Size); + case IHDR.BitDepth of + 1: + begin + // Convert only indexed, keep black and white in ifBinary + if IHDR.ColorType <> 0 then + Convert1To8(Data, Bits, Width, Height, BytesPerLine, False); + end; + 2: Convert2To8(Data, Bits, Width, Height, BytesPerLine, IHDR.ColorType = 0); + 4: Convert4To8(Data, Bits, Width, Height, BytesPerLine, IHDR.ColorType = 0); + end; + FreeMem(Data); + end + else + begin + // If source data size is the same as size of + // image Bits in assigned format we simply copy pointer reference + Bits := Data; + end; + + // LOCO transformation was used too (only for color types 2 and 6) + if (IHDR.Filter = 64) and (IHDR.ColorType in [2, 6]) then + TransformLOCOToRGB(Bits, Width * Height, BytesPerPixel); + + // Images with 16 bit channels must be swapped because of PNG's big endianity + if IHDR.BitDepth = 16 then + SwapEndianWord(Bits, Width * Height * BytesPerPixel div SizeOf(Word)); + finally + FreeMem(LineBuffer[True]); + FreeMem(LineBuffer[False]); + FreeMem(TotalBuffer); + FreeMem(ZeroLine); + end; +end; + +{$IFNDEF DONT_LINK_JNG} + +procedure TNGFileLoader.LoadImageFromJNGFrame(FrameWidth, FrameHeight: LongInt; const JHDR: TJHDR; IDATStream, + JDATStream, JDAAStream: TMemoryStream; var Image: TImageData); +var + AlphaImage: TImageData; + FakeIHDR: TIHDR; + FmtInfo: TImageFormatInfo; + I: LongInt; + AlphaPtr: PByte; + GrayPtr: PWordRec; + ColorPtr: PColor32Rec; + + procedure LoadJpegFromStream(Stream: TStream; var DestImage: TImageData); + var + JpegFormat: TCustomIOJpegFileFormat; + Handle: TImagingHandle; + DynImages: TDynImageDataArray; + begin + if JHDR.SampleDepth <> 12 then + begin + JpegFormat := TCustomIOJpegFileFormat.Create; + JpegFormat.SetCustomIO(StreamIO); + Stream.Position := 0; + Handle := StreamIO.Open(Pointer(Stream), omReadOnly); + try + JpegFormat.LoadData(Handle, DynImages, True); + DestImage := DynImages[0]; + finally + StreamIO.Close(Handle); + JpegFormat.Free; + SetLength(DynImages, 0); + end; + end + else + NewImage(FrameWidth, FrameHeight, ifR8G8B8, DestImage); + end; + +begin + LoadJpegFromStream(JDATStream, Image); + + // If present separate alpha channel is processed + if (JHDR.ColorType in [12, 14]) and (Image.Format in [ifGray8, ifR8G8B8]) then + begin + InitImage(AlphaImage); + if JHDR.AlphaCompression = 0 then + begin + // Alpha channel is PNG compressed + FakeIHDR.Width := JHDR.Width; + FakeIHDR.Height := JHDR.Height; + FakeIHDR.ColorType := 0; + FakeIHDR.BitDepth := JHDR.AlphaSampleDepth; + FakeIHDR.Filter := JHDR.AlphaFilter; + FakeIHDR.Interlacing := JHDR.AlphaInterlacing; + + LoadImageFromPNGFrame(FrameWidth, FrameHeight, FakeIHDR, IDATStream, AlphaImage); + end + else + begin + // Alpha channel is JPEG compressed + LoadJpegFromStream(JDAAStream, AlphaImage); + end; + + // Check if alpha channel is the same size as image + if (Image.Width <> AlphaImage.Width) and (Image.Height <> AlphaImage.Height) then + ResizeImage(AlphaImage, Image.Width, Image.Height, rfNearest); + + // Check alpha channels data format + GetImageFormatInfo(AlphaImage.Format, FmtInfo); + if (FmtInfo.BytesPerPixel > 1) or (not FmtInfo.HasGrayChannel) then + ConvertImage(AlphaImage, ifGray8); + + // Convert image to fromat with alpha channel + if Image.Format = ifGray8 then + ConvertImage(Image, ifA8Gray8) + else + ConvertImage(Image, ifA8R8G8B8); + + // Combine alpha channel with image + AlphaPtr := AlphaImage.Bits; + if Image.Format = ifA8Gray8 then + begin + GrayPtr := Image.Bits; + for I := 0 to Image.Width * Image.Height - 1 do + begin + GrayPtr.High := AlphaPtr^; + Inc(GrayPtr); + Inc(AlphaPtr); + end; + end + else + begin + ColorPtr := Image.Bits; + for I := 0 to Image.Width * Image.Height - 1 do + begin + ColorPtr.A := AlphaPtr^; + Inc(ColorPtr); + Inc(AlphaPtr); + end; + end; + + FreeImage(AlphaImage); + end; +end; + +{$ENDIF} + +procedure TNGFileLoader.ApplyFrameSettings(Frame: TFrameInfo; var Image: TImageData); +var + FmtInfo: TImageFormatInfo; + BackGroundColor: TColor64Rec; + ColorKey: TColor64Rec; + Alphas: PByteArray; + AlphasSize: LongInt; + IsColorKeyPresent: Boolean; + IsBackGroundPresent: Boolean; + IsColorFormat: Boolean; + + procedure ConverttRNS; + begin + if FmtInfo.IsIndexed then + begin + if Alphas = nil then + begin + GetMem(Alphas, Frame.TransparencySize); + Move(Frame.Transparency^, Alphas^, Frame.TransparencySize); + AlphasSize := Frame.TransparencySize; + end; + end + else if not FmtInfo.HasAlphaChannel then + begin + FillChar(ColorKey, SizeOf(ColorKey), 0); + Move(Frame.Transparency^, ColorKey, Min(Frame.TransparencySize, SizeOf(ColorKey))); + if IsColorFormat then + SwapValues(ColorKey.R, ColorKey.B); + SwapEndianWord(@ColorKey, 3); + // 1/2/4 bit images were converted to 8 bit so we must convert color key too + if (not Frame.IsJpegFrame) and (Frame.IHDR.ColorType in [0, 4]) then + case Frame.IHDR.BitDepth of + 1: ColorKey.B := Word(ColorKey.B * 255); + 2: ColorKey.B := Word(ColorKey.B * 85); + 4: ColorKey.B := Word(ColorKey.B * 17); + end; + IsColorKeyPresent := True; + end; + end; + + procedure ConvertbKGD; + begin + FillChar(BackGroundColor, SizeOf(BackGroundColor), 0); + Move(Frame.Background^, BackGroundColor, Min(Frame.BackgroundSize, SizeOf(BackGroundColor))); + if IsColorFormat then + SwapValues(BackGroundColor.R, BackGroundColor.B); + SwapEndianWord(@BackGroundColor, 3); + // 1/2/4 bit images were converted to 8 bit so we must convert back color too + if (not Frame.IsJpegFrame) and (Frame.IHDR.ColorType in [0, 4]) then + case Frame.IHDR.BitDepth of + 1: BackGroundColor.B := Word(BackGroundColor.B * 255); + 2: BackGroundColor.B := Word(BackGroundColor.B * 85); + 4: BackGroundColor.B := Word(BackGroundColor.B * 17); + end; + IsBackGroundPresent := True; + end; + + procedure ReconstructPalette; + var + I: LongInt; + begin + with Image do + begin + GetMem(Palette, FmtInfo.PaletteEntries * SizeOf(TColor32Rec)); + FillChar(Palette^, FmtInfo.PaletteEntries * SizeOf(TColor32Rec), $FF); + // if RGB palette was loaded from file then use it + if Frame.Palette <> nil then + for I := 0 to Min(Frame.PaletteEntries, FmtInfo.PaletteEntries) - 1 do + with Palette[I] do + begin + R := Frame.Palette[I].B; + G := Frame.Palette[I].G; + B := Frame.Palette[I].R; + end; + // if palette alphas were loaded from file then use them + if Alphas <> nil then + begin + for I := 0 to Min(AlphasSize, FmtInfo.PaletteEntries) - 1 do + Palette[I].A := Alphas[I]; + end; + end; + end; + + procedure ApplyColorKey; + var + DestFmt: TImageFormat; + Col32, Bkg32: TColor32Rec; + OldPixel, NewPixel: Pointer; + begin + case Image.Format of + ifGray8: DestFmt := ifA8Gray8; + ifGray16: DestFmt := ifA16Gray16; + ifR8G8B8: DestFmt := ifA8R8G8B8; + ifR16G16B16: DestFmt := ifA16R16G16B16; + else + DestFmt := ifUnknown; + end; + + if DestFmt <> ifUnknown then + begin + if not IsBackGroundPresent then + BackGroundColor := ColorKey; + ConvertImage(Image, DestFmt); + + // Now back color and color key must be converted to image's data format, looks ugly + case Image.Format of + ifA8Gray8: + begin + Col32 := Color32(0, 0, $FF, Byte(ColorKey.B)); + Bkg32 := Color32(0, 0, 0, Byte(BackGroundColor.B)); + end; + ifA16Gray16: + begin + ColorKey.G := $FFFF; + end; + ifA8R8G8B8: + begin + Col32 := Color32($FF, Byte(ColorKey.R), Byte(ColorKey.G), Byte(ColorKey.B)); + Bkg32 := Color32(0, Byte(BackGroundColor.R), Byte(BackGroundColor.G), Byte(BackGroundColor.B)); + end; + ifA16R16G16B16: + begin + ColorKey.A := $FFFF; + end; + end; + + if Image.Format in [ifA8Gray8, ifA8R8G8B8] then + begin + OldPixel := @Col32; + NewPixel := @Bkg32; + end + else + begin + OldPixel := @ColorKey; + NewPixel := @BackGroundColor; + end; + + ReplaceColor(Image, 0, 0, Image.Width, Image.Height, OldPixel, NewPixel); + end; + end; + +begin + Alphas := nil; + IsColorKeyPresent := False; + IsBackGroundPresent := False; + GetImageFormatInfo(Image.Format, FmtInfo); + + IsColorFormat := (Frame.IsJpegFrame and (Frame.JHDR.ColorType in [10, 14])) or + (not Frame.IsJpegFrame and (Frame.IHDR.ColorType in [2, 6])); + + // Convert some chunk data to useful format + if Frame.TransparencySize > 0 then + ConverttRNS; + if Frame.BackgroundSize > 0 then + ConvertbKGD; + + // Build palette for indexed images + if FmtInfo.IsIndexed then + ReconstructPalette; + + // Apply color keying + if IsColorKeyPresent and not FmtInfo.HasAlphaChannel then + ApplyColorKey; + + FreeMemNil(Alphas); +end; + +{ TNGFileSaver class implementation } + +procedure TNGFileSaver.StoreImageToPNGFrame(const IHDR: TIHDR; Bits: Pointer; + FmtInfo: TImageFormatInfo; IDATStream: TMemoryStream); +var + TotalBuffer, CompBuffer, ZeroLine, PrevLine: Pointer; + FilterLines: array[0..4] of PByteArray; + TotalSize, CompSize, I, BytesPerLine, BytesPerPixel: LongInt; + Filter: Byte; + Adaptive: Boolean; + + procedure FilterScanline(Filter: Byte; BytesPerPixel: LongInt; Line, PrevLine, Target: PByteArray); + var + I: LongInt; + begin + case Filter of + 0: + begin + // No filter + Move(Line^, Target^, BytesPerLine); + end; + 1: + begin + // Sub filter + Move(Line^, Target^, BytesPerPixel); + for I := BytesPerPixel to BytesPerLine - 1 do + Target[I] := (Line[I] - Line[I - BytesPerPixel]) and $FF; + end; + 2: + begin + // Up filter + for I := 0 to BytesPerLine - 1 do + Target[I] := (Line[I] - PrevLine[I]) and $FF; + end; + 3: + begin + // Average filter + for I := 0 to BytesPerPixel - 1 do + Target[I] := (Line[I] - PrevLine[I] shr 1) and $FF; + for I := BytesPerPixel to BytesPerLine - 1 do + Target[I] := (Line[I] - (Line[I - BytesPerPixel] + PrevLine[I]) shr 1) and $FF; + end; + 4: + begin + // Paeth filter + for I := 0 to BytesPerPixel - 1 do + Target[I] := (Line[I] - PaethPredictor(0, PrevLine[I], 0)) and $FF; + for I := BytesPerPixel to BytesPerLine - 1 do + Target[I] := (Line[I] - PaethPredictor(Line[I - BytesPerPixel], PrevLine[I], PrevLine[I - BytesPerPixel])) and $FF; + end; + end; + end; + + procedure AdaptiveFilter(var Filter: Byte; BytesPerPixel: LongInt; Line, PrevLine, Target: PByteArray); + var + I, J, BestTest: LongInt; + Sums: array[0..4] of LongInt; + begin + // Compute the output scanline using all five filters, + // and select the filter that gives the smallest sum of + // absolute values of outputs + FillChar(Sums, SizeOf(Sums), 0); + BestTest := MaxInt; + for I := 0 to 4 do + begin + FilterScanline(I, BytesPerPixel, Line, PrevLine, FilterLines[I]); + for J := 0 to BytesPerLine - 1 do + Sums[I] := Sums[I] + Abs(ShortInt(FilterLines[I][J])); + if Sums[I] < BestTest then + begin + Filter := I; + BestTest := Sums[I]; + end; + end; + Move(FilterLines[Filter]^, Target^, BytesPerLine); + end; + +begin + // Select precompression filter and compression level + Adaptive := False; + Filter := 0; + case PreFilter of + 6: + if not ((IHDR.BitDepth < 8) or (IHDR.ColorType = 3)) then + Adaptive := True; + 0..4: Filter := PreFilter; + else + if IHDR.ColorType in [2, 6] then + Filter := 4 + end; + + // Prepare data for compression + CompBuffer := nil; + FillChar(FilterLines, SizeOf(FilterLines), 0); + BytesPerPixel := Max(1, FmtInfo.BytesPerPixel); + BytesPerLine := FmtInfo.GetPixelsSize(FmtInfo.Format, LongInt(IHDR.Width), 1); + TotalSize := (BytesPerLine + 1) * LongInt(IHDR.Height); + GetMem(TotalBuffer, TotalSize); + GetMem(ZeroLine, BytesPerLine); + FillChar(ZeroLine^, BytesPerLine, 0); + PrevLine := ZeroLine; + + if Adaptive then + begin + for I := 0 to 4 do + GetMem(FilterLines[I], BytesPerLine); + end; + + try + // Process next scanlines + for I := 0 to IHDR.Height - 1 do + begin + // Filter scanline + if Adaptive then + begin + AdaptiveFilter(Filter, BytesPerPixel, @PByteArray(Bits)[I * BytesPerLine], + PrevLine, @PByteArray(TotalBuffer)[I * (BytesPerLine + 1) + 1]); + end + else + begin + FilterScanline(Filter, BytesPerPixel, @PByteArray(Bits)[I * BytesPerLine], + PrevLine, @PByteArray(TotalBuffer)[I * (BytesPerLine + 1) + 1]); + end; + PrevLine := @PByteArray(Bits)[I * BytesPerLine]; + // Swap red and blue if necessary + if (IHDR.ColorType in [2, 6]) and not FmtInfo.IsRBSwapped then + begin + SwapRGB(@PByteArray(TotalBuffer)[I * (BytesPerLine + 1) + 1], + IHDR.Width, IHDR.BitDepth, BytesPerPixel); + end; + // Images with 16 bit channels must be swapped because of PNG's big endianess + if IHDR.BitDepth = 16 then + begin + SwapEndianWord(@PByteArray(TotalBuffer)[I * (BytesPerLine + 1) + 1], + BytesPerLine div SizeOf(Word)); + end; + // Set filter used for this scanline + PByteArray(TotalBuffer)[I * (BytesPerLine + 1)] := Filter; + end; + // Compress IDAT data + CompressBuf(TotalBuffer, TotalSize, CompBuffer, CompSize, + CompressLevel, ZLibStrategy); + // Write IDAT data to stream + IDATStream.WriteBuffer(CompBuffer^, CompSize); + finally + FreeMem(TotalBuffer); + FreeMem(CompBuffer); + FreeMem(ZeroLine); + if Adaptive then + for I := 0 to 4 do + FreeMem(FilterLines[I]); + end; +end; + +{$IFNDEF DONT_LINK_JNG} + +procedure TNGFileSaver.StoreImageToJNGFrame(const JHDR: TJHDR; + const Image: TImageData; IDATStream, JDATStream, + JDAAStream: TMemoryStream); +var + ColorImage, AlphaImage: TImageData; + FmtInfo: TImageFormatInfo; + AlphaPtr: PByte; + GrayPtr: PWordRec; + ColorPtr: PColor32Rec; + I: LongInt; + FakeIHDR: TIHDR; + + procedure SaveJpegToStream(Stream: TStream; const Image: TImageData); + var + JpegFormat: TCustomIOJpegFileFormat; + Handle: TImagingHandle; + DynImages: TDynImageDataArray; + begin + JpegFormat := TCustomIOJpegFileFormat.Create; + JpegFormat.SetCustomIO(StreamIO); + // Only JDAT stream can be saved progressive + if Stream = JDATStream then + JpegFormat.FProgressive := Progressive + else + JpegFormat.FProgressive := False; + JpegFormat.FQuality := Quality; + SetLength(DynImages, 1); + DynImages[0] := Image; + Handle := StreamIO.Open(Pointer(Stream), omCreate); + try + JpegFormat.SaveData(Handle, DynImages, 0); + finally + StreamIO.Close(Handle); + SetLength(DynImages, 0); + JpegFormat.Free; + end; + end; + +begin + GetImageFormatInfo(Image.Format, FmtInfo); + InitImage(ColorImage); + InitImage(AlphaImage); + + if FmtInfo.HasAlphaChannel then + begin + // Create new image for alpha channel and color image without alpha + CloneImage(Image, ColorImage); + NewImage(Image.Width, Image.Height, ifGray8, AlphaImage); + case Image.Format of + ifA8Gray8: ConvertImage(ColorImage, ifGray8); + ifA8R8G8B8: ConvertImage(ColorImage, ifR8G8B8); + end; + + // Store source image's alpha to separate image + AlphaPtr := AlphaImage.Bits; + if Image.Format = ifA8Gray8 then + begin + GrayPtr := Image.Bits; + for I := 0 to Image.Width * Image.Height - 1 do + begin + AlphaPtr^ := GrayPtr.High; + Inc(GrayPtr); + Inc(AlphaPtr); + end; + end + else + begin + ColorPtr := Image.Bits; + for I := 0 to Image.Width * Image.Height - 1 do + begin + AlphaPtr^ := ColorPtr.A; + Inc(ColorPtr); + Inc(AlphaPtr); + end; + end; + + // Write color image to stream as JPEG + SaveJpegToStream(JDATStream, ColorImage); + + if LossyAlpha then + begin + // Write alpha image to stream as JPEG + SaveJpegToStream(JDAAStream, AlphaImage); + end + else + begin + // Alpha channel is PNG compressed + FakeIHDR.Width := JHDR.Width; + FakeIHDR.Height := JHDR.Height; + FakeIHDR.ColorType := 0; + FakeIHDR.BitDepth := JHDR.AlphaSampleDepth; + FakeIHDR.Filter := JHDR.AlphaFilter; + FakeIHDR.Interlacing := JHDR.AlphaInterlacing; + + GetImageFormatInfo(AlphaImage.Format, FmtInfo); + StoreImageToPNGFrame(FakeIHDR, AlphaImage.Bits, FmtInfo, IDATStream); + end; + + FreeImage(ColorImage); + FreeImage(AlphaImage); + end + else + begin + // Simply write JPEG to stream + SaveJpegToStream(JDATStream, Image); + end; +end; + +{$ENDIF} + +procedure TNGFileSaver.AddFrame(const Image: TImageData; IsJpegFrame: Boolean); +var + Frame: TFrameInfo; + FmtInfo: TImageFormatInfo; + Index: Integer; + + procedure StorePalette; + var + Pal: PPalette24; + Alphas: PByteArray; + I, PalBytes: LongInt; + AlphasDiffer: Boolean; + begin + // Fill and save RGB part of palette to PLTE chunk + PalBytes := FmtInfo.PaletteEntries * SizeOf(TColor24Rec); + GetMem(Pal, PalBytes); + AlphasDiffer := False; + for I := 0 to FmtInfo.PaletteEntries - 1 do + begin + Pal[I].B := Image.Palette[I].R; + Pal[I].G := Image.Palette[I].G; + Pal[I].R := Image.Palette[I].B; + if Image.Palette[I].A < 255 then + AlphasDiffer := True; + end; + Frame.Palette := Pal; + Frame.PaletteEntries := FmtInfo.PaletteEntries; + // Fill and save alpha part (if there are any alphas < 255) of palette to tRNS chunk + if AlphasDiffer then + begin + PalBytes := FmtInfo.PaletteEntries * SizeOf(Byte); + GetMem(Alphas, PalBytes); + for I := 0 to FmtInfo.PaletteEntries - 1 do + Alphas[I] := Image.Palette[I].A; + Frame.Transparency := Alphas; + Frame.TransparencySize := PalBytes; + end; + end; + + procedure FillFrameControlChunk(const IHDR: TIHDR; var fcTL: TfcTL); + var + Delay: Integer; + begin + fcTL.SeqNumber := 0; // Decided when writing to file + fcTL.Width := IHDR.Width; + fcTL.Height := IHDR.Height; + fcTL.XOffset := 0; + fcTL.YOffset := 0; + fcTL.DelayNumer := 1; + fcTL.DelayDenom := 3; + if FileFormat.FMetadata.HasMetaItemForSaving(SMetaFrameDelay, Index) then + begin + // Metadata contains frame delay information in milliseconds + Delay := FileFormat.FMetadata.MetaItemsForSavingMulti[SMetaFrameDelay, Index]; + fcTL.DelayNumer := Delay; + fcTL.DelayDenom := 1000; + end; + fcTL.DisposeOp := DisposeOpNone; + fcTL.BlendOp := BlendOpSource; + SwapEndianLongWord(@fcTL, 5); + fcTL.DelayNumer := SwapEndianWord(fcTL.DelayNumer); + fcTL.DelayDenom := SwapEndianWord(fcTL.DelayDenom); + end; + +begin + // Add new frame + Frame := AddFrameInfo; + Frame.IsJpegFrame := IsJpegFrame; + Index := Length(Frames) - 1; + + with Frame do + begin + GetImageFormatInfo(Image.Format, FmtInfo); + + if IsJpegFrame then + begin +{$IFNDEF DONT_LINK_JNG} + // Fill JNG header + JHDR.Width := Image.Width; + JHDR.Height := Image.Height; + case Image.Format of + ifGray8: JHDR.ColorType := 8; + ifR8G8B8: JHDR.ColorType := 10; + ifA8Gray8: JHDR.ColorType := 12; + ifA8R8G8B8: JHDR.ColorType := 14; + end; + JHDR.SampleDepth := 8; // 8-bit samples and quantization tables + JHDR.Compression := 8; // Huffman coding + JHDR.Interlacing := Iff(Progressive, 8, 0); + JHDR.AlphaSampleDepth := Iff(FmtInfo.HasAlphaChannel, 8, 0); + JHDR.AlphaCompression := Iff(LossyAlpha, 8, 0); + JHDR.AlphaFilter := 0; + JHDR.AlphaInterlacing := 0; + + StoreImageToJNGFrame(JHDR, Image, IDATMemory, JDATMemory, JDAAMemory); + + // Finally swap endian + SwapEndianLongWord(@JHDR, 2); +{$ENDIF} + end + else + begin + // Fill PNG header + IHDR.Width := Image.Width; + IHDR.Height := Image.Height; + IHDR.Compression := 0; + IHDR.Filter := 0; + IHDR.Interlacing := 0; + IHDR.BitDepth := FmtInfo.BytesPerPixel * 8; + + // Select appropiate PNG color type and modify bitdepth + if FmtInfo.HasGrayChannel then + begin + IHDR.ColorType := 0; + if FmtInfo.HasAlphaChannel then + begin + IHDR.ColorType := 4; + IHDR.BitDepth := IHDR.BitDepth div 2; + end; + end + else if FmtInfo.Format = ifBinary then + begin + IHDR.ColorType := 0; + IHDR.BitDepth := 1; + end + else if FmtInfo.IsIndexed then + IHDR.ColorType := 3 + else if FmtInfo.HasAlphaChannel then + begin + IHDR.ColorType := 6; + IHDR.BitDepth := IHDR.BitDepth div 4; + end + else + begin + IHDR.ColorType := 2; + IHDR.BitDepth := IHDR.BitDepth div 3; + end; + + if FileType = ngAPNG then + begin + // Fill fcTL chunk of APNG file + FillFrameControlChunk(IHDR, fcTL); + end; + + // Compress PNG image and store it to stream + StoreImageToPNGFrame(IHDR, Image.Bits, FmtInfo, IDATMemory); + // Store palette if necesary + if FmtInfo.IsIndexed then + StorePalette; + + // Finally swap endian + SwapEndianLongWord(@IHDR, 2); + end; + end; +end; + +function TNGFileSaver.SaveFile(Handle: TImagingHandle): Boolean; +var + I: LongInt; + Chunk: TChunkHeader; + SeqNo: LongWord; + + function GetNextSeqNo: LongWord; + begin + // Seq numbers of fcTL and fdAT are "interleaved" as they share the counter. + // Example: first fcTL for IDAT has seq=0, next is fcTL for seond frame with + // seq=1, then first fdAT with seq=2, fcTL seq=3, fdAT=4, ... + Result := SwapEndianLongWord(SeqNo); + Inc(SeqNo); + end; + + function CalcChunkCrc(const ChunkHdr: TChunkHeader; Data: Pointer; + Size: LongInt): LongWord; + begin + Result := $FFFFFFFF; + CalcCrc32(Result, @ChunkHdr.ChunkID, SizeOf(ChunkHdr.ChunkID)); + CalcCrc32(Result, Data, Size); + Result := SwapEndianLongWord(Result xor $FFFFFFFF); + end; + + procedure WriteChunk(var Chunk: TChunkHeader; ChunkData: Pointer); + var + ChunkCrc: LongWord; + SizeToWrite: LongInt; + begin + SizeToWrite := Chunk.DataSize; + Chunk.DataSize := SwapEndianLongWord(Chunk.DataSize); + ChunkCrc := CalcChunkCrc(Chunk, ChunkData, SizeToWrite); + GetIO.Write(Handle, @Chunk, SizeOf(Chunk)); + if SizeToWrite <> 0 then + GetIO.Write(Handle, ChunkData, SizeToWrite); + GetIO.Write(Handle, @ChunkCrc, SizeOf(ChunkCrc)); + end; + + procedure WritefdAT(Frame: TFrameInfo); + var + ChunkCrc: LongWord; + ChunkSeqNo: LongWord; + begin + Chunk.ChunkID := fdATChunk; + ChunkSeqNo := GetNextSeqNo; + // fdAT saves seq number LongWord before compressed pixels + Chunk.DataSize := Frame.IDATMemory.Size + SizeOf(LongWord); + Chunk.DataSize := SwapEndianLongWord(Chunk.DataSize); + // Calc CRC + ChunkCrc := $FFFFFFFF; + CalcCrc32(ChunkCrc, @Chunk.ChunkID, SizeOf(Chunk.ChunkID)); + CalcCrc32(ChunkCrc, @ChunkSeqNo, SizeOf(ChunkSeqNo)); + CalcCrc32(ChunkCrc, Frame.IDATMemory.Memory, Frame.IDATMemory.Size); + ChunkCrc := SwapEndianLongWord(ChunkCrc xor $FFFFFFFF); + // Write out all fdAT data + GetIO.Write(Handle, @Chunk, SizeOf(Chunk)); + GetIO.Write(Handle, @ChunkSeqNo, SizeOf(ChunkSeqNo)); + GetIO.Write(Handle, Frame.IDATMemory.Memory, Frame.IDATMemory.Size); + GetIO.Write(Handle, @ChunkCrc, SizeOf(ChunkCrc)); + end; + + procedure WriteGlobalMetaDataChunks(Frame: TFrameInfo); + var + XRes, YRes: Single; + begin + if FileFormat.FMetadata.GetPhysicalPixelSize(ruDpm, XRes, YRes, True) then + begin + // Save pHYs chunk + Frame.pHYs.UnitSpecifier := 1; + // PNG stores physical resolution as dots per meter + Frame.pHYs.PixelsPerUnitX := Round(XRes); + Frame.pHYs.PixelsPerUnitY := Round(YRes); + + Chunk.DataSize := SizeOf(Frame.pHYs); + Chunk.ChunkID := pHYsChunk; + SwapEndianLongWord(@Frame.pHYs, SizeOf(Frame.pHYs) div SizeOf(LongWord)); + WriteChunk(Chunk, @Frame.pHYs); + end; + end; + + procedure WritePNGMainImageChunks(Frame: TFrameInfo); + begin + with Frame do + begin + // Write IHDR chunk + Chunk.DataSize := SizeOf(IHDR); + Chunk.ChunkID := IHDRChunk; + WriteChunk(Chunk, @IHDR); + // Write PLTE chunk if data is present + if Palette <> nil then + begin + Chunk.DataSize := PaletteEntries * SizeOf(TColor24Rec); + Chunk.ChunkID := PLTEChunk; + WriteChunk(Chunk, Palette); + end; + // Write tRNS chunk if data is present + if Transparency <> nil then + begin + Chunk.DataSize := TransparencySize; + Chunk.ChunkID := tRNSChunk; + WriteChunk(Chunk, Transparency); + end; + end; + // Write metadata related chunks + WriteGlobalMetaDataChunks(Frame); + end; + +begin + Result := False; + SeqNo := 0; + + case FileType of + ngPNG, ngAPNG: GetIO.Write(Handle, @PNGSignature, SizeOf(TChar8)); + ngMNG: GetIO.Write(Handle, @MNGSignature, SizeOf(TChar8)); + ngJNG: GetIO.Write(Handle, @JNGSignature, SizeOf(TChar8)); + end; + + if FileType = ngMNG then + begin + // MNG - main header before frames + SwapEndianLongWord(@MHDR, SizeOf(MHDR) div SizeOf(LongWord)); + Chunk.DataSize := SizeOf(MHDR); + Chunk.ChunkID := MHDRChunk; + WriteChunk(Chunk, @MHDR); + end + else if FileType = ngAPNG then + begin + // APNG - IHDR and global chunks for all frames, then acTL chunk, then frames + // (fcTL+IDAT, fcTL+fdAT, fcTL+fdAT, fcTL+fdAT, ....) + WritePNGMainImageChunks(Frames[0]); + + // Animation control chunk + acTL.NumFrames := Length(Frames); + if FileFormat.FMetadata.HasMetaItemForSaving(SMetaAnimationLoops) then + begin + // Number of plays of APNG animation + acTL.NumPlay:= FileFormat.FMetadata.MetaItemsForSaving[SMetaAnimationLoops]; + end + else + acTL.NumPlay := 0; + SwapEndianLongWord(@acTL, SizeOf(acTL) div SizeOf(LongWord)); + + Chunk.DataSize := SizeOf(acTL); + Chunk.ChunkID := acTLChunk; + WriteChunk(Chunk, @acTL); + end; + + for I := 0 to Length(Frames) - 1 do + with Frames[I] do + begin + if IsJpegFrame then + begin + // Write JHDR chunk + Chunk.DataSize := SizeOf(JHDR); + Chunk.ChunkID := JHDRChunk; + WriteChunk(Chunk, @JHDR); + // Write metadata related chunks + WriteGlobalMetaDataChunks(Frames[I]); + // Write JNG image data + Chunk.DataSize := JDATMemory.Size; + Chunk.ChunkID := JDATChunk; + WriteChunk(Chunk, JDATMemory.Memory); + // Write alpha channel if present + if JHDR.AlphaSampleDepth > 0 then + begin + if JHDR.AlphaCompression = 0 then + begin + // Alpha is PNG compressed + Chunk.DataSize := IDATMemory.Size; + Chunk.ChunkID := IDATChunk; + WriteChunk(Chunk, IDATMemory.Memory); + end + else + begin + // Alpha is JNG compressed + Chunk.DataSize := JDAAMemory.Size; + Chunk.ChunkID := JDAAChunk; + WriteChunk(Chunk, JDAAMemory.Memory); + end; + end; + // Write image end + Chunk.DataSize := 0; + Chunk.ChunkID := IENDChunk; + WriteChunk(Chunk, nil); + end + else if FileType <> ngAPNG then + begin + // Regular PNG frame (single PNG image or MNG frame) + WritePNGMainImageChunks(Frames[I]); + // Write PNG image data + Chunk.DataSize := IDATMemory.Size; + Chunk.ChunkID := IDATChunk; + WriteChunk(Chunk, IDATMemory.Memory); + // Write image end + Chunk.DataSize := 0; + Chunk.ChunkID := IENDChunk; + WriteChunk(Chunk, nil); + end + else if FileType = ngAPNG then + begin + // APNG frame - Write fcTL before frame data + Chunk.DataSize := SizeOf(fcTL); + Chunk.ChunkID := fcTLChunk; + fcTl.SeqNumber := GetNextSeqNo; + WriteChunk(Chunk, @fcTL); + // Write data - IDAT for first frame and fdAT for following ones + if I = 0 then + begin + Chunk.DataSize := IDATMemory.Size; + Chunk.ChunkID := IDATChunk; + WriteChunk(Chunk, IDATMemory.Memory); + end + else + WritefdAT(Frames[I]); + // Write image end after last frame + if I = Length(Frames) - 1 then + begin + Chunk.DataSize := 0; + Chunk.ChunkID := IENDChunk; + WriteChunk(Chunk, nil); + end; + end; + end; + + if FileType = ngMNG then + begin + Chunk.DataSize := 0; + Chunk.ChunkID := MENDChunk; + WriteChunk(Chunk, nil); + end; +end; + +procedure TNGFileSaver.SetFileOptions; +begin + PreFilter := FileFormat.FPreFilter; + CompressLevel := FileFormat.FCompressLevel; + LossyAlpha := FileFormat.FLossyAlpha; + Quality := FileFormat.FQuality; + Progressive := FileFormat.FProgressive; + ZLibStrategy := FileFormat.FZLibStategy; +end; + +{ TAPNGAnimator class implementation } + +class procedure TAPNGAnimator.Animate(var Images: TDynImageDataArray; + const acTL: TacTL; const SrcFrames: array of TFrameInfo); +var + I, SrcIdx, Offset, Len: Integer; + DestFrames: TDynImageDataArray; + SrcCanvas, DestCanvas: TImagingCanvas; + PreviousCache: TImageData; + + function AnimatingNeeded: Boolean; + var + I: Integer; + begin + Result := False; + for I := 0 to Len - 1 do + with SrcFrames[I] do + begin + if (FrameWidth <> Integer(IHDR.Width)) or (FrameHeight <> Integer(IHDR.Height)) or (Len <> Integer(acTL.NumFrames)) or + (not ((fcTL.DisposeOp = DisposeOpNone) and (fcTL.BlendOp = BlendOpSource)) and + not ((fcTL.DisposeOp = DisposeOpBackground) and (fcTL.BlendOp = BlendOpSource)) and + not ((fcTL.DisposeOp = DisposeOpBackground) and (fcTL.BlendOp = BlendOpOver))) then + begin + Result := True; + Exit; + end; + end; + end; + +begin + Len := Length(SrcFrames); + if (Len = 0) or not AnimatingNeeded then + Exit; + + if (Len = Integer(acTL.NumFrames) + 1) and (SrcFrames[0].fcTL.Width = 0) then + begin + // If default image (stored in IDAT chunk) isn't part of animation we ignore it + Offset := 1; + Len := Len - 1; + end + else + Offset := 0; + + SetLength(DestFrames, Len); + DestCanvas := ImagingCanvases.FindBestCanvasForImage(Images[0]).Create; + SrcCanvas := ImagingCanvases.FindBestCanvasForImage(Images[0]).Create; + InitImage(PreviousCache); + NewImage(SrcFrames[0].IHDR.Width, SrcFrames[0].IHDR.Height, Images[0].Format, PreviousCache); + + for I := 0 to Len - 1 do + begin + SrcIdx := I + Offset; + NewImage(SrcFrames[SrcIdx].IHDR.Width, SrcFrames[SrcIdx].IHDR.Height, + Images[SrcIdx].Format, DestFrames[I]); + if DestFrames[I].Format = ifIndex8 then + Move(Images[SrcIdx].Palette^, DestFrames[I].Palette^, 256 * SizeOf(TColor32)); + DestCanvas.CreateForData(@DestFrames[I]); + + if (SrcFrames[SrcIdx].fcTL.DisposeOp = DisposeOpPrevious) and (SrcFrames[SrcIdx - 1].fcTL.DisposeOp <> DisposeOpPrevious) then + begin + // Cache current output buffer so we may return to it later (previous dispose op) + CopyRect(DestFrames[I - 1], 0, 0, DestFrames[I - 1].Width, DestFrames[I - 1].Height, + PreviousCache, 0, 0); + end; + + if (I = 0) or (SrcIdx = 0) then + begin + // Clear whole frame with transparent black color (default for first frame) + DestCanvas.FillColor32 := pcClear; + DestCanvas.Clear; + end + else if SrcFrames[SrcIdx - 1].fcTL.DisposeOp = DisposeOpBackground then + begin + // Restore background color (clear) on previous frame's area and leave previous content outside of it + CopyRect(DestFrames[I - 1], 0, 0, DestFrames[I - 1].Width, DestFrames[I - 1].Height, + DestFrames[I], 0, 0); + DestCanvas.FillColor32 := pcClear; + DestCanvas.FillRect(BoundsToRect(SrcFrames[SrcIdx - 1].fcTL.XOffset, SrcFrames[SrcIdx - 1].fcTL.YOffset, + SrcFrames[SrcIdx - 1].FrameWidth, SrcFrames[SrcIdx - 1].FrameHeight)); + end + else if SrcFrames[SrcIdx - 1].fcTL.DisposeOp = DisposeOpNone then + begin + // Clone previous frame - no change to output buffer + CopyRect(DestFrames[I - 1], 0, 0, DestFrames[I - 1].Width, DestFrames[I - 1].Height, + DestFrames[I], 0, 0); + end + else if SrcFrames[SrcIdx - 1].fcTL.DisposeOp = DisposeOpPrevious then + begin + // Revert to previous frame (cached, can't just restore DestFrames[I - 2]) + CopyRect(PreviousCache, 0, 0, PreviousCache.Width, PreviousCache.Height, + DestFrames[I], 0, 0); + end; + + // Copy pixels or alpha blend them over + if SrcFrames[SrcIdx].fcTL.BlendOp = BlendOpSource then + begin + CopyRect(Images[SrcIdx], 0, 0, Images[SrcIdx].Width, Images[SrcIdx].Height, + DestFrames[I], SrcFrames[SrcIdx].fcTL.XOffset, SrcFrames[SrcIdx].fcTL.YOffset); + end + else if SrcFrames[SrcIdx].fcTL.BlendOp = BlendOpOver then + begin + SrcCanvas.CreateForData(@Images[SrcIdx]); + SrcCanvas.DrawAlpha(SrcCanvas.ClipRect, DestCanvas, + SrcFrames[SrcIdx].fcTL.XOffset, SrcFrames[SrcIdx].fcTL.YOffset); + end; + + FreeImage(Images[SrcIdx]); + end; + + DestCanvas.Free; + SrcCanvas.Free; + FreeImage(PreviousCache); + + // Assign dest frames to final output images + Images := DestFrames; +end; + +{ TNetworkGraphicsFileFormat class implementation } + +procedure TNetworkGraphicsFileFormat.Define; +begin + inherited; + FFeatures := [ffLoad, ffSave]; + + FPreFilter := NGDefaultPreFilter; + FCompressLevel := NGDefaultCompressLevel; + FLossyAlpha := NGDefaultLossyAlpha; + FLossyCompression := NGDefaultLossyCompression; + FQuality := NGDefaultQuality; + FProgressive := NGDefaultProgressive; + FZLibStategy := NGDefaultZLibStartegy; +end; + +procedure TNetworkGraphicsFileFormat.CheckOptionsValidity; +begin + // Just check if save options has valid values + if not (FPreFilter in [0..6]) then + FPreFilter := NGDefaultPreFilter; + if not (FCompressLevel in [0..9]) then + FCompressLevel := NGDefaultCompressLevel; + if not (FQuality in [1..100]) then + FQuality := NGDefaultQuality; +end; + +function TNetworkGraphicsFileFormat.GetSupportedFormats: TImageFormats; +begin + if FLossyCompression then + Result := NGLossyFormats + else + Result := NGLosslessFormats; +end; + +procedure TNetworkGraphicsFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if not FLossyCompression then + begin + // Convert formats for lossless compression + if Info.HasGrayChannel then + begin + if Info.HasAlphaChannel then + begin + if Info.BytesPerPixel <= 2 then + // Convert <= 16bit grayscale images with alpha to ifA8Gray8 + ConvFormat := ifA8Gray8 + else + // Convert > 16bit grayscale images with alpha to ifA16Gray16 + ConvFormat := ifA16Gray16 + end + else + // Convert grayscale images without alpha to ifGray16 + ConvFormat := ifGray16; + end + else + if Info.IsFloatingPoint then + // Convert floating point images to 64 bit ARGB (or RGB if no alpha) + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA16B16G16R16, ifB16G16R16) + else if Info.HasAlphaChannel or Info.IsSpecial then + // Convert all other images with alpha or special images to A8R8G8B8 + ConvFormat := ifA8R8G8B8 + else + // Convert images without alpha to R8G8B8 + ConvFormat := ifR8G8B8; + end + else + begin + // Convert formats for lossy compression + if Info.HasGrayChannel then + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA8Gray8, ifGray8) + else + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA8R8G8B8, ifR8G8B8); + end; + + ConvertImage(Image, ConvFormat); +end; + +function TNetworkGraphicsFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + ReadCount: LongInt; + Sig: TChar8; +begin + Result := False; + if Handle <> nil then + with GetIO do + begin + FillChar(Sig, SizeOf(Sig), 0); + ReadCount := Read(Handle, @Sig, SizeOf(Sig)); + Seek(Handle, -ReadCount, smFromCurrent); + Result := (ReadCount = SizeOf(Sig)) and (Sig = FSignature); + end; +end; + +{ TPNGFileFormat class implementation } + +procedure TPNGFileFormat.Define; +begin + inherited; + FName := SPNGFormatName; + FFeatures := FFeatures + [ffMultiImage]; + FLoadAnimated := PNGDefaultLoadAnimated; + AddMasks(SPNGMasks); + + FSignature := PNGSignature; + + RegisterOption(ImagingPNGPreFilter, @FPreFilter); + RegisterOption(ImagingPNGCompressLevel, @FCompressLevel); + RegisterOption(ImagingPNGLoadAnimated, @FLoadAnimated); + RegisterOption(ImagingPNGZLibStrategy, @FZLibStategy); +end; + +function TPNGFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + I, Len: LongInt; + NGFileLoader: TNGFileLoader; +begin + Result := False; + NGFileLoader := TNGFileLoader.Create(Self); + try + // Use NG file parser to load file + if NGFileLoader.LoadFile(Handle) and (Length(NGFileLoader.Frames) > 0) then + begin + Len := Length(NGFileLoader.Frames); + SetLength(Images, Len); + for I := 0 to Len - 1 do + with NGFileLoader.Frames[I] do + begin + // Build actual image bits + if not IsJpegFrame then + NGFileLoader.LoadImageFromPNGFrame(FrameWidth, FrameHeight, IHDR, IDATMemory, Images[I]); + // Build palette, aply color key or background + + NGFileLoader.ApplyFrameSettings(NGFileLoader.Frames[I], Images[I]); + Result := True; + end; + // Animate APNG images + if (NGFileLoader.FileType = ngAPNG) and FLoadAnimated then + TAPNGAnimator.Animate(Images, NGFileLoader.acTL, NGFileLoader.Frames); + end; + finally + NGFileLoader.LoadMetaData; // Store metadata + NGFileLoader.Free; + end; +end; + +function TPNGFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +var + I: Integer; + ImageToSave: TImageData; + MustBeFreed: Boolean; + NGFileSaver: TNGFileSaver; + DefaultFormat: TImageFormat; + Screen: TImageData; + AnimWidth, AnimHeight: Integer; +begin + Result := False; + DefaultFormat := ifDefault; + AnimWidth := 0; + AnimHeight := 0; + NGFileSaver := TNGFileSaver.Create(Self); + + // Save images with more frames as APNG format + if Length(Images) > 1 then + begin + NGFileSaver.FileType := ngAPNG; + // Get max dimensions of frames + AnimWidth := Images[FFirstIdx].Width; + AnimHeight := Images[FFirstIdx].Height; + for I := FFirstIdx + 1 to FLastIdx do + begin + AnimWidth := Max(AnimWidth, Images[I].Width); + AnimHeight := Max(AnimHeight, Images[I].Height); + end; + end + else + NGFileSaver.FileType := ngPNG; + + NGFileSaver.SetFileOptions; + + with NGFileSaver do + try + // Store all frames to be saved frames file saver + for I := FFirstIdx to FLastIdx do + begin + if MakeCompatible(Images[I], ImageToSave, MustBeFreed) then + try + if FileType = ngAPNG then + begin + // IHDR chunk is shared for all frames so all frames must have the + // same data format as the first image. + if I = FFirstIdx then + begin + DefaultFormat := ImageToSave.Format; + // Subsequenet frames may be bigger than the first one. + // APNG doens't support this - max allowed size is what's written in + // IHDR - size of main/default/first image. If some frame is + // bigger than the first one we need to resize (create empty bigger + // image and copy) the first frame so all following frames could fit to + // its area. + if (ImageToSave.Width <> AnimWidth) or (ImageToSave.Height <> AnimHeight) then + begin + InitImage(Screen); + NewImage(AnimWidth, AnimHeight, ImageToSave.Format, Screen); + CopyRect(ImageToSave, 0, 0, ImageToSave.Width, ImageToSave.Height, Screen, 0, 0); + if MustBeFreed then + FreeImage(ImageToSave); + ImageToSave := Screen; + end; + end + else if ImageToSave.Format <> DefaultFormat then + begin + if MustBeFreed then + ConvertImage(ImageToSave, DefaultFormat) + else + begin + CloneImage(Images[I], ImageToSave); + ConvertImage(ImageToSave, DefaultFormat); + MustBeFreed := True; + end; + end; + end; + + // Add image as PNG frame + AddFrame(ImageToSave, False); + finally + if MustBeFreed then + FreeImage(ImageToSave); + end + else + Exit; + end; + + // Finally save PNG file + SaveFile(Handle); + Result := True; + finally + NGFileSaver.Free; + end; +end; + +{$IFNDEF DONT_LINK_MNG} + +{ TMNGFileFormat class implementation } + +procedure TMNGFileFormat.Define; +begin + inherited; + FName := SMNGFormatName; + FFeatures := FFeatures + [ffMultiImage]; + AddMasks(SMNGMasks); + + FSignature := MNGSignature; + + RegisterOption(ImagingMNGLossyCompression, @FLossyCompression); + RegisterOption(ImagingMNGLossyAlpha, @FLossyAlpha); + RegisterOption(ImagingMNGPreFilter, @FPreFilter); + RegisterOption(ImagingMNGCompressLevel, @FCompressLevel); + RegisterOption(ImagingMNGQuality, @FQuality); + RegisterOption(ImagingMNGProgressive, @FProgressive); +end; + +function TMNGFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + NGFileLoader: TNGFileLoader; + I, Len: LongInt; +begin + Result := False; + NGFileLoader := TNGFileLoader.Create(Self); + try + // Use NG file parser to load file + if NGFileLoader.LoadFile(Handle) then + begin + Len := Length(NGFileLoader.Frames); + if Len > 0 then + begin + SetLength(Images, Len); + for I := 0 to Len - 1 do + with NGFileLoader.Frames[I] do + begin + // Build actual image bits + if IsJpegFrame then + NGFileLoader.LoadImageFromJNGFrame(FrameWidth, FrameHeight, JHDR, IDATMemory, JDATMemory, JDAAMemory, Images[I]) + else + NGFileLoader.LoadImageFromPNGFrame(FrameWidth, FrameHeight, IHDR, IDATMemory, Images[I]); + // Build palette, aply color key or background + NGFileLoader.ApplyFrameSettings(NGFileLoader.Frames[I], Images[I]); + end; + end + else + begin + // Some MNG files (with BASI-IEND streams) dont have actual pixel data + SetLength(Images, 1); + NewImage(NGFileLoader.MHDR.FrameWidth, NGFileLoader.MHDR.FrameWidth, ifDefault, Images[0]); + end; + Result := True; + end; + finally + NGFileLoader.LoadMetaData; // Store metadata + NGFileLoader.Free; + end; +end; + +function TMNGFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +var + NGFileSaver: TNGFileSaver; + I, LargestWidth, LargestHeight: LongInt; + ImageToSave: TImageData; + MustBeFreed: Boolean; +begin + Result := False; + LargestWidth := 0; + LargestHeight := 0; + + NGFileSaver := TNGFileSaver.Create(Self); + NGFileSaver.FileType := ngMNG; + NGFileSaver.SetFileOptions; + + with NGFileSaver do + try + // Store all frames to be saved frames file saver + for I := FFirstIdx to FLastIdx do + begin + if MakeCompatible(Images[I], ImageToSave, MustBeFreed) then + try + // Add image as PNG or JNG frame + AddFrame(ImageToSave, FLossyCompression); + // Remember largest frame width and height + LargestWidth := Iff(LargestWidth < ImageToSave.Width, ImageToSave.Width, LargestWidth); + LargestHeight := Iff(LargestHeight < ImageToSave.Height, ImageToSave.Height, LargestHeight); + finally + if MustBeFreed then + FreeImage(ImageToSave); + end + else + Exit; + end; + + // Fill MNG header + MHDR.FrameWidth := LargestWidth; + MHDR.FrameHeight := LargestHeight; + MHDR.TicksPerSecond := 0; + MHDR.NominalLayerCount := 0; + MHDR.NominalFrameCount := Length(Frames); + MHDR.NominalPlayTime := 0; + MHDR.SimplicityProfile := 473; // 111011001 binary, defines MNG-VLC with transparency and JNG support + + // Finally save MNG file + SaveFile(Handle); + Result := True; + finally + NGFileSaver.Free; + end; +end; + +{$ENDIF} + +{$IFNDEF DONT_LINK_JNG} + +{ TJNGFileFormat class implementation } + +procedure TJNGFileFormat.Define; +begin + inherited; + FName := SJNGFormatName; + AddMasks(SJNGMasks); + + FSignature := JNGSignature; + FLossyCompression := True; + + RegisterOption(ImagingJNGLossyAlpha, @FLossyAlpha); + RegisterOption(ImagingJNGAlphaPreFilter, @FPreFilter); + RegisterOption(ImagingJNGAlphaCompressLevel, @FCompressLevel); + RegisterOption(ImagingJNGQuality, @FQuality); + RegisterOption(ImagingJNGProgressive, @FProgressive); + +end; + +function TJNGFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + NGFileLoader: TNGFileLoader; +begin + Result := False; + NGFileLoader := TNGFileLoader.Create(Self); + try + // Use NG file parser to load file + if NGFileLoader.LoadFile(Handle) and (Length(NGFileLoader.Frames) > 0) then + with NGFileLoader.Frames[0] do + begin + SetLength(Images, 1); + // Build actual image bits + if IsJpegFrame then + NGFileLoader.LoadImageFromJNGFrame(FrameWidth, FrameHeight, JHDR, IDATMemory, JDATMemory, JDAAMemory, Images[0]); + // Build palette, aply color key or background + NGFileLoader.ApplyFrameSettings(NGFileLoader.Frames[0], Images[0]); + Result := True; + end; + finally + NGFileLoader.LoadMetaData; // Store metadata + NGFileLoader.Free; + end; +end; + +function TJNGFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +var + NGFileSaver: TNGFileSaver; + ImageToSave: TImageData; + MustBeFreed: Boolean; +begin + // Make image JNG compatible, store it in saver, and save it to file + Result := MakeCompatible(Images[Index], ImageToSave, MustBeFreed); + if Result then + begin + NGFileSaver := TNGFileSaver.Create(Self); + with NGFileSaver do + try + FileType := ngJNG; + SetFileOptions; + AddFrame(ImageToSave, True); + SaveFile(Handle); + finally + // Free NG saver and compatible image + NGFileSaver.Free; + if MustBeFreed then + FreeImage(ImageToSave); + end; + end; +end; + +{$ENDIF} + +initialization + RegisterImageFileFormat(TPNGFileFormat); +{$IFNDEF DONT_LINK_MNG} + RegisterImageFileFormat(TMNGFileFormat); +{$ENDIF} +{$IFNDEF DONT_LINK_JNG} + RegisterImageFileFormat(TJNGFileFormat); +{$ENDIF} +finalization + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77 Changes/Bug Fixes ----------------------------------- + - Reads and writes APNG animation loop count metadata. + - Writes frame delays of APNG from metadata. + - Fixed color keys in 8bit depth PNG/MNG loading. + - Fixed needless (and sometimes buggy) conversion to format with alpha + channel in FPC (GetMem(0) <> nil!). + - Added support for optional ZLib compression strategy. + - Added loading and saving of ifBinary (1bit black and white) + format images. During loading grayscale 1bpp and indexed 1bpp + (with only black and white colors in palette) are treated as ifBinary. + ifBinary are saved as 1bpp grayscale PNGs. + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Reads frame delays from APNG files into metadata. + - Added loading and saving of metadata from these chunks: pHYs. + - Simplified decoding of 1/2/4 bit images a bit (less code). + + -- 0.26.3 Changes/Bug Fixes --------------------------------- + - Added APNG saving support. + - Added APNG support to NG loader and animating to PNG loader. + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - Changed file format conditional compilation to reflect changes + in LINK symbols. + + -- 0.24.3 Changes/Bug Fixes --------------------------------- + - Changes for better thread safety. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added loading of global palettes and transparencies in MNG files + (and by doing so fixed crash when loading images with global PLTE or tRNS). + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Small changes in converting to supported formats. + - MakeCompatible method moved to base class, put ConvertToSupported here. + GetSupportedFormats removed, it is now set in constructor. + - Made public properties for options registered to SetOption/GetOption + functions. + - Changed extensions to filename masks. + - Changed SaveData, LoadData, and MakeCompatible methods according + to changes in base class in Imaging unit. + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - MNG and JNG support added, PNG support redesigned to support NG file handlers + - added classes for working with NG file formats + - stuff from old ImagingPng unit added and that unit was deleted + - unit created and initial stuff added + + -- 0.15 Changes/Bug Fixes ----------------------------------- + - when saving indexed images save alpha to tRNS? + - added some defines and ifdefs to dzlib unit to allow choosing + impaszlib, fpc's paszlib, zlibex or other zlib implementation + - added colorkeying support + - fixed 16bit channel image handling - pixels were not swapped + - fixed arithmetic overflow (in paeth filter) in FPC + - data of unknown chunks are skipped and not needlesly loaded + + -- 0.13 Changes/Bug Fixes ----------------------------------- + - adaptive filtering added to PNG saving + - TPNGFileFormat class added +} + +end. diff --git a/src/lib/vampimg/ImagingOptions.inc b/src/lib/vampimg/ImagingOptions.inc new file mode 100644 index 0000000..deb21e4 --- /dev/null +++ b/src/lib/vampimg/ImagingOptions.inc @@ -0,0 +1,216 @@ +{ + User Options + Following defines and options can be changed by user. +} + +{ Source options } + +{$DEFINE USE_INLINE} // Use function inlining for some functions + // works in Free Pascal and Delphi 9+. +{$DEFINE USE_ASM} // Ff defined, assembler versions of some + // functions will be used (only for x86). + + // Debug options: If none of these two are defined + // your project settings are used. +{ $DEFINE IMAGING_DEBUG} // If defined, debug info, range/IO/overflow + // checking, stack frames, assertions, and + // other debugging options will be turned on. +{ $DEFINE IMAGING_RELEASE} // If defined, all debug info is off. + + + +(* File format support linking options. + Define formats which you don't want to be registred automatically. + Default: all formats are registered = no symbols defined. + Example: If you want to disable JPEG support just uncomment //{$DEFINE DONT_LINK_JPEG} line +*) + +//{$DEFINE DONT_LINK_JPEG} // link support for Jpeg images +//{$DEFINE DONT_LINK_PNG} // link support for PNG images +//{$DEFINE DONT_LINK_TARGA} // link support for Targa images +//{$DEFINE DONT_LINK_BITMAP} // link support for Windows Bitmap images +//{$DEFINE DONT_LINK_DDS} // link support for DDS images +//{$DEFINE DONT_LINK_GIF} // link support for GIF images +{$DEFINE DONT_LINK_MNG} // link support for MNG images +{$DEFINE DONT_LINK_JNG} // link support for JNG images +//{$DEFINE DONT_LINK_PNM} // link support for PortableMap images (PBM, PGM, PPM, PAM, PFM) +{$DEFINE DONT_LINK_RADHDR} // link support for Radiance HDR/RGBE file format + +//{$DEFINE DONT_LINK_EXTRAS} // link support for file formats defined in + // Extras package. Exactly which formats will be + // registered depends on settings in + // ImagingExtras.pas unit. + +{ Component set used in ImagignComponents.pas unit. You usually don't need + to be concerned with this - proper component library is selected automatically + according to your compiler. } + +{ $DEFINE COMPONENT_SET_VCL} // use Delphi VCL +{ $DEFINE COMPONENT_SET_LCL} // use Lazarus LCL (set automatically when compiling with FPC) + +{ + Auto Options + Following options and defines are set automatically and some + are required for Imaging to compile successfully. Do not change + anything here if you don't know what you are doing. +} + +{ Compiler options } + +{$ALIGN ON} // Field alignment: 8 Bytes (in D6+) +{$BOOLEVAL OFF} // Boolean eval: off +{$EXTENDEDSYNTAX ON} // Extended syntax: on +{$LONGSTRINGS ON} // string = AnsiString: on +{$MINENUMSIZE 4} // Min enum size: 4 B +{$TYPEDADDRESS OFF} // Typed pointers: off +{$WRITEABLECONST OFF} // Writeable constants: off + +{$IFNDEF FPC} + {$DEFINE DCC} // if not using FPC then DCC compiler is used (Delphi/BCB) + // others are not supported +{$ENDIF} + +{$IFDEF DCC} + {$DEFINE DELPHI} +{$ENDIF} + +{$IF (Defined(DCC) and (CompilerVersion >= 18.5))} + {$IFDEF RELEASE} + {$UNDEF DEBUG} // If we are using Delphi 2007+ where you can set + // DEBUG/RELEASE mode in project options and RELEASE + // is currently set we undef DEBUG mode + {$ENDIF} +{$IFEND} + +{$IF Defined(IMAGING_DEBUG)} + {$ASSERTIONS ON} + {$DEBUGINFO ON} + {$RANGECHECKS ON} + {$IOCHECKS ON} + {$OVERFLOWCHECKS ON} + {$IFDEF DCC} + {$OPTIMIZATION OFF} + {$STACKFRAMES ON} + {$LOCALSYMBOLS ON} + {$DEFINE MEMCHECK} + {$ENDIF} + {$IFDEF FPC} + {$S+} + {$CHECKPOINTER ON} + {$ENDIF} +{$ELSEIF Defined(IMAGING_RELEASE)} + {$ASSERTIONS OFF} + {$DEBUGINFO OFF} + {$RANGECHECKS OFF} + {$IOCHECKS OFF} + {$OVERFLOWCHECKS OFF} + {$IFDEF DCC} + {$OPTIMIZATION ON} + {$STACKFRAMES OFF} + {$LOCALSYMBOLS OFF} + {$ENDIF} + {$IFDEF FPC} + {$S-} + {$ENDIF} +{$IFEND} + +{$IF Defined (CPU86) and not Defined(CPUX86)} + {$DEFINE CPUX86} // Compatibility with Delphi +{$IFEND} + +{$IF Defined (CPUX86_64) and not Defined(CPUX64)} + {$DEFINE CPUX64} // Compatibility with Delphi +{$IFEND} + +{$IF Defined (DARWIN) and not Defined(MACOSX)} + {$DEFINE MACOS} // Compatibility with Delphi +{$IFEND} + +{$IF Defined(DCC) and (CompilerVersion < 23)} + {$DEFINE CPUX86} // Compatibility with older Delphi +{$IFEND} + +{ Compiler capabilities } + +// Define if compiler supports inlining of functions and procedures +{$IF (Defined(DCC) and (CompilerVersion >= 17)) or Defined(FPC)} + {$DEFINE HAS_INLINE} +{$IFEND} + +// Define if compiler supports advanced records with methods +{$IF (Defined(DCC) and (CompilerVersion >= 18)) or + (Defined(FPC) and (FPC_FULLVERSION >= 20600))} + {$DEFINE HAS_ADVANCED_RECORDS} +{$IFEND} + +// Define if compiler supports operator overloading +// (unfortunately Delphi and FPC operator overloading is not compatible). +// FPC supports Delphi compatible operator overloads since 2.6.0 +{$IF (Defined(DCC) and (CompilerVersion >= 18)) or + (Defined(FPC) and (FPC_FULLVERSION >= 20600))} + {$DEFINE HAS_OPERATOR_OVERLOADING} +{$IFEND} + +// Anonymous methods +{$IF Defined(DCC) and (CompilerVersion >= 20) } + {$DEFINE HAS_ANON_METHODS} +{$IFEND} + +// Generic types (Delphi and FPC implementations incompatible). +// Update: FPC supports Delphi compatible generics since 2.6.0 +{$IF (Defined(DCC) and (CompilerVersion >= 20)) or + (Defined(FPC) and (FPC_FULLVERSION >= 20600))} + {$DEFINE HAS_GENERICS} +{$IFEND} + +{ Imaging options check} + +{$IFNDEF HAS_INLINE} + {$UNDEF USE_INLINE} +{$ENDIF} + +{$IF not Defined(CPUX86)} + {$UNDEF USE_ASM} +{$IFEND} + +{$IFDEF FPC} + {$DEFINE COMPONENT_SET_LCL} + {$UNDEF COMPONENT_SET_VCL} +{$ENDIF} + +{$IFDEF DELPHI} + {$UNDEF COMPONENT_SET_LCL} + {$DEFINE COMPONENT_SET_VCL} +{$ENDIF} + +{ Platform options } + +{$IF Defined(WIN32) or Defined(WIN64)} + {$DEFINE MSWINDOWS} +{$IFEND} + +{$IFDEF LINUX} + {$DEFINE UNIX} +{$ENDIF} + +{ More compiler options } + +{$IFDEF FPC} // Free Pascal options - some options set above (like min enum size) + // are reset to defaults by setting {$MODE} so they are + // redeclared here + {$MODE DELPHI} // compatible with delphi + {$GOTO ON} // alow goto + {$PACKRECORDS 8} // same as ALING 8 for Delphi + {$PACKENUM 4} // Min enum size: 4 B + {$IFDEF CPU86} + {$ASMMODE INTEL} // intel assembler mode + {$ENDIF} +{$ENDIF} + +{$IFDEF HAS_INLINE} + {$INLINE ON} // turns inlining on for compilers that support it +{$ENDIF} + +{$WARNINGS OFF} +{$HINTS OFF} +{$NOTES OFF} diff --git a/src/lib/vampimg/ImagingPcx.pas b/src/lib/vampimg/ImagingPcx.pas new file mode 100644 index 0000000..d278542 --- /dev/null +++ b/src/lib/vampimg/ImagingPcx.pas @@ -0,0 +1,375 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader for ZSoft Paintbrush images known as PCX.} +unit ImagingPcx; + +{$I ImagingOptions.inc} + +interface + +uses + ImagingTypes, Imaging, ImagingFormats, ImagingUtility, ImagingIO; + +type + { Class for loading ZSoft Paintbrush images known as PCX. It is old + format which can store 1bit, 2bit, 4bit, 8bit, and 24bit (and 32bit but is + probably non-standard) images. Only loading is supported (you can still come + accross some PCX files) but saving is not (I don't wont this venerable format + to spread).} + TPCXFileFormat = class(TImageFileFormat) + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + end; + +implementation + +const + SPCXFormatName = 'ZSoft Paintbrush Image'; + SPCXMasks = '*.pcx'; + +type + TPCXHeader = packed record + Id: Byte; // Always $0A + Version: Byte; // 0, 2, 3, 4, 5 + Encoding: Byte; // 0, 1 + BitsPerPixel: Byte; // 1, 2, 4, 8 + X0, Y0: Word; // Image window top-left + X1, Y1: Word; // Image window bottom-right + DpiX: Word; + DpiY: Word; + Palette16: array [0..15] of TColor24Rec; + Reserved1: Byte; + Planes: Byte; // 1, 3, 4 + BytesPerLine: Word; + PaletteType: Word; // 1: color or s/w 2: grayscale + Reserved2: array [0..57] of Byte; + end; + +{ TPCXFileFormat } + +procedure TPCXFileFormat.Define; +begin + inherited; + FName := SPCXFormatName; + FFeatures := [ffLoad]; + + AddMasks(SPCXMasks); +end; + +function TPCXFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +const + ifMono: TImageFormat = TImageFormat(250); + ifIndex2: TImageFormat = TImageFormat(251); + ifIndex4: TImageFormat = TImageFormat(252); +var + Hdr: TPCXHeader; + PalID, B: Byte; + PalPCX: TPalette24Size256; + FileDataFormat: TImageFormat; + I, J, UncompSize, BytesPerLine, ByteNum, BitNum: LongInt; + UncompData, RowPointer, PixelIdx: PByte; + Pixel24: PColor24Rec; + Pixel32: PColor32Rec; + AlphaPlane, RedPlane, GreenPlane, BluePlane, + Plane1, Plane2, Plane3, Plane4: PByteArray; + + procedure RleDecode(Target: PByte; UnpackedSize: LongInt); + var + Count: LongInt; + Source: Byte; + begin + while UnpackedSize > 0 do + with GetIO do + begin + GetIO.Read(Handle, @Source, SizeOf(Source)); + if (Source and $C0) = $C0 then + begin + // RLE data + Count := Source and $3F; + if UnpackedSize < Count then + Count := UnpackedSize; + Read(Handle, @Source, SizeOf(Source)); + FillChar(Target^, Count, Source); + //Inc(Source); + Inc(Target, Count); + Dec(UnpackedSize, Count); + end + else + begin + // Uncompressed data + Target^ := Source; + Inc(Target); + Dec(UnpackedSize); + end; + end; + end; + +begin + Result := False; + SetLength(Images, 1); + with GetIO, Images[0] do + begin + // Read PCX header and store input position (start of image data) + Read(Handle, @Hdr, SizeOf(Hdr)); + FileDataFormat := ifUnknown; + + // Determine image's data format and find its Imaging equivalent + // (using some custom TImageFormat constants) + case Hdr.BitsPerPixel of + 1: + case Hdr.Planes of + 1: FileDataFormat := ifMono; + 4: FileDataFormat := ifIndex4; + end; + 2: FileDataFormat := ifIndex2; + 4: FileDataFormat := ifIndex4; + 8: + case Hdr.Planes of + 1: FileDataFormat := ifIndex8; + 3: FileDataFormat := ifR8G8B8; + 4: FileDataFormat := ifA8R8G8B8; + end; + end; + + // No compatible Imaging format found, exit + if FileDataFormat = ifUnknown then + Exit; + + // Get width, height, and output data format (unsupported formats + // like ifMono are converted later to ifIndex8) + Width := Hdr.X1 - Hdr.X0 + 1; + Height := Hdr.Y1 - Hdr.Y0 + 1; + if FileDataFormat in [ifIndex8, ifR8G8B8] then + Format := FileDataFormat + else + Format := ifIndex8; + + NewImage(Width, Height, Format, Images[0]); + + if not (FileDataFormat in [ifIndex8, ifR8G8B8]) then + begin + // other formats use palette embedded to file header + for I := Low(Hdr.Palette16) to High(Hdr.Palette16) do + begin + Palette[I].A := $FF; + Palette[I].R := Hdr.Palette16[I].B; + Palette[I].G := Hdr.Palette16[I].G; + Palette[I].B := Hdr.Palette16[I].R; + end; + end; + + // Now we determine various data sizes + BytesPerLine := Hdr.BytesPerLine * Hdr.Planes; + UncompSize := BytesPerLine * Height; + + GetMem(UncompData, UncompSize); + try + if Hdr.Encoding = 1 then + begin + // Image data is compressed -> read and decompress + RleDecode(UncompData, UncompSize); + end + else + begin + // Just read uncompressed data + Read(Handle, UncompData, UncompSize); + end; + + if FileDataFormat in [ifR8G8B8, ifA8R8G8B8] then + begin + // RGB and ARGB images are stored in layout different from + // Imaging's (and most other file formats'). First there is + // Width red values then there is Width green values and so on + RowPointer := UncompData; + + if FileDataFormat = ifA8R8G8B8 then + begin + Pixel32 := Bits; + for I := 0 to Height - 1 do + begin + AlphaPlane := PByteArray(RowPointer); + RedPlane := @AlphaPlane[Hdr.BytesPerLine]; + GreenPlane := @AlphaPlane[Hdr.BytesPerLine * 2]; + BluePlane := @AlphaPlane[Hdr.BytesPerLine * 3]; + for J := 0 to Width - 1 do + begin + Pixel32.A := AlphaPlane[J]; + Pixel32.R := RedPlane[J]; + Pixel32.G := GreenPlane[J]; + Pixel32.B := BluePlane[J]; + Inc(Pixel32); + end; + Inc(RowPointer, BytesPerLine); + end; + end + else + begin + Pixel24 := Bits; + for I := 0 to Height - 1 do + begin + RedPlane := PByteArray(RowPointer); + GreenPlane := @RedPlane[Hdr.BytesPerLine]; + BluePlane := @RedPlane[Hdr.BytesPerLine * 2]; + for J := 0 to Width - 1 do + begin + Pixel24.R := RedPlane[J]; + Pixel24.G := GreenPlane[J]; + Pixel24.B := BluePlane[J]; + Inc(Pixel24); + end; + Inc(RowPointer, BytesPerLine); + end; + end; + end + else if FileDataFormat = ifIndex8 then + begin + // Just copy 8bit lines + for I := 0 to Height - 1 do + Move(PByteArray(UncompData)[I * Hdr.BytesPerLine], PByteArray(Bits)[I * Width], Width); + end + else if FileDataFormat = ifMono then + begin + // Convert 1bit images to ifIndex8 + Convert1To8(UncompData, Bits, Width, Height, Hdr.BytesPerLine, False); + end + else if FileDataFormat = ifIndex2 then + begin + // Convert 2bit images to ifIndex8. Note that 2bit PCX images + // usually use (from specs, I've never seen one myself) CGA palette + // which is not array of RGB tripplets. So 2bit PCXs are loaded but + // their colors would be wrong + Convert2To8(UncompData, Bits, Width, Height, Hdr.BytesPerLine, False); + end + else if FileDataFormat = ifIndex4 then + begin + // 4bit images can be stored similar to RGB images (in four one bit planes) + // or like array of nibbles (which is more common) + if (Hdr.BitsPerPixel = 1) and (Hdr.Planes = 4) then + begin + RowPointer := UncompData; + PixelIdx := Bits; + for I := 0 to Height - 1 do + begin + Plane1 := PByteArray(RowPointer); + Plane2 := @Plane1[Hdr.BytesPerLine]; + Plane3 := @Plane1[Hdr.BytesPerLine * 2]; + Plane4 := @Plane1[Hdr.BytesPerLine * 3]; + + for J := 0 to Width - 1 do + begin + B := 0; + ByteNum := J div 8; + BitNum := 7 - (J mod 8); + if (Plane1[ByteNum] shr BitNum) and $1 <> 0 then B := B or $01; + if (Plane2[ByteNum] shr BitNum) and $1 <> 0 then B := B or $02; + if (Plane3[ByteNum] shr BitNum) and $1 <> 0 then B := B or $04; + if (Plane4[ByteNum] shr BitNum) and $1 <> 0 then B := B or $08; + PixelIdx^ := B; + Inc(PixelIdx); + end; + Inc(RowPointer, BytesPerLine); + end; + end + else if (Hdr.BitsPerPixel = 4) and (Hdr.Planes = 1) then + begin + // Convert 4bit images to ifIndex8 + Convert4To8(UncompData, Bits, Width, Height, Hdr.BytesPerLine, False); + end + end; + + if FileDataFormat = ifIndex8 then + begin + // 8bit palette is appended at the end of the file + // with $0C identifier + //Seek(Handle, -769, smFromEnd); + Read(Handle, @PalID, SizeOf(PalID)); + if PalID = $0C then + begin + Read(Handle, @PalPCX, SizeOf(PalPCX)); + for I := Low(PalPCX) to High(PalPCX) do + begin + Palette[I].A := $FF; + Palette[I].R := PalPCX[I].B; + Palette[I].G := PalPCX[I].G; + Palette[I].B := PalPCX[I].R; + end; + end + else + Seek(Handle, -SizeOf(PalID), smFromCurrent); + end; + + finally + FreeMem(UncompData); + end; + Result := True; + end; +end; + +function TPCXFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Hdr: TPCXHeader; + ReadCount: LongInt; +begin + Result := False; + if Handle <> nil then + begin + ReadCount := GetIO.Read(Handle, @Hdr, SizeOf(Hdr)); + GetIO.Seek(Handle, -ReadCount, smFromCurrent); + Result := (ReadCount >= SizeOf(Hdr)) and + (Hdr.Id = $0A) and + (Hdr.Version in [0, 2, 3, 4, 5]) and + (Hdr.Encoding in [0..1]) and + (Hdr.BitsPerPixel in [1, 2, 4, 8]) and + (Hdr.Planes in [1, 3, 4]) and + (Hdr.PaletteType in [1..2]); + end; + +end; + +initialization + RegisterImageFileFormat(TPCXFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Made loader stream-safe - stream position is exactly at the end of the + image after loading and file size doesn't need to be know during the process. + - Initial TPCXFileFormat class implemented. + +} + +end. diff --git a/src/lib/vampimg/ImagingPortableMaps.pas b/src/lib/vampimg/ImagingPortableMaps.pas new file mode 100644 index 0000000..89d862d --- /dev/null +++ b/src/lib/vampimg/ImagingPortableMaps.pas @@ -0,0 +1,977 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains loader/saver for Portable Maps file format family (or PNM). + That includes PBM, PGM, PPM, PAM, and PFM formats.} +unit ImagingPortableMaps; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, ImagingTypes, Imaging, ImagingFormats, ImagingUtility; + +type + { Types of pixels of PNM images.} + TTupleType = (ttInvalid, ttBlackAndWhite, ttGrayScale, ttRGB, ttBlackAndWhiteAlpha, + ttGrayScaleAlpha, ttRGBAlpha, ttGrayScaleFP, ttRGBFP); + + { Record with info about PNM image used in both loading and saving functions.} + TPortableMapInfo = record + Width: LongInt; + Height: LongInt; + FormatId: AnsiChar; + MaxVal: LongInt; + BitCount: LongInt; + Depth: LongInt; + TupleType: TTupleType; + Binary: Boolean; + HasPAMHeader: Boolean; + IsBigEndian: Boolean; + end; + + { Base class for Portable Map file formats (or Portable AnyMaps or PNM). + There are several types of PNM file formats that share common + (simple) structure. This class can actually load all supported PNM formats. + Saving is also done by this class but descendants (each for different PNM + format) control it.} + TPortableMapFileFormat = class(TImageFileFormat) + protected + FIdNumbers: TChar2; + FSaveBinary: LongBool; + FUSFormat: TFormatSettings; + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveDataInternal(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt; var MapInfo: TPortableMapInfo): Boolean; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + published + { If set to True images will be saved in binary format. If it is False + they will be saved in text format (which could result in 5-10x bigger file). + Default is value True. Note that PAM and PFM files are always saved in binary.} + property SaveBinary: LongBool read FSaveBinary write FSaveBinary; + end; + + { Portable Bit Map is used to store monochrome 1bit images. Raster data + can be saved as text or binary data. Either way value of 0 represents white + and 1 is black. As Imaging does not have support for 1bit data formats + PBM images can be loaded but not saved. Loaded images are returned in + ifGray8 format (witch pixel values scaled from 1bit to 8bit).} + TPBMFileFormat = class(TPortableMapFileFormat) + protected + procedure Define; override; + end; + + { Portable Gray Map is used to store grayscale 8bit or 16bit images. + Raster data can be saved as text or binary data.} + TPGMFileFormat = class(TPortableMapFileFormat) + protected + procedure Define; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + end; + + { Portable Pixel Map is used to store RGB images with 8bit or 16bit channels. + Raster data can be saved as text or binary data.} + TPPMFileFormat = class(TPortableMapFileFormat) + protected + procedure Define; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + end; + + { Portable Arbitrary Map is format that can store image data formats + of PBM, PGM, and PPM formats with optional alpha channel. Raster data + can be stored only in binary format. All data formats supported + by this format are ifGray8, ifGray16, ifA8Gray8, ifA16Gray16, + ifR8G8B8, ifR16G16R16, ifA8R8G8B8, and ifA16R16G16B16.} + TPAMFileFormat = class(TPortableMapFileFormat) + protected + procedure Define; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + end; + + { Portable Float Map is unofficial extension of PNM format family which + can store images with floating point pixels. Raster data is saved in + binary format as array of IEEE 32 bit floating point numbers. One channel + or RGB images are supported by PFM format (so no alpha).} + TPFMFileFormat = class(TPortableMapFileFormat) + protected + procedure Define; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + end; + +implementation + +const + PortableMapDefaultBinary = True; + + SPBMFormatName = 'Portable Bit Map'; + SPBMMasks = '*.pbm'; + SPGMFormatName = 'Portable Gray Map'; + SPGMMasks = '*.pgm'; + PGMSupportedFormats = [ifGray8, ifGray16]; + SPPMFormatName = 'Portable Pixel Map'; + SPPMMasks = '*.ppm'; + PPMSupportedFormats = [ifR8G8B8, ifR16G16B16]; + SPAMFormatName = 'Portable Arbitrary Map'; + SPAMMasks = '*.pam'; + PAMSupportedFormats = [ifGray8, ifGray16, ifA8Gray8, ifA16Gray16, + ifR8G8B8, ifR16G16B16, ifA8R8G8B8, ifA16R16G16B16]; + SPFMFormatName = 'Portable Float Map'; + SPFMMasks = '*.pfm'; + PFMSupportedFormats = [ifR32F, ifB32G32R32F]; + +const + { TAB, CR, LF, and Space are used as seperators in Portable map headers and data.} + WhiteSpaces = [#9, #10, #13, #32]; + SPAMWidth = 'WIDTH'; + SPAMHeight = 'HEIGHT'; + SPAMDepth = 'DEPTH'; + SPAMMaxVal = 'MAXVAL'; + SPAMTupleType = 'TUPLTYPE'; + SPAMEndHdr = 'ENDHDR'; + + { Size of buffer used to speed up text PNM loading/saving.} + LineBufferCapacity = 16 * 1024; + + TupleTypeNames: array[TTupleType] of string = ( + 'INVALID', 'BLACKANDWHITE', 'GRAYSCALE', 'RGB', + 'BLACKANDWHITE_ALPHA', 'GRAYSCALE_ALPHA', 'RGB_ALPHA', 'GRAYSCALEFP', + 'RGBFP'); + +{ TPortableMapFileFormat } + +procedure TPortableMapFileFormat.Define; +begin + inherited; + FFeatures := [ffLoad, ffSave]; + FSaveBinary := PortableMapDefaultBinary; + FUSFormat := GetFormatSettingsForFloats; +end; + +function TPortableMapFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + I, ScanLineSize, MonoSize: LongInt; + Dest: PByte; + MonoData: Pointer; + Info: TImageFormatInfo; + LineBuffer: array[0..LineBufferCapacity - 1] of AnsiChar; + LineEnd, LinePos: LongInt; + MapInfo: TPortableMapInfo; + LineBreak: string; + + procedure CheckBuffer; + begin + if (LineEnd = 0) or (LinePos = LineEnd) then + begin + // Reload buffer if its is empty or its end was reached + LineEnd := GetIO.Read(Handle, @LineBuffer[0], LineBufferCapacity); + LinePos := 0; + end; + end; + + procedure FixInputPos; + begin + // Sets input's position to its real pos as it would be without buffering + if LineEnd > 0 then + begin + GetIO.Seek(Handle, -LineEnd + LinePos, smFromCurrent); + LineEnd := 0; + end; + end; + + function ReadString: string; + var + S: AnsiString; + C: AnsiChar; + begin + // First skip all whitespace chars + SetLength(S, 1); + repeat + CheckBuffer; + S[1] := LineBuffer[LinePos]; + Inc(LinePos); + if S[1] = '#' then + repeat + // Comment detected, skip everything until next line is reached + CheckBuffer; + S[1] := LineBuffer[LinePos]; + Inc(LinePos); + until S[1] = #10; + until not(S[1] in WhiteSpaces); + // Now we have reached some chars other than white space, read them until + // there is whitespace again + repeat + SetLength(S, Length(S) + 1); + CheckBuffer; + S[Length(S)] := LineBuffer[LinePos]; + Inc(LinePos); + // Repeat until current char is whitespace or end of file is reached + // (Line buffer has 0 bytes which happens only on EOF) + until (S[Length(S)] in WhiteSpaces) or (LineEnd = 0); + // Get rid of last char - whitespace or null + SetLength(S, Length(S) - 1); + // Move position to the beginning of next string (skip white space - needed + // to make the loader stop at the right input position) + repeat + CheckBuffer; + C := LineBuffer[LinePos]; + Inc(LinePos); + until not (C in WhiteSpaces) or (LineEnd = 0); + // Dec pos, current is the begining of the the string + Dec(LinePos); + + Result := string(S); + end; + + function ReadIntValue: LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} + begin + Result := StrToInt(ReadString); + end; + + procedure FindLineBreak; + var + C: AnsiChar; + begin + LineBreak := #10; + repeat + CheckBuffer; + C := LineBuffer[LinePos]; + Inc(LinePos); + + if C = #13 then + LineBreak := #13#10; + + until C = #10; + end; + + function ParseHeader: Boolean; + var + Id: TChar2; + I: TTupleType; + TupleTypeName: string; + Scale: Single; + begin + Result := False; + with GetIO do + begin + FillChar(MapInfo, SizeOf(MapInfo), 0); + Read(Handle, @Id, SizeOf(Id)); + FindLineBreak; + + if Id[1] in ['1'..'6'] then + begin + // Read header for PBM, PGM, and PPM files + MapInfo.Width := ReadIntValue; + MapInfo.Height := ReadIntValue; + + if Id[1] in ['1', '4'] then + begin + MapInfo.MaxVal := 1; + MapInfo.BitCount := 1 + end + else + begin + // Read channel max value, <=255 for 8bit images, >255 for 16bit images + // but some programs think its max colors so put <=256 here + MapInfo.MaxVal := ReadIntValue; + MapInfo.BitCount := Iff(MapInfo.MaxVal <= 256, 8, 16); + end; + + MapInfo.Depth := 1; + case Id[1] of + '1', '4': MapInfo.TupleType := ttBlackAndWhite; + '2', '5': MapInfo.TupleType := ttGrayScale; + '3', '6': + begin + MapInfo.TupleType := ttRGB; + MapInfo.Depth := 3; + end; + end; + end + else if Id[1] = '7' then + begin + // Read values from PAM header + // WIDTH + if (ReadString <> SPAMWidth) then Exit; + MapInfo.Width := ReadIntValue; + // HEIGHT + if (ReadString <> SPAMheight) then Exit; + MapInfo.Height := ReadIntValue; + // DEPTH + if (ReadString <> SPAMDepth) then Exit; + MapInfo.Depth := ReadIntValue; + // MAXVAL + if (ReadString <> SPAMMaxVal) then Exit; + MapInfo.MaxVal := ReadIntValue; + MapInfo.BitCount := Iff(MapInfo.MaxVal <= 256, 8, 16); + // TUPLETYPE + if (ReadString <> SPAMTupleType) then Exit; + TupleTypeName := ReadString; + for I := Low(TTupleType) to High(TTupleType) do + if SameText(TupleTypeName, TupleTypeNames[I]) then + begin + MapInfo.TupleType := I; + Break; + end; + // ENDHDR + if (ReadString <> SPAMEndHdr) then Exit; + end + else if Id[1] in ['F', 'f'] then + begin + // Read header of PFM file + MapInfo.Width := ReadIntValue; + MapInfo.Height := ReadIntValue; + Scale := StrToFloatDef(ReadString, 0, FUSFormat); + MapInfo.IsBigEndian := Scale > 0.0; + if Id[1] = 'F' then + MapInfo.TupleType := ttRGBFP + else + MapInfo.TupleType := ttGrayScaleFP; + MapInfo.Depth := Iff(MapInfo.TupleType = ttRGBFP, 3, 1); + MapInfo.BitCount := Iff(MapInfo.TupleType = ttRGBFP, 96, 32); + end; + + FixInputPos; + MapInfo.Binary := (Id[1] in ['4', '5', '6', '7', 'F', 'f']); + + if MapInfo.Binary and not (Id[1] in ['F', 'f']) then + begin + // Mimic the behaviour of Photoshop and other editors/viewers: + // If linenreaks in file are DOS CR/LF 16bit binary values are + // little endian, Unix LF only linebreak indicates big endian. + MapInfo.IsBigEndian := LineBreak = #10; + end; + + // Check if values found in header are valid + Result := (MapInfo.Width > 0) and (MapInfo.Height > 0) and + (MapInfo.BitCount in [1, 8, 16, 32, 96]) and (MapInfo.TupleType <> ttInvalid); + // Now check if image has proper number of channels (PAM) + if Result then + case MapInfo.TupleType of + ttBlackAndWhite, ttGrayScale: Result := MapInfo.Depth = 1; + ttBlackAndWhiteAlpha, ttGrayScaleAlpha: Result := MapInfo.Depth = 2; + ttRGB: Result := MapInfo.Depth = 3; + ttRGBAlpha: Result := MapInfo.Depth = 4; + end; + end; + end; + +begin + Result := False; + LineEnd := 0; + LinePos := 0; + SetLength(Images, 1); + + with GetIO, Images[0] do + begin + Format := ifUnknown; + // Try to parse file header + if not ParseHeader then Exit; + // Select appropriate data format based on values read from file header + case MapInfo.TupleType of + ttBlackAndWhite: Format := ifGray8; + ttBlackAndWhiteAlpha: Format := ifA8Gray8; + ttGrayScale: Format := IffFormat(MapInfo.BitCount = 8, ifGray8, ifGray16); + ttGrayScaleAlpha: Format := IffFormat(MapInfo.BitCount = 8, ifA8Gray8, ifA16Gray16); + ttRGB: Format := IffFormat(MapInfo.BitCount = 8, ifR8G8B8, ifR16G16B16); + ttRGBAlpha: Format := IffFormat(MapInfo.BitCount = 8, ifA8R8G8B8, ifA16R16G16B16); + ttGrayScaleFP: Format := ifR32F; + ttRGBFP: Format := ifB32G32R32F; + end; + // Exit if no matching data format was found + if Format = ifUnknown then Exit; + + NewImage(MapInfo.Width, MapInfo.Height, Format, Images[0]); + Info := GetFormatInfo(Format); + + // Now read pixels from file to dest image + if not MapInfo.Binary then + begin + Dest := Bits; + for I := 0 to Width * Height - 1 do + begin + case Format of + ifGray8: + begin + Dest^ := ReadIntValue; + if MapInfo.BitCount = 1 then + // If source is 1bit mono image (where 0=white, 1=black) + // we must scale it to 8bits + Dest^ := 255 - Dest^ * 255; + end; + ifGray16: PWord(Dest)^ := ReadIntValue; + ifR8G8B8: + with PColor24Rec(Dest)^ do + begin + R := ReadIntValue; + G := ReadIntValue; + B := ReadIntValue; + end; + ifR16G16B16: + with PColor48Rec(Dest)^ do + begin + R := ReadIntValue; + G := ReadIntValue; + B := ReadIntValue; + end; + end; + Inc(Dest, Info.BytesPerPixel); + end; + end + else + begin + if MapInfo.BitCount > 1 then + begin + if not (MapInfo.TupleType in [ttGrayScaleFP, ttRGBFP]) then + begin + // Just copy bytes from binary Portable Maps (non 1bit, non FP) + Read(Handle, Bits, Size); + end + else + begin + Dest := Bits; + // FP images are in BGR order and endian swap maybe needed. + // Some programs store scanlines in bottom-up order but + // I will stick with Photoshops behaviour here + Read(Handle, Bits, Size); + if MapInfo.IsBigEndian then + SwapEndianLongWord(PLongWord(Dest), Size div SizeOf(LongWord)); + end; + + if MapInfo.TupleType in [ttBlackAndWhite, ttBlackAndWhiteAlpha] then + begin + // Black and white PAM files must be scaled to 8bits. Note that + // in PAM files 1=white, 0=black (reverse of PBM) + for I := 0 to Width * Height * Iff(MapInfo.TupleType = ttBlackAndWhiteAlpha, 2, 1) - 1 do + PByteArray(Bits)[I] := PByteArray(Bits)[I] * 255; + end + else if MapInfo.TupleType in [ttRGB, ttRGBAlpha] then + begin + // Swap channels of RGB/ARGB images. Binary RGB image files use BGR order. + SwapChannels(Images[0], ChannelBlue, ChannelRed); + end; + + // Swap byte order if needed + if (MapInfo.BitCount = 16) and MapInfo.IsBigEndian then + SwapEndianWord(Bits, Width * Height * Info.BytesPerPixel div SizeOf(Word)); + end + else + begin + // Handle binary PBM files (ttBlackAndWhite 1bit) + ScanLineSize := (Width + 7) div 8; + // Get total binary data size, read it from file to temp + // buffer and convert the data to Gray8 + MonoSize := ScanLineSize * Height; + GetMem(MonoData, MonoSize); + try + Read(Handle, MonoData, MonoSize); + Convert1To8(MonoData, Bits, Width, Height, ScanLineSize, False); + // 1bit mono images must be scaled to 8bit, but inverted (where 0=white, 1=black) + for I := 0 to Width * Height - 1 do + PByteArray(Bits)[I] := 255 - PByteArray(Bits)[I] * 255; + finally + FreeMem(MonoData); + end; + end; + end; + + FixInputPos; + + if (MapInfo.MaxVal <> Pow2Int(MapInfo.BitCount) - 1) and + (MapInfo.TupleType in [ttGrayScale, ttGrayScaleAlpha, ttRGB, ttRGBAlpha]) then + begin + Dest := Bits; + // Scale color values according to MaxVal we got from header + // if necessary. + for I := 0 to Width * Height * Info.BytesPerPixel div (MapInfo.BitCount shr 3) - 1 do + begin + if MapInfo.BitCount = 8 then + Dest^ := Dest^ * 255 div MapInfo.MaxVal + else + PWord(Dest)^ := PWord(Dest)^ * 65535 div MapInfo.MaxVal; + Inc(Dest, MapInfo.BitCount shr 3); + end; + end; + + Result := True; + end; +end; + +function TPortableMapFileFormat.SaveDataInternal(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: Integer; var MapInfo: TPortableMapInfo): Boolean; +const + // Use Unix linebreak, for many viewers/editors it means that + // 16bit samples are stored as big endian - so we need to swap byte order + // before saving + LineDelimiter = #10; + PixelDelimiter = #32; +var + ImageToSave: TImageData; + MustBeFreed: Boolean; + Info: TImageFormatInfo; + I, LineLength: LongInt; + Src: PByte; + Pixel32: TColor32Rec; + Pixel64: TColor64Rec; + W: Word; + + procedure WriteString(S: string; Delimiter: Char = LineDelimiter); + begin + SetLength(S, Length(S) + 1); + S[Length(S)] := Delimiter; + {$IF Defined(DCC) and Defined(UNICODE)} + GetIO.Write(Handle, @AnsiString(S)[1], Length(S)); + {$ELSE} + GetIO.Write(Handle, @S[1], Length(S)); + {$IFEND} + Inc(LineLength, Length(S)); + end; + + procedure WriteHeader; + begin + WriteString('P' + MapInfo.FormatId); + if not MapInfo.HasPAMHeader then + begin + // Write header of PGM, PPM, and PFM files + WriteString(IntToStr(ImageToSave.Width)); + WriteString(IntToStr(ImageToSave.Height)); + case MapInfo.TupleType of + ttGrayScale, ttRGB: WriteString(IntToStr(Pow2Int(MapInfo.BitCount) - 1)); + ttGrayScaleFP, ttRGBFP: + begin + // Negative value indicates that raster data is saved in little endian + WriteString(FloatToStr(-1.0, FUSFormat)); + end; + end; + end + else + begin + // Write PAM file header + WriteString(Format('%s %d', [SPAMWidth, ImageToSave.Width])); + WriteString(Format('%s %d', [SPAMHeight, ImageToSave.Height])); + WriteString(Format('%s %d', [SPAMDepth, MapInfo.Depth])); + WriteString(Format('%s %d', [SPAMMaxVal, Pow2Int(MapInfo.BitCount) - 1])); + WriteString(Format('%s %s', [SPAMTupleType, TupleTypeNames[MapInfo.TupleType]])); + WriteString(SPAMEndHdr); + end; + end; + +begin + Result := False; + if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then + with GetIO, ImageToSave do + try + Info := GetFormatInfo(Format); + // Fill values of MapInfo record that were not filled by + // descendants in their SaveData methods + MapInfo.BitCount := (Info.BytesPerPixel div Info.ChannelCount) * 8; + MapInfo.Depth := Info.ChannelCount; + if MapInfo.TupleType = ttInvalid then + begin + if Info.HasGrayChannel then + begin + if Info.HasAlphaChannel then + MapInfo.TupleType := ttGrayScaleAlpha + else + MapInfo.TupleType := ttGrayScale; + end + else + begin + if Info.HasAlphaChannel then + MapInfo.TupleType := ttRGBAlpha + else + MapInfo.TupleType := ttRGB; + end; + end; + // Write file header + WriteHeader; + + if not MapInfo.Binary then + begin + Src := Bits; + LineLength := 0; + // For each pixel find its text representation and write it to file + for I := 0 to Width * Height - 1 do + begin + case Format of + ifGray8: WriteString(IntToStr(Src^), PixelDelimiter); + ifGray16: WriteString(IntToStr(PWord(Src)^), PixelDelimiter); + ifR8G8B8: + with PColor24Rec(Src)^ do + WriteString(SysUtils.Format('%d %d %d', [R, G, B]), PixelDelimiter); + ifR16G16B16: + with PColor48Rec(Src)^ do + WriteString(SysUtils.Format('%d %d %d', [R, G, B]), PixelDelimiter); + end; + // Lines in text PNM images should have length <70 + if LineLength > 65 then + begin + LineLength := 0; + WriteString('', LineDelimiter); + end; + Inc(Src, Info.BytesPerPixel); + end; + end + else + begin + // Write binary images + if not (MapInfo.TupleType in [ttGrayScaleFP, ttRGBFP]) then + begin + // Save integer binary images + if MapInfo.BitCount = 8 then + begin + if MapInfo.TupleType in [ttGrayScale, ttGrayScaleAlpha] then + begin + // 8bit grayscale images can be written in one Write call + Write(Handle, Bits, Size); + end + else + begin + // 8bit RGB/ARGB images: red and blue must be swapped and + // 3 or 4 bytes must be written + Src := Bits; + for I := 0 to Width * Height - 1 do + with PColor32Rec(Src)^ do + begin + if MapInfo.TupleType = ttRGBAlpha then + Pixel32.A := A; + Pixel32.R := B; + Pixel32.G := G; + Pixel32.B := R; + Write(Handle, @Pixel32, Info.BytesPerPixel); + Inc(Src, Info.BytesPerPixel); + end; + end; + end + else + begin + // Images with 16bit channels: make sure that channel values are saved in big endian + Src := Bits; + if MapInfo.TupleType in [ttGrayScale, ttGrayScaleAlpha] then + begin + // 16bit grayscale image + for I := 0 to Width * Height * Info.BytesPerPixel div SizeOf(Word) - 1 do + begin + W := SwapEndianWord(PWord(Src)^); + Write(Handle, @W, SizeOf(Word)); + Inc(Src, SizeOf(Word)); + end; + end + else + begin + // RGB images with 16bit channels: swap RB and endian too + for I := 0 to Width * Height - 1 do + with PColor64Rec(Src)^ do + begin + if MapInfo.TupleType = ttRGBAlpha then + Pixel64.A := SwapEndianWord(A); + Pixel64.R := SwapEndianWord(B); + Pixel64.G := SwapEndianWord(G); + Pixel64.B := SwapEndianWord(R); + Write(Handle, @Pixel64, Info.BytesPerPixel); + Inc(Src, Info.BytesPerPixel); + end; + end; + end; + end + else + begin + // Floating point images (no need to swap endian here - little + // endian is specified in file header) + Write(Handle, Bits, Size); + end; + end; + Result := True; + finally + if MustBeFreed then + FreeImage(ImageToSave); + end; +end; + +function TPortableMapFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Id: TChar4; + ReadCount: LongInt; +begin + Result := False; + if Handle <> nil then + with GetIO do + begin + ReadCount := Read(Handle, @Id, SizeOf(Id)); + Seek(Handle, -ReadCount, smFromCurrent); + Result := (Id[0] = 'P') and (Id[1] in [FIdNumbers[0], FIdNumbers[1]]) and + (Id[2] in WhiteSpaces); + end; +end; + +{ TPBMFileFormat } + +procedure TPBMFileFormat.Define; +begin + inherited; + FName := SPBMFormatName; + FFeatures := [ffLoad]; + AddMasks(SPBMMasks); + FIdNumbers := '14'; +end; + +{ TPGMFileFormat } + +procedure TPGMFileFormat.Define; +begin + inherited; + FName := SPGMFormatName; + FSupportedFormats := PGMSupportedFormats; + AddMasks(SPGMMasks); + RegisterOption(ImagingPGMSaveBinary, @FSaveBinary); + FIdNumbers := '25'; +end; + +function TPGMFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: Integer): Boolean; +var + MapInfo: TPortableMapInfo; +begin + FillChar(MapInfo, SizeOf(MapInfo), 0); + if FSaveBinary then + MapInfo.FormatId := FIdNumbers[1] + else + MapInfo.FormatId := FIdNumbers[0]; + MapInfo.Binary := FSaveBinary; + Result := SaveDataInternal(Handle, Images, Index, MapInfo); +end; + +procedure TPGMFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if Info.IsFloatingPoint then + // All FP images go to 16bit + ConvFormat := ifGray16 + else if Info.HasGrayChannel then + // Grayscale will be 8 or 16 bit - depends on input's bitcount + ConvFormat := IffFormat(Info.BytesPerPixel div Info.ChannelCount > 1, + ifGray16, ifGray8) + else if Info.BytesPerPixel > 4 then + // Large bitcounts -> 16bit + ConvFormat := ifGray16 + else + // Rest of the formats -> 8bit + ConvFormat := ifGray8; + + ConvertImage(Image, ConvFormat); +end; + +{ TPPMFileFormat } + +procedure TPPMFileFormat.Define; +begin + inherited; + FName := SPPMFormatName; + FSupportedFormats := PPMSupportedFormats; + AddMasks(SPPMMasks); + RegisterOption(ImagingPPMSaveBinary, @FSaveBinary); + FIdNumbers := '36'; +end; + +function TPPMFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: Integer): Boolean; +var + MapInfo: TPortableMapInfo; +begin + FillChar(MapInfo, SizeOf(MapInfo), 0); + if FSaveBinary then + MapInfo.FormatId := FIdNumbers[1] + else + MapInfo.FormatId := FIdNumbers[0]; + MapInfo.Binary := FSaveBinary; + Result := SaveDataInternal(Handle, Images, Index, MapInfo); +end; + +procedure TPPMFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if Info.IsFloatingPoint then + // All FP images go to 48bit RGB + ConvFormat := ifR16G16B16 + else if Info.HasGrayChannel then + // Grayscale will be 24 or 48 bit RGB - depends on input's bitcount + ConvFormat := IffFormat(Info.BytesPerPixel div Info.ChannelCount > 1, + ifR16G16B16, ifR8G8B8) + else if Info.BytesPerPixel > 4 then + // Large bitcounts -> 48bit RGB + ConvFormat := ifR16G16B16 + else + // Rest of the formats -> 24bit RGB + ConvFormat := ifR8G8B8; + + ConvertImage(Image, ConvFormat); +end; + +{ TPAMFileFormat } + +procedure TPAMFileFormat.Define; +begin + inherited; + FName := SPAMFormatName; + FSupportedFormats := PAMSupportedFormats; + AddMasks(SPAMMasks); + FIdNumbers := '77'; +end; + +function TPAMFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: Integer): Boolean; +var + MapInfo: TPortableMapInfo; +begin + FillChar(MapInfo, SizeOf(MapInfo), 0); + MapInfo.FormatId := FIdNumbers[0]; + MapInfo.Binary := True; + MapInfo.HasPAMHeader := True; + Result := SaveDataInternal(Handle, Images, Index, MapInfo); +end; + +procedure TPAMFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if Info.IsFloatingPoint then + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA16R16G16B16, ifR16G16B16) + else if Info.HasGrayChannel then + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA16Gray16, ifGray16) + else + begin + if Info.BytesPerPixel <= 4 then + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA8R8G8B8, ifR8G8B8) + else + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA16R16G16B16, ifR16G16B16); + end; + ConvertImage(Image, ConvFormat); +end; + +{ TPFMFileFormat } + +procedure TPFMFileFormat.Define; +begin + inherited; + FName := SPFMFormatName; + AddMasks(SPFMMasks); + FIdNumbers := 'Ff'; + FSupportedFormats := PFMSupportedFormats; +end; + +function TPFMFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: Integer): Boolean; +var + Info: TImageFormatInfo; + MapInfo: TPortableMapInfo; +begin + FillChar(MapInfo, SizeOf(MapInfo), 0); + Info := GetFormatInfo(Images[Index].Format); + + if (Info.ChannelCount > 1) or Info.IsIndexed then + MapInfo.TupleType := ttRGBFP + else + MapInfo.TupleType := ttGrayScaleFP; + + if MapInfo.TupleType = ttGrayScaleFP then + MapInfo.FormatId := FIdNumbers[1] + else + MapInfo.FormatId := FIdNumbers[0]; + + MapInfo.Binary := True; + Result := SaveDataInternal(Handle, Images, Index, MapInfo); +end; + +procedure TPFMFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +begin + if (Info.ChannelCount > 1) or Info.IsIndexed then + ConvertImage(Image, ifB32G32R32F) + else + ConvertImage(Image, ifR32F); +end; + +initialization + RegisterImageFileFormat(TPBMFileFormat); + RegisterImageFileFormat(TPGMFileFormat); + RegisterImageFileFormat(TPPMFileFormat); + RegisterImageFileFormat(TPAMFileFormat); + RegisterImageFileFormat(TPFMFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 Changes/Bug Fixes ----------------------------------- + - Native RGB floating point format of PFM is now supported by Imaging + so we use it now for saving instead of A32B32G32B32. + - String to float formatting changes (don't change global settings). + + -- 0.26.3 Changes/Bug Fixes ----------------------------------- + - Fixed D2009 Unicode related bug in PNM saving. + + -- 0.24.3 Changes/Bug Fixes ----------------------------------- + - Improved compatibility of 16bit/component image loading. + - Changes for better thread safety. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Made modifications to ASCII PNM loading to be more "stream-safe". + - Fixed bug: indexed images saved as grayscale in PFM. + - Changed converting to supported formats little bit. + - Added scaling of channel values (non-FP and non-mono images) according + to MaxVal. + - Added buffering to loading of PNM files. More than 10x faster now + for text files. + - Added saving support to PGM, PPM, PAM, and PFM format. + - Added PFM file format. + - Initial version created. +} + +end. diff --git a/src/lib/vampimg/ImagingPsd.pas b/src/lib/vampimg/ImagingPsd.pas new file mode 100644 index 0000000..cd395ca --- /dev/null +++ b/src/lib/vampimg/ImagingPsd.pas @@ -0,0 +1,800 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader/saver for Photoshop PSD image format.} +unit ImagingPsd; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, ImagingTypes, Imaging, ImagingColors, ImagingUtility; + +type + { Class for loading and saving Adobe Photoshop PSD images. + Loading and saving of indexed, grayscale, RGB(A), HDR (FP32), and CMYK + (auto converted to RGB) images is supported. Non-HDR gray, RGB, + and CMYK images can have 8bit or 16bit color channels. + There is no support for loading mono images, duotone images are treated + like grayscale images, and multichannel and CIE Lab images are loaded as + RGB images but without actual conversion to RGB color space. + Also no layer information is loaded.} + TPSDFileFormat = class(TImageFileFormat) + private + FSaveAsLayer: LongBool; + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + published + property SaveAsLayer: LongBool read FSaveAsLayer write FSaveAsLayer; + end; + +implementation + +uses + ImagingExtras; + +const + SPSDFormatName = 'Photoshop Image'; + SPSDMasks = '*.psd,*.pdd'; + PSDSupportedFormats: TImageFormats = [ifIndex8, ifGray8, ifA8Gray8, + ifR8G8B8, ifA8R8G8B8, ifGray16, ifA16Gray16, ifR16G16B16, ifA16R16G16B16, + ifR32F, ifR32G32B32F, ifA32R32G32B32F]; + PSDDefaultSaveAsLayer = True; + +const + SPSDMagic = '8BPS'; + CompressionNone: Word = 0; + CompressionRLE: Word = 1; + +type + {$MINENUMSIZE 2} + { PSD Image color mode.} + TPSDColorMode = ( + cmMono = 0, + cmGrayscale = 1, + cmIndexed = 2, + cmRGB = 3, + cmCMYK = 4, + cmMultiChannel = 7, + cmDuoTone = 8, + cmLab = 9 + ); + + { PSD image main header.} + TPSDHeader = packed record + Signature: TChar4; // Format ID '8BPS' + Version: Word; // Always 1 + Reserved: array[0..5] of Byte; // Reserved, all zero + Channels: Word; // Number of color channels (1-24) including alpha channels + Rows : LongWord; // Height of image in pixels (1-30000) + Columns: LongWord; // Width of image in pixels (1-30000) + Depth: Word; // Number of bits per channel (1, 8, and 16) + Mode: TPSDColorMode; // Color mode + end; + + TPSDChannelInfo = packed record + ChannelID: Word; // 0 = Red, 1 = Green, 2 = Blue etc., -1 = Transparency mask, -2 = User mask + Size: LongWord; // Size of channel data. + end; + +procedure SwapHeader(var Header: TPSDHeader); +begin + Header.Version := SwapEndianWord(Header.Version); + Header.Channels := SwapEndianWord(Header.Channels); + Header.Depth := SwapEndianWord(Header.Depth); + Header.Rows := SwapEndianLongWord(Header.Rows); + Header.Columns := SwapEndianLongWord(Header.Columns); + Header.Mode := TPSDColorMode(SwapEndianWord(Word(Header.Mode))); +end; + +{ + TPSDFileFormat class implementation +} + +procedure TPSDFileFormat.Define; +begin + inherited; + FName := SPSDFormatName; + FFeatures := [ffLoad, ffSave]; + FSupportedFormats := PSDSupportedFormats; + AddMasks(SPSDMasks); + + FSaveAsLayer := PSDDefaultSaveAsLayer; + RegisterOption(ImagingPSDSaveAsLayer, @FSaveAsLayer); +end; + +function TPSDFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Header: TPSDHeader; + ByteCount: LongWord; + RawPal: array[0..767] of Byte; + Compression, PackedSize: Word; + LineSize, ChannelPixelSize, WidthBytes, + CurrChannel, MaxRLESize, I, Y, X: LongInt; + Info: TImageFormatInfo; + PackedLine, LineBuffer: PByte; + RLELineSizes: array of Word; + Col32: TColor32Rec; + Col64: TColor64Rec; + PCol32: PColor32Rec; + PCol64: PColor64Rec; + + { PackBits RLE decode code from Mike Lischke's GraphicEx library.} + procedure DecodeRLE(Source, Dest: PByte; PackedSize, UnpackedSize: LongInt); + var + Count: LongInt; + begin + while (UnpackedSize > 0) and (PackedSize > 0) do + begin + Count := ShortInt(Source^); + Inc(Source); + Dec(PackedSize); + if Count < 0 then + begin + // Replicate next byte -Count + 1 times + if Count = -128 then + Continue; + Count := -Count + 1; + if Count > UnpackedSize then + Count := UnpackedSize; + FillChar(Dest^, Count, Source^); + Inc(Source); + Dec(PackedSize); + Inc(Dest, Count); + Dec(UnpackedSize, Count); + end + else + begin + // Copy next Count + 1 bytes from input + Inc(Count); + if Count > UnpackedSize then + Count := UnpackedSize; + if Count > PackedSize then + Count := PackedSize; + Move(Source^, Dest^, Count); + Inc(Dest, Count); + Inc(Source, Count); + Dec(PackedSize, Count); + Dec(UnpackedSize, Count); + end; + end; + end; + +begin + Result := False; + SetLength(Images, 1); + with GetIO, Images[0] do + begin + // Read PSD header + Read(Handle, @Header, SizeOf(Header)); + SwapHeader(Header); + + // Determine image data format + Format := ifUnknown; + case Header.Mode of + cmGrayscale, cmDuoTone: + begin + if Header.Depth in [8, 16] then + begin + if Header.Channels = 1 then + Format := IffFormat(Header.Depth = 8, ifGray8, ifGray16) + else if Header.Channels >= 2 then + Format := IffFormat(Header.Depth = 8, ifA8Gray8, ifA16Gray16); + end + else if (Header.Depth = 32) and (Header.Channels = 1) then + Format := ifR32F; + end; + cmIndexed: + begin + if Header.Depth = 8 then + Format := ifIndex8; + end; + cmRGB, cmMultiChannel, cmCMYK, cmLab: + begin + if Header.Depth in [8, 16] then + begin + if Header.Channels = 3 then + Format := IffFormat(Header.Depth = 8, ifR8G8B8, ifR16G16B16) + else if Header.Channels >= 4 then + Format := IffFormat(Header.Depth = 8, ifA8R8G8B8, ifA16R16G16B16); + end + else if Header.Depth = 32 then + begin + if Header.Channels = 3 then + Format := ifR32G32B32F + else if Header.Channels >= 4 then + Format := ifA32R32G32B32F; + end; + end; + cmMono:; // Not supported + end; + + // Exit if no compatible format was found + if Format = ifUnknown then + Exit; + + NewImage(Header.Columns, Header.Rows, Format, Images[0]); + Info := GetFormatInfo(Format); + + // Read or skip Color Mode Data Block (palette) + Read(Handle, @ByteCount, SizeOf(ByteCount)); + ByteCount := SwapEndianLongWord(ByteCount); + if Format = ifIndex8 then + begin + // Read palette only for indexed images + Read(Handle, @RawPal, SizeOf(RawPal)); + for I := 0 to 255 do + begin + Palette[I].A := $FF; + Palette[I].R := RawPal[I + 0]; + Palette[I].G := RawPal[I + 256]; + Palette[I].B := RawPal[I + 512]; + end; + end + else + Seek(Handle, ByteCount, smFromCurrent); + + // Skip Image Resources Block + Read(Handle, @ByteCount, SizeOf(ByteCount)); + ByteCount := SwapEndianLongWord(ByteCount); + Seek(Handle, ByteCount, smFromCurrent); + // Now there is Layer and Mask Information Block + Read(Handle, @ByteCount, SizeOf(ByteCount)); + ByteCount := SwapEndianLongWord(ByteCount); + // Skip Layer and Mask Information Block + Seek(Handle, ByteCount, smFromCurrent); + + // Read compression flag + Read(Handle, @Compression, SizeOf(Compression)); + Compression := SwapEndianWord(Compression); + + if Compression = CompressionRLE then + begin + // RLE compressed PSDs (most) have first lengths of compressed scanlines + // for each channel stored + SetLength(RLELineSizes, Height * Header.Channels); + Read(Handle, @RLELineSizes[0], Length(RLELineSizes) * SizeOf(Word)); + SwapEndianWord(@RLELineSizes[0], Height * Header.Channels); + MaxRLESize := RLELineSizes[0]; + for I := 1 to High(RLELineSizes) do + begin + if MaxRLESize < RLELineSizes[I] then + MaxRLESize := RLELineSizes[I]; + end; + end + else + MaxRLESize := 0; + + ChannelPixelSize := Info.BytesPerPixel div Info.ChannelCount; + LineSize := Width * ChannelPixelSize; + WidthBytes := Width * Info.BytesPerPixel; + GetMem(LineBuffer, LineSize); + GetMem(PackedLine, MaxRLESize); + + try + // Image color chanels are stored separately in PSDs so we will load + // one by one and copy their data to appropriate addresses of dest image. + for I := 0 to Header.Channels - 1 do + begin + // Now determine to which color channel of destination image we are going + // to write pixels. + if I <= 4 then + begin + // If PSD has alpha channel we need to switch current channel order - + // PSDs have alpha stored after blue channel but Imaging has alpha + // before red. + if Info.HasAlphaChannel and (Header.Mode <> cmCMYK) then + begin + if I = Info.ChannelCount - 1 then + CurrChannel := I + else + CurrChannel := Info.ChannelCount - 2 - I; + end + else + CurrChannel := Info.ChannelCount - 1 - I; + end + else + begin + // No valid channel remains + CurrChannel := -1; + end; + + if CurrChannel >= 0 then + begin + for Y := 0 to Height - 1 do + begin + if Compression = CompressionRLE then + begin + // Read RLE line and decompress it + PackedSize := RLELineSizes[I * Height + Y]; + Read(Handle, PackedLine, PackedSize); + DecodeRLE(PackedLine, LineBuffer, PackedSize, LineSize); + end + else + begin + // Just read uncompressed line + Read(Handle, LineBuffer, LineSize); + end; + + // Swap endian if needed + if ChannelPixelSize = 4 then + SwapEndianLongWord(PLongWord(LineBuffer), Width) + else if ChannelPixelSize = 2 then + SwapEndianWord(PWordArray(LineBuffer), Width); + + if Info.ChannelCount > 1 then + begin + // Copy each pixel fragment to its right place in destination image + for X := 0 to Width - 1 do + begin + Move(PByteArray(LineBuffer)[X * ChannelPixelSize], + PByteArray(Bits)[Y * WidthBytes + X * Info.BytesPerPixel + CurrChannel * ChannelPixelSize], + ChannelPixelSize); + end; + end + else + begin + // Just copy the line + Move(LineBuffer^, PByteArray(Bits)[Y * LineSize], LineSize); + end; + end; + end + else + begin + // Skip current color channel, not needed for image loading - just to + // get stream's position to the end of PSD + if Compression = CompressionRLE then + begin + for Y := 0 to Height - 1 do + Seek(Handle, RLELineSizes[I * Height + Y], smFromCurrent); + end + else + Seek(Handle, LineSize * Height, smFromCurrent); + end; + end; + + if Header.Mode = cmCMYK then + begin + // Convert CMYK images to RGB (alpha is ignored here). PSD stores CMYK + // channels in the way that first requires substraction from max channel value + if ChannelPixelSize = 1 then + begin + PCol32 := Bits; + for X := 0 to Width * Height - 1 do + begin + Col32.A := 255 - PCol32.A; + Col32.R := 255 - PCol32.R; + Col32.G := 255 - PCol32.G; + Col32.B := 255 - PCol32.B; + CMYKToRGB(Col32.A, Col32.R, Col32.G, Col32.B, PCol32.R, PCol32.G, PCol32.B); + PCol32.A := 255; + Inc(PCol32); + end; + end + else + begin + PCol64 := Bits; + for X := 0 to Width * Height - 1 do + begin + Col64.A := 65535 - PCol64.A; + Col64.R := 65535 - PCol64.R; + Col64.G := 65535 - PCol64.G; + Col64.B := 65535 - PCol64.B; + CMYKToRGB16(Col64.A, Col64.R, Col64.G, Col64.B, PCol64.R, PCol64.G, PCol64.B); + PCol64.A := 65535; + Inc(PCol64); + end; + end; + end; + + Result := True; + finally + FreeMem(LineBuffer); + FreeMem(PackedLine); + end; + end; +end; + +function TPSDFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +type + TURect = packed record + Top, Left, Bottom, Right: LongWord; + end; +const + BlendMode: TChar8 = '8BIMnorm'; + LayerOptions: array[0..3] of Byte = (255, 0, 0, 0); + LayerName: array[0..7] of AnsiChar = #7'Layer 0'; +var + MustBeFreed: Boolean; + ImageToSave: TImageData; + Info: TImageFormatInfo; + Header: TPSDHeader; + I, CurrChannel, ChannelPixelSize: LongInt; + LayerBlockOffset, SaveOffset, ChannelInfoOffset: Integer; + ChannelInfo: TPSDChannelInfo; + R: TURect; + LongVal: LongWord; + WordVal, LayerCount: Word; + RawPal: array[0..767] of Byte; + ChannelDataSizes: array of Integer; + + function PackLine(Src, Dest: PByteArray; Length: Integer): Integer; + var + I, Remaining: Integer; + begin + Remaining := Length; + Result := 0; + while Remaining > 0 do + begin + I := 0; + // Look for characters same as the first + while (I < 128) and (Remaining - I > 0) and (Src[0] = Src[I]) do + Inc(I); + + if I > 2 then + begin + Dest[0] := Byte(-(I - 1)); + Dest[1] := Src[0]; + Dest := PByteArray(@Dest[2]); + + Src := PByteArray(@Src[I]); + Dec(Remaining, I); + Inc(Result, 2); + end + else + begin + // Look for different characters + I := 0; + while (I < 128) and (Remaining - (I + 1) > 0) and + ((Src[I] <> Src[I + 1]) or (Remaining - (I + 2) <= 0) or + (Src[I] <> Src[I + 2])) do + begin + Inc(I); + end; + // If there's only 1 remaining, the previous WHILE doesn't catch it + if Remaining = 1 then + I := 1; + + if I > 0 then + begin + // Some distinct ones found + Dest[0] := I - 1; + Move(Src[0], Dest[1], I); + Dest := PByteArray(@Dest[1 + I]); + Src := PByteArray(@Src[I]); + Dec(Remaining, I); + Inc(Result, I + 1); + end; + end; + end; + end; + + procedure WriteChannelData(SeparateChannelStorage: Boolean); + var + I, X, Y, LineSize, WidthBytes, RLETableOffset, CurrentOffset, WrittenLineSize: Integer; + LineBuffer, RLEBuffer: PByteArray; + RLELengths: array of Word; + Compression: Word; + begin + LineSize := ImageToSave.Width * ChannelPixelSize; + WidthBytes := ImageToSave.Width * Info.BytesPerPixel; + GetMem(LineBuffer, LineSize); + GetMem(RLEBuffer, LineSize * 3); + SetLength(RLELengths, ImageToSave.Height * Info.ChannelCount); + RLETableOffset := 0; + // No compression for FP32, Photoshop won't open them + Compression := Iff(Info.IsFloatingPoint, CompressionNone, CompressionRLE); + + if not SeparateChannelStorage then + begin + // This is for storing background merged image. There's only one + // compression flag and one RLE lenghts table for all channels + WordVal := Swap(Compression); + GetIO.Write(Handle, @WordVal, SizeOf(WordVal)); + if Compression = CompressionRLE then + begin + RLETableOffset := GetIO.Tell(Handle); + GetIO.Write(Handle, @RLELengths[0], SizeOf(Word) * ImageToSave.Height * Info.ChannelCount); + end; + end; + + for I := 0 to Info.ChannelCount - 1 do + begin + if SeparateChannelStorage then + begin + // Layer image data has compression flag and RLE lenghts table + // independent for each channel + WordVal := Swap(CompressionRLE); + GetIO.Write(Handle, @WordVal, SizeOf(WordVal)); + if Compression = CompressionRLE then + begin + RLETableOffset := GetIO.Tell(Handle); + GetIO.Write(Handle, @RLELengths[0], SizeOf(Word) * ImageToSave.Height); + ChannelDataSizes[I] := 0; + end; + end; + + // Now determine which color channel we are going to write to file. + if Info.HasAlphaChannel then + begin + if I = Info.ChannelCount - 1 then + CurrChannel := I + else + CurrChannel := Info.ChannelCount - 2 - I; + end + else + CurrChannel := Info.ChannelCount - 1 - I; + + for Y := 0 to ImageToSave.Height - 1 do + begin + if Info.ChannelCount > 1 then + begin + // Copy each pixel fragment to its right place in destination image + for X := 0 to ImageToSave.Width - 1 do + begin + Move(PByteArray(ImageToSave.Bits)[Y * WidthBytes + X * Info.BytesPerPixel + CurrChannel * ChannelPixelSize], + PByteArray(LineBuffer)[X * ChannelPixelSize], ChannelPixelSize); + end; + end + else + Move(PByteArray(ImageToSave.Bits)[Y * LineSize], LineBuffer^, LineSize); + + // Write current channel line to file (swap endian if needed first) + if ChannelPixelSize = 4 then + SwapEndianLongWord(PLongWord(LineBuffer), ImageToSave.Width) + else if ChannelPixelSize = 2 then + SwapEndianWord(PWordArray(LineBuffer), ImageToSave.Width); + + if Compression = CompressionRLE then + begin + // Compress and write line + WrittenLineSize := PackLine(LineBuffer, RLEBuffer, LineSize); + RLELengths[ImageToSave.Height * I + Y] := SwapEndianWord(WrittenLineSize); + GetIO.Write(Handle, RLEBuffer, WrittenLineSize); + end + else + begin + WrittenLineSize := LineSize; + GetIO.Write(Handle, LineBuffer, WrittenLineSize); + end; + + if SeparateChannelStorage then + Inc(ChannelDataSizes[I], WrittenLineSize); + end; + + if SeparateChannelStorage and (Compression = CompressionRLE) then + begin + // Update channel RLE lengths + CurrentOffset := GetIO.Tell(Handle); + GetIO.Seek(Handle, RLETableOffset, smFromBeginning); + GetIO.Write(Handle, @RLELengths[ImageToSave.Height * I], SizeOf(Word) * ImageToSave.Height); + GetIO.Seek(Handle, CurrentOffset, smFromBeginning); + Inc(ChannelDataSizes[I], SizeOf(Word) * ImageToSave.Height); + end; + end; + + if not SeparateChannelStorage and (Compression = CompressionRLE) then + begin + // Update channel RLE lengths + CurrentOffset := GetIO.Tell(Handle); + GetIO.Seek(Handle, RLETableOffset, smFromBeginning); + GetIO.Write(Handle, @RLELengths[0], SizeOf(Word) * ImageToSave.Height * Info.ChannelCount); + GetIO.Seek(Handle, CurrentOffset, smFromBeginning); + end; + + FreeMem(LineBuffer); + FreeMem(RLEBuffer); + end; + +begin + Result := False; + if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then + with GetIO, ImageToSave do + try + Info := GetFormatInfo(Format); + ChannelPixelSize := Info.BytesPerPixel div Info.ChannelCount; + + // Fill header with proper info and save it + FillChar(Header, SizeOf(Header), 0); + Header.Signature := SPSDMagic; + Header.Version := 1; + Header.Channels := Info.ChannelCount; + Header.Rows := Height; + Header.Columns := Width; + Header.Depth := Info.BytesPerPixel div Info.ChannelCount * 8; + if Info.IsIndexed then + Header.Mode := cmIndexed + else if Info.HasGrayChannel or (Info.ChannelCount = 1) then + Header.Mode := cmGrayscale + else + Header.Mode := cmRGB; + + SwapHeader(Header); + Write(Handle, @Header, SizeOf(Header)); + + // Write palette size and data + LongVal := SwapEndianLongWord(IffUnsigned(Info.IsIndexed, SizeOf(RawPal), 0)); + Write(Handle, @LongVal, SizeOf(LongVal)); + if Info.IsIndexed then + begin + for I := 0 to Info.PaletteEntries - 1 do + begin + RawPal[I] := Palette[I].R; + RawPal[I + 256] := Palette[I].G; + RawPal[I + 512] := Palette[I].B; + end; + Write(Handle, @RawPal, SizeOf(RawPal)); + end; + + // Write empty resource and layer block sizes + LongVal := 0; + Write(Handle, @LongVal, SizeOf(LongVal)); + LayerBlockOffset := Tell(Handle); + Write(Handle, @LongVal, SizeOf(LongVal)); + + if FSaveAsLayer and (ChannelPixelSize < 4) then // No Layers for FP32 images + begin + LayerCount := SwapEndianWord(Iff(Info.HasAlphaChannel, Word(-1), 1)); // Must be -1 to get transparency in Photoshop + R.Top := 0; + R.Left := 0; + R.Bottom := SwapEndianLongWord(Height); + R.Right := SwapEndianLongWord(Width); + WordVal := SwapEndianWord(Info.ChannelCount); + Write(Handle, @LongVal, SizeOf(LongVal)); // Layer section size, empty now + Write(Handle, @LayerCount, SizeOf(LayerCount)); // Layer count + Write(Handle, @R, SizeOf(R)); // Bounds rect + Write(Handle, @WordVal, SizeOf(WordVal)); // Channel count + + ChannelInfoOffset := Tell(Handle); + SetLength(ChannelDataSizes, Info.ChannelCount); // Empty channel infos + FillChar(ChannelInfo, SizeOf(ChannelInfo), 0); + for I := 0 to Info.ChannelCount - 1 do + Write(Handle, @ChannelInfo, SizeOf(ChannelInfo)); + + Write(Handle, @BlendMode, SizeOf(BlendMode)); // Blend mode = normal + Write(Handle, @LayerOptions, SizeOf(LayerOptions)); // Predefined options + LongVal := SwapEndianLongWord(16); // Extra data size (4 (mask size) + 4 (ranges size) + 8 (name)) + Write(Handle, @LongVal, SizeOf(LongVal)); + LongVal := 0; + Write(Handle, @LongVal, SizeOf(LongVal)); // Mask size = 0 + LongVal := 0; + Write(Handle, @LongVal, SizeOf(LongVal)); // Blend ranges size + Write(Handle, @LayerName, SizeOf(LayerName)); // Layer name + + WriteChannelData(True); // Write Layer image data + + Write(Handle, @LongVal, SizeOf(LongVal)); // Global mask info size = 0 + + SaveOffset := Tell(Handle); + Seek(Handle, LayerBlockOffset, smFromBeginning); + + // Update layer and mask section sizes + LongVal := SwapEndianLongWord(SaveOffset - LayerBlockOffset - 4); + Write(Handle, @LongVal, SizeOf(LongVal)); + LongVal := SwapEndianLongWord(SaveOffset - LayerBlockOffset - 8); + Write(Handle, @LongVal, SizeOf(LongVal)); + + // Update layer channel info + Seek(Handle, ChannelInfoOffset, smFromBeginning); + for I := 0 to Info.ChannelCount - 1 do + begin + ChannelInfo.ChannelID := SwapEndianWord(I); + if (I = Info.ChannelCount - 1) and Info.HasAlphaChannel then + ChannelInfo.ChannelID := Swap(Word(-1)); + ChannelInfo.Size := SwapEndianLongWord(ChannelDataSizes[I] + 2); // datasize (incl RLE table) + comp. flag + Write(Handle, @ChannelInfo, SizeOf(ChannelInfo)); + end; + + Seek(Handle, SaveOffset, smFromBeginning); + end; + + // Write background merged image + WriteChannelData(False); + + Result := True; + finally + if MustBeFreed then + FreeImage(ImageToSave); + end; +end; + +procedure TPSDFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if Info.IsFloatingPoint then + begin + if Info.ChannelCount = 1 then + ConvFormat := ifR32F + else if Info.HasAlphaChannel then + ConvFormat := ifA32R32G32B32F + else + ConvFormat := ifR32G32B32F; + end + else if Info.HasGrayChannel then + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA16Gray16, ifGray16) + else if Info.RBSwapFormat in GetSupportedFormats then + ConvFormat := Info.RBSwapFormat + else + ConvFormat := IffFormat(Info.HasAlphaChannel, ifA8R8G8B8, ifR8G8B8); + + ConvertImage(Image, ConvFormat); +end; + +function TPSDFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Header: TPSDHeader; + ReadCount: LongInt; +begin + Result := False; + if Handle <> nil then + begin + ReadCount := GetIO.Read(Handle, @Header, SizeOf(Header)); + SwapHeader(Header); + GetIO.Seek(Handle, -ReadCount, smFromCurrent); + Result := (ReadCount >= SizeOf(Header)) and + (Header.Signature = SPSDMagic) and + (Header.Version = 1); + end; +end; + +initialization + RegisterImageFileFormat(TPSDFileFormat); + +{ + File Notes: + + -- 0.77.1 --------------------------------------------------- + - 3 channel RGB float images are loaded and saved directly + as ifR32G32B32F. + + -- 0.26.1 Changes/Bug Fixes --------------------------------- + - PSDs are now saved with RLE compression. + - Mask layer saving added to SaveData for images with alpha + (shows proper transparency when opened in Photoshop). Can be + enabled/disabled using option + - Fixed memory leak in SaveData. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Saving implemented. + - Loading implemented. + - Unit created with initial stuff! +} + +end. diff --git a/src/lib/vampimg/ImagingRadiance.pas b/src/lib/vampimg/ImagingRadiance.pas new file mode 100644 index 0000000..122e0c2 --- /dev/null +++ b/src/lib/vampimg/ImagingRadiance.pas @@ -0,0 +1,497 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader/saver for Radiance HDR/RGBE images.} +unit ImagingRadiance; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, Classes, Imaging, ImagingTypes, ImagingUtility; + +type + { Radiance is a suite of tools for performing lighting simulation. It's + development started in 1985 and it pioneered the concept of + high dynamic range imaging. Radiance defined an image format for storing + HDR images, now described as RGBE image format. Since it was the first + HDR image format, this format is supported by many other software packages. + + Radiance image file consists of three sections: a header, resolution string, + followed by the pixel data. Each pixel is stored as 4 bytes, one byte + mantissa for each r, g, b and a shared one byte exponent. + The pixel data may be stored uncompressed or using run length encoding. + + Imaging translates RGBE pixels to original float values and stores them + in ifR32G32B32F data format. It can read both compressed and uncompressed + files, and saves files as compressed.} + THdrFileFormat = class(TImageFileFormat) + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + end; + +implementation + +uses + Math, ImagingIO; + +const + SHdrFormatName = 'Radiance HDR/RGBE'; + SHdrMasks = '*.hdr'; + HdrSupportedFormats: TImageFormats = [ifR32G32B32F]; + +type + TSignature = array[0..9] of AnsiChar; + THdrFormat = (hfRgb, hfXyz); + + THdrHeader = record + Format: THdrFormat; + Width: Integer; + Height: Integer; + end; + + TRgbe = packed record + R, G, B, E: Byte; + end; + PRgbe = ^TRgbe; + TDynRgbeArray = array of TRgbe; + +const + RadianceSignature: TSignature = '#?RADIANCE'; + RgbeSignature: TSignature = '#?RGBE'; + MaxLineLength = 256; + SFmtRgbeRle = '32-bit_rle_rgbe'; + SFmtXyzeRle = '32-bit_rle_xyze'; + +resourcestring + SErrorBadHeader = 'Bad HDR/RGBE header format.'; + SWrongScanLineWidth = 'Wrong scanline width.'; + SXyzNotSupported = 'XYZ color space not supported.'; + +{ THdrFileFormat } + +procedure THdrFileFormat.Define; +begin + inherited; + FName := SHdrFormatName; + FFeatures := [ffLoad, ffSave]; + FSupportedFormats := HdrSupportedFormats; + + AddMasks(SHdrMasks); +end; + +function THdrFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Header: THdrHeader; + IO: TIOFunctions; + + function ReadHeader: Boolean; + const + CommentIds: TAnsiCharSet = ['#', '!']; + var + Line: AnsiString; + HasResolution: Boolean; + Count, Idx: Integer; + ValStr, NativeLine: string; + ValFloat: Double; + begin + Result := False; + HasResolution := False; + Count := 0; + + repeat + if not ReadLine(IO, Handle, Line) then + Exit; + + Inc(Count); + if Count > 16 then // Too long header for HDR + Exit; + + if Length(Line) = 0 then + Continue; + if Line[1] in CommentIds then + Continue; + + NativeLine := string(Line); + + if StrMaskMatch(NativeLine, 'Format=*') then + begin + // Data format parsing + ValStr := Copy(NativeLine, 8, MaxInt); + if ValStr = SFmtRgbeRle then + Header.Format := hfRgb + else if ValStr = SFmtXyzeRle then + Header.Format := hfXyz + else + Exit; + end; + + if StrMaskMatch(NativeLine, 'Gamma=*') then + begin + ValStr := Copy(NativeLine, 7, MaxInt); + if TryStrToFloat(ValStr, ValFloat, GetFormatSettingsForFloats) then + FMetadata.SetMetaItem(SMetaGamma, ValFloat); + end; + + if StrMaskMatch(NativeLine, 'Exposure=*') then + begin + ValStr := Copy(NativeLine, 10, MaxInt); + if TryStrToFloat(ValStr, ValFloat, GetFormatSettingsForFloats) then + FMetadata.SetMetaItem(SMetaExposure, ValFloat); + end; + + if StrMaskMatch(NativeLine, '?Y * ?X *') then + begin + Idx := Pos('X', NativeLine); + ValStr := SubString(NativeLine, 4, Idx - 2); + if not TryStrToInt(ValStr, Header.Height) then + Exit; + ValStr := Copy(NativeLine, Idx + 2, MaxInt); + if not TryStrToInt(ValStr, Header.Width) then + Exit; + + if (NativeLine[1] = '-') then + Header.Height := -Header.Height; + if (NativeLine[Idx - 1] = '-') then + Header.Width := -Header.Width; + + HasResolution := True; + end; + + until HasResolution; + Result := True; + end; + + procedure DecodeRgbe(const Src: TRgbe; Dest: PColor96FPRec); {$IFDEF USE_INLINE}inline;{$ENDIF} + var + Mult: Single; + begin + if Src.E > 0 then + begin + Mult := Math.Ldexp(1, Src.E - 128); + Dest.R := Src.R / 255 * Mult; + Dest.G := Src.G / 255 * Mult; + Dest.B := Src.B / 255 * Mult; + end + else + begin + Dest.R := 0; + Dest.G := 0; + Dest.B := 0; + end; + end; + + procedure ReadCompressedLine(Width, Y: Integer; var DestBuffer: TDynRgbeArray); + var + Pos: Integer; + I, X, Count: Integer; + Code, Value: Byte; + LineBuff: TDynByteArray; + Rgbe: TRgbe; + Ptr: PByte; + begin + SetLength(LineBuff, Width); + IO.Read(Handle, @Rgbe, SizeOf(Rgbe)); + + if ((Rgbe.B shl 8) or Rgbe.E) <> Width then + RaiseImaging(SWrongScanLineWidth); + + for I := 0 to 3 do + begin + Pos := 0; + while Pos < Width do + begin + IO.Read(Handle, @Code, SizeOf(Byte)); + if Code > 128 then + begin + Count := Code - 128; + IO.Read(Handle, @Value, SizeOf(Byte)); + FillMemoryByte(@LineBuff[Pos], Count, Value); + end + else + begin + Count := Code; + IO.Read(Handle, @LineBuff[Pos], Count * SizeOf(Byte)); + end; + Inc(Pos, Count); + end; + + Ptr := @PByteArray(@DestBuffer[0])[I]; + for X := 0 to Width - 1 do + begin + Ptr^ := LineBuff[X]; + Inc(Ptr, 4); + end; + end; + end; + + procedure ReadPixels(var Image: TImageData); + var + Y, X, SrcLineLen: Integer; + Dest: PColor96FPRec; + Compressed: Boolean; + Rgbe: TRgbe; + Buffer: TDynRgbeArray; + begin + Dest := Image.Bits; + Compressed := not ((Image.Width < 8) or (Image.Width > $7FFFF)); + SrcLineLen := Image.Width * SizeOf(TRgbe); + + IO.Read(Handle, @Rgbe, SizeOf(Rgbe)); + IO.Seek(Handle, -SizeOf(Rgbe), smFromCurrent); + + if (Rgbe.R <> 2) or (Rgbe.G <> 2) or ((Rgbe.B and 128) > 0) then + Compressed := False; + + SetLength(Buffer, Image.Width); + + for Y := 0 to Image.Height - 1 do + begin + if Compressed then + ReadCompressedLine(Image.Width, Y, Buffer) + else + IO.Read(Handle, @Buffer[0], SrcLineLen); + + for X := 0 to Image.Width - 1 do + begin + DecodeRgbe(Buffer[X], Dest); + Inc(Dest); + end; + end; + end; + +begin + IO := GetIO; + SetLength(Images, 1); + + // Read header, allocate new image and, then read and convert the pixels + if not ReadHeader then + RaiseImaging(SErrorBadHeader); + if (Header.Format = hfXyz) then + RaiseImaging(SXyzNotSupported); + + NewImage(Abs(Header.Width), Abs(Header.Height), ifR32G32B32F, Images[0]); + ReadPixels(Images[0]); + + // Flip/mirror the image as needed (height < 0 is default top-down) + if Header.Width < 0 then + MirrorImage(Images[0]); + if Header.Height > 0 then + FlipImage(Images[0]); + + Result := True; +end; + +function THdrFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: Integer): Boolean; +const + LineEnd = #$0A; + SPrgComment = '#Made with Vampyre Imaging Library'; + SSizeFmt = '-Y %d +X %d'; +var + ImageToSave: TImageData; + MustBeFreed: Boolean; + IO: TIOFunctions; + + procedure SaveHeader; + begin + WriteLine(IO, Handle, RadianceSignature, LineEnd); + WriteLine(IO, Handle, SPrgComment, LineEnd); + WriteLine(IO, Handle, 'FORMAT=' + SFmtRgbeRle, LineEnd + LineEnd); + WriteLine(IO, Handle, AnsiString(Format(SSizeFmt, [ImageToSave.Height, ImageToSave.Width])), LineEnd); + end; + + procedure EncodeRgbe(const Src: TColor96FPRec; var DestR, DestG, DestB, DestE: Byte); {$IFDEF USE_INLINE}inline;{$ENDIF} + var + V, M: {$IFDEF FPC}Float{$ELSE}Extended{$ENDIF}; + E: Integer; + begin + V := Src.R; + if (Src.G > V) then + V := Src.G; + if (Src.B > V) then + V := Src.B; + + if V < 1e-32 then + begin + DestR := 0; + DestG := 0; + DestB := 0; + DestE := 0; + end + else + begin + Frexp(V, M, E); + V := M * 256.0 / V; + DestR := ClampToByte(Round(Src.R * V)); + DestG := ClampToByte(Round(Src.G * V)); + DestB := ClampToByte(Round(Src.B * V)); + DestE := ClampToByte(E + 128); + end; + end; + + procedure WriteRleLine(const Line: array of Byte; Width: Integer); + const + MinRunLength = 4; + var + Cur, BeginRun, RunCount, OldRunCount, NonRunCount: Integer; + Buf: array[0..1] of Byte; + begin + Cur := 0; + while Cur < Width do + begin + BeginRun := Cur; + RunCount := 0; + OldRunCount := 0; + while (RunCount < MinRunLength) and (BeginRun < Width) do + begin + Inc(BeginRun, RunCount); + OldRunCount := RunCount; + RunCount := 1; + while (BeginRun + RunCount < Width) and (RunCount < 127) and (Line[BeginRun] = Line[BeginRun + RunCount]) do + Inc(RunCount); + end; + if (OldRunCount > 1) and (OldRunCount = BeginRun - Cur) then + begin + Buf[0] := 128 + OldRunCount; + Buf[1] := Line[Cur]; + IO.Write(Handle, @Buf, 2); + Cur := BeginRun; + end; + while Cur < BeginRun do + begin + NonRunCount := Min(128, BeginRun - Cur); + Buf[0] := NonRunCount; + IO.Write(Handle, @Buf, 1); + IO.Write(Handle, @Line[Cur], NonRunCount); + Inc(Cur, NonRunCount); + end; + if RunCount >= MinRunLength then + begin + Buf[0] := 128 + RunCount; + Buf[1] := Line[BeginRun]; + IO.Write(Handle, @Buf, 2); + Inc(Cur, RunCount); + end; + end; + end; + + procedure SavePixels; + var + Y, X, I, Width: Integer; + SrcPtr: PColor96FPRecArray; + Components: array of array of Byte; + StartLine: array[0..3] of Byte; + begin + Width := ImageToSave.Width; + // Save using RLE, each component is compressed separately + SetLength(Components, 4, Width); + + for Y := 0 to ImageToSave.Height - 1 do + begin + SrcPtr := @PColor96FPRecArray(ImageToSave.Bits)[ImageToSave.Width * Y]; + + // Identify line as using "new" RLE scheme (separate components) + StartLine[0] := 2; + StartLine[1] := 2; + StartLine[2] := Width shr 8; + StartLine[3] := Width and $FF; + IO.Write(Handle, @StartLine, SizeOf(StartLine)); + + for X := 0 to Width - 1 do + begin + EncodeRgbe(SrcPtr[X], Components[0, X], Components[1, X], + Components[2, X], Components[3, X]); + end; + + for I := 0 to 3 do + WriteRleLine(Components[I], Width); + end; + end; + +begin + Result := False; + IO := GetIO; + // Makes image to save compatible with Jpeg saving capabilities + if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then + with ImageToSave do + try + // Save header + SaveHeader; + // Save uncompressed pixels + SavePixels; + finally + if MustBeFreed then + FreeImage(ImageToSave); + end; +end; + +procedure THdrFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +begin + ConvertImage(Image, ifR32G32B32F); +end; + +function THdrFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + FileSig: TSignature; + ReadCount: Integer; +begin + Result := False; + if Handle <> nil then + begin + ReadCount := GetIO.Read(Handle, @FileSig, SizeOf(FileSig)); + GetIO.Seek(Handle, -ReadCount, smFromCurrent); + Result := (ReadCount = SizeOf(FileSig)) and + ((FileSig = RadianceSignature) or CompareMem(@FileSig, @RgbeSignature, 6)); + end; +end; + +initialization + RegisterImageFileFormat(THdrFileFormat); + +{ + File Notes: + + -- 0.77.1 --------------------------------------------------- + - Added RLE compression to saving. + - Added image saving. + - Unit created with initial stuff (loading only). + +} + +end. diff --git a/src/lib/vampimg/ImagingTarga.pas b/src/lib/vampimg/ImagingTarga.pas new file mode 100644 index 0000000..66af5f2 --- /dev/null +++ b/src/lib/vampimg/ImagingTarga.pas @@ -0,0 +1,619 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader/saver for Targa images.} +unit ImagingTarga; + +{$I ImagingOptions.inc} + +interface + +uses + ImagingTypes, Imaging, ImagingFormats, ImagingUtility; + +type + { Class for loading and saving Truevision Targa images. + It can load/save 8bit indexed or grayscale, 16 bit RGB or grayscale, + 24 bit RGB and 32 bit ARGB images with or without RLE compression.} + TTargaFileFormat = class(TImageFileFormat) + protected + FUseRLE: LongBool; + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + published + { Controls that RLE compression is used during saving. Accessible trough + ImagingTargaRLE option.} + property UseRLE: LongBool read FUseRLE write FUseRLE; + end; + +implementation + +const + STargaFormatName = 'Truevision Targa Image'; + STargaMasks = '*.tga'; + TargaSupportedFormats: TImageFormats = [ifIndex8, ifGray8, ifA1R5G5B5, + ifR8G8B8, ifA8R8G8B8]; + TargaDefaultRLE = False; + +const + STargaSignature = 'TRUEVISION-XFILE'; + +type + { Targa file header.} + TTargaHeader = packed record + IDLength: Byte; + ColorMapType: Byte; + ImageType: Byte; + ColorMapOff: Word; + ColorMapLength: Word; + ColorEntrySize: Byte; + XOrg: SmallInt; + YOrg: SmallInt; + Width: SmallInt; + Height: SmallInt; + PixelSize: Byte; + Desc: Byte; + end; + + { Footer at the end of TGA file.} + TTargaFooter = packed record + ExtOff: LongWord; // Extension Area Offset + DevDirOff: LongWord; // Developer Directory Offset + Signature: TChar16; // TRUEVISION-XFILE + Reserved: Byte; // ASCII period '.' + NullChar: Byte; // 0 + end; + + +{ TTargaFileFormat class implementation } + +procedure TTargaFileFormat.Define; +begin + inherited; + FName := STargaFormatName; + FFeatures := [ffLoad, ffSave]; + FSupportedFormats := TargaSupportedFormats; + + FUseRLE := TargaDefaultRLE; + + AddMasks(STargaMasks); + RegisterOption(ImagingTargaRLE, @FUseRLE); +end; + +function TTargaFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Hdr: TTargaHeader; + Foo: TTargaFooter; + FooterFound, ExtFound: Boolean; + I, PSize, PalSize: LongWord; + Pal: Pointer; + FmtInfo: TImageFormatInfo; + WordValue: Word; + + procedure LoadRLE; + var + I, CPixel, Cnt: LongInt; + Bpp, Rle: Byte; + Buffer, Dest, Src: PByte; + BufSize: LongInt; + begin + with GetIO, Images[0] do + begin + // Alocates buffer large enough to hold the worst case + // RLE compressed data and reads then from input + BufSize := Width * Height * FmtInfo.BytesPerPixel; + BufSize := BufSize + BufSize div 2 + 1; + GetMem(Buffer, BufSize); + Src := Buffer; + Dest := Bits; + BufSize := Read(Handle, Buffer, BufSize); + + Cnt := Width * Height; + Bpp := FmtInfo.BytesPerPixel; + CPixel := 0; + while CPixel < Cnt do + begin + Rle := Src^; + Inc(Src); + if Rle < 128 then + begin + // Process uncompressed pixel + Rle := Rle + 1; + CPixel := CPixel + Rle; + for I := 0 to Rle - 1 do + begin + // Copy pixel from src to dest + case Bpp of + 1: Dest^ := Src^; + 2: PWord(Dest)^ := PWord(Src)^; + 3: PColor24Rec(Dest)^ := PColor24Rec(Src)^; + 4: PLongWord(Dest)^ := PLongWord(Src)^; + end; + Inc(Src, Bpp); + Inc(Dest, Bpp); + end; + end + else + begin + // Process compressed pixels + Rle := Rle - 127; + CPixel := CPixel + Rle; + // Copy one pixel from src to dest (many times there) + for I := 0 to Rle - 1 do + begin + case Bpp of + 1: Dest^ := Src^; + 2: PWord(Dest)^ := PWord(Src)^; + 3: PColor24Rec(Dest)^ := PColor24Rec(Src)^; + 4: PLongWord(Dest)^ := PLongWord(Src)^; + end; + Inc(Dest, Bpp); + end; + Inc(Src, Bpp); + end; + end; + // set position in source to real end of compressed data + Seek(Handle, -(BufSize - LongInt(LongWord(Src) - LongWord(Buffer))), + smFromCurrent); + FreeMem(Buffer); + end; + end; + +begin + SetLength(Images, 1); + with GetIO, Images[0] do + begin + // Read targa header + Read(Handle, @Hdr, SizeOf(Hdr)); + // Skip image ID info + Seek(Handle, Hdr.IDLength, smFromCurrent); + // Determine image format + Format := ifUnknown; + case Hdr.ImageType of + 1, 9: Format := ifIndex8; + 2, 10: case Hdr.PixelSize of + 15: Format := ifX1R5G5B5; + 16: Format := ifA1R5G5B5; + 24: Format := ifR8G8B8; + 32: Format := ifA8R8G8B8; + end; + 3, 11: Format := ifGray8; + end; + // Format was not assigned by previous testing (it should be in + // well formed targas), so formats which reflects bit dept are selected + if Format = ifUnknown then + case Hdr.PixelSize of + 8: Format := ifGray8; + 15: Format := ifX1R5G5B5; + 16: Format := ifA1R5G5B5; + 24: Format := ifR8G8B8; + 32: Format := ifA8R8G8B8; + end; + NewImage(Hdr.Width, Hdr.Height, Format, Images[0]); + FmtInfo := GetFormatInfo(Format); + + if (Hdr.ColorMapType = 1) and (Hdr.ImageType in [1, 9]) then + begin + // Read palette + PSize := Hdr.ColorMapLength * (Hdr.ColorEntrySize shr 3); + GetMem(Pal, PSize); + try + Read(Handle, Pal, PSize); + // Process palette + PalSize := Iff(Hdr.ColorMapLength > FmtInfo.PaletteEntries, + FmtInfo.PaletteEntries, Hdr.ColorMapLength); + for I := 0 to PalSize - 1 do + case Hdr.ColorEntrySize of + 24: + with Palette[I] do + begin + A := $FF; + R := PPalette24(Pal)[I].R; + G := PPalette24(Pal)[I].G; + B := PPalette24(Pal)[I].B; + end; + // I've never seen tga with these palettes so they are untested + 16: + with Palette[I] do + begin + A := (PWordArray(Pal)[I] and $8000) shr 12; + R := (PWordArray(Pal)[I] and $FC00) shr 7; + G := (PWordArray(Pal)[I] and $03E0) shr 2; + B := (PWordArray(Pal)[I] and $001F) shl 3; + end; + 32: + with Palette[I] do + begin + A := PPalette32(Pal)[I].A; + R := PPalette32(Pal)[I].R; + G := PPalette32(Pal)[I].G; + B := PPalette32(Pal)[I].B; + end; + end; + finally + FreeMemNil(Pal); + end; + end; + + case Hdr.ImageType of + 0, 1, 2, 3: + // Load uncompressed mode images + Read(Handle, Bits, Size); + 9, 10, 11: + // Load RLE compressed mode images + LoadRLE; + end; + + // Check if there is alpha channel present in A1R5GB5 images, if it is not + // change format to X1R5G5B5 + if Format = ifA1R5G5B5 then + begin + if not Has16BitImageAlpha(Width * Height, Bits) then + Format := ifX1R5G5B5; + end; + + // We must find true end of file and set input' position to it + // paint programs appends extra info at the end of Targas + // some of them multiple times (PSP Pro 8) + repeat + ExtFound := False; + FooterFound := False; + + if Read(Handle, @WordValue, 2) = 2 then + begin + // 495 = size of Extension Area + if WordValue = 495 then + begin + Seek(Handle, 493, smFromCurrent); + ExtFound := True; + end + else + Seek(Handle, -2, smFromCurrent); + end; + + if Read(Handle, @Foo, SizeOf(Foo)) = SizeOf(Foo) then + begin + if Foo.Signature = STargaSignature then + FooterFound := True + else + Seek(Handle, -SizeOf(Foo), smFromCurrent); + end; + until (not ExtFound) and (not FooterFound); + + // Some editors save targas flipped + if Hdr.Desc < 31 then + FlipImage(Images[0]); + + Result := True; + end; +end; + +function TTargaFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +var + I: LongInt; + Hdr: TTargaHeader; + FmtInfo: TImageFormatInfo; + Pal: PPalette24; + ImageToSave: TImageData; + MustBeFreed: Boolean; + + procedure SaveRLE; + var + Dest: PByte; + WidthBytes, Written, I, Total, DestSize: LongInt; + + function CountDiff(Data: PByte; Bpp, PixelCount: Longint): LongInt; + var + Pixel: LongWord; + NextPixel: LongWord; + N: LongInt; + begin + N := 0; + Pixel := 0; + NextPixel := 0; + if PixelCount = 1 then + begin + Result := PixelCount; + Exit; + end; + case Bpp of + 1: Pixel := Data^; + 2: Pixel := PWord(Data)^; + 3: PColor24Rec(@Pixel)^ := PColor24Rec(Data)^; + 4: Pixel := PLongWord(Data)^; + end; + while PixelCount > 1 do + begin + Inc(Data, Bpp); + case Bpp of + 1: NextPixel := Data^; + 2: NextPixel := PWord(Data)^; + 3: PColor24Rec(@NextPixel)^ := PColor24Rec(Data)^; + 4: NextPixel := PLongWord(Data)^; + end; + if NextPixel = Pixel then + Break; + Pixel := NextPixel; + N := N + 1; + PixelCount := PixelCount - 1; + end; + if NextPixel = Pixel then + Result := N + else + Result := N + 1; + end; + + function CountSame(Data: PByte; Bpp, PixelCount: LongInt): LongInt; + var + Pixel: LongWord; + NextPixel: LongWord; + N: LongInt; + begin + N := 1; + Pixel := 0; + NextPixel := 0; + case Bpp of + 1: Pixel := Data^; + 2: Pixel := PWord(Data)^; + 3: PColor24Rec(@Pixel)^ := PColor24Rec(Data)^; + 4: Pixel := PLongWord(Data)^; + end; + PixelCount := PixelCount - 1; + while PixelCount > 0 do + begin + Inc(Data, Bpp); + case Bpp of + 1: NextPixel := Data^; + 2: NextPixel := PWord(Data)^; + 3: PColor24Rec(@NextPixel)^ := PColor24Rec(Data)^; + 4: NextPixel := PLongWord(Data)^; + end; + if NextPixel <> Pixel then + Break; + N := N + 1; + PixelCount := PixelCount - 1; + end; + Result := N; + end; + + procedure RleCompressLine(Data: PByte; PixelCount, Bpp: LongInt; Dest: + PByte; var Written: LongInt); + const + MaxRun = 128; + var + DiffCount: LongInt; + SameCount: LongInt; + RleBufSize: LongInt; + begin + RleBufSize := 0; + while PixelCount > 0 do + begin + DiffCount := CountDiff(Data, Bpp, PixelCount); + SameCount := CountSame(Data, Bpp, PixelCount); + if (DiffCount > MaxRun) then + DiffCount := MaxRun; + if (SameCount > MaxRun) then + SameCount := MaxRun; + if (DiffCount > 0) then + begin + Dest^ := Byte(DiffCount - 1); + Inc(Dest); + PixelCount := PixelCount - DiffCount; + RleBufSize := RleBufSize + (DiffCount * Bpp) + 1; + Move(Data^, Dest^, DiffCount * Bpp); + Inc(Data, DiffCount * Bpp); + Inc(Dest, DiffCount * Bpp); + end; + if SameCount > 1 then + begin + Dest^ := Byte((SameCount - 1) or $80); + Inc(Dest); + PixelCount := PixelCount - SameCount; + RleBufSize := RleBufSize + Bpp + 1; + Inc(Data, (SameCount - 1) * Bpp); + case Bpp of + 1: Dest^ := Data^; + 2: PWord(Dest)^ := PWord(Data)^; + 3: PColor24Rec(Dest)^ := PColor24Rec(Data)^; + 4: PLongWord(Dest)^ := PLongWord(Data)^; + end; + Inc(Data, Bpp); + Inc(Dest, Bpp); + end; + end; + Written := RleBufSize; + end; + + begin + with ImageToSave do + begin + // Allocate enough space to hold the worst case compression + // result and then compress source's scanlines + WidthBytes := Width * FmtInfo.BytesPerPixel; + DestSize := WidthBytes * Height; + DestSize := DestSize + DestSize div 2 + 1; + GetMem(Dest, DestSize); + Total := 0; + try + for I := 0 to Height - 1 do + begin + RleCompressLine(@PByteArray(Bits)[I * WidthBytes], Width, + FmtInfo.BytesPerPixel, @PByteArray(Dest)[Total], Written); + Total := Total + Written; + end; + GetIO.Write(Handle, Dest, Total); + finally + FreeMem(Dest); + end; + end; + end; + +begin + Result := False; + if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then + with GetIO, ImageToSave do + try + FmtInfo := GetFormatInfo(Format); + // Fill targa header + FillChar(Hdr, SizeOf(Hdr), 0); + Hdr.IDLength := 0; + Hdr.ColorMapType := Iff(FmtInfo.PaletteEntries > 0, 1, 0); + Hdr.Width := Width; + Hdr.Height := Height; + Hdr.PixelSize := FmtInfo.BytesPerPixel * 8; + Hdr.ColorMapLength := FmtInfo.PaletteEntries; + Hdr.ColorEntrySize := Iff(FmtInfo.PaletteEntries > 0, 24, 0); + Hdr.ColorMapOff := 0; + // This indicates that targa is stored in top-left format + // as our images -> no flipping is needed. + Hdr.Desc := 32; + // Set alpha channel size in descriptor (mostly ignored by other software though) + if Format = ifA8R8G8B8 then + Hdr.Desc := Hdr.Desc or 8 + else if Format = ifA1R5G5B5 then + Hdr.Desc := Hdr.Desc or 1; + + // Choose image type + if FmtInfo.IsIndexed then + Hdr.ImageType := Iff(FUseRLE, 9, 1) + else + if FmtInfo.HasGrayChannel then + Hdr.ImageType := Iff(FUseRLE, 11, 3) + else + Hdr.ImageType := Iff(FUseRLE, 10, 2); + + Write(Handle, @Hdr, SizeOf(Hdr)); + + // Write palette + if FmtInfo.PaletteEntries > 0 then + begin + GetMem(Pal, FmtInfo.PaletteEntries * SizeOf(TColor24Rec)); + try + for I := 0 to FmtInfo.PaletteEntries - 1 do + with Pal[I] do + begin + R := Palette[I].R; + G := Palette[I].G; + B := Palette[I].B; + end; + Write(Handle, Pal, FmtInfo.PaletteEntries * SizeOf(TColor24Rec)); + finally + FreeMemNil(Pal); + end; + end; + + if FUseRLE then + // Save rle compressed mode images + SaveRLE + else + // Save uncompressed mode images + Write(Handle, Bits, Size); + + Result := True; + finally + if MustBeFreed then + FreeImage(ImageToSave); + end; +end; + +procedure TTargaFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +var + ConvFormat: TImageFormat; +begin + if Info.HasGrayChannel then + // Convert all grayscale images to Gray8 (preserve alpha of AxGrayx formats) + ConvFormat := IffFormat(not Info.HasAlphaChannel, ifGray8, ifA8R8G8B8) + else if Info.IsIndexed then + // Convert all indexed images to Index8 + ConvFormat := ifIndex8 + else if Info.HasAlphaChannel then + // Convert images with alpha channel to A8R8G8B8 + ConvFormat := ifA8R8G8B8 + else if Info.UsePixelFormat then + // Convert 16bit images (without alpha channel) to A1R5G5B5 + ConvFormat := ifA1R5G5B5 + else + // Convert all other formats to R8G8B8 + ConvFormat := ifR8G8B8; + + ConvertImage(Image, ConvFormat); +end; + +function TTargaFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Hdr: TTargaHeader; + ReadCount: LongInt; +begin + Result := False; + if Handle <> nil then + begin + ReadCount := GetIO.Read(Handle, @Hdr, SizeOf(Hdr)); + GetIO.Seek(Handle, -ReadCount, smFromCurrent); + Result := (ReadCount >= SizeOf(Hdr)) and + (Hdr.ImageType in [0, 1, 2, 3, 9, 10, 11]) and + (Hdr.PixelSize in [1, 8, 15, 16, 24, 32]) and + (Hdr.ColorEntrySize in [0, 16, 24, 32]); + end; +end; + +initialization + RegisterImageFileFormat(TTargaFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - MakeCompatible method moved to base class, put ConvertToSupported here. + GetSupportedFormats removed, it is now set in constructor. + - Made public properties for options registered to SetOption/GetOption + functions. + - Changed extensions to filename masks. + - Changed SaveData, LoadData, and MakeCompatible methods according + to changes in base class in Imaging unit. + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - 16 bit images are usually without alpha but some has alpha + channel and there is no indication of it - so I have added + a check: if all pixels of image are with alpha = 0 image is treated + as X1R5G5B5 otherwise as A1R5G5B5 + - fixed problems with some nonstandard 15 bit images +} + +end. diff --git a/src/lib/vampimg/ImagingTypes.pas b/src/lib/vampimg/ImagingTypes.pas new file mode 100644 index 0000000..9c5e1f1 --- /dev/null +++ b/src/lib/vampimg/ImagingTypes.pas @@ -0,0 +1,564 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains basic types and constants used by Imaging library.} +unit ImagingTypes; + +{$I ImagingOptions.inc} + +interface + +const + { Current Major version of Imaging.} + ImagingVersionMajor = 0; + { Current Minor version of Imaging.} + ImagingVersionMinor = 77; + { Current patch of Imaging.} + ImagingVersionPatch = 2; + + { Imaging Option Ids whose values can be set/get by SetOption/ + GetOption functions.} + + { Defines Jpeg compression quality, ranges from 1 (ugly/small) to 100 (nice/large). + Default value is 90.} + ImagingJpegQuality = 10; + { Specifies whether Jpeg images are saved in progressive format, + can be 0 or 1. Default value is 0.} + ImagingJpegProgressive = 11; + + { Specifies whether Windows Bitmaps are saved using RLE compression + (only for 1/4/8 bit images), can be 0 or 1. Default value is 1.} + ImagingBitmapRLE = 12; + + { Specifies whether Targa images are saved using RLE compression, + can be 0 or 1. Default value is 0.} + ImagingTargaRLE = 13; + + { Value of this option is non-zero if last loaded DDS file was cube map.} + ImagingDDSLoadedCubeMap = 14; + { Value of this option is non-zero if last loaded DDS file was volume texture.} + ImagingDDSLoadedVolume = 15; + { Value of this option is number of mipmap levels of last loaded DDS image.} + ImagingDDSLoadedMipMapCount = 16; + { Value of this option is depth (slices of volume texture or faces of + cube map) of last loaded DDS image.} + ImagingDDSLoadedDepth = 17; + { If it is non-zero next saved DDS file should be stored as cube map.} + ImagingDDSSaveCubeMap = 18; + { If it is non-zero next saved DDS file should be stored as volume texture.} + ImagingDDSSaveVolume = 19; + { Sets the number of mipmaps which should be stored in the next saved DDS file. + Only applies to cube maps and volumes, ordinary 2D textures save all + levels present in input.} + ImagingDDSSaveMipMapCount = 20; + { Sets the depth (slices of volume texture or faces of cube map) + of the next saved DDS file.} + ImagingDDSSaveDepth = 21; + + { Sets precompression filter used when saving PNG images. Allowed values + are: 0 (none), 1 (sub), 2 (up), 3 (average), 4 (paeth), + 5 (use 0 for indexed/gray images and 4 for RGB/ARGB images), + 6 (adaptive filtering - use best filter for each scanline - very slow). + Note that filters 3 and 4 are much slower than filters 1 and 2. + Default value is 5.} + ImagingPNGPreFilter = 25; + { Sets ZLib compression level used when saving PNG images. + Allowed values are in range 0 (no compresstion) to 9 (best compression). + Default value is 5.} + ImagingPNGCompressLevel = 26; + { Boolean option that specifies whether PNG images with more frames (APNG format) + are animated by Imaging (according to frame disposal/blend methods) or just + raw frames are loaded and sent to user (if you want to animate APNG yourself). + Default value is 1.} + ImagingPNGLoadAnimated = 27; + { Sets ZLib compression strategy used when saving PNG files (see deflateInit2() + in ZLib for details). Allowed values are: 0 (default), 1 (filtered), + 2 (huffman only). Default value is 0.} + ImagingPNGZLibStrategy = 28; + + { Specifies whether MNG animation frames are saved with lossy or lossless + compression. Lossless frames are saved as PNG images and lossy frames are + saved as JNG images. Allowed values are 0 (False) and 1 (True). + Default value is 0.} + ImagingMNGLossyCompression = 32; + { Defines whether alpha channel of lossy compressed MNG frames + (when ImagingMNGLossyCompression is 1) is lossy compressed too. + Allowed values are 0 (False) and 1 (True). Default value is 0.} + ImagingMNGLossyAlpha = 33; + { Sets precompression filter used when saving MNG frames as PNG images. + For details look at ImagingPNGPreFilter.} + ImagingMNGPreFilter = 34; + { Sets ZLib compression level used when saving MNG frames as PNG images. + For details look at ImagingPNGCompressLevel.} + ImagingMNGCompressLevel = 35; + { Specifies compression quality used when saving MNG frames as JNG images. + For details look at ImagingJpegQuality.} + ImagingMNGQuality = 36; + { Specifies whether images are saved in progressive format when saving MNG + frames as JNG images. For details look at ImagingJpegProgressive.} + ImagingMNGProgressive = 37; + + { Specifies whether alpha channels of JNG images are lossy compressed. + Allowed values are 0 (False) and 1 (True). Default value is 0.} + ImagingJNGLossyAlpha = 40; + { Sets precompression filter used when saving lossless alpha channels. + For details look at ImagingPNGPreFilter.} + ImagingJNGAlphaPreFilter = 41; + { Sets ZLib compression level used when saving lossless alpha channels. + For details look at ImagingPNGCompressLevel.} + ImagingJNGAlphaCompressLevel = 42; + { Defines compression quality used when saving JNG images (and lossy alpha channels). + For details look at ImagingJpegQuality.} + ImagingJNGQuality = 43; + { Specifies whether JNG images are saved in progressive format. + For details look at ImagingJpegProgressive.} + ImagingJNGProgressive = 44; + + { Specifies whether PGM files are stored in text or in binary format. + Allowed values are 0 (store as text - very! large files) and 1 (save binary). + Default value is 1.} + ImagingPGMSaveBinary = 50; + + { Specifies whether PPM files are stored in text or in binary format. + Allowed values are 0 (store as text - very! large files) and 1 (save binary). + Default value is 1.} + ImagingPPMSaveBinary = 51; + + { Boolean option that specifies whether GIF images with more frames + are animated by Imaging (according to frame disposal methods) or just + raw frames are loaded and sent to user (if you want to animate GIF yourself). + Default value is 1. + Raw frames are 256 color indexed images (ifIndex8), whereas + animated frames are always in 32bit ifA8R8G8B8 format (simplifies animating).} + ImagingGIFLoadAnimated = 56; + + { This option is used when reducing number of colors used in + image (mainly when converting from ARGB image to indexed + format). Mask is 'anded' (bitwise AND) with every pixel's + channel value when creating color histogram. If $FF is used + all 8bits of color channels are used which can result in very + slow proccessing of large images with many colors so you can + use lower masks to speed it up (FC, F8 and F0 are good + choices). Allowed values are in range <0, $FF> and default is + $FE. } + ImagingColorReductionMask = 128; + { This option can be used to override image data format during image + loading. If set to format different from ifUnknown all loaded images + are automaticaly converted to this format. Useful when you have + many files in various formats but you want them all in one format for + further proccessing. Allowed values are in + range and + default value is ifUnknown.} + ImagingLoadOverrideFormat = 129; + { This option can be used to override image data format during image + saving. If set to format different from ifUnknown all images + to be saved are automaticaly internaly converted to this format. + Note that image file formats support only a subset of Imaging data formats + so final saved file may in different format than this override. + Allowed values are in range + and default value is ifUnknown.} + ImagingSaveOverrideFormat = 130; + { Specifies resampling filter used when generating mipmaps. It is used + in GenerateMipMaps low level function and Direct3D and OpenGL extensions. + Allowed values are in range + + and default value is 1 (linear filter).} + ImagingMipMapFilter = 131; + { Specifies treshold value used when automatically converting images to + ifBinary format. For adaptive tresholding see ImagingBinary.pas unit. + Default value is 128 and allowed range is 0..255.} + ImagingBinaryTreshold = 132; + + { Returned by GetOption if given Option Id is invalid.} + InvalidOption = -$7FFFFFFF; + + { Indices that can be used to access channel values in array parts + of structures like TColor32Rec. Note that this order can be + used only for ARGB images. For ABGR image you must swap Red and Blue.} + ChannelBlue = 0; + ChannelGreen = 1; + ChannelRed = 2; + ChannelAlpha = 3; + +type + { Enum defining image data format. In formats with more channels, + first channel after "if" is stored in the most significant bits and channel + before end is stored in the least significant.} + TImageFormat = ( + ifUnknown = 0, + ifDefault = 1, + { Indexed formats using palette } + ifIndex8 = 10, + { Grayscale/Luminance formats } + ifGray8 = 40, + ifA8Gray8 = 41, + ifGray16 = 42, + ifGray32 = 43, + ifGray64 = 44, + ifA16Gray16 = 45, + { ARGB formats } + ifX5R1G1B1 = 80, + ifR3G3B2 = 81, + ifR5G6B5 = 82, + ifA1R5G5B5 = 83, + ifA4R4G4B4 = 84, + ifX1R5G5B5 = 85, + ifX4R4G4B4 = 86, + ifR8G8B8 = 87, + ifA8R8G8B8 = 88, + ifX8R8G8B8 = 89, + ifR16G16B16 = 90, + ifA16R16G16B16 = 91, + ifB16G16R16 = 92, + ifA16B16G16R16 = 93, + { Floating point formats } + ifR32F = 160, + ifA32R32G32B32F = 161, + ifA32B32G32R32F = 162, + ifR16F = 163, + ifA16R16G16B16F = 164, + ifA16B16G16R16F = 165, + ifR32G32B32F = 166, + ifB32G32R32F = 167, + { Special formats } + ifDXT1 = 200, + ifDXT3 = 201, + ifDXT5 = 202, + ifBTC = 203, + ifATI1N = 204, + ifATI2N = 205, + ifBinary = 206 + { Passtrough formats } + {ifETC1 = 220, + ifETC2RGB = 221, + ifETC2RGBA = 222, + ifETC2PA = 223, + ifDXBC6 = 224, + ifDXBC7 = 225} + ); + + { Color value for 32 bit images.} + TColor32 = LongWord; + PColor32 = ^TColor32; + + { Color value for 64 bit images.} + TColor64 = type Int64; + PColor64 = ^TColor64; + + { Color record for 24 bit images, which allows access to individual color + channels.} + TColor24Rec = packed record + case LongInt of + 0: (B, G, R: Byte); + 1: (Channels: array[0..2] of Byte); + end; + PColor24Rec = ^TColor24Rec; + TColor24RecArray = array[0..MaxInt div SizeOf(TColor24Rec) - 1] of TColor24Rec; + PColor24RecArray = ^TColor24RecArray; + + { Color record for 32 bit images, which allows access to individual color + channels.} + TColor32Rec = packed record + case LongInt of + 0: (Color: TColor32); + 1: (B, G, R, A: Byte); + 2: (Channels: array[0..3] of Byte); + 3: (Color24Rec: TColor24Rec); + end; + PColor32Rec = ^TColor32Rec; + TColor32RecArray = array[0..MaxInt div SizeOf(TColor32Rec) - 1] of TColor32Rec; + PColor32RecArray = ^TColor32RecArray; + + { Color record for 48 bit images, which allows access to individual color + channels.} + TColor48Rec = packed record + case LongInt of + 0: (B, G, R: Word); + 1: (Channels: array[0..2] of Word); + end; + PColor48Rec = ^TColor48Rec; + TColor48RecArray = array[0..MaxInt div SizeOf(TColor48Rec) - 1] of TColor48Rec; + PColor48RecArray = ^TColor48RecArray; + + { Color record for 64 bit images, which allows access to individual color + channels.} + TColor64Rec = packed record + case LongInt of + 0: (Color: TColor64); + 1: (B, G, R, A: Word); + 2: (Channels: array[0..3] of Word); + 3: (Color48Rec: TColor48Rec); + end; + PColor64Rec = ^TColor64Rec; + TColor64RecArray = array[0..MaxInt div SizeOf(TColor64Rec) - 1] of TColor64Rec; + PColor64RecArray = ^TColor64RecArray; + + { Color record for 96 bit floating point images, which allows access to + individual color channels.} + TColor96FPRec = packed record + case Integer of + 0: (B, G, R: Single); + 1: (Channels: array[0..2] of Single); + end; + PColor96FPRec = ^TColor96FPRec; + TColor96FPRecArray = array[0..MaxInt div SizeOf(TColor96FPRec) - 1] of TColor96FPRec; + PColor96FPRecArray = ^TColor96FPRecArray; + + { Color record for 128 bit floating point images, which allows access to + individual color channels.} + TColorFPRec = packed record + case LongInt of + 0: (B, G, R, A: Single); + 1: (Channels: array[0..3] of Single); + 2: (Color96Rec: TColor96FPRec); + end; + PColorFPRec = ^TColorFPRec; + TColorFPRecArray = array[0..MaxInt div SizeOf(TColorFPRec) - 1] of TColorFPRec; + PColorFPRecArray = ^TColorFPRecArray; + + { 16 bit floating-point value. It has 1 sign bit, 5 exponent bits, + and 10 mantissa bits.} + THalfFloat = type Word; + PHalfFloat = ^THalfFloat; + + { Color record for 64 bit floating point images, which allows access to + individual color channels.} + TColorHFRec = packed record + case LongInt of + 0: (B, G, R, A: THalfFloat); + 1: (Channels: array[0..3] of THalfFloat); + end; + PColorHFRec = ^TColorHFRec; + TColorHFRecArray = array[0..MaxInt div SizeOf(TColorHFRec) - 1] of TColorHFRec; + PColorHFRecArray = ^TColorHFRecArray; + + { Palette for indexed mode images with 32 bit colors.} + TPalette32 = TColor32RecArray; + TPalette32Size256 = array[0..255] of TColor32Rec; + PPalette32 = ^TPalette32; + + { Palette for indexd mode images with 24 bit colors.} + TPalette24 = TColor24RecArray; + TPalette24Size256 = array[0..255] of TColor24Rec; + PPalette24 = ^TPalette24; + + { Record that stores single image data and information describing it.} + TImageData = packed record + Width: LongInt; // Width of image in pixels + Height: LongInt; // Height of image in pixels + Format: TImageFormat; // Data format of image + Size: LongInt; // Size of image bits in Bytes + Bits: Pointer; // Pointer to memory containing image bits + Palette: PPalette32; // Image palette for indexed images + Tag: Pointer; // User data + end; + PImageData = ^TImageData; + + { Pixel format information used in conversions to/from 16 and 8 bit ARGB + image formats.} + TPixelFormatInfo = packed record + ABitCount, RBitCount, GBitCount, BBitCount: Byte; + ABitMask, RBitMask, GBitMask, BBitMask: LongWord; + AShift, RShift, GShift, BShift: Byte; + ARecDiv, RRecDiv, GRecDiv, BRecDiv: Byte; + end; + PPixelFormatInfo = ^TPixelFormatInfo; + + PImageFormatInfo = ^TImageFormatInfo; + + { Look at TImageFormatInfo.GetPixelsSize for details.} + TFormatGetPixelsSizeFunc = function(Format: TImageFormat; Width, + Height: LongInt): LongInt; + { Look at TImageFormatInfo.CheckDimensions for details.} + TFormatCheckDimensionsProc = procedure(Format: TImageFormat; var Width, + Height: LongInt); + { Function for getting pixel colors. Native pixel is read from Image and + then translated to 32 bit ARGB.} + TGetPixel32Func = function(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32): TColor32Rec; + { Function for getting pixel colors. Native pixel is read from Image and + then translated to FP ARGB.} + TGetPixelFPFunc = function(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32): TColorFPRec; + { Procedure for setting pixel colors. Input 32 bit ARGB color is translated to + native format and then written to Image.} + TSetPixel32Proc = procedure(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32;const Color: TColor32Rec); + { Procedure for setting pixel colors. Input FP ARGB color is translated to + native format and then written to Image.} + TSetPixelFPProc = procedure(Bits: Pointer; Info: PImageFormatInfo; + Palette: PPalette32; const Color: TColorFPRec); + + { Additional information for each TImageFormat value.} + TImageFormatInfo = packed record + Format: TImageFormat; // Format described by this record + Name: array[0..15] of Char; // Symbolic name of format + BytesPerPixel: LongInt; // Number of bytes per pixel (note: it is + // 0 for formats where BitsPerPixel < 8 (e.g. DXT). + // Use GetPixelsSize function to get size of + // image data. + ChannelCount: LongInt; // Number of image channels (R, G, B, A, Gray) + PaletteEntries: LongInt; // Number of palette entries + HasGrayChannel: Boolean; // True if image has grayscale channel + HasAlphaChannel: Boolean; // True if image has alpha channel + IsFloatingPoint: Boolean; // True if image has floating point pixels + UsePixelFormat: Boolean; // True if image uses pixel format + IsRBSwapped: Boolean; // True if Red and Blue channels are swapped + // e.g. A16B16G16R16 has IsRBSwapped True + RBSwapFormat: TImageFormat; // Indicates supported format with swapped + // Red and Blue channels, ifUnknown if such + // format does not exist + IsIndexed: Boolean; // True if image uses palette + IsSpecial: Boolean; // True if image is in special format + IsPasstrough: Boolean; // True if image is in passtrough program (Imaging + // iself doesn't know how to decode and encode it - + // complex texture compressions etc.) + PixelFormat: PPixelFormatInfo; // Pixel format structure + GetPixelsSize: TFormatGetPixelsSizeFunc; // Returns size in bytes of + // Width * Height pixels of image + CheckDimensions: TFormatCheckDimensionsProc; // some formats have limited + // values of Width and Height. This + // procedure checks and changes dimensions + // to be valid for given format. + GetPixel32: TGetPixel32Func; // 32bit ARGB pixel get function + GetPixelFP: TGetPixelFPFunc; // FP ARGB pixel get function + SetPixel32: TSetPixel32Proc; // 32bit ARGB pixel set procedure + SetPixelFP: TSetPixelFPProc; // FP ARGB pixel set procedure + SpecialNearestFormat: TImageFormat; // Regular image format used when + // compressing/decompressing special images + // as source/target + end; + + { Handle to list of image data records.} + TImageDataList = Pointer; + PImageDataList = ^TImageDataList; + + { Handle to input/output.} + TImagingHandle = Pointer; + + { Filters used in functions that resize images or their portions.} + TResizeFilter = ( + rfNearest = 0, + rfBilinear = 1, + rfBicubic = 2, + rfLanczos = 3); + + { Seek origin mode for IO function Seek.} + TSeekMode = ( + smFromBeginning = 0, + smFromCurrent = 1, + smFromEnd = 2); + + TOpenMode = ( + omReadOnly = 0, // Opens file for reading only + omCreate = 1, // Creates new file (overwriting any existing) and opens it for writing + omReadWrite = 2 // Opens for reading and writing. Non existing file is created. + ); + + { IO functions used for reading and writing images from/to input/output.} + TOpenProc = function(Source: PChar; Mode: TOpenMode): TImagingHandle; cdecl; + TCloseProc = procedure(Handle: TImagingHandle); cdecl; + TEofProc = function(Handle: TImagingHandle): Boolean; cdecl; + TSeekProc = function(Handle: TImagingHandle; Offset: LongInt; Mode: TSeekMode): LongInt; cdecl; + TTellProc = function(Handle: TImagingHandle): LongInt; cdecl; + TReadProc = function(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): LongInt; cdecl; + TWriteProc = function(Handle: TImagingHandle; Buffer: Pointer; Count: LongInt): LongInt; cdecl; + +{$IFNDEF FPC} +type +{$IF CompilerVersion <= 18.5} + PtrUInt = LongWord; +{$ELSE} + PtrUInt = NativeUInt; +{$IFEND} +{$ENDIF} + +implementation + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - add lookup tables to pixel formats for fast conversions + + -- 0.77.1 --------------------------------------------------- + - Added "Passtrough" image data formats. + - Added Tag to TImageData for storing user data. + - Added ImagingPNGZLibStrategy option. + - Changed IO functions. Merged open functions to one + and added third open mode R/W (for TIFF append etc.). + - Added new image data formats and related structures: + ifR32G32B32F, ifB32G32G32F. + + -- 0.26.5 Changes/Bug Fixes --------------------------------- + - Added ifBinary image format and ImagingBinaryTreshold option. + - Lanczos filter added to TResizeFilter enum. + + -- 0.24.3 Changes/Bug Fixes --------------------------------- + - Added ifATI1N and ifATI2N image data formats. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added ifBTC image format and SpecialNearestFormat field + to TImageFormatInfo. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Added option constants for PGM and PPM file formats. + - Added TPalette32Size256 and TPalette24Size256 types. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - added ImagingVersionPatch constant so bug fix only releases + can be distinguished from ordinary major/minor releases + - renamed TPixelFormat to TPixelFormatInfo to avoid name collisions + with Graphics.TPixelFormat + - added new image data formats: ifR16F, ifA16R16G16B16F, + ifA16B16G16R16F + - added pixel get/set function pointers to TImageFormatInfo + - added 16bit half float type and color record + - renamed TColorFRec to TColorFPRec (and related types too) + + -- 0.17 Changes/Bug Fixes ----------------------------------- + - added option ImagingMipMapFilter which now controls resampling filter + used when generating mipmaps + - added TResizeFilter type + - added ChannelCount to TImageFormatInfo + - added new option constants for MNG and JNG images + + -- 0.15 Changes/Bug Fixes ----------------------------------- + - added RBSwapFormat to TImageFormatInfo for faster conversions + between swapped formats (it just calls SwapChannels now if + RBSwapFormat is not ifUnknown) + - moved TImageFormatInfo and required types from Imaging unit + here, removed TImageFormatShortInfo + - added new options: ImagingLoadOverrideFormat, ImagingSaveOverrideFormat + + -- 0.13 Changes/Bug Fixes ----------------------------------- + - new ImagingColorReductionMask option added + - new image format added: ifA16Gray16 + +} + +end. diff --git a/src/lib/vampimg/ImagingUtility.pas b/src/lib/vampimg/ImagingUtility.pas new file mode 100644 index 0000000..c137e1d --- /dev/null +++ b/src/lib/vampimg/ImagingUtility.pas @@ -0,0 +1,1691 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains utility functions and types for Imaging library.} +unit ImagingUtility; + +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, Classes, Types; + +const + STrue = 'True'; + SFalse = 'False'; + +type + TByteArray = array[0..MaxInt - 1] of Byte; + PByteArray = ^TByteArray; + TWordArray = array[0..MaxInt div 2 - 1] of Word; + PWordArray = ^TWordArray; + TLongIntArray = array[0..MaxInt div 4 - 1] of LongInt; + PLongIntArray = ^TLongIntArray; + TLongWordArray = array[0..MaxInt div 4 - 1] of LongWord; + PLongWordArray = ^TLongWordArray; + TInt64Array = array[0..MaxInt div 8 - 1] of Int64; + PInt64Array = ^TInt64Array; + TSingleArray = array[0..MaxInt div 4 - 1] of Single; + PSingleArray = ^TSingleArray; + TBooleanArray = array[0..MaxInt - 1] of Boolean; + PBooleanArray = ^TBooleanArray; + + TDynByteArray = array of Byte; + TDynIntegerArray = array of Integer; + TDynBooleanArray = array of Boolean; + TDynStringArray = array of string; + + TWordRec = packed record + case Integer of + 0: (WordValue: Word); + 1: (Low, High: Byte); + end; + PWordRec = ^TWordRec; + TWordRecArray = array[0..MaxInt div 2 - 1] of TWordRec; + PWordRecArray = ^TWordRecArray; + + TLongWordRec = packed record + case Integer of + 0: (LongWordValue: LongWord); + 1: (Low, High: Word); + { Array variants - Index 0 means lowest significant byte (word, ...).} + 2: (Words: array[0..1] of Word); + 3: (Bytes: array[0..3] of Byte); + end; + PLongWordRec = ^TLongWordRec; + TLongWordRecArray = array[0..MaxInt div 4 - 1] of TLongWordRec; + PLongWordRecArray = ^TLongWordRecArray; + + TInt64Rec = packed record + case Integer of + 0: (Int64Value: Int64); + 1: (Low, High: LongWord); + { Array variants - Index 0 means lowest significant byte (word, ...).} + 2: (Words: array[0..3] of Word); + 3: (Bytes: array[0..7] of Byte); + end; + PInt64Rec = ^TInt64Rec; + TInt64RecArray = array[0..MaxInt div 8 - 1] of TInt64Rec; + PInt64RecArray = ^TInt64RecArray; + + TFloatHelper = record + Data: Int64; + case Integer of + 0: (Data64: Int64); + 1: (Data32: LongWord); + end; + PFloatHelper = ^TFloatHelper; + + TFloatRect = record + Left, Top, Right, Bottom: Single; + end; + + TChar2 = array[0..1] of AnsiChar; + TChar3 = array[0..2] of AnsiChar; + TChar4 = array[0..3] of AnsiChar; + TChar8 = array[0..7] of AnsiChar; + TChar16 = array[0..15] of AnsiChar; + TAnsiCharSet = set of AnsiChar; + + ENotImplemented = class(Exception) + public + constructor Create; + end; + + { Options for BuildFileList function: + flFullNames - file names in result will have full path names + (ExtractFileDir(Path) + FileName) + flRelNames - file names in result will have names relative to + ExtractFileDir(Path) dir + flRecursive - adds files in subdirectories found in Path.} + TFileListOption = (flFullNames, flRelNames, flRecursive); + TFileListOptions = set of TFileListOption; + + +{ Frees class instance and sets its reference to nil.} +procedure FreeAndNil(var Obj); +{ Frees pointer and sets it to nil.} +procedure FreeMemNil(var P); {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Replacement of standard System.FreeMem procedure which checks if P is nil + (this is only needed for Free Pascal, Delphi makes checks in its FreeMem).} +procedure FreeMem(P: Pointer); {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns current exception object. Do not call outside exception handler.} +function GetExceptObject: Exception; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns time value with microsecond resolution.} +function GetTimeMicroseconds: Int64; +{ Returns time value with milisecond resolution.} +function GetTimeMilliseconds: Int64; + +{ Returns file extension (without "." dot)} +function GetFileExt(const FileName: string): string; +{ Returns file name of application's executable.} +function GetAppExe: string; +{ Returns directory where application's exceutable is located without + path delimiter at the end.} +function GetAppDir: string; +{ Works like SysUtils.ExtractFileName but supports '/' and '\' dir delimiters + at the same time (whereas ExtractFileName supports on default delimiter on current platform).} +function GetFileName(const FileName: string): string; +{ Works like SysUtils.ExtractFileDir but supports '/' and '\' dir delimiters + at the same time (whereas ExtractFileDir supports on default delimiter on current platform).} +function GetFileDir(const FileName: string): string; +{ Returns True if Subject matches given Mask with optional case sensitivity. + Mask can contain ? and * special characters: ? matches + one character, * matches zero or more characters.} +function StrMaskMatch(const Subject, Mask: string; CaseSensitive: Boolean = False): Boolean; +{ This function fills Files string list with names of files found + with FindFirst/FindNext functions (See details on Path/Atrr here). + - BuildFileList('c:\*.*', faAnyFile, List, [flRecursive]) returns + list of all files (only name.ext - no path) on C drive + - BuildFileList('d:\*.*', faDirectory, List, [flFullNames]) returns + list of all directories (d:\dirxxx) in root of D drive.} +function BuildFileList(Path: string; Attr: LongInt; Files: TStrings; + Options: TFileListOptions = []): Boolean; +{ Similar to RTL's Pos function but with optional Offset where search will start. + This function is in the RTL StrUtils unit but } +function PosEx(const SubStr, S: string; Offset: LongInt = 1): LongInt; +{ Same as PosEx but without case sensitivity.} +function PosNoCase(const SubStr, S: string; Offset: LongInt = 1): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns a sub-string from S which is followed by + Sep separator and deletes the sub-string from S including the separator.} +function StrToken(var S: string; Sep: Char): string; +{ Same as StrToken but searches from the end of S string.} +function StrTokenEnd(var S: string; Sep: Char): string; +{ Fills instance of TStrings with tokens from string S where tokens are separated by + one of Seps characters.} +procedure StrTokensToList(const S: string; Sep: Char; Tokens: TStrings); +{ Returns string representation of integer number (with digit grouping). + Uses current locale.} +function IntToStrFmt(const I: Int64): string; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns string representation of float number (with digit grouping). + Uses current locale.} +function FloatToStrFmt(const F: Double; Precision: Integer = 2): string; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns format settings for parsing floats (dot as decimal separator). + Useful when fomatting/parsing floats etc.} +function GetFormatSettingsForFloats: TFormatSettings; +{ Returns True if S contains at least one of the substrings in SubStrs array. Case sensitive.} +function ContainsAnySubStr(const S: string; const SubStrs: array of string): Boolean; +{ Extracts substring starting at IdxStart ending at IdxEnd. + S[IdxEnd] is not included in the result.} +function SubString(const S: string; IdxStart, IdxEnd: Integer): string; {$IFDEF USE_INLINE}inline;{$ENDIF} + +{ Clamps integer value to range } +function ClampInt(Number: LongInt; Min, Max: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Clamps float value to range } +function ClampFloat(Number: Single; Min, Max: Single): Single; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Clamps integer value to Byte boundaries.} +function ClampToByte(Value: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Clamps integer value to Word boundaries.} +function ClampToWord(Value: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns True if Num is power of 2.} +function IsPow2(Num: LongInt): Boolean; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns next power of 2 greater than or equal to Num + (if Num itself is power of 2 then it retuns Num).} +function NextPow2(Num: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Raises 2 to the given integer power (in range [0, 30]).} +function Pow2Int(Exponent: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Raises Base to any power.} +function Power(const Base, Exponent: Single): Single; +{ Returns log base 2 of integer X (max 2^30) or -1 if X is not power of 2.} +function Log2Int(X: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns log base 2 of X.} +function Log2(X: Single): Single; +{ Returns log base 10 of X.} +function Log10(X: Single): Single; +{ Returns largest integer <= Val (for 5.9 returns 5).} +function Floor(Value: Single): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns smallest integer >= Val (for 5.1 returns 6).} +function Ceil(Value: Single): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns lesser of two integer numbers.} +function Min(A, B: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns lesser of two float numbers.} +function MinFloat(A, B: Single): Single; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns greater of two integer numbers.} +function Max(A, B: LongInt): LongInt; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns greater of two float numbers.} +function MaxFloat(A, B: Single): Single; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns result from multiplying Number by Numerator and then dividing by Denominator. + Denominator must be greater than 0.} +function MulDiv(Number, Numerator, Denominator: Word): Word; {$IFDEF USE_INLINE}inline;{$ENDIF} + +{ Switches Boolean value.} +procedure Switch(var Value: Boolean); {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function Iff(Condition: Boolean; TruePart, FalsePart: LongInt): LongInt; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function IffUnsigned(Condition: Boolean; TruePart, FalsePart: LongWord): LongWord; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function Iff(Condition, TruePart, FalsePart: Boolean): Boolean; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function Iff(Condition: Boolean; const TruePart, FalsePart: string): string; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function Iff(Condition: Boolean; TruePart, FalsePart: Char): Char; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function Iff(Condition: Boolean; TruePart, FalsePart: Pointer): Pointer; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function Iff(Condition: Boolean; const TruePart, FalsePart: Int64): Int64; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ If Condition is True then TruePart is retured, otherwise + FalsePart is returned.} +function IffFloat(Condition: Boolean; TruePart, FalsePart: Single): Single; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Swaps two Boolean values} +procedure SwapValues(var A, B: Boolean); overload; +{ Swaps two Byte values} +procedure SwapValues(var A, B: Byte); overload; +{ Swaps two Word values} +procedure SwapValues(var A, B: Word); overload; +{ Swaps two LongInt values} +procedure SwapValues(var A, B: LongInt); overload; +{ Swaps two Single values} +procedure SwapValues(var A, B: Single); overload; +{ Swaps two LongInt values if necessary to ensure that Min <= Max.} +procedure SwapMin(var Min, Max: LongInt); {$IFDEF USE_INLINE}inline;{$ENDIF} +{ This function returns True if running on little endian machine.} +function IsLittleEndian: Boolean; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Swaps byte order of Word value.} +function SwapEndianWord(Value: Word): Word; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Swaps byte order of multiple Word values.} +procedure SwapEndianWord(P: PWordArray; Count: LongInt); overload; +{ Swaps byte order of LongWord value.} +function SwapEndianLongWord(Value: LongWord): LongWord; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Swaps byte order of multiple LongWord values.} +procedure SwapEndianLongWord(P: PLongWord; Count: LongInt); overload; + +{ Calculates CRC32 for the given data.} +procedure CalcCrc32(var Crc: LongWord; Data: Pointer; Size: LongInt); +{ Fills given memory with given Byte value. Size is size of buffer in bytes.} +procedure FillMemoryByte(Data: Pointer; Size: LongInt; Value: Byte); +{ Fills given memory with given Word value. Size is size of buffer in bytes.} +procedure FillMemoryWord(Data: Pointer; Size: LongInt; Value: Word); +{ Fills given memory with given LongWord value. Size is size of buffer in bytes.} +procedure FillMemoryLongWord(Data: Pointer; Size: LongInt; Value: LongWord); +{ Fills given memory zeroes.} +{$EXTERNALSYM ZeroMemory} // Conflicts with WinAPI ZeroMemory in C++ Builder +procedure ZeroMemory(Data: Pointer; Size: Integer); {$IFDEF USE_INLINE}inline;{$ENDIF} + +{ Returns how many mipmap levels can be created for image of given size.} +function GetNumMipMapLevels(Width, Height: LongInt): LongInt; +{ Returns total number of levels of volume texture with given depth and + mipmap count (this is not depth * mipmaps!).} +function GetVolumeLevelCount(Depth, MipMaps: LongInt): LongInt; +{ Returns rectangle (X, Y, X + Width, Y + Height).} +function BoundsToRect(X, Y, Width, Height: LongInt): TRect; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns rectangle (R.Left, R.Top, R.Left + R.Right, R.Top + R.Bottom).} +function BoundsToRect(const R: TRect): TRect; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Returns rectangle (R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top).} +function RectToBounds(const R: TRect): TRect; overload; {$IFDEF USE_INLINE}inline;{$ENDIF} +{ Clips given bounds to Clip rectangle.} +procedure ClipRectBounds(var X, Y, Width, Height: LongInt; const Clip: TRect); +{ Clips given source bounds and dest position. It is used by various CopyRect + functions that copy rect from one image to another. It handles clipping the same way + as Win32 BitBlt function. } +procedure ClipCopyBounds(var SrcX, SrcY, Width, Height, DstX, DstY: LongInt; + SrcImageWidth, SrcImageHeight: LongInt; const DstClip: TRect); +{ Clips given source bounds and dest bounds. It is used by various StretchRect + functions that stretch rectangle of pixels from one image to another. + It handles clipping the same way as Win32 StretchBlt function. } +procedure ClipStretchBounds(var SrcX, SrcY, SrcWidth, SrcHeight, DstX, DstY, + DstWidth, DstHeight: LongInt; SrcImageWidth, SrcImageHeight: LongInt; const DstClip: TRect); +{ Scales one rectangle to fit into another. Proportions are preserved so + it could be used for 'Stretch To Fit Window' image drawing for instance.} +function ScaleRectToRect(const SourceRect, TargetRect: TRect): TRect; +{ Scales given size to fit into max size while keeping the original ascpect ration. + Useful for calculating thumbnail dimensions etc.} +function ScaleSizeToFit(const CurrentSize, MaxSize: TSize): TSize; +{ Returns width of given rect. Part of RTL in newer Delphi.} +function RectWidth(const Rect: TRect): Integer; +{ Returns height of given rect. Part of RTL in newer Delphi.} +function RectHeight(const Rect: TRect): Integer; +{ Returns True if R1 fits into R2.} +function RectInRect(const R1, R2: TRect): Boolean; +{ Returns True if R1 and R2 intersects.} +function RectIntersects(const R1, R2: TRect): Boolean; + +{ Converts pixel size in micrometers to corrensponding DPI.} +function PixelSizeToDpi(SizeInMicroMeters: Single): Single; +{ Converts DPI to corrensponding pixel size in micrometers.} +function DpiToPixelSize(Dpi: Single): Single; + +function FloatRect(ALeft, ATop, ARight, ABottom: Single): TFloatRect; +function FloatRectWidth(const R: TFloatRect): Single; +function FloatRectHeight(const R: TFloatRect): Single; + +{ Formats given message for usage in Exception.Create(..). Use only + in except block - returned message contains message of last raised exception.} +function FormatExceptMsg(const Msg: string; const Args: array of const): string; +{ Outputs debug message - shows message dialog in Windows and writes to console + in Linux/Unix.} +procedure DebugMsg(const Msg: string; const Args: array of const); + +implementation + +uses +{$IF Defined(MSWINDOWS)} + Windows; +{$ELSEIF Defined(FPC)} + Dos, BaseUnix, Unix; +{$ELSEIF Defined(DELPHI)} + Posix.SysTime; +{$IFEND} + +var + FloatFormatSettings: TFormatSettings; + +constructor ENotImplemented.Create; +begin + inherited Create('Not implemented'); +end; + +procedure FreeAndNil(var Obj); +var + Temp: TObject; +begin + Temp := TObject(Obj); + Pointer(Obj) := nil; + Temp.Free; +end; + +procedure FreeMemNil(var P); +begin + FreeMem(Pointer(P)); + Pointer(P) := nil; +end; + +procedure FreeMem(P: Pointer); +begin + if P <> nil then + System.FreeMem(P); +end; + +function GetExceptObject: Exception; +begin + Result := Exception(ExceptObject); +end; + +{$IF Defined(MSWINDOWS)} +var + PerfFrequency: Int64; + InvPerfFrequency: Single; + +function GetTimeMicroseconds: Int64; +var + Time: Int64; +begin + QueryPerformanceCounter(Time); + Result := Round(1000000 * InvPerfFrequency * Time); +end; +{$ELSEIF Defined(DELPHI)} +function GetTimeMicroseconds: Int64; +var + Time: TimeVal; +begin + Posix.SysTime.GetTimeOfDay(Time, nil); + Result := Int64(Time.tv_sec) * 1000000 + Time.tv_usec; +end; +{$ELSEIF Defined(FPC)} +function GetTimeMicroseconds: Int64; +var + TimeVal: TTimeVal; +begin + fpGetTimeOfDay(@TimeVal, nil); + Result := Int64(TimeVal.tv_sec) * 1000000 + TimeVal.tv_usec; +end; +{$IFEND} + +function GetTimeMilliseconds: Int64; +begin + Result := GetTimeMicroseconds div 1000; +end; + +function GetFileExt(const FileName: string): string; +begin + Result := ExtractFileExt(FileName); + if Length(Result) > 1 then + Delete(Result, 1, 1); +end; + +function GetAppExe: string; +{$IF Defined(MSWINDOWS)} +var + FileName: array[0..MAX_PATH] of Char; +begin + SetString(Result, FileName, + Windows.GetModuleFileName(MainInstance, FileName, SizeOf(FileName))); +{$ELSEIF Defined(DELPHI)} // Delphi non Win targets +var + FileName: array[0..1024] of Char; +begin + SetString(Result, FileName, + System.GetModuleFileName(MainInstance, FileName, SizeOf(FileName))); +{$ELSE} +begin + Result := ParamStr(0); +{$IFEND} +end; + +function GetAppDir: string; +begin + Result := ExtractFileDir(GetAppExe); +end; + +function GetFileName(const FileName: string): string; +var + I: Integer; +begin + I := LastDelimiter('\/' + DriveDelim, FileName); + Result := Copy(FileName, I + 1, MaxInt); +end; + +function GetFileDir(const FileName: string): string; +const + Delims = '\/' + DriveDelim; +var + I: Integer; +begin + I := LastDelimiter(Delims, Filename); + if (I > 1) and + ((FileName[I] = Delims[1]) or (FileName[I] = Delims[2])) and + (not IsDelimiter(Delims, FileName, I - 1)) then Dec(I); + Result := Copy(FileName, 1, I); +end; + +function StrMaskMatch(const Subject, Mask: string; CaseSensitive: Boolean): Boolean; +var + MaskLen, KeyLen : LongInt; + + function CharMatch(A, B: Char): Boolean; + begin + if CaseSensitive then + Result := A = B + else + Result := AnsiUpperCase (A) = AnsiUpperCase (B); + end; + + function MatchAt(MaskPos, KeyPos: LongInt): Boolean; + begin + while (MaskPos <= MaskLen) and (KeyPos <= KeyLen) do + begin + case Mask[MaskPos] of + '?' : + begin + Inc(MaskPos); + Inc(KeyPos); + end; + '*' : + begin + while (MaskPos <= MaskLen) and (Mask[MaskPos] = '*') do + Inc(MaskPos); + if MaskPos > MaskLen then + begin + Result := True; + Exit; + end; + repeat + if MatchAt(MaskPos, KeyPos) then + begin + Result := True; + Exit; + end; + Inc(KeyPos); + until KeyPos > KeyLen; + Result := False; + Exit; + end; + else + if not CharMatch(Mask[MaskPos], Subject[KeyPos]) then + begin + Result := False; + Exit; + end + else + begin + Inc(MaskPos); + Inc(KeyPos); + end; + end; + end; + + while (MaskPos <= MaskLen) and (AnsiChar(Mask[MaskPos]) in ['?', '*']) do + Inc(MaskPos); + if (MaskPos <= MaskLen) or (KeyPos <= KeyLen) then + begin + Result := False; + Exit; + end; + + Result := True; + end; + +begin + MaskLen := Length(Mask); + KeyLen := Length(Subject); + if MaskLen = 0 then + begin + Result := True; + Exit; + end; + Result := MatchAt(1, 1); +end; + +function BuildFileList(Path: string; Attr: LongInt; + Files: TStrings; Options: TFileListOptions): Boolean; +var + FileMask: string; + RootDir: string; + Folders: TStringList; + CurrentItem: LongInt; + Counter: LongInt; + LocAttr: LongInt; + + procedure BuildFolderList; + var + FindInfo: TSearchRec; + Rslt: LongInt; + begin + Counter := Folders.Count - 1; + CurrentItem := 0; + while CurrentItem <= Counter do + begin + // Searching for subfolders + Rslt := SysUtils.FindFirst(Folders[CurrentItem] + '*', faDirectory, FindInfo); + try + while Rslt = 0 do + begin + if (FindInfo.Name <> '.') and (FindInfo.Name <> '..') and + (FindInfo.Attr and faDirectory = faDirectory) then + Folders.Add(Folders[CurrentItem] + FindInfo.Name + PathDelim); + Rslt := SysUtils.FindNext(FindInfo); + end; + finally + SysUtils.FindClose(FindInfo); + end; + Counter := Folders.Count - 1; + Inc(CurrentItem); + end; + end; + + procedure FillFileList(CurrentCounter: LongInt); + var + FindInfo: TSearchRec; + Res: LongInt; + CurrentFolder: string; + begin + CurrentFolder := Folders[CurrentCounter]; + Res := SysUtils.FindFirst(CurrentFolder + FileMask, LocAttr, FindInfo); + if flRelNames in Options then + CurrentFolder := ExtractRelativePath(RootDir, CurrentFolder); + try + while Res = 0 do + begin + if (FindInfo.Name <> '.') and (FindInfo.Name <> '..') then + begin + if (flFullNames in Options) or (flRelNames in Options) then + Files.Add(CurrentFolder + FindInfo.Name) + else + Files.Add(FindInfo.Name); + end; + Res := SysUtils.FindNext(FindInfo); + end; + finally + SysUtils.FindClose(FindInfo); + end; + end; + +begin + FileMask := ExtractFileName(Path); + RootDir := ExtractFilePath(Path); + Folders := TStringList.Create; + Folders.Add(RootDir); + Files.Clear; +{$IFDEF DCC} + {$WARN SYMBOL_PLATFORM OFF} +{$ENDIF} + if Attr = faAnyFile then + LocAttr := faSysFile or faHidden or faArchive or faReadOnly + else + LocAttr := Attr; +{$IFDEF DCC} + {$WARN SYMBOL_PLATFORM ON} +{$ENDIF} + // Here's the recursive search for nested folders + if flRecursive in Options then + BuildFolderList; + if Attr <> faDirectory then + for Counter := 0 to Folders.Count - 1 do + FillFileList(Counter) + else + Files.AddStrings(Folders); + Folders.Free; + Result := True; +end; + +function PosEx(const SubStr, S: string; Offset: LongInt = 1): LongInt; +var + I, X: LongInt; + Len, LenSubStr: LongInt; +begin + I := Offset; + LenSubStr := Length(SubStr); + Len := Length(S) - LenSubStr + 1; + while I <= Len do + begin + if S[I] = SubStr[1] then + begin + X := 1; + while (X < LenSubStr) and (S[I + X] = SubStr[X + 1]) do + Inc(X); + if (X = LenSubStr) then + begin + Result := I; + Exit; + end; + end; + Inc(I); + end; + Result := 0; +end; + +function PosNoCase(const SubStr, S: string; Offset: LongInt): LongInt; +begin + Result := PosEx(AnsiLowerCase(SubStr), AnsiLowerCase(S), Offset); +end; + +function StrToken(var S: string; Sep: Char): string; +var + I: LongInt; +begin + I := Pos(Sep, S); + if I <> 0 then + begin + Result := Copy(S, 1, I - 1); + Delete(S, 1, I); + end + else + begin + Result := S; + S := ''; + end; +end; + +function StrTokenEnd(var S: string; Sep: Char): string; +var + I, J: LongInt; +begin + J := 0; + I := Pos(Sep, S); + while I <> 0 do + begin + J := I; + I := PosEx(Sep, S, J + 1); + end; + if J <> 0 then + begin + Result := Copy(S, J + 1, MaxInt); + Delete(S, J, MaxInt); + end + else + begin + Result := S; + S := ''; + end; +end; + +procedure StrTokensToList(const S: string; Sep: Char; Tokens: TStrings); +var + Token, Str: string; +begin + Tokens.Clear; + Str := S; + while Str <> '' do + begin + Token := StrToken(Str, Sep); + Tokens.Add(Token); + end; +end; + +function IntToStrFmt(const I: Int64): string; +begin + Result := Format('%.0n', [I * 1.0]); +end; + +function FloatToStrFmt(const F: Double; Precision: Integer): string; +begin + Result := Format('%.' + IntToStr(Precision) + 'n', [F]); +end; + +function GetFormatSettingsForFloats: TFormatSettings; +begin + Result := FloatFormatSettings; +end; + +function ContainsAnySubStr(const S: string; const SubStrs: array of string): Boolean; +var + I: Integer; +begin + Result := False; + for I := 0 to High(SubStrs) do + begin + Result := Pos(SubStrs[I], S) > 0; + if Result then + Exit; + end; +end; + +function SubString(const S: string; IdxStart, IdxEnd: Integer): string; +begin + Result := Copy(S, IdxStart, IdxEnd - IdxStart); +end; + +function ClampInt(Number: LongInt; Min, Max: LongInt): LongInt; +begin + Result := Number; + if Result < Min then + Result := Min + else if Result > Max then + Result := Max; +end; + +function ClampFloat(Number: Single; Min, Max: Single): Single; +begin + Result := Number; + if Result < Min then + Result := Min + else if Result > Max then + Result := Max; +end; + +function ClampToByte(Value: LongInt): LongInt; +begin + Result := Value; + if Result > 255 then + Result := 255 + else if Result < 0 then + Result := 0; +end; + +function ClampToWord(Value: LongInt): LongInt; +begin + Result := Value; + if Result > 65535 then + Result := 65535 + else if Result < 0 then + Result := 0; +end; + +function IsPow2(Num: LongInt): Boolean; +begin + Result := (Num and -Num) = Num; +end; + +function NextPow2(Num: LongInt): LongInt; +begin + Result := Num and -Num; + while Result < Num do + Result := Result shl 1; +end; + +function Pow2Int(Exponent: LongInt): LongInt; +begin + Result := 1 shl Exponent; +end; + +function Power(const Base, Exponent: Single): Single; +begin + if Exponent = 0.0 then + Result := 1.0 + else if (Base = 0.0) and (Exponent > 0.0) then + Result := 0.0 + else + Result := Exp(Exponent * Ln(Base)); +end; + +function Log2Int(X: LongInt): LongInt; +begin + case X of + 1: Result := 0; + 2: Result := 1; + 4: Result := 2; + 8: Result := 3; + 16: Result := 4; + 32: Result := 5; + 64: Result := 6; + 128: Result := 7; + 256: Result := 8; + 512: Result := 9; + 1024: Result := 10; + 2048: Result := 11; + 4096: Result := 12; + 8192: Result := 13; + 16384: Result := 14; + 32768: Result := 15; + 65536: Result := 16; + 131072: Result := 17; + 262144: Result := 18; + 524288: Result := 19; + 1048576: Result := 20; + 2097152: Result := 21; + 4194304: Result := 22; + 8388608: Result := 23; + 16777216: Result := 24; + 33554432: Result := 25; + 67108864: Result := 26; + 134217728: Result := 27; + 268435456: Result := 28; + 536870912: Result := 29; + 1073741824: Result := 30; + else + Result := -1; + end; +end; + +function Log2(X: Single): Single; +{$IFDEF USE_ASM} +asm + FLD1 + FLD X + FYL2X + FWAIT +end; +{$ELSE} +const + Ln2: Single = 0.6931471; +begin + Result := Ln(X) / Ln2; +end; +{$ENDIF} + +function Log10(X: Single): Single; +{$IFDEF USE_ASM} +asm + FLDLG2 + FLD X + FYL2X + FWAIT +end; +{$ELSE} +const + Ln10: Single = 2.30258509299405; +begin + Result := Ln(X) / Ln10; +end; +{$ENDIF} + +function Floor(Value: Single): LongInt; +begin + Result := Trunc(Value); + if Frac(Value) < 0.0 then + Dec(Result); +end; + +function Ceil(Value: Single): LongInt; +begin + Result := Trunc(Value); + if Frac(Value) > 0.0 then + Inc(Result); +end; + +procedure Switch(var Value: Boolean); +begin + Value := not Value; +end; + +function Iff(Condition: Boolean; TruePart, FalsePart: LongInt): LongInt; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +function IffUnsigned(Condition: Boolean; TruePart, FalsePart: LongWord): LongWord; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +function Iff(Condition, TruePart, FalsePart: Boolean): Boolean; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +function Iff(Condition: Boolean; const TruePart, FalsePart: string): string; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +function Iff(Condition: Boolean; TruePart, FalsePart: Char): Char; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +function Iff(Condition: Boolean; TruePart, FalsePart: Pointer): Pointer; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +function Iff(Condition: Boolean; const TruePart, FalsePart: Int64): Int64; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +function IffFloat(Condition: Boolean; TruePart, FalsePart: Single): Single; +begin + if Condition then + Result := TruePart + else + Result := FalsePart; +end; + +procedure SwapValues(var A, B: Boolean); +var + Tmp: Boolean; +begin + Tmp := A; + A := B; + B := Tmp; +end; + +procedure SwapValues(var A, B: Byte); +var + Tmp: Byte; +begin + Tmp := A; + A := B; + B := Tmp; +end; + +procedure SwapValues(var A, B: Word); +var + Tmp: Word; +begin + Tmp := A; + A := B; + B := Tmp; +end; + +procedure SwapValues(var A, B: LongInt); +var + Tmp: LongInt; +begin + Tmp := A; + A := B; + B := Tmp; +end; + +procedure SwapValues(var A, B: Single); +var + Tmp: Single; +begin + Tmp := A; + A := B; + B := Tmp; +end; + +procedure SwapMin(var Min, Max: LongInt); +var + Tmp: LongInt; +begin + if Min > Max then + begin + Tmp := Min; + Min := Max; + Max := Tmp; + end; +end; + +function Min(A, B: LongInt): LongInt; +begin + if A < B then + Result := A + else + Result := B; +end; + +function MinFloat(A, B: Single): Single; +begin + if A < B then + Result := A + else + Result := B; +end; + +function Max(A, B: LongInt): LongInt; +begin + if A > B then + Result := A + else + Result := B; +end; + +function MaxFloat(A, B: Single): Single; +begin + if A > B then + Result := A + else + Result := B; +end; + +function MulDiv(Number, Numerator, Denominator: Word): Word; +{$IF Defined(USE_ASM) and (not Defined(USE_INLINE))} +asm + MUL DX + DIV CX +end; +{$ELSE} +begin + Result := Number * Numerator div Denominator; +end; +{$IFEND} + +function IsLittleEndian: Boolean; +var + W: Word; +begin + W := $00FF; + Result := PByte(@W)^ = $FF; +end; + +function SwapEndianWord(Value: Word): Word; +{$IF Defined(USE_ASM) and (not Defined(USE_INLINE))} +asm + XCHG AH, AL +end; +{$ELSE} +begin + TWordRec(Result).Low := TWordRec(Value).High; + TWordRec(Result).High := TWordRec(Value).Low; +end; +{$IFEND} + +procedure SwapEndianWord(P: PWordArray; Count: LongInt); +{$IFDEF USE_ASM} +asm +@Loop: + MOV CX, [EAX] + XCHG CH, CL + MOV [EAX], CX + ADD EAX, 2 + DEC EDX + JNZ @Loop +end; +{$ELSE} +var + I: LongInt; + Temp: Word; +begin + for I := 0 to Count - 1 do + begin + Temp := P[I]; + TWordRec(P[I]).Low := TWordRec(Temp).High; + TWordRec(P[I]).High := TWordRec(Temp).Low; + end; +end; +{$ENDIF} + +function SwapEndianLongWord(Value: LongWord): LongWord; +{$IF Defined(USE_ASM) and (not Defined(USE_INLINE))} +asm + BSWAP EAX +end; +{$ELSE} +begin + TLongWordRec(Result).Bytes[0] := TLongWordRec(Value).Bytes[3]; + TLongWordRec(Result).Bytes[1] := TLongWordRec(Value).Bytes[2]; + TLongWordRec(Result).Bytes[2] := TLongWordRec(Value).Bytes[1]; + TLongWordRec(Result).Bytes[3] := TLongWordRec(Value).Bytes[0]; +end; +{$IFEND} + +procedure SwapEndianLongWord(P: PLongWord; Count: LongInt); +{$IFDEF USE_ASM} +asm +@Loop: + MOV ECX, [EAX] + BSWAP ECX + MOV [EAX], ECX + ADD EAX, 4 + DEC EDX + JNZ @Loop +end; +{$ELSE} +var + I: LongInt; + Temp: LongWord; +begin + for I := 0 to Count - 1 do + begin + Temp := PLongWordArray(P)[I]; + TLongWordRec(PLongWordArray(P)[I]).Bytes[0] := TLongWordRec(Temp).Bytes[3]; + TLongWordRec(PLongWordArray(P)[I]).Bytes[1] := TLongWordRec(Temp).Bytes[2]; + TLongWordRec(PLongWordArray(P)[I]).Bytes[2] := TLongWordRec(Temp).Bytes[1]; + TLongWordRec(PLongWordArray(P)[I]).Bytes[3] := TLongWordRec(Temp).Bytes[0]; + end; +end; +{$ENDIF} + +type + TCrcTable = array[Byte] of LongWord; +var + CrcTable: TCrcTable; + +procedure InitCrcTable; +const + Polynom = $EDB88320; +var + I, J: LongInt; + C: LongWord; +begin + for I := 0 to 255 do + begin + C := I; + for J := 0 to 7 do + begin + if (C and $01) <> 0 then + C := Polynom xor (C shr 1) + else + C := C shr 1; + end; + CrcTable[I] := C; + end; +end; + +procedure CalcCrc32(var Crc: LongWord; Data: Pointer; Size: LongInt); +var + I: LongInt; + B: PByte; +begin + B := Data; + for I := 0 to Size - 1 do + begin + Crc := (Crc shr 8) xor CrcTable[B^ xor Byte(Crc)]; + Inc(B); + end +end; + +procedure FillMemoryByte(Data: Pointer; Size: LongInt; Value: Byte); +{$IFDEF USE_ASM} +asm + PUSH EDI + MOV EDI, EAX + MOV EAX, ECX + MOV AH, AL + MOV CX, AX + SHL EAX, 16 + MOV AX, CX + MOV ECX, EDX + SAR ECX, 2 + JS @Exit + REP STOSD + MOV ECX, EDX + AND ECX, 3 + REP STOSB + POP EDI +@Exit: +end; +{$ELSE} +begin + FillChar(Data^, Size, Value); +end; +{$ENDIF} + +procedure FillMemoryWord(Data: Pointer; Size: LongInt; Value: Word); +{$IFDEF USE_ASM} +asm + PUSH EDI + PUSH EBX + MOV EBX, EDX + MOV EDI, EAX + MOV EAX, ECX + MOV CX, AX + SHL EAX, 16 + MOV AX, CX + MOV ECX, EDX + SHR ECX, 2 + JZ @Word + REP STOSD +@Word: + MOV ECX, EBX + AND ECX, 2 + JZ @Byte + MOV [EDI], AX + ADD EDI, 2 +@Byte: + MOV ECX, EBX + AND ECX, 1 + JZ @Exit + MOV [EDI], AL +@Exit: + POP EBX + POP EDI +end; +{$ELSE} +var + I, V: LongWord; +begin + V := Value * $10000 + Value; + for I := 0 to Size div 4 - 1 do + PLongWordArray(Data)[I] := V; + case Size mod 4 of + 1: PByteArray(Data)[Size - 1] := Lo(Value); + 2: PWordArray(Data)[Size div 2] := Value; + 3: + begin + PWordArray(Data)[Size div 2 - 1] := Value; + PByteArray(Data)[Size - 1] := Lo(Value); + end; + end; +end; +{$ENDIF} + +procedure FillMemoryLongWord(Data: Pointer; Size: LongInt; Value: LongWord); +{$IFDEF USE_ASM} +asm + PUSH EDI + PUSH EBX + MOV EBX, EDX + MOV EDI, EAX + MOV EAX, ECX + MOV ECX, EDX + SHR ECX, 2 + JZ @Word + REP STOSD +@Word: + MOV ECX, EBX + AND ECX, 2 + JZ @Byte + MOV [EDI], AX + ADD EDI, 2 +@Byte: + MOV ECX, EBX + AND ECX, 1 + JZ @Exit + MOV [EDI], AL +@Exit: + POP EBX + POP EDI +end; +{$ELSE} +var + I: LongInt; +begin + for I := 0 to Size div 4 - 1 do + PLongWordArray(Data)[I] := Value; + case Size mod 4 of + 1: PByteArray(Data)[Size - 1] := TLongWordRec(Value).Bytes[0]; + 2: PWordArray(Data)[Size div 2] := TLongWordRec(Value).Words[0]; + 3: + begin + PWordArray(Data)[Size div 2 - 1] := TLongWordRec(Value).Words[0]; + PByteArray(Data)[Size - 1] := TLongWordRec(Value).Bytes[0]; + end; + end; +end; +{$ENDIF} + +procedure ZeroMemory(Data: Pointer; Size: Integer); +begin + FillMemoryByte(Data, Size, 0); +end; + +function GetNumMipMapLevels(Width, Height: LongInt): LongInt; +begin + Result := 0; + if (Width > 0) and (Height > 0) then + begin + Result := 1; + while (Width <> 1) or (Height <> 1) do + begin + Width := Width div 2; + Height := Height div 2; + if Width < 1 then Width := 1; + if Height < 1 then Height := 1; + Inc(Result); + end; + end; +end; + +function GetVolumeLevelCount(Depth, MipMaps: LongInt): LongInt; +var + I: LongInt; +begin + Result := Depth; + for I := 1 to MipMaps - 1 do + Inc(Result, ClampInt(Depth shr I, 1, Depth)); +end; + +function BoundsToRect(X, Y, Width, Height: LongInt): TRect; +begin + Result.Left := X; + Result.Top := Y; + Result.Right := X + Width; + Result.Bottom := Y + Height; +end; + +function BoundsToRect(const R: TRect): TRect; +begin + Result.Left := R.Left; + Result.Top := R.Top; + Result.Right := R.Left + R.Right; + Result.Bottom := R.Top + R.Bottom; +end; + +function RectToBounds(const R: TRect): TRect; +begin + Result.Left := R.Left; + Result.Top := R.Top; + Result.Right := R.Right - R.Left; + Result.Bottom := R.Bottom - R.Top; +end; + +procedure ClipRectBounds(var X, Y, Width, Height: LongInt; const Clip: TRect); + + procedure ClipDim(var AStart, ALength: LongInt; ClipMin, ClipMax: LongInt); + begin + if AStart < ClipMin then + begin + ALength := ALength - (ClipMin - AStart); + AStart := ClipMin; + end; + if AStart + ALength > ClipMax then ALength := Max(0, ClipMax - AStart); + end; + +begin + ClipDim(X, Width, Clip.Left, Clip.Right); + ClipDim(Y, Height, Clip.Top, Clip.Bottom); +end; + +procedure ClipCopyBounds(var SrcX, SrcY, Width, Height, DstX, DstY: LongInt; SrcImageWidth, SrcImageHeight: LongInt; const DstClip: TRect); + + procedure ClipDim(var SrcPos, DstPos, Size: LongInt; SrcClipMax, + DstClipMin, DstClipMax: LongInt); + var + OldDstPos: LongInt; + Diff: LongInt; + begin + OldDstPos := Iff(DstPos < 0, DstPos, 0); + if DstPos < DstClipMin then + begin + Diff := DstClipMin - DstPos; + Size := Size - Diff; + SrcPos := SrcPos + Diff; + DstPos := DstClipMin; + end; + if SrcPos < 0 then + begin + Size := Size + SrcPos - OldDstPos; + DstPos := DstPos - SrcPos + OldDstPos; + SrcPos := 0; + end; + if SrcPos + Size > SrcClipMax then Size := SrcClipMax - SrcPos; + if DstPos + Size > DstClipMax then Size := DstClipMax - DstPos; + end; + +begin + ClipDim(SrcX, DstX, Width, SrcImageWidth, DstClip.Left, DstClip.Right); + ClipDim(SrcY, DstY, Height, SrcImageHeight, DstClip.Top, DstClip.Bottom); +end; + +procedure ClipStretchBounds(var SrcX, SrcY, SrcWidth, SrcHeight, DstX, DstY, + DstWidth, DstHeight: LongInt; SrcImageWidth, SrcImageHeight: LongInt; const DstClip: TRect); + + procedure ClipDim(var SrcPos, DstPos, SrcSize, DstSize: LongInt; SrcClipMax, + DstClipMin, DstClipMax: LongInt); + var + OldSize: LongInt; + Diff: LongInt; + Scale: Single; + begin + Scale := DstSize / SrcSize; + if DstPos < DstClipMin then + begin + Diff := DstClipMin - DstPos; + DstSize := DstSize - Diff; + SrcPos := SrcPos + Round(Diff / Scale); + SrcSize := SrcSize - Round(Diff / Scale); + DstPos := DstClipMin; + end; + if SrcPos < 0 then + begin + SrcSize := SrcSize + SrcPos; + DstPos := DstPos - Round(SrcPos * Scale); + DstSize := DstSize + Round(SrcPos * Scale); + SrcPos := 0; + end; + if SrcPos + SrcSize > SrcClipMax then + begin + OldSize := SrcSize; + SrcSize := SrcClipMax - SrcPos; + DstSize := Round(DstSize * (SrcSize / OldSize)); + end; + if DstPos + DstSize > DstClipMax then + begin + OldSize := DstSize; + DstSize := DstClipMax - DstPos; + SrcSize := Round(SrcSize * (DstSize / OldSize)); + end; + end; + +begin + ClipDim(SrcX, DstX, SrcWidth, DstWidth, SrcImageWidth, DstClip.Left, DstClip.Right); + ClipDim(SrcY, DstY, SrcHeight, DstHeight, SrcImageHeight, DstClip.Top, DstClip.Bottom); +end; + +function ScaleRectToRect(const SourceRect, TargetRect: TRect): TRect; +var + SourceWidth: LongInt; + SourceHeight: LongInt; + TargetWidth: LongInt; + TargetHeight: LongInt; + ScaledWidth: LongInt; + ScaledHeight: LongInt; +begin + SourceWidth := SourceRect.Right - SourceRect.Left; + SourceHeight := SourceRect.Bottom - SourceRect.Top; + TargetWidth := TargetRect.Right - TargetRect.Left; + TargetHeight := TargetRect.Bottom - TargetRect.Top; + + if SourceWidth * TargetHeight < SourceHeight * TargetWidth then + begin + ScaledWidth := (SourceWidth * TargetHeight) div SourceHeight; + Result := BoundsToRect(TargetRect.Left + ((TargetWidth - ScaledWidth) div 2), + TargetRect.Top, ScaledWidth, TargetHeight); + end + else + begin + ScaledHeight := (SourceHeight * TargetWidth) div SourceWidth; + Result := BoundsToRect(TargetRect.Left, TargetRect.Top + ((TargetHeight - ScaledHeight) div 2), + TargetWidth, ScaledHeight); + end; +end; + +function ScaleSizeToFit(const CurrentSize, MaxSize: Types.TSize): Types.TSize; +var + SR, TR, ScaledRect: TRect; +begin + SR := Types.Rect(0, 0, CurrentSize.CX, CurrentSize.CY); + TR := Types.Rect(0, 0, MaxSize.CX, MaxSize.CY); + ScaledRect := ScaleRectToRect(SR, TR); + Result.CX := ScaledRect.Right - ScaledRect.Left; + Result.CY := ScaledRect.Bottom - ScaledRect.Top; +end; + +function RectWidth(const Rect: TRect): Integer; +begin + Result := Rect.Right - Rect.Left; +end; + +function RectHeight(const Rect: TRect): Integer; +begin + Result := Rect.Bottom - Rect.Top; +end; + +function RectInRect(const R1, R2: TRect): Boolean; +begin + Result:= + (R1.Left >= R2.Left) and + (R1.Top >= R2.Top) and + (R1.Right <= R2.Right) and + (R1.Bottom <= R2.Bottom); +end; + +function RectIntersects(const R1, R2: TRect): Boolean; +begin + Result := + not (R1.Left > R2.Right) and + not (R1.Top > R2.Bottom) and + not (R1.Right < R2.Left) and + not (R1.Bottom < R2.Top); +end; + +function PixelSizeToDpi(SizeInMicroMeters: Single): Single; +begin + Result := 25400 / SizeInMicroMeters; +end; + +function DpiToPixelSize(Dpi: Single): Single; +begin + Result := 1e03 / (Dpi / 25.4); +end; + +function FloatRect(ALeft, ATop, ARight, ABottom: Single): TFloatRect; +begin + with Result do + begin + Left := ALeft; + Top := ATop; + Right := ARight; + Bottom := ABottom; + end; +end; + +function FloatRectWidth(const R: TFloatRect): Single; +begin + Result := R.Right - R.Left; +end; + +function FloatRectHeight(const R: TFloatRect): Single; +begin + Result := R.Bottom - R.Top; +end; + +function FormatExceptMsg(const Msg: string; const Args: array of const): string; +begin + Result := Format(Msg + SLineBreak + 'Message: ' + GetExceptObject.Message, Args); +end; + +procedure DebugMsg(const Msg: string; const Args: array of const); +var + FmtMsg: string; +begin + FmtMsg := Format(Msg, Args); +{$IFDEF MSWINDOWS} + if IsConsole then + WriteLn('DebugMsg: ' + FmtMsg) + else + MessageBox(GetActiveWindow, PChar(FmtMsg), 'DebugMsg', MB_OK); +{$ENDIF} +{$IFDEF UNIX} + WriteLn('DebugMsg: ' + FmtMsg); +{$ENDIF} +{$IFDEF MSDOS} + WriteLn('DebugMsg: ' + FmtMsg); +{$ENDIF} +end; + +initialization + InitCrcTable; +{$IFDEF MSWINDOWS} + QueryPerformanceFrequency(PerfFrequency); + InvPerfFrequency := 1.0 / PerfFrequency; +{$ENDIF} + +{$IF Defined(DELPHI)} + {$IF CompilerVersion >= 23} + FloatFormatSettings := TFormatSettings.Create('en-US'); + {$ELSE} + GetLocaleFormatSettings(1033, FloatFormatSettings); + {$IFEND} +{$ELSE FPC} + FloatFormatSettings := DefaultFormatSettings; + FloatFormatSettings.DecimalSeparator := '.'; +{$IFEND} + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.77.1 ---------------------------------------------------- + - Added GetFileName, GetFileDir, RectWidth, RectHeight function. + - Added ScaleSizeToFit function. + - Added ZeroMemory and SwapValues for Booleans. + - Added Substring function. + - Renamed MatchFileNameMask to StrMaskMatch (it's for general use not + just filenames). + - Delphi XE2 new targets (Win64, OSX32) compatibility changes. + - Added GetFormatSettingsForFloats function. + + -- 0.26.5 Changes/Bug Fixes ----------------------------------- + - Added Log10 function. + - Added TFloatRect type and helper functions FloatRect, FloatRectWidth, + FloatRectHeight. + - Added string function ContainsAnySubStr. + - Added functions PixelSizeToDpi, DpiToPixelSize. + + -- 0.26.1 Changes/Bug Fixes ----------------------------------- + - Some formatting changes. + - Changed some string functions to work with localized strings. + - ASM version of PosEx had bugs, removed it. + - Added StrTokensToList function. + + -- 0.25.0 Changes/Bug Fixes ----------------------------------- + - Fixed error in ClipCopyBounds which was causing ... bad clipping! + + -- 0.24.3 Changes/Bug Fixes ----------------------------------- + - Added GetTimeMilliseconds function. + - Added IntToStrFmt and FloatToStrFmt helper functions. + + -- 0.23 Changes/Bug Fixes ----------------------------------- + - Added RectInRect and RectIntersects functions + - Added some string utils: StrToken, StrTokenEnd, PosEx, PosNoCase. + - Moved BuildFileList here from DemoUtils. + + -- 0.21 Changes/Bug Fixes ----------------------------------- + - Moved GetVolumeLevelCount from ImagingDds here. + - Renamed FillMemory to FillMemoryByte to avoid name collision in C++ Builder. + - Added Iff function for Char, Pointer, and Int64 types. + - Added IsLittleEndian function. + - Added array types for TWordRec, TLongWordRec, and TInt64Rec. + - Added MatchFileNameMask function. + + -- 0.19 Changes/Bug Fixes ----------------------------------- + - added ScaleRectToRect (thanks to Paul Michell) + - added BoundsToRect, ClipBounds, ClipCopyBounds, ClipStretchBounds functions + - added MulDiv function + - FreeAndNil is not inline anymore - caused AV in one program + + -- 0.17 Changes/Bug Fixes ----------------------------------- + + - GetAppExe didn't return absolute path in FreeBSD, fixed + - added debug message output + - fixed Unix compatibility issues (thanks to Ales Katona). + Imaging now compiles in FreeBSD and maybe in other Unixes as well. + + -- 0.15 Changes/Bug Fixes ----------------------------------- + - added some new utility functions + + -- 0.13 Changes/Bug Fixes ----------------------------------- + - added many new utility functions + - minor change in SwapEndian to avoid range check error + +} +end. diff --git a/src/lib/vampimg/ImagingXpm.pas b/src/lib/vampimg/ImagingXpm.pas new file mode 100644 index 0000000..2e10dc2 --- /dev/null +++ b/src/lib/vampimg/ImagingXpm.pas @@ -0,0 +1,580 @@ +{ + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + The contents of this file are used with permission, subject to the Mozilla + Public License Version 1.1 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/MPL-1.1.html + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for + the specific language governing rights and limitations under the License. + + Alternatively, the contents of this file may be used under the terms of the + GNU Lesser General Public License (the "LGPL License"), in which case the + provisions of the LGPL License are applicable instead of those above. + If you wish to allow use of your version of this file only under the terms + of the LGPL License and not to allow others to use your version of this file + under the MPL, indicate your decision by deleting the provisions above and + replace them with the notice and other provisions required by the LGPL + License. If you do not delete the provisions above, a recipient may use + your version of this file under either the MPL or the LGPL License. + + For more information about the LGPL: http://www.gnu.org/copyleft/lesser.html +} + +{ This unit contains image format loader for X Window Pixmap images. } +unit ImagingXpm; +{$I ImagingOptions.inc} + +interface + +uses + SysUtils, Classes, Contnrs, ImagingTypes, Imaging, ImagingUtility, + ImagingFormats, ImagingIO, ImagingCanvases; + +type + { Class for loading X Window Pixmap images known as XPM. + It is ASCII-text-based format, basicaly a fragment of C code + declaring static array. Loaded image is in ifA8R8G8B8 data format. + Loading as well as saving is supported now. } + TXPMFileFormat = class(TImageFileFormat) + protected + procedure Define; override; + function LoadData(Handle: TImagingHandle; var Images: TDynImageDataArray; + OnlyFirstLevel: Boolean): Boolean; override; + function SaveData(Handle: TImagingHandle; const Images: TDynImageDataArray; + Index: LongInt): Boolean; override; + procedure ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); override; + public + function TestFormat(Handle: TImagingHandle): Boolean; override; + end; + +implementation + +const + SXPMFormatName = 'X Window Pixmap'; + SXPMMasks = '*.xpm'; + XPMSupportedFormats: TImageFormats = [ifA8R8G8B8]; + +const + SXPMId = '/* XPM */'; + WhiteSpaces = [#9, #10, #13, #32]; + +const + BucketCount = 257; + +type + TColorHolder = class + public + Color: TColor32; + end; + + TBucketItem = record + Key: TColor32; + Data: string[8]; + end; + + TBucketItemArray = array of TBucketItem; + + TBucket = record + Count: Integer; + ItemIdxStart: Integer; + Items: TBucketItemArray; + end; + + TBucketArray = array of TBucket; + + { Simple color-string hash table for faster than linear searches + during XPM saving. } + TSimpleBucketList = class + private + FBuckets: TBucketArray; + FItemCount: Integer; + FABucket, FAIndex: Integer; + function GetData(AKey: TColor32): string; + procedure SetData(AKey: TColor32; const AData: string); + function FindItem(AKey: TColor32; out ABucket, AIndex: Integer): Boolean; + public + constructor Create; + procedure Add(AKey: TColor32; const AData: string); + function Exists(AKey: TColor32): Boolean; + function EnumNext(out AData: string): TColor32; + property Data[AKey: TColor32]: string read GetData write SetData; default; + property ItemCount: Integer read FItemCount; + end; + + { TSimpleBucketList } + +constructor TSimpleBucketList.Create; +begin + SetLength(FBuckets, BucketCount); +end; + +function TSimpleBucketList.GetData(AKey: TColor32): string; +var + Bucket, Index: Integer; +begin + Result := ''; + if FindItem(AKey, Bucket, Index) then + Result := string(FBuckets[Bucket].Items[Index].Data); +end; + +procedure TSimpleBucketList.SetData(AKey: TColor32; const AData: string); +var + Bucket, Index: Integer; +begin + if FindItem(AKey, Bucket, Index) then + FBuckets[Bucket].Items[Index].Data := ShortString(AData); +end; + +function TSimpleBucketList.EnumNext(out AData: string): TColor32; +begin + // Skip empty buckets + while FAIndex >= FBuckets[FABucket].Count do + begin + Inc(FABucket); + if FABucket >= Length(FBuckets) then + FABucket := 0; + FAIndex := 0; + end; + + Result := FBuckets[FABucket].Items[FAIndex].Key; + AData := string(FBuckets[FABucket].Items[FAIndex].Data); + Inc(FAIndex); +end; + +function TSimpleBucketList.FindItem(AKey: TColor32; out ABucket, + AIndex: Integer): Boolean; +var + I: Integer; + Col: TColor32Rec; +begin + Result := False; + Col := TColor32Rec(AKey); + ABucket := (Col.A + 11 * Col.B + 59 * Col.R + 119 * Col.G) mod BucketCount; + with FBuckets[ABucket] do + for I := 0 to Count - 1 do + if Items[I].Key = AKey then + begin + AIndex := I; + Result := True; + Break; + end; +end; + +procedure TSimpleBucketList.Add(AKey: TColor32; const AData: string); +var + Bucket, Index, Delta, Size: Integer; +begin + if not FindItem(AKey, Bucket, Index) then + with FBuckets[Bucket] do + begin + Size := Length(Items); + if Count = Size then + begin + if Size > 64 then + Delta := Size div 4 + else + Delta := 16; + SetLength(Items, Size + Delta); + end; + + with Items[Count] do + begin + Key := AKey; + Data := ShortString(AData); + end; + Inc(Count); + Inc(FItemCount); + end; +end; + +function TSimpleBucketList.Exists(AKey: TColor32): Boolean; +var + Bucket, Index: Integer; +begin + Result := FindItem(AKey, Bucket, Index); +end; + +{ + TXPMFileFormat implementation +} + +procedure TXPMFileFormat.Define; +begin + inherited; + FName := SXPMFormatName; + FFeatures := [ffLoad, ffSave]; + FSupportedFormats := XPMSupportedFormats; + + AddMasks(SXPMMasks); +end; + +function TXPMFileFormat.LoadData(Handle: TImagingHandle; + var Images: TDynImageDataArray; OnlyFirstLevel: Boolean): Boolean; +var + Contents, PalLookup: TStringList; + S: AnsiString; + I, J, NumColors, Cpp, Line: Integer; + + procedure SkipWhiteSpace(var Line: string); + begin + while (Length(Line) > 0) and (AnsiChar(Line[1]) in WhiteSpaces) do + Delete(Line, 1, 1); + end; + + function ReadString(var Line: string): string; + begin + Result := ''; + SkipWhiteSpace(Line); + while (Length(Line) > 0) and not (AnsiChar(Line[1]) in WhiteSpaces) do + begin + SetLength(Result, Length(Result) + 1); + Result[Length(Result)] := Line[1]; + Delete(Line, 1, 1); + end; + end; + + function ReadInt(var Line: string): Integer; + begin + Result := StrToInt(ReadString(Line)); + end; + + function ParseHeader: Boolean; + var + S: string; + begin + S := Contents[0]; + try + Images[0].Width := ReadInt(S); + Images[0].Height := ReadInt(S); + NumColors := ReadInt(S); + Cpp := ReadInt(S); + Line := 1; + Result := True; + except + Result := False; + end; + end; + + function NamedToColor(const ColStr: string): TColor32; + var + S: string; + begin + S := LowerCase(ColStr); + if (S = 'transparent') or (S = 'none') then + Result := pcClear + else if S = 'black' then + Result := pcBlack + else if S = 'blue' then + Result := pcBlue + else if S = 'green' then + Result := pcGreen + else if S = 'cyan' then + Result := pcAqua + else if S = 'red' then + Result := pcRed + else if S = 'magenta' then + Result := pcFuchsia + else if S = 'yellow' then + Result := pcYellow + else if S = 'white' then + Result := pcWhite + else if S = 'gray' then + Result := pcLtGray + else if S = 'dkblue' then + Result := pcNavy + else if S = 'dkgreen' then + Result := pcGreen + else if S = 'dkcyan' then + Result := pcTeal + else if S = 'dkred' then + Result := pcMaroon + else if S = 'dkmagenta' then + Result := pcPurple + else if S = 'dkyellow' then + Result := pcOlive + else if S = 'maroon' then + Result := pcMaroon + else if S = 'olive' then + Result := pcOlive + else if S = 'navy' then + Result := pcNavy + else if S = 'purple' then + Result := pcPurple + else if S = 'teal' then + Result := pcTeal + else if S = 'silver' then + Result := pcSilver + else if S = 'lime' then + Result := pcLime + else if S = 'fuchsia' then + Result := pcFuchsia + else if S = 'aqua' then + Result := pcAqua + else + Result := pcClear; + end; + + procedure ParsePalette; + var + I: Integer; + S, ColType, ColStr, Code: string; + Color: TColor32; + Holder: TColorHolder; + begin + for I := 0 to NumColors - 1 do + begin + Holder := TColorHolder.Create; + // Parse pixel code and color + S := Contents[Line + I]; + Code := Copy(S, 1, Cpp); + Delete(S, 1, Cpp); + ColType := ReadString(S); + ColStr := ReadString(S); + // Convert color from hex number or named constant + if ColStr[1] = '#' then + begin + Delete(ColStr, 1, 1); + Color := LongWord(StrToInt('$' + Trim(ColStr))) or $FF000000; + end + else + Color := NamedToColor(ColStr); + // Store code and color in table for later lookup + Holder.Color := Color; + PalLookup.AddObject(Code, Holder); + end; + Inc(Line, NumColors); + end; + + procedure ParsePixels; + var + X, Y, Idx: Integer; + S, Code: string; + Pix: PColor32; + begin + Pix := Images[0].Bits; + for Y := 0 to Images[0].Height - 1 do + begin + S := Contents[Line + Y]; + for X := 0 to Images[0].Width - 1 do + begin + // Read code and look up color in the palette + Code := Copy(S, X * Cpp + 1, Cpp); + if PalLookup.Find(Code, Idx) then + Pix^ := TColorHolder(PalLookup.Objects[Idx]).Color + else + Pix^ := pcClear; + Inc(Pix); + end; + end; + end; + +begin + Result := False; + SetLength(Images, 1); + with GetIO, Images[0] do + begin + // Look up table for XPM palette entries + PalLookup := TStringList.Create; + PalLookup.Sorted := True; + PalLookup.CaseSensitive := True; + // Read whole file and assign it to string list + Contents := TStringList.Create; + SetLength(S, GetInputSize(GetIO, Handle)); + Read(Handle, @S[1], Length(S)); + Contents.Text := string(S); + // Remove quotes and other stuff + for I := Contents.Count - 1 downto 0 do + begin + J := Pos('"', Contents[I]); + if J > 0 then + Contents[I] := Copy(Contents[I], J + 1, LastDelimiter('"', Contents[I]) - J - 1) + else + Contents.Delete(I); + end; + // Parse header and create new image + if not ParseHeader then + Exit; + NewImage(Width, Height, ifA8R8G8B8, Images[0]); + // Read palette entries and assign colors to pixels + ParsePalette; + ParsePixels; + + Contents.Free; + for I := 0 to PalLookup.Count - 1 do + PalLookup.Objects[I].Free; + PalLookup.Free; + Result := True; + end; +end; + +function TXPMFileFormat.SaveData(Handle: TImagingHandle; + const Images: TDynImageDataArray; Index: LongInt): Boolean; +const + ColorCharsCount = 92; + ColorChars = ' .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`''][{}|'; +var + X, Y: Integer; + ImageToSave: TImageData; + MustBeFreed: Boolean; + StrFile: TStringList; + ColTable: TSimpleBucketList; + Stream: TMemoryStream; + Line, Id: string; + CharsPerPixel: Integer; + Ptr: PColor32Rec; + ColRec: TColor32Rec; + + procedure BuildColorTables(const Img: TImageData); + var + I: Integer; + begin + Ptr := Img.Bits; + for I := 0 to Img.Width * Img.Height - 1 do + begin + if not ColTable.Exists(Ptr.Color) then + ColTable.Add(Ptr.Color, ''); + Inc(Ptr); + end; + end; + + procedure MakeStrIdsForColors; + var + I, J, K: Integer; + Id, Data: string; + begin + SetLength(Id, CharsPerPixel); + for I := 0 to ColTable.ItemCount - 1 do + begin + ColRec.Color := ColTable.EnumNext(Data); + K := I; + for J := 0 to CharsPerPixel - 1 do + begin + Id[J + 1] := ColorChars[K mod ColorCharsCount + 1]; + K := K div ColorCharsCount; + end; + ColTable.Data[ColRec.Color] := Id; + end; + end; + +begin + Result := False; + + StrFile := TStringList.Create; + ColTable := TSimpleBucketList.Create; + Stream := TMemoryStream.Create; + + if MakeCompatible(Images[Index], ImageToSave, MustBeFreed) then + try + // Put all unique colors of image to table + BuildColorTables(ImageToSave); + // Compute the character per pixel + CharsPerPixel := 1; + X := ColorCharsCount; + while ColTable.ItemCount > X do + begin + X := X * ColorCharsCount; + Inc(CharsPerPixel); + end; + // Assign char id to each color + MakeStrIdsForColors; + + // Start writing XPM file + StrFile.Add(SXPMId); + StrFile.Add('static char *graphic[] = {'); + StrFile.Add('/* width height num_colors chars_per_pixel */'); + StrFile.Add(SysUtils.Format('"%d %d %d %d", ', [ImageToSave.Width, + ImageToSave.Height, ColTable.ItemCount, CharsPerPixel])); + StrFile.Add('/* colors */'); + + // Write 'colors' part of XPM file + for X := 0 to ColTable.ItemCount - 1 do + begin + ColRec.Color := ColTable.EnumNext(Id); + if ColRec.A >= 128 then + StrFile.Add(Format('"%s c #%.2x%.2x%.2x",', [Id, ColRec.R, ColRec.G, ColRec.B])) + else + StrFile.Add(Format('"%s c None",', [Id])); + end; + + StrFile.Add('/* pixels */'); + + // Write pixels - for aech pixel of image find its char id + // and append it to line + Ptr := ImageToSave.Bits; + for Y := 0 to ImageToSave.Height - 1 do + begin + Line := ''; + for X := 0 to ImageToSave.Width - 1 do + begin + Line := Line + ColTable.Data[Ptr.Color]; + Inc(Ptr); + end; + Line := '"' + Line + '"'; + if Y < ImageToSave.Height - 1 then + Line := Line + ','; + StrFile.Add(Line); + end; + + StrFile.Add('};'); + + // Finally save strings to stream and write stream's data to output + // (we could directly write lines from list to output, but stream method + // takes care of D2009+ Unicode strings). + StrFile.SaveToStream(Stream); + GetIO.Write(Handle, Stream.Memory, Stream.Size); + + Result := True; + finally + StrFile.Free; + ColTable.Free; + Stream.Free; + if MustBeFreed then + FreeImage(ImageToSave); + end; +end; + +procedure TXPMFileFormat.ConvertToSupported(var Image: TImageData; + const Info: TImageFormatInfo); +begin + ConvertImage(Image, ifA8R8G8B8) +end; + +function TXPMFileFormat.TestFormat(Handle: TImagingHandle): Boolean; +var + Id: array[0 .. 8] of AnsiChar; + ReadCount: Integer; +begin + Result := False; + if Handle <> nil then + begin + ReadCount := GetIO.Read(Handle, @Id, SizeOf(Id)); + GetIO.Seek(Handle, -ReadCount, smFromCurrent); + Result := (Id = SXPMId) and (ReadCount = SizeOf(Id)); + end; +end; + +initialization + +RegisterImageFileFormat(TXPMFileFormat); + +{ + File Notes: + + -- TODOS ---------------------------------------------------- + - nothing now + + -- 0.26.3 Changes/Bug Fixes ----------------------------------- + - Added XPM saving. + + -- 0.25.0 Changes/Bug Fixes ----------------------------------- + - Added XPM loading. + - Unit created. +} + +end. diff --git a/src/lib/vampimg/JpegLib/imjcapimin.pas b/src/lib/vampimg/JpegLib/imjcapimin.pas new file mode 100644 index 0000000..d16c2ae --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcapimin.pas @@ -0,0 +1,401 @@ +unit imjcapimin; +{$N+} +{ This file contains application interface code for the compression half + of the JPEG library. These are the "minimum" API routines that may be + needed in either the normal full-compression case or the transcoding-only + case. + + Most of the routines intended to be called directly by an application + are in this file or in jcapistd.c. But also see jcparam.c for + parameter-setup helper routines, jcomapi.c for routines shared by + compression and decompression, and jctrans.c for the transcoding case. } + +{ jcapimin.c ; Copyright (C) 1994-1998, Thomas G. Lane. } + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib, + imjcomapi, + imjmemmgr, + imjcmarker; + +{ Initialization of JPEG compression objects. + Nomssi: This is a macro in the original code. + + jpeg_create_compress() and jpeg_create_decompress() are the exported + names that applications should call. These expand to calls on + jpeg_CreateCompress and jpeg_CreateDecompress with additional information + passed for version mismatch checking. + NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. } + +procedure jpeg_create_compress(cinfo : j_compress_ptr); + + +{ Initialization of a JPEG compression object. + The error manager must already be set up (in case memory manager fails). } + +{GLOBAL} +procedure jpeg_CreateCompress (cinfo : j_compress_ptr; + version : int; + structsize : size_t); + +{ Destruction of a JPEG compression object } + +{GLOBAL} +procedure jpeg_destroy_compress (cinfo : j_compress_ptr); + + +{ Abort processing of a JPEG compression operation, + but don't destroy the object itself. } + +{GLOBAL} +procedure jpeg_abort_compress (cinfo : j_compress_ptr); + + +{ Forcibly suppress or un-suppress all quantization and Huffman tables. + Marks all currently defined tables as already written (if suppress) + or not written (if !suppress). This will control whether they get emitted + by a subsequent jpeg_start_compress call. + + This routine is exported for use by applications that want to produce + abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + since it is called by jpeg_start_compress, we put it here --- otherwise + jcparam.o would be linked whether the application used it or not. } + +{GLOBAL} +procedure jpeg_suppress_tables (cinfo : j_compress_ptr; + suppress : boolean); + + +{ Finish JPEG compression. + + If a multipass operating mode was selected, this may do a great deal of + work including most of the actual output. } + +{GLOBAL} +procedure jpeg_finish_compress (cinfo : j_compress_ptr); + +{ Write a special marker. + This is only recommended for writing COM or APPn markers. + Must be called after jpeg_start_compress() and before + first call to jpeg_write_scanlines() or jpeg_write_raw_data(). } + +{GLOBAL} +procedure jpeg_write_marker (cinfo : j_compress_ptr; + marker : int; + dataptr : JOCTETptr; + datalen : uInt); + +{GLOBAL} +procedure jpeg_write_m_header (cinfo : j_compress_ptr; + marker : int; + datalen : uint); +{GLOBAL} +procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int); + +{ Alternate compression function: just write an abbreviated table file. + Before calling this, all parameters and a data destination must be set up. + + To produce a pair of files containing abbreviated tables and abbreviated + image data, one would proceed as follows: + + initialize JPEG object + set JPEG parameters + set destination to table file + jpeg_write_tables(cinfo); + set destination to image file + jpeg_start_compress(cinfo, FALSE); + write data... + jpeg_finish_compress(cinfo); + + jpeg_write_tables has the side effect of marking all tables written + (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + will not re-emit the tables unless it is passed write_all_tables=TRUE. } + + + +{GLOBAL} +procedure jpeg_write_tables (cinfo : j_compress_ptr); + +implementation + +procedure jpeg_create_compress(cinfo : j_compress_ptr); +begin + jpeg_CreateCompress(cinfo, JPEG_LIB_VERSION, + size_t(sizeof(jpeg_compress_struct))); +end; + +{ Initialization of a JPEG compression object. + The error manager must already be set up (in case memory manager fails). } + +{GLOBAL} +procedure jpeg_CreateCompress (cinfo : j_compress_ptr; + version : int; + structsize : size_t); +var + i : int; +var + err : jpeg_error_mgr_ptr; + client_data : voidp; +begin + + { Guard against version mismatches between library and caller. } + cinfo^.mem := NIL; { so jpeg_destroy knows mem mgr not called } + if (version <> JPEG_LIB_VERSION) then + ERREXIT2(j_common_ptr(cinfo), JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize <> SIZEOF(jpeg_compress_struct)) then + ERREXIT2(j_common_ptr(cinfo), JERR_BAD_STRUCT_SIZE, + int(SIZEOF(jpeg_compress_struct)), int(structsize)); + + { For debugging purposes, we zero the whole master structure. + But the application has already set the err pointer, and may have set + client_data, so we have to save and restore those fields. + Note: if application hasn't set client_data, tools like Purify may + complain here. } + + err := cinfo^.err; + client_data := cinfo^.client_data; { ignore Purify complaint here } + MEMZERO(cinfo, SIZEOF(jpeg_compress_struct)); + cinfo^.err := err; + cinfo^.is_decompressor := FALSE; + + { Initialize a memory manager instance for this object } + jinit_memory_mgr(j_common_ptr(cinfo)); + + { Zero out pointers to permanent structures. } + cinfo^.progress := NIL; + cinfo^.dest := NIL; + + cinfo^.comp_info := NIL; + + for i := 0 to pred(NUM_QUANT_TBLS) do + cinfo^.quant_tbl_ptrs[i] := NIL; + + for i := 0 to pred(NUM_HUFF_TBLS) do + begin + cinfo^.dc_huff_tbl_ptrs[i] := NIL; + cinfo^.ac_huff_tbl_ptrs[i] := NIL; + end; + + cinfo^.script_space := NIL; + + cinfo^.input_gamma := 1.0; { in case application forgets } + + { OK, I'm ready } + cinfo^.global_state := CSTATE_START; +end; + + +{ Destruction of a JPEG compression object } + +{GLOBAL} +procedure jpeg_destroy_compress (cinfo : j_compress_ptr); +begin + jpeg_destroy(j_common_ptr(cinfo)); { use common routine } +end; + + +{ Abort processing of a JPEG compression operation, + but don't destroy the object itself. } + +{GLOBAL} +procedure jpeg_abort_compress (cinfo : j_compress_ptr); +begin + jpeg_abort(j_common_ptr(cinfo)); { use common routine } +end; + + +{ Forcibly suppress or un-suppress all quantization and Huffman tables. + Marks all currently defined tables as already written (if suppress) + or not written (if !suppress). This will control whether they get emitted + by a subsequent jpeg_start_compress call. + + This routine is exported for use by applications that want to produce + abbreviated JPEG datastreams. It logically belongs in jcparam.c, but + since it is called by jpeg_start_compress, we put it here --- otherwise + jcparam.o would be linked whether the application used it or not. } + +{GLOBAL} +procedure jpeg_suppress_tables (cinfo : j_compress_ptr; + suppress : boolean); +var + i : int; + qtbl : JQUANT_TBL_PTR; + htbl : JHUFF_TBL_PTR; +begin + for i := 0 to pred(NUM_QUANT_TBLS) do + begin + qtbl := cinfo^.quant_tbl_ptrs[i]; + if (qtbl <> NIL) then + qtbl^.sent_table := suppress; + end; + + for i := 0 to pred(NUM_HUFF_TBLS) do + begin + htbl := cinfo^.dc_huff_tbl_ptrs[i]; + if (htbl <> NIL) then + htbl^.sent_table := suppress; + htbl := cinfo^.ac_huff_tbl_ptrs[i]; + if (htbl <> NIL) then + htbl^.sent_table := suppress; + end; +end; + + +{ Finish JPEG compression. + + If a multipass operating mode was selected, this may do a great deal of + work including most of the actual output. } + +{GLOBAL} +procedure jpeg_finish_compress (cinfo : j_compress_ptr); +var + iMCU_row : JDIMENSION; +begin + if (cinfo^.global_state = CSTATE_SCANNING) or + (cinfo^.global_state = CSTATE_RAW_OK) then + begin + { Terminate first pass } + if (cinfo^.next_scanline < cinfo^.image_height) then + ERREXIT(j_common_ptr(cinfo), JERR_TOO_LITTLE_DATA); + cinfo^.master^.finish_pass (cinfo); + end + else + if (cinfo^.global_state <> CSTATE_WRCOEFS) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + { Perform any remaining passes } + while (not cinfo^.master^.is_last_pass) do + begin + cinfo^.master^.prepare_for_pass (cinfo); + for iMCU_row := 0 to pred(cinfo^.total_iMCU_rows) do + begin + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.pass_counter := long (iMCU_row); + cinfo^.progress^.pass_limit := long (cinfo^.total_iMCU_rows); + cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); + end; + { We bypass the main controller and invoke coef controller directly; + all work is being done from the coefficient buffer. } + + if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(NIL))) then + ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND); + end; + cinfo^.master^.finish_pass (cinfo); + end; + { Write EOI, do final cleanup } + cinfo^.marker^.write_file_trailer (cinfo); + cinfo^.dest^.term_destination (cinfo); + { We can use jpeg_abort to release memory and reset global_state } + jpeg_abort(j_common_ptr(cinfo)); +end; + + +{ Write a special marker. + This is only recommended for writing COM or APPn markers. + Must be called after jpeg_start_compress() and before + first call to jpeg_write_scanlines() or jpeg_write_raw_data(). } + +{GLOBAL} +procedure jpeg_write_marker (cinfo : j_compress_ptr; + marker : int; + dataptr : JOCTETptr; + datalen : uInt); +var + write_marker_byte : procedure(info : j_compress_ptr; val : int); +begin + if (cinfo^.next_scanline <> 0) or + ((cinfo^.global_state <> CSTATE_SCANNING) and + (cinfo^.global_state <> CSTATE_RAW_OK) and + (cinfo^.global_state <> CSTATE_WRCOEFS)) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + cinfo^.marker^.write_marker_header (cinfo, marker, datalen); + write_marker_byte := cinfo^.marker^.write_marker_byte; { copy for speed } + while (datalen <> 0) do + begin + Dec(datalen); + write_marker_byte (cinfo, dataptr^); + Inc(dataptr); + end; +end; + +{ Same, but piecemeal. } + +{GLOBAL} +procedure jpeg_write_m_header (cinfo : j_compress_ptr; + marker : int; + datalen : uint); +begin + if (cinfo^.next_scanline <> 0) or + ((cinfo^.global_state <> CSTATE_SCANNING) and + (cinfo^.global_state <> CSTATE_RAW_OK) and + (cinfo^.global_state <> CSTATE_WRCOEFS)) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + cinfo^.marker^.write_marker_header (cinfo, marker, datalen); +end; + +{GLOBAL} +procedure jpeg_write_m_byte (cinfo : j_compress_ptr; val : int); +begin + cinfo^.marker^.write_marker_byte (cinfo, val); +end; + + +{ Alternate compression function: just write an abbreviated table file. + Before calling this, all parameters and a data destination must be set up. + + To produce a pair of files containing abbreviated tables and abbreviated + image data, one would proceed as follows: + + initialize JPEG object + set JPEG parameters + set destination to table file + jpeg_write_tables(cinfo); + set destination to image file + jpeg_start_compress(cinfo, FALSE); + write data... + jpeg_finish_compress(cinfo); + + jpeg_write_tables has the side effect of marking all tables written + (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress + will not re-emit the tables unless it is passed write_all_tables=TRUE. } + +{GLOBAL} +procedure jpeg_write_tables (cinfo : j_compress_ptr); +begin + if (cinfo^.global_state <> CSTATE_START) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + { (Re)initialize error mgr and destination modules } + cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo)); + cinfo^.dest^.init_destination (cinfo); + { Initialize the marker writer ... bit of a crock to do it here. } + jinit_marker_writer(cinfo); + { Write them tables! } + cinfo^.marker^.write_tables_only (cinfo); + { And clean up. } + cinfo^.dest^.term_destination (cinfo); + + { In library releases up through v6a, we called jpeg_abort() here to free + any working memory allocated by the destination manager and marker + writer. Some applications had a problem with that: they allocated space + of their own from the library memory manager, and didn't want it to go + away during write_tables. So now we do nothing. This will cause a + memory leak if an app calls write_tables repeatedly without doing a full + compression cycle or otherwise resetting the JPEG object. However, that + seems less bad than unexpectedly freeing memory in the normal case. + An app that prefers the old behavior can call jpeg_abort for itself after + each call to jpeg_write_tables(). } +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcapistd.pas b/src/lib/vampimg/JpegLib/imjcapistd.pas new file mode 100644 index 0000000..bc487a7 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcapistd.pas @@ -0,0 +1,222 @@ +unit imjcapistd; + +{ Original : jcapistd.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +{ This file is part of the Independent JPEG Group's software. + For conditions of distribution and use, see the accompanying README file. + + This file contains application interface code for the compression half + of the JPEG library. These are the "standard" API routines that are + used in the normal full-compression case. They are not used by a + transcoding-only application. Note that if an application links in + jpeg_start_compress, it will end up linking in the entire compressor. + We thus must separate this file from jcapimin.c to avoid linking the + whole compression library into a transcoder. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib, + imjcapimin, imjcinit; + + + +{ Compression initialization. + Before calling this, all parameters and a data destination must be set up. + + We require a write_all_tables parameter as a failsafe check when writing + multiple datastreams from the same compression object. Since prior runs + will have left all the tables marked sent_table=TRUE, a subsequent run + would emit an abbreviated stream (no tables) by default. This may be what + is wanted, but for safety's sake it should not be the default behavior: + programmers should have to make a deliberate choice to emit abbreviated + images. Therefore the documentation and examples should encourage people + to pass write_all_tables=TRUE; then it will take active thought to do the + wrong thing. } + +{GLOBAL} +procedure jpeg_start_compress (cinfo : j_compress_ptr; + write_all_tables : boolean); + + +{ Write some scanlines of data to the JPEG compressor. + + The return value will be the number of lines actually written. + This should be less than the supplied num_lines only in case that + the data destination module has requested suspension of the compressor, + or if more than image_height scanlines are passed in. + + Note: we warn about excess calls to jpeg_write_scanlines() since + this likely signals an application programmer error. However, + excess scanlines passed in the last valid call are *silently* ignored, + so that the application need not adjust num_lines for end-of-image + when using a multiple-scanline buffer. } + +{GLOBAL} +function jpeg_write_scanlines (cinfo : j_compress_ptr; + scanlines : JSAMPARRAY; + num_lines : JDIMENSION) : JDIMENSION; + +{ Alternate entry point to write raw data. + Processes exactly one iMCU row per call, unless suspended. } + +{GLOBAL} +function jpeg_write_raw_data (cinfo : j_compress_ptr; + data : JSAMPIMAGE; + num_lines : JDIMENSION) : JDIMENSION; + +implementation + +{ Compression initialization. + Before calling this, all parameters and a data destination must be set up. + + We require a write_all_tables parameter as a failsafe check when writing + multiple datastreams from the same compression object. Since prior runs + will have left all the tables marked sent_table=TRUE, a subsequent run + would emit an abbreviated stream (no tables) by default. This may be what + is wanted, but for safety's sake it should not be the default behavior: + programmers should have to make a deliberate choice to emit abbreviated + images. Therefore the documentation and examples should encourage people + to pass write_all_tables=TRUE; then it will take active thought to do the + wrong thing. } + +{GLOBAL} +procedure jpeg_start_compress (cinfo : j_compress_ptr; + write_all_tables : boolean); +begin + if (cinfo^.global_state <> CSTATE_START) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + if (write_all_tables) then + jpeg_suppress_tables(cinfo, FALSE); { mark all tables to be written } + + { (Re)initialize error mgr and destination modules } + cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo)); + cinfo^.dest^.init_destination (cinfo); + { Perform master selection of active modules } + jinit_compress_master(cinfo); + { Set up for the first pass } + cinfo^.master^.prepare_for_pass (cinfo); + { Ready for application to drive first pass through jpeg_write_scanlines + or jpeg_write_raw_data. } + + cinfo^.next_scanline := 0; + if cinfo^.raw_data_in then + cinfo^.global_state := CSTATE_RAW_OK + else + cinfo^.global_state := CSTATE_SCANNING; +end; + + +{ Write some scanlines of data to the JPEG compressor. + + The return value will be the number of lines actually written. + This should be less than the supplied num_lines only in case that + the data destination module has requested suspension of the compressor, + or if more than image_height scanlines are passed in. + + Note: we warn about excess calls to jpeg_write_scanlines() since + this likely signals an application programmer error. However, + excess scanlines passed in the last valid call are *silently* ignored, + so that the application need not adjust num_lines for end-of-image + when using a multiple-scanline buffer. } + +{GLOBAL} +function jpeg_write_scanlines (cinfo : j_compress_ptr; + scanlines : JSAMPARRAY; + num_lines : JDIMENSION) : JDIMENSION; +var + row_ctr, rows_left : JDIMENSION; +begin + if (cinfo^.global_state <> CSTATE_SCANNING) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + if (cinfo^.next_scanline >= cinfo^.image_height) then + WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA); + + { Call progress monitor hook if present } + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.pass_counter := long (cinfo^.next_scanline); + cinfo^.progress^.pass_limit := long (cinfo^.image_height); + cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); + end; + + { Give master control module another chance if this is first call to + jpeg_write_scanlines. This lets output of the frame/scan headers be + delayed so that application can write COM, etc, markers between + jpeg_start_compress and jpeg_write_scanlines. } + if (cinfo^.master^.call_pass_startup) then + cinfo^.master^.pass_startup (cinfo); + + { Ignore any extra scanlines at bottom of image. } + rows_left := cinfo^.image_height - cinfo^.next_scanline; + if (num_lines > rows_left) then + num_lines := rows_left; + + row_ctr := 0; + cinfo^.main^.process_data (cinfo, scanlines, {var}row_ctr, num_lines); + Inc(cinfo^.next_scanline, row_ctr); + jpeg_write_scanlines := row_ctr; +end; + + +{ Alternate entry point to write raw data. + Processes exactly one iMCU row per call, unless suspended. } + +{GLOBAL} +function jpeg_write_raw_data (cinfo : j_compress_ptr; + data : JSAMPIMAGE; + num_lines : JDIMENSION) : JDIMENSION; +var + lines_per_iMCU_row : JDIMENSION; +begin + if (cinfo^.global_state <> CSTATE_RAW_OK) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + if (cinfo^.next_scanline >= cinfo^.image_height) then + begin + WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA); + jpeg_write_raw_data := 0; + exit; + end; + + { Call progress monitor hook if present } + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.pass_counter := long(cinfo^.next_scanline); + cinfo^.progress^.pass_limit := long(cinfo^.image_height); + cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); + end; + + { Give master control module another chance if this is first call to + jpeg_write_raw_data. This lets output of the frame/scan headers be + delayed so that application can write COM, etc, markers between + jpeg_start_compress and jpeg_write_raw_data. } + + if (cinfo^.master^.call_pass_startup) then + cinfo^.master^.pass_startup (cinfo); + + { Verify that at least one iMCU row has been passed. } + lines_per_iMCU_row := cinfo^.max_v_samp_factor * DCTSIZE; + if (num_lines < lines_per_iMCU_row) then + ERREXIT(j_common_ptr(cinfo), JERR_BUFFER_SIZE); + + { Directly compress the row. } + if (not cinfo^.coef^.compress_data (cinfo, data)) then + begin + { If compressor did not consume the whole row, suspend processing. } + jpeg_write_raw_data := 0; + exit; + end; + + { OK, we processed one iMCU row. } + Inc(cinfo^.next_scanline, lines_per_iMCU_row); + jpeg_write_raw_data := lines_per_iMCU_row; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjccoefct.pas b/src/lib/vampimg/JpegLib/imjccoefct.pas new file mode 100644 index 0000000..7d6ee6f --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjccoefct.pas @@ -0,0 +1,521 @@ +unit imjccoefct; + +{ This file contains the coefficient buffer controller for compression. + This controller is the top level of the JPEG compressor proper. + The coefficient buffer lies between forward-DCT and entropy encoding steps.} + +{ Original: jccoefct.c; Copyright (C) 1994-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjerror, + imjdeferr, + imjutils, + imjpeglib; + +{ We use a full-image coefficient buffer when doing Huffman optimization, + and also for writing multiple-scan JPEG files. In all cases, the DCT + step is run during the first pass, and subsequent passes need only read + the buffered coefficients. } +{$ifdef ENTROPY_OPT_SUPPORTED} + {$define FULL_COEF_BUFFER_SUPPORTED} +{$else} + {$ifdef C_MULTISCAN_FILES_SUPPORTED} + {$define FULL_COEF_BUFFER_SUPPORTED} + {$endif} +{$endif} + +{ Initialize coefficient buffer controller. } + +{GLOBAL} +procedure jinit_c_coef_controller (cinfo : j_compress_ptr; + need_full_buffer : boolean); + +implementation + +{ Private buffer controller object } + +type + my_coef_ptr = ^my_coef_controller; + my_coef_controller = record + pub : jpeg_c_coef_controller; { public fields } + + iMCU_row_num : JDIMENSION; { iMCU row # within image } + mcu_ctr : JDIMENSION; { counts MCUs processed in current row } + MCU_vert_offset : int; { counts MCU rows within iMCU row } + MCU_rows_per_iMCU_row : int; { number of such rows needed } + + { For single-pass compression, it's sufficient to buffer just one MCU + (although this may prove a bit slow in practice). We allocate a + workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each + MCU constructed and sent. (On 80x86, the workspace is FAR even though + it's not really very big; this is to keep the module interfaces unchanged + when a large coefficient buffer is necessary.) + In multi-pass modes, this array points to the current MCU's blocks + within the virtual arrays. } + + MCU_buffer : array[0..C_MAX_BLOCKS_IN_MCU-1] of JBLOCKROW; + + { In multi-pass modes, we need a virtual block array for each component. } + whole_image : array[0..MAX_COMPONENTS-1] of jvirt_barray_ptr; + end; + + +{ Forward declarations } +{METHODDEF} +function compress_data(cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE) : boolean; forward; +{$ifdef FULL_COEF_BUFFER_SUPPORTED} +{METHODDEF} +function compress_first_pass(cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE) : boolean; forward; +{METHODDEF} +function compress_output(cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE) : boolean; forward; +{$endif} + + +{LOCAL} +procedure start_iMCU_row (cinfo : j_compress_ptr); +{ Reset within-iMCU-row counters for a new row } +var + coef : my_coef_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + + { In an interleaved scan, an MCU row is the same as an iMCU row. + In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + But at the bottom of the image, process only what's left. } + if (cinfo^.comps_in_scan > 1) then + begin + coef^.MCU_rows_per_iMCU_row := 1; + end + else + begin + if (coef^.iMCU_row_num < (cinfo^.total_iMCU_rows-1)) then + coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.v_samp_factor + else + coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.last_row_height; + end; + + coef^.mcu_ctr := 0; + coef^.MCU_vert_offset := 0; +end; + + +{ Initialize for a processing pass. } + +{METHODDEF} +procedure start_pass_coef (cinfo : j_compress_ptr; + pass_mode : J_BUF_MODE); +var + coef : my_coef_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + + coef^.iMCU_row_num := 0; + start_iMCU_row(cinfo); + + case (pass_mode) of + JBUF_PASS_THRU: + begin + if (coef^.whole_image[0] <> NIL) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + coef^.pub.compress_data := compress_data; + end; +{$ifdef FULL_COEF_BUFFER_SUPPORTED} + JBUF_SAVE_AND_PASS: + begin + if (coef^.whole_image[0] = NIL) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + coef^.pub.compress_data := compress_first_pass; + end; + JBUF_CRANK_DEST: + begin + if (coef^.whole_image[0] = NIL) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + coef^.pub.compress_data := compress_output; + end; +{$endif} + else + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + end; +end; + + +{ Process some data in the single-pass case. + We process the equivalent of one fully interleaved MCU row ("iMCU" row) + per call, ie, v_samp_factor block rows for each component in the image. + Returns TRUE if the iMCU row is completed, FALSE if suspended. + + NB: input_buf contains a plane for each component in image, + which we index according to the component's SOF position. } + + +{METHODDEF} +function compress_data (cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE) : boolean; +var + coef : my_coef_ptr; + MCU_col_num : JDIMENSION; { index of current MCU within row } + last_MCU_col : JDIMENSION; + last_iMCU_row : JDIMENSION; + blkn, bi, ci, yindex, yoffset, blockcnt : int; + ypos, xpos : JDIMENSION; + compptr : jpeg_component_info_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + last_MCU_col := cinfo^.MCUs_per_row - 1; + last_iMCU_row := cinfo^.total_iMCU_rows - 1; + + { Loop to write as much as one whole iMCU row } + for yoffset := coef^.MCU_vert_offset to pred(coef^.MCU_rows_per_iMCU_row) do + begin + for MCU_col_num := coef^.mcu_ctr to last_MCU_col do + begin + { Determine where data comes from in input_buf and do the DCT thing. + Each call on forward_DCT processes a horizontal row of DCT blocks + as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks + sequentially. Dummy blocks at the right or bottom edge are filled in + specially. The data in them does not matter for image reconstruction, + so we fill them with values that will encode to the smallest amount of + data, viz: all zeroes in the AC entries, DC entries equal to previous + block's DC value. (Thanks to Thomas Kinsman for this idea.) } + + blkn := 0; + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + if (MCU_col_num < last_MCU_col) then + blockcnt := compptr^.MCU_width + else + blockcnt := compptr^.last_col_width; + xpos := MCU_col_num * JDIMENSION(compptr^.MCU_sample_width); + ypos := yoffset * DCTSIZE; { ypos = (yoffset+yindex) * DCTSIZE } + for yindex := 0 to pred(compptr^.MCU_height) do + begin + if (coef^.iMCU_row_num < last_iMCU_row) or + (yoffset+yindex < compptr^.last_row_height) then + begin + cinfo^.fdct^.forward_DCT (cinfo, compptr, + input_buf^[compptr^.component_index], + coef^.MCU_buffer[blkn], + ypos, xpos, JDIMENSION (blockcnt)); + + if (blockcnt < compptr^.MCU_width) then + begin + { Create some dummy blocks at the right edge of the image. } + jzero_far({FAR}pointer(coef^.MCU_buffer[blkn + blockcnt]), + (compptr^.MCU_width - blockcnt) * SIZEOF(JBLOCK)); + for bi := blockcnt to pred(compptr^.MCU_width) do + begin + coef^.MCU_buffer[blkn+bi]^[0][0] := coef^.MCU_buffer[blkn+bi-1]^[0][0]; + end; + end; + end + else + begin + { Create a row of dummy blocks at the bottom of the image. } + jzero_far({FAR}pointer(coef^.MCU_buffer[blkn]), + compptr^.MCU_width * SIZEOF(JBLOCK)); + for bi := 0 to pred(compptr^.MCU_width) do + begin + coef^.MCU_buffer[blkn+bi]^[0][0] := coef^.MCU_buffer[blkn-1]^[0][0]; + end; + end; + Inc(blkn, compptr^.MCU_width); + Inc(ypos, DCTSIZE); + end; + end; + { Try to write the MCU. In event of a suspension failure, we will + re-DCT the MCU on restart (a bit inefficient, could be fixed...) } + + if (not cinfo^.entropy^.encode_mcu (cinfo, JBLOCKARRAY(@coef^.MCU_buffer)^)) then + begin + { Suspension forced; update state counters and exit } + coef^.MCU_vert_offset := yoffset; + coef^.mcu_ctr := MCU_col_num; + compress_data := FALSE; + exit; + end; + end; + { Completed an MCU row, but perhaps not an iMCU row } + coef^.mcu_ctr := 0; + end; + { Completed the iMCU row, advance counters for next one } + Inc(coef^.iMCU_row_num); + start_iMCU_row(cinfo); + compress_data := TRUE; +end; + + +{$ifdef FULL_COEF_BUFFER_SUPPORTED} + +{ Process some data in the first pass of a multi-pass case. + We process the equivalent of one fully interleaved MCU row ("iMCU" row) + per call, ie, v_samp_factor block rows for each component in the image. + This amount of data is read from the source buffer, DCT'd and quantized, + and saved into the virtual arrays. We also generate suitable dummy blocks + as needed at the right and lower edges. (The dummy blocks are constructed + in the virtual arrays, which have been padded appropriately.) This makes + it possible for subsequent passes not to worry about real vs. dummy blocks. + + We must also emit the data to the entropy encoder. This is conveniently + done by calling compress_output() after we've loaded the current strip + of the virtual arrays. + + NB: input_buf contains a plane for each component in image. All + components are DCT'd and loaded into the virtual arrays in this pass. + However, it may be that only a subset of the components are emitted to + the entropy encoder during this first pass; be careful about looking + at the scan-dependent variables (MCU dimensions, etc). } + +{METHODDEF} +function compress_first_pass (cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE) : boolean; +var + coef : my_coef_ptr; + last_iMCU_row : JDIMENSION; + blocks_across, MCUs_across, MCUindex : JDIMENSION; + bi, ci, h_samp_factor, block_row, block_rows, ndummy : int; + lastDC : JCOEF; + compptr : jpeg_component_info_ptr; + buffer : JBLOCKARRAY; + thisblockrow, lastblockrow : JBLOCKROW; +begin + coef := my_coef_ptr (cinfo^.coef); + last_iMCU_row := cinfo^.total_iMCU_rows - 1; + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Align the virtual buffer for this component. } + buffer := cinfo^.mem^.access_virt_barray + (j_common_ptr(cinfo), coef^.whole_image[ci], + coef^.iMCU_row_num * JDIMENSION(compptr^.v_samp_factor), + JDIMENSION (compptr^.v_samp_factor), TRUE); + { Count non-dummy DCT block rows in this iMCU row. } + if (coef^.iMCU_row_num < last_iMCU_row) then + block_rows := compptr^.v_samp_factor + else + begin + { NB: can't use last_row_height here, since may not be set! } + block_rows := int (compptr^.height_in_blocks) mod compptr^.v_samp_factor; + if (block_rows = 0) then + block_rows := compptr^.v_samp_factor; + end; + blocks_across := compptr^.width_in_blocks; + h_samp_factor := compptr^.h_samp_factor; + { Count number of dummy blocks to be added at the right margin. } + ndummy := int (blocks_across) mod h_samp_factor; + if (ndummy > 0) then + ndummy := h_samp_factor - ndummy; + { Perform DCT for all non-dummy blocks in this iMCU row. Each call + on forward_DCT processes a complete horizontal row of DCT blocks. } + + for block_row := 0 to pred(block_rows) do + begin + thisblockrow := buffer^[block_row]; + cinfo^.fdct^.forward_DCT (cinfo, compptr, + input_buf^[ci], + thisblockrow, + JDIMENSION (block_row * DCTSIZE), + JDIMENSION (0), + blocks_across); + if (ndummy > 0) then + begin + { Create dummy blocks at the right edge of the image. } + Inc(JBLOCK_PTR(thisblockrow), blocks_across); { => first dummy block } + jzero_far({FAR}pointer(thisblockrow), ndummy * SIZEOF(JBLOCK)); + {lastDC := thisblockrow^[-1][0];} + { work around Range Checking } + Dec(JBLOCK_PTR(thisblockrow)); + lastDC := thisblockrow^[0][0]; + Inc(JBLOCK_PTR(thisblockrow)); + + for bi := 0 to pred(ndummy) do + begin + thisblockrow^[bi][0] := lastDC; + end; + end; + end; + { If at end of image, create dummy block rows as needed. + The tricky part here is that within each MCU, we want the DC values + of the dummy blocks to match the last real block's DC value. + This squeezes a few more bytes out of the resulting file... } + + if (coef^.iMCU_row_num = last_iMCU_row) then + begin + Inc(blocks_across, ndummy); { include lower right corner } + MCUs_across := blocks_across div JDIMENSION(h_samp_factor); + for block_row := block_rows to pred(compptr^.v_samp_factor) do + begin + thisblockrow := buffer^[block_row]; + lastblockrow := buffer^[block_row-1]; + jzero_far({FAR} pointer(thisblockrow), + size_t(blocks_across * SIZEOF(JBLOCK))); + for MCUindex := 0 to pred(MCUs_across) do + begin + lastDC := lastblockrow^[h_samp_factor-1][0]; + for bi := 0 to pred(h_samp_factor) do + begin + thisblockrow^[bi][0] := lastDC; + end; + Inc(JBLOCK_PTR(thisblockrow), h_samp_factor); { advance to next MCU in row } + Inc(JBLOCK_PTR(lastblockrow), h_samp_factor); + end; + end; + end; + Inc(compptr); + end; + { NB: compress_output will increment iMCU_row_num if successful. + A suspension return will result in redoing all the work above next time.} + + + { Emit data to the entropy encoder, sharing code with subsequent passes } + compress_first_pass := compress_output(cinfo, input_buf); +end; + + +{ Process some data in subsequent passes of a multi-pass case. + We process the equivalent of one fully interleaved MCU row ("iMCU" row) + per call, ie, v_samp_factor block rows for each component in the scan. + The data is obtained from the virtual arrays and fed to the entropy coder. + Returns TRUE if the iMCU row is completed, FALSE if suspended. + + NB: input_buf is ignored; it is likely to be a NIL pointer. } + +{METHODDEF} +function compress_output (cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE) : boolean; +var + coef : my_coef_ptr; + MCU_col_num : JDIMENSION; { index of current MCU within row } + blkn, ci, xindex, yindex, yoffset : int; + start_col : JDIMENSION; + buffer : array[0..MAX_COMPS_IN_SCAN-1] of JBLOCKARRAY; + buffer_ptr : JBLOCKROW; + compptr : jpeg_component_info_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + + { Align the virtual buffers for the components used in this scan. + NB: during first pass, this is safe only because the buffers will + already be aligned properly, so jmemmgr.c won't need to do any I/O. } + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + buffer[ci] := cinfo^.mem^.access_virt_barray ( + j_common_ptr(cinfo), coef^.whole_image[compptr^.component_index], + coef^.iMCU_row_num * JDIMENSION(compptr^.v_samp_factor), + JDIMENSION (compptr^.v_samp_factor), FALSE); + end; + + { Loop to process one whole iMCU row } + for yoffset := coef^.MCU_vert_offset to pred(coef^.MCU_rows_per_iMCU_row) do + begin + for MCU_col_num := coef^.mcu_ctr to pred(cinfo^.MCUs_per_row) do + begin + { Construct list of pointers to DCT blocks belonging to this MCU } + blkn := 0; { index of current DCT block within MCU } + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + start_col := MCU_col_num * JDIMENSION(compptr^.MCU_width); + for yindex := 0 to pred(compptr^.MCU_height) do + begin + buffer_ptr := JBLOCKROW(@ buffer[ci]^[yindex+yoffset]^[start_col]); + for xindex := 0 to pred(compptr^.MCU_width) do + begin + coef^.MCU_buffer[blkn] := buffer_ptr; + Inc(blkn); + Inc(JBLOCK_PTR(buffer_ptr)); + end; + end; + end; + { Try to write the MCU. } + if (not cinfo^.entropy^.encode_mcu (cinfo, coef^.MCU_buffer)) then + begin + { Suspension forced; update state counters and exit } + coef^.MCU_vert_offset := yoffset; + coef^.mcu_ctr := MCU_col_num; + compress_output := FALSE; + exit; + end; + end; + { Completed an MCU row, but perhaps not an iMCU row } + coef^.mcu_ctr := 0; + end; + { Completed the iMCU row, advance counters for next one } + Inc(coef^.iMCU_row_num); + start_iMCU_row(cinfo); + compress_output := TRUE; +end; + +{$endif} { FULL_COEF_BUFFER_SUPPORTED } + + +{ Initialize coefficient buffer controller. } + +{GLOBAL} +procedure jinit_c_coef_controller (cinfo : j_compress_ptr; + need_full_buffer : boolean); +var + coef : my_coef_ptr; +var + buffer : JBLOCKROW; + i : int; +var + ci : int; + compptr : jpeg_component_info_ptr; +begin + coef := my_coef_ptr ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_coef_controller)) ); + cinfo^.coef := jpeg_c_coef_controller_ptr(coef); + coef^.pub.start_pass := start_pass_coef; + + { Create the coefficient buffer. } + if (need_full_buffer) then + begin +{$ifdef FULL_COEF_BUFFER_SUPPORTED} + { Allocate a full-image virtual array for each component, } + { padded to a multiple of samp_factor DCT blocks in each direction. } + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + coef^.whole_image[ci] := cinfo^.mem^.request_virt_barray + (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE, + JDIMENSION (jround_up( long (compptr^.width_in_blocks), + long (compptr^.h_samp_factor) )), + JDIMENSION (jround_up(long (compptr^.height_in_blocks), + long (compptr^.v_samp_factor))), + JDIMENSION (compptr^.v_samp_factor)); + Inc(compptr); + end; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); +{$endif} + end + else + begin + { We only need a single-MCU buffer. } + buffer := JBLOCKROW ( + cinfo^.mem^.alloc_large (j_common_ptr(cinfo), JPOOL_IMAGE, + C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)) ); + for i := 0 to pred(C_MAX_BLOCKS_IN_MCU) do + begin + coef^.MCU_buffer[i] := JBLOCKROW(@ buffer^[i]); + end; + coef^.whole_image[0] := NIL; { flag for no virtual arrays } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjccolor.pas b/src/lib/vampimg/JpegLib/imjccolor.pas new file mode 100644 index 0000000..09fb8af --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjccolor.pas @@ -0,0 +1,530 @@ +unit imjccolor; + +{ This file contains input colorspace conversion routines. } + +{ Original : jccolor.c ; Copyright (C) 1991-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib; + +{ Module initialization routine for input colorspace conversion. } + +{GLOBAL} +procedure jinit_color_converter (cinfo : j_compress_ptr); + +implementation + +{ Private subobject } +type + INT32_FIELD = array[0..MaxInt div SizeOf(INT32) - 1] of INT32; + INT32_FIELD_PTR = ^INT32_FIELD; + +type + my_cconvert_ptr = ^my_color_converter; + my_color_converter = record + pub : jpeg_color_converter; { public fields } + + { Private state for RGB -> YCC conversion } + rgb_ycc_tab : INT32_FIELD_PTR; { => table for RGB to YCbCr conversion } + end; {my_color_converter;} + + +{*************** RGB -> YCbCr conversion: most common case *************} + +{ + YCbCr is defined per CCIR 601-1, except that Cb and Cr are + normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + The conversion equations to be implemented are therefore + Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE + Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE + (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, + rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and + negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) + were not represented exactly. Now we sacrifice exact representation of + maximum red and maximum blue in order to get exact grayscales. + + To avoid floating-point arithmetic, we represent the fractional constants + as integers scaled up by 2^16 (about 4 digits precision); we have to divide + the products by 2^16, with appropriate rounding, to get the correct answer. + + For even more speed, we avoid doing any multiplications in the inner loop + by precalculating the constants times R,G,B for all possible values. + For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + for 12-bit samples it is still acceptable. It's not very reasonable for + 16-bit samples, but if you want lossless storage you shouldn't be changing + colorspace anyway. + The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included + in the tables to save adding them separately in the inner loop. } +const + SCALEBITS = 16; { speediest right-shift on some machines } + CBCR_OFFSET = INT32(CENTERJSAMPLE shl SCALEBITS); + ONE_HALF = INT32(1) shl (SCALEBITS-1); + + +{ We allocate one big table and divide it up into eight parts, instead of + doing eight alloc_small requests. This lets us use a single table base + address, which can be held in a register in the inner loops on many + machines (more than can hold all eight addresses, anyway). } + + R_Y_OFF = 0; { offset to R => Y section } + G_Y_OFF = 1*(MAXJSAMPLE+1); { offset to G => Y section } + B_Y_OFF = 2*(MAXJSAMPLE+1); { etc. } + R_CB_OFF = 3*(MAXJSAMPLE+1); + G_CB_OFF = 4*(MAXJSAMPLE+1); + B_CB_OFF = 5*(MAXJSAMPLE+1); + R_CR_OFF = B_CB_OFF; { B=>Cb, R=>Cr are the same } + G_CR_OFF = 6*(MAXJSAMPLE+1); + B_CR_OFF = 7*(MAXJSAMPLE+1); + TABLE_SIZE = 8*(MAXJSAMPLE+1); + + +{ Initialize for RGB->YCC colorspace conversion. } + +{METHODDEF} +procedure rgb_ycc_start (cinfo : j_compress_ptr); +const + FIX_0_29900 = INT32(Round(0.29900 * (1 shl SCALEBITS))); + FIX_0_58700 = INT32(Round(0.58700 * (1 shl SCALEBITS))); + FIX_0_11400 = INT32(Round(0.11400 * (1 shl SCALEBITS))); + FIX_0_16874 = INT32(Round(0.16874 * (1 shl SCALEBITS))); + FIX_0_33126 = INT32(Round(0.33126 * (1 shl SCALEBITS))); + FIX_0_50000 = INT32(Round(0.50000 * (1 shl SCALEBITS))); + FIX_0_41869 = INT32(Round(0.41869 * (1 shl SCALEBITS))); + FIX_0_08131 = INT32(Round(0.08131 * (1 shl SCALEBITS))); +var + cconvert : my_cconvert_ptr; + rgb_ycc_tab : INT32_FIELD_PTR; + i : INT32; +begin + cconvert := my_cconvert_ptr (cinfo^.cconvert); + + { Allocate and fill in the conversion tables. } + rgb_ycc_tab := INT32_FIELD_PTR( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))) ); + cconvert^.rgb_ycc_tab := rgb_ycc_tab; + + for i := 0 to MAXJSAMPLE do + begin + rgb_ycc_tab^[i+R_Y_OFF] := FIX_0_29900 * i; + rgb_ycc_tab^[i+G_Y_OFF] := FIX_0_58700 * i; + rgb_ycc_tab^[i+B_Y_OFF] := FIX_0_11400 * i + ONE_HALF; + rgb_ycc_tab^[i+R_CB_OFF] := (-FIX_0_16874) * i; + rgb_ycc_tab^[i+G_CB_OFF] := (-FIX_0_33126) * i; + { We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. + This ensures that the maximum output will round to MAXJSAMPLE + not MAXJSAMPLE+1, and thus that we don't have to range-limit. } + + rgb_ycc_tab^[i+B_CB_OFF] := FIX_0_50000 * i + CBCR_OFFSET + ONE_HALF-1; +{ B=>Cb and R=>Cr tables are the same + rgb_ycc_tab^[i+R_CR_OFF] := FIX_0_50000 * i + CBCR_OFFSET + ONE_HALF-1; +} + rgb_ycc_tab^[i+G_CR_OFF] := (-FIX_0_41869) * i; + rgb_ycc_tab^[i+B_CR_OFF] := (-FIX_0_08131) * i; + end; +end; + + +{ Convert some rows of samples to the JPEG colorspace. + + Note that we change from the application's interleaved-pixel format + to our internal noninterleaved, one-plane-per-component format. + The input buffer is therefore three times as wide as the output buffer. + + A starting row offset is provided only for the output buffer. The caller + can easily adjust the passed input_buf value to accommodate any row + offset required on that side. } + +{METHODDEF} +procedure rgb_ycc_convert (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPIMAGE; + output_row : JDIMENSION; + num_rows : int); +var + cconvert : my_cconvert_ptr; + {register} r, g, b : int; + {register} ctab : INT32_FIELD_PTR; + {register} inptr : JSAMPROW; + {register} outptr0, outptr1, outptr2 : JSAMPROW; + {register} col : JDIMENSION; + num_cols : JDIMENSION; +begin + cconvert := my_cconvert_ptr (cinfo^.cconvert); + ctab := cconvert^.rgb_ycc_tab; + num_cols := cinfo^.image_width; + + while (num_rows > 0) do + begin + Dec(num_rows); + inptr := input_buf^[0]; + Inc(JSAMPROW_PTR(input_buf)); + outptr0 := output_buf^[0]^[output_row]; + outptr1 := output_buf^[1]^[output_row]; + outptr2 := output_buf^[2]^[output_row]; + Inc(output_row); + for col := 0 to pred(num_cols) do + begin + r := GETJSAMPLE(inptr^[RGB_RED]); + g := GETJSAMPLE(inptr^[RGB_GREEN]); + b := GETJSAMPLE(inptr^[RGB_BLUE]); + Inc(JSAMPLE_PTR(inptr), RGB_PIXELSIZE); + { If the inputs are 0..MAXJSAMPLE, the outputs of these equations + must be too; we do not need an explicit range-limiting operation. + Hence the value being shifted is never negative, and we don't + need the general RIGHT_SHIFT macro. } + + { Y } + outptr0^[col] := JSAMPLE( + ((ctab^[r+R_Y_OFF] + ctab^[g+G_Y_OFF] + ctab^[b+B_Y_OFF]) + shr SCALEBITS) ); + { Cb } + outptr1^[col] := JSAMPLE( + ((ctab^[r+R_CB_OFF] + ctab^[g+G_CB_OFF] + ctab^[b+B_CB_OFF]) + shr SCALEBITS) ); + { Cr } + outptr2^[col] := JSAMPLE( + ((ctab^[r+R_CR_OFF] + ctab^[g+G_CR_OFF] + ctab^[b+B_CR_OFF]) + shr SCALEBITS) ); + end; + end; +end; + + +{*************** Cases other than RGB -> YCbCr *************} + + +{ Convert some rows of samples to the JPEG colorspace. + This version handles RGB -> grayscale conversion, which is the same + as the RGB -> Y portion of RGB -> YCbCr. + We assume rgb_ycc_start has been called (we only use the Y tables). } + +{METHODDEF} +procedure rgb_gray_convert (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPIMAGE; + output_row : JDIMENSION; + num_rows : int); +var + cconvert : my_cconvert_ptr; + {register} r, g, b : int; + {register} ctab :INT32_FIELD_PTR; + {register} inptr : JSAMPROW; + {register} outptr : JSAMPROW; + {register} col : JDIMENSION; + num_cols : JDIMENSION; +begin + cconvert := my_cconvert_ptr (cinfo^.cconvert); + ctab := cconvert^.rgb_ycc_tab; + num_cols := cinfo^.image_width; + + while (num_rows > 0) do + begin + Dec(num_rows); + inptr := input_buf[0]; + Inc(JSAMPROW_PTR(input_buf)); + outptr := output_buf[0][output_row]; + Inc(output_row); + for col := 0 to num_cols - 1 do + begin + r := GETJSAMPLE(inptr[RGB_RED]); + g := GETJSAMPLE(inptr[RGB_GREEN]); + b := GETJSAMPLE(inptr[RGB_BLUE]); + Inc(JSAMPLE_PTR(inptr), RGB_PIXELSIZE); + (* Y *) + // kylix 3 compiler crashes on this + // it also crashes Delphi OSX compiler 9 years later :( + {$IF not (Defined(DCC) and not Defined(MSWINDOWS))} + outptr[col] := JSAMPLE(((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) shr SCALEBITS)); + {$IFEND} + end; + end; +end; + + +{ Convert some rows of samples to the JPEG colorspace. + This version handles Adobe-style CMYK -> YCCK conversion, + where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same + conversion as above, while passing K (black) unchanged. + We assume rgb_ycc_start has been called. } + +{METHODDEF} +procedure cmyk_ycck_convert (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPIMAGE; + output_row : JDIMENSION; + num_rows : int); +var + cconvert : my_cconvert_ptr; + {register} r, g, b : int; + {register} ctab : INT32_FIELD_PTR; + {register} inptr : JSAMPROW; + {register} outptr0, outptr1, outptr2, outptr3 : JSAMPROW; + {register} col : JDIMENSION; + num_cols : JDIMENSION; +begin + cconvert := my_cconvert_ptr (cinfo^.cconvert); + ctab := cconvert^.rgb_ycc_tab; + num_cols := cinfo^.image_width; + + while (num_rows > 0) do + begin + Dec(num_rows); + inptr := input_buf^[0]; + Inc(JSAMPROW_PTR(input_buf)); + outptr0 := output_buf^[0]^[output_row]; + outptr1 := output_buf^[1]^[output_row]; + outptr2 := output_buf^[2]^[output_row]; + outptr3 := output_buf^[3]^[output_row]; + Inc(output_row); + for col := 0 to pred(num_cols) do + begin + r := MAXJSAMPLE - GETJSAMPLE(inptr^[0]); + g := MAXJSAMPLE - GETJSAMPLE(inptr^[1]); + b := MAXJSAMPLE - GETJSAMPLE(inptr^[2]); + { K passes through as-is } + outptr3^[col] := inptr^[3]; { don't need GETJSAMPLE here } + Inc(JSAMPLE_PTR(inptr), 4); + { If the inputs are 0..MAXJSAMPLE, the outputs of these equations + must be too; we do not need an explicit range-limiting operation. + Hence the value being shifted is never negative, and we don't + need the general RIGHT_SHIFT macro. } + + { Y } + outptr0^[col] := JSAMPLE ( + ((ctab^[r+R_Y_OFF] + ctab^[g+G_Y_OFF] + ctab^[b+B_Y_OFF]) + shr SCALEBITS) ); + { Cb } + outptr1^[col] := JSAMPLE( + ((ctab^[r+R_CB_OFF] + ctab^[g+G_CB_OFF] + ctab^[b+B_CB_OFF]) + shr SCALEBITS) ); + { Cr } + outptr2^[col] := JSAMPLE ( + ((ctab^[r+R_CR_OFF] + ctab^[g+G_CR_OFF] + ctab^[b+B_CR_OFF]) + shr SCALEBITS) ); + end; + end; +end; + + +{ Convert some rows of samples to the JPEG colorspace. + This version handles grayscale output with no conversion. + The source can be either plain grayscale or YCbCr (since Y = gray). } + +{METHODDEF} +procedure grayscale_convert (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPIMAGE; + output_row : JDIMENSION; + num_rows: int); +var + {register} inptr : JSAMPROW; + {register} outptr : JSAMPROW; + {register} col : JDIMENSION; + num_cols :JDIMENSION; + instride : int; +begin + num_cols := cinfo^.image_width; + instride := cinfo^.input_components; + + while (num_rows > 0) do + begin + Dec(num_rows); + inptr := input_buf^[0]; + Inc(JSAMPROW_PTR(input_buf)); + outptr := output_buf^[0]^[output_row]; + Inc(output_row); + for col := 0 to pred(num_cols) do + begin + outptr^[col] := inptr^[0]; { don't need GETJSAMPLE() here } + Inc(JSAMPLE_PTR(inptr), instride); + end; + end; +end; + + +{ Convert some rows of samples to the JPEG colorspace. + This version handles multi-component colorspaces without conversion. + We assume input_components = num_components. } + +{METHODDEF} +procedure null_convert (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPIMAGE; + output_row : JDIMENSION; + num_rows : int); +var + {register} inptr : JSAMPROW; + {register} outptr : JSAMPROW; + {register} col : JDIMENSION; + {register} ci : int; + nc : int; + num_cols : JDIMENSION; +begin + nc := cinfo^.num_components; + num_cols := cinfo^.image_width; + + while (num_rows > 0) do + begin + Dec(num_rows); + { It seems fastest to make a separate pass for each component. } + for ci := 0 to pred(nc) do + begin + inptr := input_buf^[0]; + outptr := output_buf^[ci]^[output_row]; + for col := 0 to pred(num_cols) do + begin + outptr^[col] := inptr^[ci]; { don't need GETJSAMPLE() here } + Inc(JSAMPLE_PTR(inptr), nc); + end; + end; + Inc(JSAMPROW_PTR(input_buf)); + Inc(output_row); + end; +end; + + +{ Empty method for start_pass. } + +{METHODDEF} +procedure null_method (cinfo : j_compress_ptr); +begin + { no work needed } +end; + + +{ Module initialization routine for input colorspace conversion. } + +{GLOBAL} +procedure jinit_color_converter (cinfo : j_compress_ptr); +var + cconvert : my_cconvert_ptr; +begin + cconvert := my_cconvert_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_color_converter)) ); + cinfo^.cconvert := jpeg_color_converter_ptr(cconvert); + { set start_pass to null method until we find out differently } + cconvert^.pub.start_pass := null_method; + + { Make sure input_components agrees with in_color_space } + case (cinfo^.in_color_space) of + JCS_GRAYSCALE: + if (cinfo^.input_components <> 1) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_IN_COLORSPACE); + +{$ifdef RGB_PIXELSIZE <> 3} + JCS_RGB: + if (cinfo^.input_components <> RGB_PIXELSIZE) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_IN_COLORSPACE); +{$else} { share code with YCbCr } + JCS_RGB, +{$endif} + JCS_YCbCr: + if (cinfo^.input_components <> 3) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_IN_COLORSPACE); + + JCS_CMYK, + JCS_YCCK: + if (cinfo^.input_components <> 4) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_IN_COLORSPACE); + + else { JCS_UNKNOWN can be anything } + if (cinfo^.input_components < 1) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_IN_COLORSPACE); + end; + + { Check num_components, set conversion method based on requested space } + case (cinfo^.jpeg_color_space) of + JCS_GRAYSCALE: + begin + if (cinfo^.num_components <> 1) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + if (cinfo^.in_color_space = JCS_GRAYSCALE) then + cconvert^.pub.color_convert := grayscale_convert + else + if (cinfo^.in_color_space = JCS_RGB) then + begin + cconvert^.pub.start_pass := rgb_ycc_start; + cconvert^.pub.color_convert := rgb_gray_convert; + end + else + if (cinfo^.in_color_space = JCS_YCbCr) then + cconvert^.pub.color_convert := grayscale_convert + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + JCS_RGB: + begin + if (cinfo^.num_components <> 3) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + if (cinfo^.in_color_space = JCS_RGB) and (RGB_PIXELSIZE = 3) then + cconvert^.pub.color_convert := null_convert + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + JCS_YCbCr: + begin + if (cinfo^.num_components <> 3) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + if (cinfo^.in_color_space = JCS_RGB) then + begin + cconvert^.pub.start_pass := rgb_ycc_start; + cconvert^.pub.color_convert := rgb_ycc_convert; + end + else + if (cinfo^.in_color_space = JCS_YCbCr) then + cconvert^.pub.color_convert := null_convert + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + JCS_CMYK: + begin + if (cinfo^.num_components <> 4) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + if (cinfo^.in_color_space = JCS_CMYK) then + cconvert^.pub.color_convert := null_convert + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + JCS_YCCK: + begin + if (cinfo^.num_components <> 4) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + if (cinfo^.in_color_space = JCS_CMYK) then + begin + cconvert^.pub.start_pass := rgb_ycc_start; + cconvert^.pub.color_convert := cmyk_ycck_convert; + end + else + if (cinfo^.in_color_space = JCS_YCCK) then + cconvert^.pub.color_convert := null_convert + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + else { allow null conversion of JCS_UNKNOWN } + begin + if (cinfo^.jpeg_color_space <> cinfo^.in_color_space) or + (cinfo^.num_components <> cinfo^.input_components) then + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + cconvert^.pub.color_convert := null_convert; + end; + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcdctmgr.pas b/src/lib/vampimg/JpegLib/imjcdctmgr.pas new file mode 100644 index 0000000..f63569e --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcdctmgr.pas @@ -0,0 +1,514 @@ +unit imjcdctmgr; + +{ Original : jcdctmgr.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +{ This file is part of the Independent JPEG Group's software. + For conditions of distribution and use, see the accompanying README file. + + This file contains the forward-DCT management logic. + This code selects a particular DCT implementation to be used, + and it performs related housekeeping chores including coefficient + quantization. } + +interface + +{$N+} +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib, + imjdct, { Private declarations for DCT subsystem } + imjfdctint, imjfdctfst, imjfdctflt; + +{ Initialize FDCT manager. } + +{GLOBAL} +procedure jinit_forward_dct (cinfo : j_compress_ptr); + +implementation + + +{ Private subobject for this module } + +type + my_fdct_ptr = ^my_fdct_controller; + my_fdct_controller = record + pub : jpeg_forward_dct; { public fields } + + { Pointer to the DCT routine actually in use } + do_dct : forward_DCT_method_ptr; + + { The actual post-DCT divisors --- not identical to the quant table + entries, because of scaling (especially for an unnormalized DCT). + Each table is given in normal array order. } + + divisors : array[0..NUM_QUANT_TBLS-1] of DCTELEM_FIELD_PTR; + + {$ifdef DCT_FLOAT_SUPPORTED} + { Same as above for the floating-point case. } + do_float_dct : float_DCT_method_ptr; + float_divisors : array[0..NUM_QUANT_TBLS-1] of FAST_FLOAT_FIELD_PTR; + {$endif} + end; + + +{ Initialize for a processing pass. + Verify that all referenced Q-tables are present, and set up + the divisor table for each one. + In the current implementation, DCT of all components is done during + the first pass, even if only some components will be output in the + first scan. Hence all components should be examined here. } + +{METHODDEF} +procedure start_pass_fdctmgr (cinfo : j_compress_ptr); +var + fdct : my_fdct_ptr; + ci, qtblno, i : int; + compptr : jpeg_component_info_ptr; + qtbl : JQUANT_TBL_PTR; + dtbl : DCTELEM_FIELD_PTR; +{$ifdef DCT_IFAST_SUPPORTED} +const + CONST_BITS = 14; + aanscales : array[0..DCTSIZE2-1] of INT16 = + ({ precomputed values scaled up by 14 bits } + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247); + {SHIFT_TEMPS} + + { Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + + function DESCALE(x : INT32; n : int) : INT32; + var + shift_temp : INT32; + begin + shift_temp := x + (INT32(1) shl (n-1)); + {$ifdef RIGHT_SHIFT_IS_UNSIGNED} + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else + {$endif} + Descale := (shift_temp shr n); + end; + +{$endif} +{$ifdef DCT_FLOAT_SUPPORTED} +var + fdtbl : FAST_FLOAT_FIELD_PTR; + row, col : int; +const + aanscalefactor : array[0..DCTSIZE-1] of double = + (1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379); +{$endif} +begin + fdct := my_fdct_ptr (cinfo^.fdct); + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + qtblno := compptr^.quant_tbl_no; + { Make sure specified quantization table is present } + if (qtblno < 0) or (qtblno >= NUM_QUANT_TBLS) or + (cinfo^.quant_tbl_ptrs[qtblno] = NIL) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_QUANT_TABLE, qtblno); + qtbl := cinfo^.quant_tbl_ptrs[qtblno]; + { Compute divisors for this quant table } + { We may do this more than once for same table, but it's not a big deal } + case (cinfo^.dct_method) of +{$ifdef DCT_ISLOW_SUPPORTED} + JDCT_ISLOW: + begin + { For LL&M IDCT method, divisors are equal to raw quantization + coefficients multiplied by 8 (to counteract scaling). } + + if (fdct^.divisors[qtblno] = NIL) then + begin + fdct^.divisors[qtblno] := DCTELEM_FIELD_PTR( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)) ); + end; + dtbl := fdct^.divisors[qtblno]; + for i := 0 to pred(DCTSIZE2) do + begin + dtbl^[i] := (DCTELEM(qtbl^.quantval[i])) shl 3; + end; + end; +{$endif} +{$ifdef DCT_IFAST_SUPPORTED} + JDCT_IFAST: + begin + { For AA&N IDCT method, divisors are equal to quantization + coefficients scaled by scalefactor[row]*scalefactor[col], where + scalefactor[0] := 1 + scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7 + We apply a further scale factor of 8. } + + + if (fdct^.divisors[qtblno] = NIL) then + begin + fdct^.divisors[qtblno] := DCTELEM_FIELD_PTR( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(DCTELEM)) ); + end; + dtbl := fdct^.divisors[qtblno]; + for i := 0 to pred(DCTSIZE2) do + begin + dtbl^[i] := DCTELEM( + {MULTIPLY16V16} + DESCALE( INT32(qtbl^.quantval[i]) * INT32 (aanscales[i]), + CONST_BITS-3) ); + end; + end; +{$endif} +{$ifdef DCT_FLOAT_SUPPORTED} + + JDCT_FLOAT: + begin + { For float AA&N IDCT method, divisors are equal to quantization + coefficients scaled by scalefactor[row]*scalefactor[col], where + scalefactor[0] := 1 + scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7 + We apply a further scale factor of 8. + What's actually stored is 1/divisor so that the inner loop can + use a multiplication rather than a division. } + + if (fdct^.float_divisors[qtblno] = NIL) then + begin + fdct^.float_divisors[qtblno] := FAST_FLOAT_FIELD_PTR( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + DCTSIZE2 * SIZEOF(FAST_FLOAT)) ); + end; + fdtbl := fdct^.float_divisors[qtblno]; + i := 0; + for row := 0 to pred(DCTSIZE) do + begin + for col := 0 to pred(DCTSIZE) do + begin + fdtbl^[i] := {FAST_FLOAT} + (1.0 / (( {double}(qtbl^.quantval[i]) * + aanscalefactor[row] * aanscalefactor[col] * 8.0))); + Inc(i); + end; + end; + end; +{$endif} + else + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); + end; + Inc(compptr); + end; +end; + + +{ Perform forward DCT on one or more blocks of a component. + + The input samples are taken from the sample_data[] array starting at + position start_row/start_col, and moving to the right for any additional + blocks. The quantized coefficients are returned in coef_blocks[]. } + +{METHODDEF} +procedure forward_DCT (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + sample_data : JSAMPARRAY; + coef_blocks : JBLOCKROW; + start_row : JDIMENSION; + start_col : JDIMENSION; + num_blocks : JDIMENSION); +{ This version is used for integer DCT implementations. } +var + { This routine is heavily used, so it's worth coding it tightly. } + fdct : my_fdct_ptr; + do_dct : forward_DCT_method_ptr; + divisors : DCTELEM_FIELD_PTR; + workspace : array[0..DCTSIZE2-1] of DCTELEM; { work area for FDCT subroutine } + bi : JDIMENSION; +var + {register} workspaceptr : DCTELEMPTR; + {register} elemptr : JSAMPLE_PTR; + {register} elemr : int; +{$ifndef DCTSIZE_IS_8} +var + {register} elemc : int; +{$endif} +var + {register} temp, qval : DCTELEM; + {register} i : int; + {register} output_ptr : JCOEFPTR; +begin + fdct := my_fdct_ptr (cinfo^.fdct); + do_dct := fdct^.do_dct; + divisors := fdct^.divisors[compptr^.quant_tbl_no]; + + Inc(JSAMPROW_PTR(sample_data), start_row); { fold in the vertical offset once } + + for bi := 0 to pred(num_blocks) do + begin + + { Load data into workspace, applying unsigned->signed conversion } + + workspaceptr := @workspace[0]; + for elemr := 0 to pred(DCTSIZE) do + begin + elemptr := @sample_data^[elemr]^[start_col]; +{$ifdef DCTSIZE_IS_8} { unroll the inner loop } + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + {Inc(elemptr); - Value never used } +{$else} + for elemc := pred(DCTSIZE) downto 0 do + begin + workspaceptr^ := GETJSAMPLE(elemptr^) - CENTERJSAMPLE; + Inc(workspaceptr); + Inc(elemptr); + end; +{$endif} + end; + + { Perform the DCT } + do_dct (workspace); + + { Quantize/descale the coefficients, and store into coef_blocks[] } + + output_ptr := JCOEFPTR(@coef_blocks^[bi]); + for i := 0 to pred(DCTSIZE2) do + begin + qval := divisors^[i]; + temp := workspace[i]; + { Divide the coefficient value by qval, ensuring proper rounding. + Since C does not specify the direction of rounding for negative + quotients, we have to force the dividend positive for portability. + + In most files, at least half of the output values will be zero + (at default quantization settings, more like three-quarters...) + so we should ensure that this case is fast. On many machines, + a comparison is enough cheaper than a divide to make a special test + a win. Since both inputs will be nonnegative, we need only test + for a < b to discover whether a/b is 0. + If your machine's division is fast enough, define FAST_DIVIDE. } + + if (temp < 0) then + begin + temp := -temp; + Inc(temp, qval shr 1); { for rounding } + {DIVIDE_BY(temp, qval);} + {$ifdef FAST_DIVIDE} + temp := temp div qval; + {$else} + if (temp >= qval) then + temp := temp div qval + else + temp := 0; + {$endif} + temp := -temp; + end + else + begin + Inc(temp, qval shr 1); { for rounding } + {DIVIDE_BY(temp, qval);} + {$ifdef FAST_DIVIDE} + temp := temp div qval; + {$else} + if (temp >= qval) then + temp := temp div qval + else + temp := 0; + {$endif} + end; + output_ptr^[i] := JCOEF (temp); + end; + Inc(start_col, DCTSIZE); + end; +end; + + +{$ifdef DCT_FLOAT_SUPPORTED} + +{METHODDEF} +procedure forward_DCT_float (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + sample_data : JSAMPARRAY; + coef_blocks : JBLOCKROW; + start_row : JDIMENSION; + start_col : JDIMENSION; + num_blocks : JDIMENSION); +{ This version is used for floating-point DCT implementations. } +var + { This routine is heavily used, so it's worth coding it tightly. } + fdct : my_fdct_ptr; + do_dct : float_DCT_method_ptr; + divisors : FAST_FLOAT_FIELD_PTR; + workspace : array[0..DCTSIZE2-1] of FAST_FLOAT; { work area for FDCT subroutine } + bi : JDIMENSION; +var + {register} workspaceptr : FAST_FLOAT_PTR; + {register} elemptr : JSAMPLE_PTR; + {register} elemr : int; +{$ifndef DCTSIZE_IS_8} +var + {register} elemc : int; +{$endif} +var + {register} temp : FAST_FLOAT; + {register} i : int; + {register} output_ptr : JCOEFPTR; +begin + fdct := my_fdct_ptr (cinfo^.fdct); + do_dct := fdct^.do_float_dct; + divisors := fdct^.float_divisors[compptr^.quant_tbl_no]; + + Inc(JSAMPROW_PTR(sample_data), start_row); { fold in the vertical offset once } + + for bi := 0 to pred(num_blocks) do + begin + { Load data into workspace, applying unsigned->signed conversion } + + workspaceptr := @workspace[0]; + for elemr := 0 to pred(DCTSIZE) do + begin + elemptr := @(sample_data^[elemr]^[start_col]); +{$ifdef DCTSIZE_IS_8} { unroll the inner loop } + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + Inc(elemptr); + workspaceptr^ := {FAST_FLOAT}(GETJSAMPLE(elemptr^) - CENTERJSAMPLE); + Inc(workspaceptr); + {Inc(elemptr); - value never used } +{$else} + for elemc := pred(DCTSIZE) downto 0 do + begin + workspaceptr^ := {FAST_FLOAT}( + (GETJSAMPLE(elemptr^) - CENTERJSAMPLE) ); + Inc(workspaceptr); + Inc(elemptr); + end; +{$endif} + end; + + + { Perform the DCT } + do_dct (workspace); + + { Quantize/descale the coefficients, and store into coef_blocks[] } + + output_ptr := JCOEFPTR(@(coef_blocks^[bi])); + + for i := 0 to pred(DCTSIZE2) do + begin + { Apply the quantization and scaling factor } + temp := workspace[i] * divisors^[i]; + { Round to nearest integer. + Since C does not specify the direction of rounding for negative + quotients, we have to force the dividend positive for portability. + The maximum coefficient size is +-16K (for 12-bit data), so this + code should work for either 16-bit or 32-bit ints. } + output_ptr^[i] := JCOEF ( int(Trunc (temp + {FAST_FLOAT}(16384.5))) - 16384); + end; + Inc(start_col, DCTSIZE); + end; +end; + +{$endif} { DCT_FLOAT_SUPPORTED } + + +{ Initialize FDCT manager. } + +{GLOBAL} +procedure jinit_forward_dct (cinfo : j_compress_ptr); +var + fdct : my_fdct_ptr; + i : int; +begin + fdct := my_fdct_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_fdct_controller)) ); + cinfo^.fdct := jpeg_forward_dct_ptr (fdct); + fdct^.pub.start_pass := start_pass_fdctmgr; + + case (cinfo^.dct_method) of +{$ifdef DCT_ISLOW_SUPPORTED} + JDCT_ISLOW: + begin + fdct^.pub.forward_DCT := forward_DCT; + fdct^.do_dct := jpeg_fdct_islow; + end; +{$endif} +{$ifdef DCT_IFAST_SUPPORTED} + JDCT_IFAST: + begin + fdct^.pub.forward_DCT := forward_DCT; + fdct^.do_dct := jpeg_fdct_ifast; + end; +{$endif} +{$ifdef DCT_FLOAT_SUPPORTED} + JDCT_FLOAT: + begin + fdct^.pub.forward_DCT := forward_DCT_float; + fdct^.do_float_dct := jpeg_fdct_float; + end; +{$endif} + else + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); + end; + + { Mark divisor tables unallocated } + for i := 0 to pred(NUM_QUANT_TBLS) do + begin + fdct^.divisors[i] := NIL; +{$ifdef DCT_FLOAT_SUPPORTED} + fdct^.float_divisors[i] := NIL; +{$endif} + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjchuff.pas b/src/lib/vampimg/JpegLib/imjchuff.pas new file mode 100644 index 0000000..66856dc --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjchuff.pas @@ -0,0 +1,1116 @@ +unit imjchuff; + +{ This file contains Huffman entropy encoding routines. + + Much of the complexity here has to do with supporting output suspension. + If the data destination module demands suspension, we want to be able to + back up to the start of the current MCU. To do this, we copy state + variables into local working storage, and update them back to the + permanent JPEG objects only upon successful completion of an MCU. } + +{ Original: jchuff.c; Copyright (C) 1991-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, { longptr definition missing } + imjpeglib, + imjdeferr, + imjerror, + imjutils, + imjinclude, + imjcomapi; + +{ The legal range of a DCT coefficient is + -1024 .. +1023 for 8-bit data; + -16384 .. +16383 for 12-bit data. + Hence the magnitude should always fit in 10 or 14 bits respectively. } + + +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + MAX_COEF_BITS = 10; +{$else} +const + MAX_COEF_BITS = 14; +{$endif} + +{ Derived data constructed for each Huffman table } +{ Declarations shared with jcphuff.c } +type + c_derived_tbl_ptr = ^c_derived_tbl; + c_derived_tbl = record + ehufco : array[0..256-1] of uInt; { code for each symbol } + ehufsi : array[0..256-1] of byte; { length of code for each symbol } + { If no code has been allocated for a symbol S, ehufsi[S] contains 0 } + end; +{ for JCHUFF und JCPHUFF } +type + TLongTable = array[0..256] of long; + TLongTablePtr = ^TLongTable; + +{ Compute the derived values for a Huffman table. + Note this is also used by jcphuff.c. } + +{GLOBAL} +procedure jpeg_make_c_derived_tbl (cinfo : j_compress_ptr; + isDC : boolean; + tblno : int; + var pdtbl : c_derived_tbl_ptr); + +{ Generate the optimal coding for the given counts, fill htbl. + Note this is also used by jcphuff.c. } + +{GLOBAL} +procedure jpeg_gen_optimal_table (cinfo : j_compress_ptr; + htbl : JHUFF_TBL_PTR; + var freq : TLongTable); { Nomssi } + +{ Module initialization routine for Huffman entropy encoding. } + +{GLOBAL} +procedure jinit_huff_encoder (cinfo : j_compress_ptr); + +implementation + +{ Expanded entropy encoder object for Huffman encoding. + + The savable_state subrecord contains fields that change within an MCU, + but must not be updated permanently until we complete the MCU. } + +type + savable_state = record + put_buffer : INT32; { current bit-accumulation buffer } + put_bits : int; { # of bits now in it } + last_dc_val : array[0..MAX_COMPS_IN_SCAN-1] of int; + { last DC coef for each component } + end; + + +type + huff_entropy_ptr = ^huff_entropy_encoder; + huff_entropy_encoder = record + pub : jpeg_entropy_encoder; { public fields } + + saved : savable_state; { Bit buffer & DC state at start of MCU } + + { These fields are NOT loaded into local working state. } + restarts_to_go : uInt; { MCUs left in this restart interval } + next_restart_num : int; { next restart number to write (0-7) } + + { Pointers to derived tables (these workspaces have image lifespan) } + dc_derived_tbls : array[0..NUM_HUFF_TBLS-1] of c_derived_tbl_ptr; + ac_derived_tbls : array[0..NUM_HUFF_TBLS-1] of c_derived_tbl_ptr; + + {$ifdef ENTROPY_OPT_SUPPORTED} { Statistics tables for optimization } + dc_count_ptrs : array[0..NUM_HUFF_TBLS-1] of TLongTablePtr; + ac_count_ptrs : array[0..NUM_HUFF_TBLS-1] of TLongTablePtr; + {$endif} + end; + + + +{ Working state while writing an MCU. + This struct contains all the fields that are needed by subroutines. } + +type + working_state = record + next_output_byte : JOCTETptr; { => next byte to write in buffer } + free_in_buffer : size_t; { # of byte spaces remaining in buffer } + cur : savable_state; { Current bit buffer & DC state } + cinfo : j_compress_ptr; { dump_buffer needs access to this } + end; + + +{ Forward declarations } +{METHODDEF} +function encode_mcu_huff (cinfo : j_compress_ptr; + const MCU_data : array of JBLOCKROW) : boolean; + forward; +{METHODDEF} +procedure finish_pass_huff (cinfo : j_compress_ptr); forward; +{$ifdef ENTROPY_OPT_SUPPORTED} +{METHODDEF} +function encode_mcu_gather (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; + forward; + +{METHODDEF} +procedure finish_pass_gather (cinfo : j_compress_ptr); forward; +{$endif} + + +{ Initialize for a Huffman-compressed scan. + If gather_statistics is TRUE, we do not output anything during the scan, + just count the Huffman symbols used and generate Huffman code tables. } + +{METHODDEF} +procedure start_pass_huff (cinfo : j_compress_ptr; + gather_statistics : boolean); +var + entropy : huff_entropy_ptr; + ci, dctbl, actbl : int; + compptr : jpeg_component_info_ptr; +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + + if (gather_statistics) then + begin +{$ifdef ENTROPY_OPT_SUPPORTED} + entropy^.pub.encode_mcu := encode_mcu_gather; + entropy^.pub.finish_pass := finish_pass_gather; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + begin + entropy^.pub.encode_mcu := encode_mcu_huff; + entropy^.pub.finish_pass := finish_pass_huff; + end; + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + dctbl := compptr^.dc_tbl_no; + actbl := compptr^.ac_tbl_no; + if (gather_statistics) then + begin +{$ifdef ENTROPY_OPT_SUPPORTED} + { Check for invalid table indexes } + { (make_c_derived_tbl does this in the other path) } + if (dctbl < 0) or (dctbl >= NUM_HUFF_TBLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, dctbl); + if (actbl < 0) or (actbl >= NUM_HUFF_TBLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, actbl); + { Allocate and zero the statistics tables } + { Note that jpeg_gen_optimal_table expects 257 entries in each table! } + if (entropy^.dc_count_ptrs[dctbl] = NIL) then + entropy^.dc_count_ptrs[dctbl] := TLongTablePtr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + 257 * SIZEOF(long)) ); + MEMZERO(entropy^.dc_count_ptrs[dctbl], 257 * SIZEOF(long)); + if (entropy^.ac_count_ptrs[actbl] = NIL) then + entropy^.ac_count_ptrs[actbl] := TLongTablePtr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + 257 * SIZEOF(long)) ); + MEMZERO(entropy^.ac_count_ptrs[actbl], 257 * SIZEOF(long)); +{$endif} + end + else + begin + { Compute derived values for Huffman tables } + { We may do this more than once for a table, but it's not expensive } + jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, + entropy^.dc_derived_tbls[dctbl]); + jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, + entropy^.ac_derived_tbls[actbl]); + end; + { Initialize DC predictions to 0 } + entropy^.saved.last_dc_val[ci] := 0; + end; + + { Initialize bit buffer to empty } + entropy^.saved.put_buffer := 0; + entropy^.saved.put_bits := 0; + + { Initialize restart stuff } + entropy^.restarts_to_go := cinfo^.restart_interval; + entropy^.next_restart_num := 0; +end; + + +{ Compute the derived values for a Huffman table. + This routine also performs some validation checks on the table. + + Note this is also used by jcphuff.c. } + +{GLOBAL} +procedure jpeg_make_c_derived_tbl (cinfo : j_compress_ptr; + isDC : boolean; + tblno : int; + var pdtbl : c_derived_tbl_ptr); +var + htbl : JHUFF_TBL_PTR; + dtbl : c_derived_tbl_ptr; + p, i, l, lastp, si, maxsymbol : int; + huffsize : array[0..257-1] of byte; + huffcode : array[0..257-1] of uInt; + code : uInt; +begin + { Note that huffsize[] and huffcode[] are filled in code-length order, + paralleling the order of the symbols themselves in htbl->huffval[]. } + + { Find the input Huffman table } + if (tblno < 0) or (tblno >= NUM_HUFF_TBLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, tblno); + if isDC then + htbl := cinfo^.dc_huff_tbl_ptrs[tblno] + else + htbl := cinfo^.ac_huff_tbl_ptrs[tblno]; + if (htbl = NIL) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, tblno); + + { Allocate a workspace if we haven't already done so. } + if (pdtbl = NIL) then + pdtbl := c_derived_tbl_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(c_derived_tbl)) ); + dtbl := pdtbl; + + { Figure C.1: make table of Huffman code length for each symbol } + + p := 0; + for l := 1 to 16 do + begin + i := int(htbl^.bits[l]); + if (i < 0) and (p + i > 256) then { protect against table overrun } + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + while (i > 0) do + begin + huffsize[p] := byte(l); + Inc(p); + Dec(i); + end; + end; + huffsize[p] := 0; + lastp := p; + + { Figure C.2: generate the codes themselves } + { We also validate that the counts represent a legal Huffman code tree. } + + code := 0; + si := huffsize[0]; + p := 0; + while (huffsize[p] <> 0) do + begin + while (( int(huffsize[p]) ) = si) do + begin + huffcode[p] := code; + Inc(p); + Inc(code); + end; + { code is now 1 more than the last code used for codelength si; but + it must still fit in si bits, since no code is allowed to be all ones. } + + if (INT32(code) >= (INT32(1) shl si)) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + code := code shl 1; + Inc(si); + end; + + { Figure C.3: generate encoding tables } + { These are code and size indexed by symbol value } + + { Set all codeless symbols to have code length 0; + this lets us detect duplicate VAL entries here, and later + allows emit_bits to detect any attempt to emit such symbols. } + + MEMZERO(@dtbl^.ehufsi, SIZEOF(dtbl^.ehufsi)); + + { This is also a convenient place to check for out-of-range + and duplicated VAL entries. We allow 0..255 for AC symbols + but only 0..15 for DC. (We could constrain them further + based on data depth and mode, but this seems enough.) } + + if isDC then + maxsymbol := 15 + else + maxsymbol := 255; + + for p := 0 to pred(lastp) do + begin + i := htbl^.huffval[p]; + if (i < 0) or (i > maxsymbol) or (dtbl^.ehufsi[i] <> 0) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + dtbl^.ehufco[i] := huffcode[p]; + dtbl^.ehufsi[i] := huffsize[p]; + end; +end; + + +{ Outputting bytes to the file } + + +{LOCAL} +function dump_buffer (var state : working_state) : boolean; +{ Empty the output buffer; return TRUE if successful, FALSE if must suspend } +var + dest : jpeg_destination_mgr_ptr; +begin + dest := state.cinfo^.dest; + + if (not dest^.empty_output_buffer (state.cinfo)) then + begin + dump_buffer := FALSE; + exit; + end; + { After a successful buffer dump, must reset buffer pointers } + state.next_output_byte := dest^.next_output_byte; + state.free_in_buffer := dest^.free_in_buffer; + dump_buffer := TRUE; +end; + + +{ Outputting bits to the file } + +{ Only the right 24 bits of put_buffer are used; the valid bits are + left-justified in this part. At most 16 bits can be passed to emit_bits + in one call, and we never retain more than 7 bits in put_buffer + between calls, so 24 bits are sufficient. } + + +{LOCAL} +function emit_bits (var state : working_state; + code : uInt; + size : int) : boolean; {INLINE} +{ Emit some bits; return TRUE if successful, FALSE if must suspend } +var + { This routine is heavily used, so it's worth coding tightly. } + {register} put_buffer : INT32; + {register} put_bits : int; +var + c : int; +begin + put_buffer := INT32 (code); + put_bits := state.cur.put_bits; + + { if size is 0, caller used an invalid Huffman table entry } + if (size = 0) then + ERREXIT(j_common_ptr(state.cinfo), JERR_HUFF_MISSING_CODE); + + put_buffer := put_buffer and pred(INT32(1) shl size); + { mask off any extra bits in code } + + Inc(put_bits, size); { new number of bits in buffer } + + put_buffer := put_buffer shl (24 - put_bits); + { align incoming bits } + put_buffer := put_buffer or state.cur.put_buffer; + { and merge with old buffer contents } + while (put_bits >= 8) do + begin + c := int ((put_buffer shr 16) and $FF); + + {emit_byte(state, c, return FALSE);} + { Emit a byte, return FALSE if must suspend. } + state.next_output_byte^ := JOCTET (c); + Inc(state.next_output_byte); + Dec(state.free_in_buffer); + if (state.free_in_buffer = 0) then + if not dump_buffer(state) then + begin + emit_bits := FALSE; + exit; + end; + + if (c = $FF) then { need to stuff a zero byte? } + begin + {emit_byte(state, 0, return FALSE);} + state.next_output_byte^ := JOCTET (0); + Inc(state.next_output_byte); + Dec(state.free_in_buffer); + if (state.free_in_buffer = 0) then + if not dump_buffer(state) then + begin + emit_bits := FALSE; + exit; + end; + + end; + put_buffer := put_buffer shl 8; + Dec(put_bits, 8); + end; + + state.cur.put_buffer := put_buffer; { update state variables } + state.cur.put_bits := put_bits; + + emit_bits := TRUE; +end; + + +{LOCAL} +function flush_bits (var state : working_state) : boolean; +begin + if (not emit_bits(state, $7F, 7)) then { fill any partial byte with ones } + begin + flush_bits := FALSE; + exit; + end; + state.cur.put_buffer := 0; { and reset bit-buffer to empty } + state.cur.put_bits := 0; + flush_bits := TRUE; +end; + + +{ Encode a single block's worth of coefficients } + +{LOCAL} +function encode_one_block (var state : working_state; + const block : JBLOCK; + last_dc_val : int; + dctbl : c_derived_tbl_ptr; + actbl : c_derived_tbl_ptr) : boolean; +var + {register} temp, temp2 : int; + {register} nbits : int; + {register} k, r, i : int; +begin + { Encode the DC coefficient difference per section F.1.2.1 } + + temp2 := block[0] - last_dc_val; + temp := temp2; + + if (temp < 0) then + begin + temp := -temp; { temp is abs value of input } + { For a negative input, want temp2 := bitwise complement of abs(input) } + { This code assumes we are on a two's complement machine } + Dec(temp2); + end; + + { Find the number of bits needed for the magnitude of the coefficient } + nbits := 0; + while (temp <> 0) do + begin + Inc(nbits); + temp := temp shr 1; + end; + + { Check for out-of-range coefficient values. + Since we're encoding a difference, the range limit is twice as much. } + + if (nbits > MAX_COEF_BITS+1) then + ERREXIT(j_common_ptr(state.cinfo), JERR_BAD_DCT_COEF); + + { Emit the Huffman-coded symbol for the number of bits } + if not emit_bits(state, dctbl^.ehufco[nbits], dctbl^.ehufsi[nbits]) then + begin + encode_one_block := FALSE; + exit; + end; + + { Emit that number of bits of the value, if positive, } + { or the complement of its magnitude, if negative. } + if (nbits <> 0) then { emit_bits rejects calls with size 0 } + if not emit_bits(state, uInt(temp2), nbits) then + begin + encode_one_block := FALSE; + exit; + end; + + { Encode the AC coefficients per section F.1.2.2 } + + r := 0; { r := run length of zeros } + + for k := 1 to pred(DCTSIZE2) do + begin + temp := block[jpeg_natural_order[k]]; + if (temp = 0) then + begin + Inc(r); + end + else + begin + { if run length > 15, must emit special run-length-16 codes ($F0) } + while (r > 15) do + begin + if not emit_bits(state, actbl^.ehufco[$F0], actbl^.ehufsi[$F0]) then + begin + encode_one_block := FALSE; + exit; + end; + Dec(r, 16); + end; + + temp2 := temp; + if (temp < 0) then + begin + temp := -temp; { temp is abs value of input } + { This code assumes we are on a two's complement machine } + Dec(temp2); + end; + + { Find the number of bits needed for the magnitude of the coefficient } + nbits := 0; { there must be at least one 1 bit } + repeat + Inc(nbits); + temp := temp shr 1; + until (temp = 0); + + { Check for out-of-range coefficient values } + if (nbits > MAX_COEF_BITS) then + ERREXIT(j_common_ptr(state.cinfo), JERR_BAD_DCT_COEF); + + { Emit Huffman symbol for run length / number of bits } + i := (r shl 4) + nbits; + if not emit_bits(state, actbl^.ehufco[i], actbl^.ehufsi[i]) then + begin + encode_one_block := FALSE; + exit; + end; + + { Emit that number of bits of the value, if positive, } + { or the complement of its magnitude, if negative. } + if not emit_bits(state, uInt(temp2), nbits) then + begin + encode_one_block := FALSE; + exit; + end; + + r := 0; + end; + end; + + { If the last coef(s) were zero, emit an end-of-block code } + if (r > 0) then + if not emit_bits(state, actbl^.ehufco[0], actbl^.ehufsi[0]) then + begin + encode_one_block := FALSE; + exit; + end; + + encode_one_block := TRUE; +end; + + +{ Emit a restart marker & resynchronize predictions. } + +{LOCAL} +function emit_restart (var state : working_state; + restart_num : int) : boolean; +var + ci : int; +begin + if (not flush_bits(state)) then + begin + emit_restart := FALSE; + exit; + end; + + {emit_byte(state, $FF, return FALSE);} + { Emit a byte, return FALSE if must suspend. } + state.next_output_byte^ := JOCTET ($FF); + Inc(state.next_output_byte); + Dec(state.free_in_buffer); + if (state.free_in_buffer = 0) then + if not dump_buffer(state) then + begin + emit_restart := FALSE; + exit; + end; + + {emit_byte(state, JPEG_RST0 + restart_num, return FALSE);} + { Emit a byte, return FALSE if must suspend. } + state.next_output_byte^ := JOCTET (JPEG_RST0 + restart_num); + Inc(state.next_output_byte); + Dec(state.free_in_buffer); + if (state.free_in_buffer = 0) then + if not dump_buffer(state) then + begin + emit_restart := FALSE; + exit; + end; + + { Re-initialize DC predictions to 0 } + for ci := 0 to pred(state.cinfo^.comps_in_scan) do + state.cur.last_dc_val[ci] := 0; + + { The restart counter is not updated until we successfully write the MCU. } + + emit_restart := TRUE; +end; + + +{ Encode and output one MCU's worth of Huffman-compressed coefficients. } + +{METHODDEF} +function encode_mcu_huff (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; +var + entropy : huff_entropy_ptr; + state : working_state; + blkn, ci : int; + compptr : jpeg_component_info_ptr; +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + { Load up working state } + state.next_output_byte := cinfo^.dest^.next_output_byte; + state.free_in_buffer := cinfo^.dest^.free_in_buffer; + {ASSIGN_STATE(state.cur, entropy^.saved);} + state.cur := entropy^.saved; + state.cinfo := cinfo; + + { Emit restart marker if needed } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + if not emit_restart(state, entropy^.next_restart_num) then + begin + encode_mcu_huff := FALSE; + exit; + end; + end; + + { Encode the MCU data blocks } + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + ci := cinfo^.MCU_membership[blkn]; + compptr := cinfo^.cur_comp_info[ci]; + if not encode_one_block(state, + MCU_data[blkn]^[0], + state.cur.last_dc_val[ci], + entropy^.dc_derived_tbls[compptr^.dc_tbl_no], + entropy^.ac_derived_tbls[compptr^.ac_tbl_no]) then + begin + encode_mcu_huff := FALSE; + exit; + end; + { Update last_dc_val } + state.cur.last_dc_val[ci] := MCU_data[blkn]^[0][0]; + end; + + { Completed MCU, so update state } + cinfo^.dest^.next_output_byte := state.next_output_byte; + cinfo^.dest^.free_in_buffer := state.free_in_buffer; + {ASSIGN_STATE(entropy^.saved, state.cur);} + entropy^.saved := state.cur; + + { Update restart-interval state too } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + begin + entropy^.restarts_to_go := cinfo^.restart_interval; + Inc(entropy^.next_restart_num); + with entropy^ do + next_restart_num := next_restart_num and 7; + end; + Dec(entropy^.restarts_to_go); + end; + + encode_mcu_huff := TRUE; +end; + + +{ Finish up at the end of a Huffman-compressed scan. } + +{METHODDEF} +procedure finish_pass_huff (cinfo : j_compress_ptr); +var + entropy : huff_entropy_ptr; + state : working_state; +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + + { Load up working state ... flush_bits needs it } + state.next_output_byte := cinfo^.dest^.next_output_byte; + state.free_in_buffer := cinfo^.dest^.free_in_buffer; + {ASSIGN_STATE(state.cur, entropy^.saved);} + state.cur := entropy^.saved; + state.cinfo := cinfo; + + { Flush out the last data } + if not flush_bits(state) then + ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND); + + { Update state } + cinfo^.dest^.next_output_byte := state.next_output_byte; + cinfo^.dest^.free_in_buffer := state.free_in_buffer; + {ASSIGN_STATE(entropy^.saved, state.cur);} + entropy^.saved := state.cur; +end; + + +{ Huffman coding optimization. + + We first scan the supplied data and count the number of uses of each symbol + that is to be Huffman-coded. (This process MUST agree with the code above.) + Then we build a Huffman coding tree for the observed counts. + Symbols which are not needed at all for the particular image are not + assigned any code, which saves space in the DHT marker as well as in + the compressed data. } + +{$ifdef ENTROPY_OPT_SUPPORTED} + + +{ Process a single block's worth of coefficients } + +{LOCAL} +procedure htest_one_block (cinfo : j_compress_ptr; + const block : JBLOCK; + last_dc_val : int; + dc_counts : TLongTablePtr; + ac_counts : TLongTablePtr); + +var + {register} temp : int; + {register} nbits : int; + {register} k, r : int; +begin + { Encode the DC coefficient difference per section F.1.2.1 } + temp := block[0] - last_dc_val; + if (temp < 0) then + temp := -temp; + + { Find the number of bits needed for the magnitude of the coefficient } + nbits := 0; + while (temp <> 0) do + begin + Inc(nbits); + temp := temp shr 1; + end; + + { Check for out-of-range coefficient values. + Since we're encoding a difference, the range limit is twice as much. } + + if (nbits > MAX_COEF_BITS+1) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_DCT_COEF); + + { Count the Huffman symbol for the number of bits } + Inc(dc_counts^[nbits]); + + { Encode the AC coefficients per section F.1.2.2 } + + r := 0; { r := run length of zeros } + + for k := 1 to pred(DCTSIZE2) do + begin + temp := block[jpeg_natural_order[k]]; + if (temp = 0) then + begin + Inc(r); + end + else + begin + { if run length > 15, must emit special run-length-16 codes ($F0) } + while (r > 15) do + begin + Inc(ac_counts^[$F0]); + Dec(r, 16); + end; + + { Find the number of bits needed for the magnitude of the coefficient } + if (temp < 0) then + temp := -temp; + + { Find the number of bits needed for the magnitude of the coefficient } + nbits := 0; { there must be at least one 1 bit } + repeat + Inc(nbits); + temp := temp shr 1; + until (temp = 0); + + + { Count Huffman symbol for run length / number of bits } + Inc(ac_counts^[(r shl 4) + nbits]); + + r := 0; + end; + end; + + { If the last coef(s) were zero, emit an end-of-block code } + if (r > 0) then + Inc(ac_counts^[0]); +end; + + +{ Trial-encode one MCU's worth of Huffman-compressed coefficients. + No data is actually output, so no suspension return is possible. } + +{METHODDEF} +function encode_mcu_gather (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; +var + entropy : huff_entropy_ptr; + blkn, ci : int; + compptr : jpeg_component_info_ptr; +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + { Take care of restart intervals if needed } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + begin + { Re-initialize DC predictions to 0 } + for ci := 0 to pred(cinfo^.comps_in_scan) do + entropy^.saved.last_dc_val[ci] := 0; + { Update restart state } + entropy^.restarts_to_go := cinfo^.restart_interval; + end; + Dec(entropy^.restarts_to_go); + end; + + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + ci := cinfo^.MCU_membership[blkn]; + compptr := cinfo^.cur_comp_info[ci]; + htest_one_block(cinfo, MCU_data[blkn]^[0], + entropy^.saved.last_dc_val[ci], + entropy^.dc_count_ptrs[compptr^.dc_tbl_no], + entropy^.ac_count_ptrs[compptr^.ac_tbl_no]); + entropy^.saved.last_dc_val[ci] := MCU_data[blkn]^[0][0]; + end; + + encode_mcu_gather := TRUE; +end; + + +{ Generate the best Huffman code table for the given counts, fill htbl. + Note this is also used by jcphuff.c. + + The JPEG standard requires that no symbol be assigned a codeword of all + one bits (so that padding bits added at the end of a compressed segment + can't look like a valid code). Because of the canonical ordering of + codewords, this just means that there must be an unused slot in the + longest codeword length category. Section K.2 of the JPEG spec suggests + reserving such a slot by pretending that symbol 256 is a valid symbol + with count 1. In theory that's not optimal; giving it count zero but + including it in the symbol set anyway should give a better Huffman code. + But the theoretically better code actually seems to come out worse in + practice, because it produces more all-ones bytes (which incur stuffed + zero bytes in the final file). In any case the difference is tiny. + + The JPEG standard requires Huffman codes to be no more than 16 bits long. + If some symbols have a very small but nonzero probability, the Huffman tree + must be adjusted to meet the code length restriction. We currently use + the adjustment method suggested in JPEG section K.2. This method is *not* + optimal; it may not choose the best possible limited-length code. But + typically only very-low-frequency symbols will be given less-than-optimal + lengths, so the code is almost optimal. Experimental comparisons against + an optimal limited-length-code algorithm indicate that the difference is + microscopic --- usually less than a hundredth of a percent of total size. + So the extra complexity of an optimal algorithm doesn't seem worthwhile. } + + +{GLOBAL} +procedure jpeg_gen_optimal_table (cinfo : j_compress_ptr; + htbl : JHUFF_TBL_PTR; + var freq : TLongTable); +const + MAX_CLEN = 32; { assumed maximum initial code length } +var + bits : array[0..MAX_CLEN+1-1] of UINT8; { bits[k] := # of symbols with code length k } + codesize : array[0..257-1] of int; { codesize[k] := code length of symbol k } + others : array[0..257-1] of int; { next symbol in current branch of tree } + c1, c2 : int; + p, i, j : int; + v : long; +begin + { This algorithm is explained in section K.2 of the JPEG standard } + + MEMZERO(@bits, SIZEOF(bits)); + MEMZERO(@codesize, SIZEOF(codesize)); + for i := 0 to 256 do + others[i] := -1; { init links to empty } + + freq[256] := 1; { make sure 256 has a nonzero count } + { Including the pseudo-symbol 256 in the Huffman procedure guarantees + that no real symbol is given code-value of all ones, because 256 + will be placed last in the largest codeword category. } + + { Huffman's basic algorithm to assign optimal code lengths to symbols } + + while TRUE do + begin + { Find the smallest nonzero frequency, set c1 := its symbol } + { In case of ties, take the larger symbol number } + c1 := -1; + v := long(1000000000); + for i := 0 to 256 do + begin + if (freq[i] <> 0) and (freq[i] <= v) then + begin + v := freq[i]; + c1 := i; + end; + end; + + { Find the next smallest nonzero frequency, set c2 := its symbol } + { In case of ties, take the larger symbol number } + c2 := -1; + v := long(1000000000); + for i := 0 to 256 do + begin + if (freq[i] <> 0) and (freq[i] <= v) and (i <> c1) then + begin + v := freq[i]; + c2 := i; + end; + end; + + { Done if we've merged everything into one frequency } + if (c2 < 0) then + break; + + { Else merge the two counts/trees } + Inc(freq[c1], freq[c2]); + freq[c2] := 0; + + { Increment the codesize of everything in c1's tree branch } + Inc(codesize[c1]); + while (others[c1] >= 0) do + begin + c1 := others[c1]; + Inc(codesize[c1]); + end; + + others[c1] := c2; { chain c2 onto c1's tree branch } + + { Increment the codesize of everything in c2's tree branch } + Inc(codesize[c2]); + while (others[c2] >= 0) do + begin + c2 := others[c2]; + Inc(codesize[c2]); + end; + end; + + { Now count the number of symbols of each code length } + for i := 0 to 256 do + begin + if (codesize[i]<>0) then + begin + { The JPEG standard seems to think that this can't happen, } + { but I'm paranoid... } + if (codesize[i] > MAX_CLEN) then + ERREXIT(j_common_ptr(cinfo), JERR_HUFF_CLEN_OVERFLOW); + + Inc(bits[codesize[i]]); + end; + end; + + { JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure + Huffman procedure assigned any such lengths, we must adjust the coding. + Here is what the JPEG spec says about how this next bit works: + Since symbols are paired for the longest Huffman code, the symbols are + removed from this length category two at a time. The prefix for the pair + (which is one bit shorter) is allocated to one of the pair; then, + skipping the BITS entry for that prefix length, a code word from the next + shortest nonzero BITS entry is converted into a prefix for two code words + one bit longer. } + + for i := MAX_CLEN downto 17 do + begin + while (bits[i] > 0) do + begin + j := i - 2; { find length of new prefix to be used } + while (bits[j] = 0) do + Dec(j); + + Dec(bits[i], 2); { remove two symbols } + Inc(bits[i-1]); { one goes in this length } + Inc(bits[j+1], 2); { two new symbols in this length } + Dec(bits[j]); { symbol of this length is now a prefix } + end; + end; + + { Delphi 2: FOR-loop variable 'i' may be undefined after loop } + i := 16; { Nomssi: work around } + + { Remove the count for the pseudo-symbol 256 from the largest codelength } + while (bits[i] = 0) do { find largest codelength still in use } + Dec(i); + Dec(bits[i]); + + { Return final symbol counts (only for lengths 0..16) } + MEMCOPY(@htbl^.bits, @bits, SIZEOF(htbl^.bits)); + + { Return a list of the symbols sorted by code length } + { It's not real clear to me why we don't need to consider the codelength + changes made above, but the JPEG spec seems to think this works. } + + p := 0; + for i := 1 to MAX_CLEN do + begin + for j := 0 to 255 do + begin + if (codesize[j] = i) then + begin + htbl^.huffval[p] := UINT8 (j); + Inc(p); + end; + end; + end; + + { Set sent_table FALSE so updated table will be written to JPEG file. } + htbl^.sent_table := FALSE; +end; + + +{ Finish up a statistics-gathering pass and create the new Huffman tables. } + +{METHODDEF} +procedure finish_pass_gather (cinfo : j_compress_ptr); +var + entropy : huff_entropy_ptr; + ci, dctbl, actbl : int; + compptr : jpeg_component_info_ptr; + htblptr : ^JHUFF_TBL_PTR; + did_dc : array[0..NUM_HUFF_TBLS-1] of boolean; + did_ac : array[0..NUM_HUFF_TBLS-1] of boolean; +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + + { It's important not to apply jpeg_gen_optimal_table more than once + per table, because it clobbers the input frequency counts! } + + MEMZERO(@did_dc, SIZEOF(did_dc)); + MEMZERO(@did_ac, SIZEOF(did_ac)); + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + dctbl := compptr^.dc_tbl_no; + actbl := compptr^.ac_tbl_no; + if (not did_dc[dctbl]) then + begin + htblptr := @(cinfo^.dc_huff_tbl_ptrs[dctbl]); + if ( htblptr^ = NIL) then + htblptr^ := jpeg_alloc_huff_table(j_common_ptr(cinfo)); + jpeg_gen_optimal_table(cinfo, htblptr^, entropy^.dc_count_ptrs[dctbl]^); + did_dc[dctbl] := TRUE; + end; + if (not did_ac[actbl]) then + begin + htblptr := @(cinfo^.ac_huff_tbl_ptrs[actbl]); + if ( htblptr^ = NIL) then + htblptr^ := jpeg_alloc_huff_table(j_common_ptr(cinfo)); + jpeg_gen_optimal_table(cinfo, htblptr^, entropy^.ac_count_ptrs[actbl]^); + did_ac[actbl] := TRUE; + end; + end; +end; + +{$endif} { ENTROPY_OPT_SUPPORTED } + + +{ Module initialization routine for Huffman entropy encoding. } + +{GLOBAL} +procedure jinit_huff_encoder (cinfo : j_compress_ptr); +var + entropy : huff_entropy_ptr; + i : int; +begin + entropy := huff_entropy_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(huff_entropy_encoder)) ); + cinfo^.entropy := jpeg_entropy_encoder_ptr (entropy); + entropy^.pub.start_pass := start_pass_huff; + + { Mark tables unallocated } + for i := 0 to pred(NUM_HUFF_TBLS) do + begin + entropy^.ac_derived_tbls[i] := NIL; + entropy^.dc_derived_tbls[i] := NIL; +{$ifdef ENTROPY_OPT_SUPPORTED} + entropy^.ac_count_ptrs[i] := NIL; + entropy^.dc_count_ptrs[i] := NIL; +{$endif} + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcinit.pas b/src/lib/vampimg/JpegLib/imjcinit.pas new file mode 100644 index 0000000..9adaee6 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcinit.pas @@ -0,0 +1,95 @@ +unit imjcinit; + +{ Original: jcinit.c ; Copyright (C) 1991-1997, Thomas G. Lane. } + +{ This file contains initialization logic for the JPEG compressor. + This routine is in charge of selecting the modules to be executed and + making an initialization call to each one. + + Logically, this code belongs in jcmaster.c. It's split out because + linking this routine implies linking the entire compression library. + For a transcoding-only application, we want to be able to use jcmaster.c + without linking in the whole library. } + +interface + +{$I imjconfig.inc} + +uses + imjinclude, + imjdeferr, + imjerror, + imjpeglib, +{$ifdef C_PROGRESSIVE_SUPPORTED} + imjcphuff, +{$endif} + imjchuff, imjcmaster, imjccolor, imjcsample, imjcprepct, + imjcdctmgr, imjccoefct, imjcmainct, imjcmarker; + +{ Master selection of compression modules. + This is done once at the start of processing an image. We determine + which modules will be used and give them appropriate initialization calls. } + +{GLOBAL} +procedure jinit_compress_master (cinfo : j_compress_ptr); + +implementation + + + +{ Master selection of compression modules. + This is done once at the start of processing an image. We determine + which modules will be used and give them appropriate initialization calls. } + +{GLOBAL} +procedure jinit_compress_master (cinfo : j_compress_ptr); +begin + { Initialize master control (includes parameter checking/processing) } + jinit_c_master_control(cinfo, FALSE { full compression }); + + { Preprocessing } + if (not cinfo^.raw_data_in) then + begin + jinit_color_converter(cinfo); + jinit_downsampler(cinfo); + jinit_c_prep_controller(cinfo, FALSE { never need full buffer here }); + end; + { Forward DCT } + jinit_forward_dct(cinfo); + { Entropy encoding: either Huffman or arithmetic coding. } + if (cinfo^.arith_code) then + begin + ERREXIT(j_common_ptr(cinfo), JERR_ARITH_NOTIMPL); + end + else + begin + if (cinfo^.progressive_mode) then + begin +{$ifdef C_PROGRESSIVE_SUPPORTED} + jinit_phuff_encoder(cinfo); +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + jinit_huff_encoder(cinfo); + end; + + { Need a full-image coefficient buffer in any multi-pass mode. } + jinit_c_coef_controller(cinfo, + (cinfo^.num_scans > 1) or (cinfo^.optimize_coding)); + jinit_c_main_controller(cinfo, FALSE { never need full buffer here }); + + jinit_marker_writer(cinfo); + + { We can now tell the memory manager to allocate virtual arrays. } + cinfo^.mem^.realize_virt_arrays (j_common_ptr(cinfo)); + + { Write the datastream header (SOI) immediately. + Frame and scan headers are postponed till later. + This lets application insert special markers after the SOI. } + + cinfo^.marker^.write_file_header (cinfo); +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcmainct.pas b/src/lib/vampimg/JpegLib/imjcmainct.pas new file mode 100644 index 0000000..983ac83 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcmainct.pas @@ -0,0 +1,343 @@ +unit imjcmainct; + +{ This file contains the main buffer controller for compression. + The main buffer lies between the pre-processor and the JPEG + compressor proper; it holds downsampled data in the JPEG colorspace. } + +{ Original : jcmainct.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +{ Note: currently, there is no operating mode in which a full-image buffer + is needed at this step. If there were, that mode could not be used with + "raw data" input, since this module is bypassed in that case. However, + we've left the code here for possible use in special applications. } + +{$undef FULL_MAIN_BUFFER_SUPPORTED} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, +{$ifdef FULL_MAIN_BUFFER_SUPPORTED} + imjutils, +{$endif} + imjpeglib; + +{ Initialize main buffer controller. } + +{GLOBAL} +procedure jinit_c_main_controller (cinfo : j_compress_ptr; + need_full_buffer : boolean); + +implementation + + +{ Private buffer controller object } + +type + my_main_ptr = ^my_main_controller; + my_main_controller = record + pub : jpeg_c_main_controller; { public fields } + + cur_iMCU_row : JDIMENSION; { number of current iMCU row } + rowgroup_ctr : JDIMENSION; { counts row groups received in iMCU row } + suspended : boolean; { remember if we suspended output } + pass_mode : J_BUF_MODE; { current operating mode } + + { If using just a strip buffer, this points to the entire set of buffers + (we allocate one for each component). In the full-image case, this + points to the currently accessible strips of the virtual arrays. } + + buffer : array[0..MAX_COMPONENTS-1] of JSAMPARRAY; + + {$ifdef FULL_MAIN_BUFFER_SUPPORTED} + { If using full-image storage, this array holds pointers to virtual-array + control blocks for each component. Unused if not full-image storage. } + + whole_image : array[0..MAX_COMPONENTS-1] of jvirt_sarray_ptr; + {$endif} + end; {my_main_controller} + + +{ Forward declarations } +{METHODDEF} +procedure process_data_simple_main(cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr: JDIMENSION; + in_rows_avail : JDIMENSION); forward; + +{$ifdef FULL_MAIN_BUFFER_SUPPORTED} +{METHODDEF} +procedure process_data_buffer_main(cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr : JDIMENSION; + in_rows_avail : JDIMENSION); forward; +{$endif} + + +{ Initialize for a processing pass. } + +{METHODDEF} +procedure start_pass_main (cinfo : j_compress_ptr; + pass_mode : J_BUF_MODE); +var + main : my_main_ptr; +begin + main := my_main_ptr (cinfo^.main); + + { Do nothing in raw-data mode. } + if (cinfo^.raw_data_in) then + exit; + + main^.cur_iMCU_row := 0; { initialize counters } + main^.rowgroup_ctr := 0; + main^.suspended := FALSE; + main^.pass_mode := pass_mode; { save mode for use by process_data } + + case (pass_mode) of + JBUF_PASS_THRU: + begin +{$ifdef FULL_MAIN_BUFFER_SUPPORTED} + if (main^.whole_image[0] <> NIL) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); +{$endif} + main^.pub.process_data := process_data_simple_main; + end; +{$ifdef FULL_MAIN_BUFFER_SUPPORTED} + JBUF_SAVE_SOURCE, + JBUF_CRANK_DEST, + JBUF_SAVE_AND_PASS: + begin + if (main^.whole_image[0] = NIL) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + main^.pub.process_data := process_data_buffer_main; + end; +{$endif} + else + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + end; +end; + + +{ Process some data. + This routine handles the simple pass-through mode, + where we have only a strip buffer. } + +{METHODDEF} +procedure process_data_simple_main (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr : JDIMENSION; + in_rows_avail : JDIMENSION); +var + main : my_main_ptr; +begin + main := my_main_ptr (cinfo^.main); + + while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do + begin + { Read input data if we haven't filled the main buffer yet } + if (main^.rowgroup_ctr < DCTSIZE) then + cinfo^.prep^.pre_process_data (cinfo, + input_buf, + in_row_ctr, + in_rows_avail, + JSAMPIMAGE(@main^.buffer), + main^.rowgroup_ctr, + JDIMENSION(DCTSIZE)); + + { If we don't have a full iMCU row buffered, return to application for + more data. Note that preprocessor will always pad to fill the iMCU row + at the bottom of the image. } + if (main^.rowgroup_ctr <> DCTSIZE) then + exit; + + { Send the completed row to the compressor } + if (not cinfo^.coef^.compress_data (cinfo, JSAMPIMAGE(@main^.buffer))) then + begin + { If compressor did not consume the whole row, then we must need to + suspend processing and return to the application. In this situation + we pretend we didn't yet consume the last input row; otherwise, if + it happened to be the last row of the image, the application would + think we were done. } + + if (not main^.suspended) then + begin + Dec(in_row_ctr); + main^.suspended := TRUE; + end; + exit; + end; + { We did finish the row. Undo our little suspension hack if a previous + call suspended; then mark the main buffer empty. } + + if (main^.suspended) then + begin + Inc(in_row_ctr); + main^.suspended := FALSE; + end; + main^.rowgroup_ctr := 0; + Inc(main^.cur_iMCU_row); + end; +end; + + +{$ifdef FULL_MAIN_BUFFER_SUPPORTED} + +{ Process some data. + This routine handles all of the modes that use a full-size buffer. } + +{METHODDEF} +procedure process_data_buffer_main (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr : JDIMENSION; + in_rows_avail : JDIMENSION); +var + main : my_main_ptr; + ci : int; + compptr : jpeg_component_info_ptr; + writing : boolean; +begin + main := my_main_ptr (cinfo^.main); + writing := (main^.pass_mode <> JBUF_CRANK_DEST); + + while (main^.cur_iMCU_row < cinfo^.total_iMCU_rows) do + begin + { Realign the virtual buffers if at the start of an iMCU row. } + if (main^.rowgroup_ctr = 0) then + begin + compptr := cinfo^.comp_info; + for ci := 0 to pred(cinfo^.num_components) do + begin + main^.buffer[ci] := cinfo^.mem^.access_virt_sarray + (j_common_ptr (cinfo), main^.whole_image[ci], + main^.cur_iMCU_row * (compptr^.v_samp_factor * DCTSIZE), + JDIMENSION (compptr^.v_samp_factor * DCTSIZE), writing); + Inc(compptr); + end; + { In a read pass, pretend we just read some source data. } + if (not writing) then + begin + Inc(in_row_ctr, cinfo^.max_v_samp_factor * DCTSIZE); + main^.rowgroup_ctr := DCTSIZE; + end; + end; + + { If a write pass, read input data until the current iMCU row is full. } + { Note: preprocessor will pad if necessary to fill the last iMCU row. } + if (writing) then + begin + cinfo^.prep^.pre_process_data (cinfo, + input_buf, in_row_ctr, in_rows_avail, + JSAMPIMAGE(@main^.buffer), + main^.rowgroup_ctr, + JDIMENSION (DCTSIZE)); + + { Return to application if we need more data to fill the iMCU row. } + if (main^.rowgroup_ctr < DCTSIZE) then + exit; + end; + + { Emit data, unless this is a sink-only pass. } + if (main^.pass_mode <> JBUF_SAVE_SOURCE) then + begin + if (not cinfo^.coef^.compress_data (cinfo, + JSAMPIMAGE(@main^.buffer))) then + begin + { If compressor did not consume the whole row, then we must need to + suspend processing and return to the application. In this situation + we pretend we didn't yet consume the last input row; otherwise, if + it happened to be the last row of the image, the application would + think we were done. } + + if (not main^.suspended) then + begin + Dec(in_row_ctr); + main^.suspended := TRUE; + end; + exit; + end; + { We did finish the row. Undo our little suspension hack if a previous + call suspended; then mark the main buffer empty. } + + if (main^.suspended) then + begin + Inc(in_row_ctr); + main^.suspended := FALSE; + end; + end; + + { If get here, we are done with this iMCU row. Mark buffer empty. } + main^.rowgroup_ctr := 0; + Inc(main^.cur_iMCU_row); + end; +end; + +{$endif} { FULL_MAIN_BUFFER_SUPPORTED } + + +{ Initialize main buffer controller. } + +{GLOBAL} +procedure jinit_c_main_controller (cinfo : j_compress_ptr; + need_full_buffer : boolean); +var + main : my_main_ptr; + ci : int; + compptr : jpeg_component_info_ptr; +begin + main := my_main_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_main_controller)) ); + cinfo^.main := jpeg_c_main_controller_ptr(main); + main^.pub.start_pass := start_pass_main; + + { We don't need to create a buffer in raw-data mode. } + if (cinfo^.raw_data_in) then + exit; + + { Create the buffer. It holds downsampled data, so each component + may be of a different size. } + + if (need_full_buffer) then + begin +{$ifdef FULL_MAIN_BUFFER_SUPPORTED} + { Allocate a full-image virtual array for each component } + { Note we pad the bottom to a multiple of the iMCU height } + compptr := cinfo^.comp_info; + for ci := 0 to pred(cinfo^.num_components) do + begin + main^.whole_image[ci] := cinfo^.mem^.request_virt_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE, + compptr^.width_in_blocks * DCTSIZE, + JDIMENSION (jround_up( long (compptr^.height_in_blocks), + long (compptr^.v_samp_factor)) * DCTSIZE), + JDIMENSION (compptr^.v_samp_factor * DCTSIZE)); + Inc(compptr); + end; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); +{$endif} + end + else + begin +{$ifdef FULL_MAIN_BUFFER_SUPPORTED} + main^.whole_image[0] := NIL; { flag for no virtual arrays } +{$endif} + { Allocate a strip buffer for each component } + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + main^.buffer[ci] := cinfo^.mem^.alloc_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, + compptr^.width_in_blocks * DCTSIZE, + JDIMENSION (compptr^.v_samp_factor * DCTSIZE)); + Inc(compptr); + end; + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcmarker.pas b/src/lib/vampimg/JpegLib/imjcmarker.pas new file mode 100644 index 0000000..35463dc --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcmarker.pas @@ -0,0 +1,724 @@ +unit imjcmarker; + +{ This file contains routines to write JPEG datastream markers. } + +{ Original: jcmarker.c; Copyright (C) 1991-1998, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjinclude, imjmorecfg, imjerror, + imjdeferr, imjpeglib, imjutils; + + +const + { JPEG marker codes } + M_SOF0 = $c0; + M_SOF1 = $c1; + M_SOF2 = $c2; + M_SOF3 = $c3; + + M_SOF5 = $c5; + M_SOF6 = $c6; + M_SOF7 = $c7; + + M_JPG = $c8; + M_SOF9 = $c9; + M_SOF10 = $ca; + M_SOF11 = $cb; + + M_SOF13 = $cd; + M_SOF14 = $ce; + M_SOF15 = $cf; + + M_DHT = $c4; + + M_DAC = $cc; + + M_RST0 = $d0; + M_RST1 = $d1; + M_RST2 = $d2; + M_RST3 = $d3; + M_RST4 = $d4; + M_RST5 = $d5; + M_RST6 = $d6; + M_RST7 = $d7; + + M_SOI = $d8; + M_EOI = $d9; + M_SOS = $da; + M_DQT = $db; + M_DNL = $dc; + M_DRI = $dd; + M_DHP = $de; + M_EXP = $df; + + M_APP0 = $e0; + M_APP1 = $e1; + M_APP2 = $e2; + M_APP3 = $e3; + M_APP4 = $e4; + M_APP5 = $e5; + M_APP6 = $e6; + M_APP7 = $e7; + M_APP8 = $e8; + M_APP9 = $e9; + M_APP10 = $ea; + M_APP11 = $eb; + M_APP12 = $ec; + M_APP13 = $ed; + M_APP14 = $ee; + M_APP15 = $ef; + + M_JPG0 = $f0; + M_JPG13 = $fd; + M_COM = $fe; + + M_TEM = $01; + + M_ERROR = $100; + +type + JPEG_MARKER = Word; + +{ Private state } + +type + my_marker_ptr = ^my_marker_writer; + my_marker_writer = record + pub : jpeg_marker_writer; { public fields } + + last_restart_interval : uint; { last DRI value emitted; 0 after SOI } + end; + + + + +{GLOBAL} +procedure jinit_marker_writer (cinfo : j_compress_ptr); + +implementation + +{ Basic output routines. + + Note that we do not support suspension while writing a marker. + Therefore, an application using suspension must ensure that there is + enough buffer space for the initial markers (typ. 600-700 bytes) before + calling jpeg_start_compress, and enough space to write the trailing EOI + (a few bytes) before calling jpeg_finish_compress. Multipass compression + modes are not supported at all with suspension, so those two are the only + points where markers will be written. } + + +{LOCAL} +procedure emit_byte (cinfo : j_compress_ptr; val : int); +{ Emit a byte } +var + dest : jpeg_destination_mgr_ptr; +begin + dest := cinfo^.dest; + + dest^.next_output_byte^ := JOCTET(val); + Inc(dest^.next_output_byte); + + Dec(dest^.free_in_buffer); + if (dest^.free_in_buffer = 0) then + begin + if not dest^.empty_output_buffer(cinfo) then + ERREXIT(j_common_ptr(cinfo), JERR_CANT_SUSPEND); + end; +end; + + +{LOCAL} +procedure emit_marker(cinfo : j_compress_ptr; mark : JPEG_MARKER); +{ Emit a marker code } +begin + emit_byte(cinfo, $FF); + emit_byte(cinfo, int(mark)); +end; + + +{LOCAL} +procedure emit_2bytes (cinfo : j_compress_ptr; value : int); +{ Emit a 2-byte integer; these are always MSB first in JPEG files } +begin + emit_byte(cinfo, (value shr 8) and $FF); + emit_byte(cinfo, value and $FF); +end; + + +{ Routines to write specific marker types. } + +{LOCAL} +function emit_dqt (cinfo : j_compress_ptr; index : int) : int; +{ Emit a DQT marker } +{ Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking } +var + qtbl : JQUANT_TBL_PTR; + prec : int; + i : int; +var + qval : uint; +begin + qtbl := cinfo^.quant_tbl_ptrs[index]; + if (qtbl = NIL) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_QUANT_TABLE, index); + + prec := 0; + for i := 0 to Pred(DCTSIZE2) do + begin + if (qtbl^.quantval[i] > 255) then + prec := 1; + end; + + if not qtbl^.sent_table then + begin + emit_marker(cinfo, M_DQT); + + if (prec <> 0) then + emit_2bytes(cinfo, DCTSIZE2*2 + 1 + 2) + else + emit_2bytes(cinfo, DCTSIZE2 + 1 + 2); + + emit_byte(cinfo, index + (prec shl 4)); + + for i := 0 to Pred(DCTSIZE2) do + begin + { The table entries must be emitted in zigzag order. } + qval := qtbl^.quantval[jpeg_natural_order[i]]; + if (prec <> 0) then + emit_byte(cinfo, int(qval shr 8)); + emit_byte(cinfo, int(qval and $FF)); + end; + + qtbl^.sent_table := TRUE; + end; + + emit_dqt := prec; +end; + + +{LOCAL} +procedure emit_dht (cinfo : j_compress_ptr; index : int; is_ac : boolean); +{ Emit a DHT marker } +var + htbl : JHUFF_TBL_PTR; + length, i : int; +begin + if (is_ac) then + begin + htbl := cinfo^.ac_huff_tbl_ptrs[index]; + index := index + $10; { output index has AC bit set } + end + else + begin + htbl := cinfo^.dc_huff_tbl_ptrs[index]; + end; + + if (htbl = NIL) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, index); + + if not htbl^.sent_table then + begin + emit_marker(cinfo, M_DHT); + + length := 0; + for i := 1 to 16 do + length := length + htbl^.bits[i]; + + emit_2bytes(cinfo, length + 2 + 1 + 16); + emit_byte(cinfo, index); + + for i := 1 to 16 do + emit_byte(cinfo, htbl^.bits[i]); + + for i := 0 to Pred(length) do + emit_byte(cinfo, htbl^.huffval[i]); + + htbl^.sent_table := TRUE; + end; +end; + + +{LOCAL} +procedure emit_dac (cinfo : j_compress_ptr); +{ Emit a DAC marker } +{ Since the useful info is so small, we want to emit all the tables in } +{ one DAC marker. Therefore this routine does its own scan of the table. } +{$ifdef C_ARITH_CODING_SUPPORTED} +var + dc_in_use : array[0..NUM_ARITH_TBLS] of byte; + ac_in_use : array[0..NUM_ARITH_TBLS] of byte; + length, i : int; + compptr : jpeg_component_info_ptr; +begin + for i := 0 to pred(NUM_ARITH_TBLS) do + begin + dc_in_use[i] := 0; + ac_in_use[i] := 0; + end; + + for i := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[i]; + dc_in_use[compptr^.dc_tbl_no] := 1; + ac_in_use[compptr^.ac_tbl_no] := 1; + end; + + length := 0; + for i := 0 to pred(NUM_ARITH_TBLS) do + Inc(length, dc_in_use[i] + ac_in_use[i]); + + emit_marker(cinfo, M_DAC); + + emit_2bytes(cinfo, length*2 + 2); + + for i := 0 to pred(NUM_ARITH_TBLS) do + begin + if (dc_in_use[i] <> 0) then + begin + emit_byte(cinfo, i); + emit_byte(cinfo, cinfo^.arith_dc_L[i] + (cinfo^.arith_dc_U[i] shl 4)); + end; + if (ac_in_use[i] <> 0) then + begin + emit_byte(cinfo, i + $10); + emit_byte(cinfo, cinfo^.arith_ac_K[i]); + end; + end; +end; +{$else} +begin +end; +{$endif} {C_ARITH_CODING_SUPPORTED} + + +{LOCAL} +procedure emit_dri (cinfo : j_compress_ptr); +{ Emit a DRI marker } +begin + emit_marker(cinfo, M_DRI); + + emit_2bytes(cinfo, 4); { fixed length } + + emit_2bytes(cinfo, int(cinfo^.restart_interval)); +end; + + +{LOCAL} +procedure emit_sof (cinfo : j_compress_ptr; code : JPEG_MARKER); +{ Emit a SOF marker } +var + ci : int; + compptr : jpeg_component_info_ptr; +begin + emit_marker(cinfo, code); + + emit_2bytes(cinfo, 3 * cinfo^.num_components + 2 + 5 + 1); { length } + + { Make sure image isn't bigger than SOF field can handle } + if (long(cinfo^.image_height) > long(65535)) or + (long(cinfo^.image_width) > long(65535)) then + ERREXIT1(j_common_ptr(cinfo), JERR_IMAGE_TOO_BIG, uInt(65535)); + + emit_byte(cinfo, cinfo^.data_precision); + emit_2bytes(cinfo, int(cinfo^.image_height)); + emit_2bytes(cinfo, int(cinfo^.image_width)); + + emit_byte(cinfo, cinfo^.num_components); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to Pred(cinfo^.num_components) do + begin + emit_byte(cinfo, compptr^.component_id); + emit_byte(cinfo, (compptr^.h_samp_factor shl 4) + compptr^.v_samp_factor); + emit_byte(cinfo, compptr^.quant_tbl_no); + Inc(compptr); + end; +end; + + +{LOCAL} +procedure emit_sos (cinfo : j_compress_ptr); +{ Emit a SOS marker } +var + i, td, ta : int; + compptr : jpeg_component_info_ptr; +begin + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 * cinfo^.comps_in_scan + 2 + 1 + 3); { length } + + emit_byte(cinfo, cinfo^.comps_in_scan); + + for i := 0 to Pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[i]; + emit_byte(cinfo, compptr^.component_id); + td := compptr^.dc_tbl_no; + ta := compptr^.ac_tbl_no; + if (cinfo^.progressive_mode) then + begin + { Progressive mode: only DC or only AC tables are used in one scan; + furthermore, Huffman coding of DC refinement uses no table at all. + We emit 0 for unused field(s); this is recommended by the P&M text + but does not seem to be specified in the standard. } + + if (cinfo^.Ss = 0) then + begin + ta := 0; { DC scan } + if (cinfo^.Ah <> 0) and not cinfo^.arith_code then + td := 0; { no DC table either } + end + else + begin + td := 0; { AC scan } + end; + end; + emit_byte(cinfo, (td shl 4) + ta); + end; + + emit_byte(cinfo, cinfo^.Ss); + emit_byte(cinfo, cinfo^.Se); + emit_byte(cinfo, (cinfo^.Ah shl 4) + cinfo^.Al); +end; + + +{LOCAL} +procedure emit_jfif_app0 (cinfo : j_compress_ptr); +{ Emit a JFIF-compliant APP0 marker } +{ + Length of APP0 block (2 bytes) + Block ID (4 bytes - ASCII "JFIF") + Zero byte (1 byte to terminate the ID string) + Version Major, Minor (2 bytes - major first) + Units (1 byte - $00 = none, $01 = inch, $02 = cm) + Xdpu (2 bytes - dots per unit horizontal) + Ydpu (2 bytes - dots per unit vertical) + Thumbnail X size (1 byte) + Thumbnail Y size (1 byte) +} +begin + emit_marker(cinfo, M_APP0); + + emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); { length } + + emit_byte(cinfo, $4A); { Identifier: ASCII "JFIF" } + emit_byte(cinfo, $46); + emit_byte(cinfo, $49); + emit_byte(cinfo, $46); + emit_byte(cinfo, 0); + emit_byte(cinfo, cinfo^.JFIF_major_version); { Version fields } + emit_byte(cinfo, cinfo^.JFIF_minor_version); + emit_byte(cinfo, cinfo^.density_unit); { Pixel size information } + emit_2bytes(cinfo, int(cinfo^.X_density)); + emit_2bytes(cinfo, int(cinfo^.Y_density)); + emit_byte(cinfo, 0); { No thumbnail image } + emit_byte(cinfo, 0); +end; + + +{LOCAL} +procedure emit_adobe_app14 (cinfo : j_compress_ptr); +{ Emit an Adobe APP14 marker } +{ + Length of APP14 block (2 bytes) + Block ID (5 bytes - ASCII "Adobe") + Version Number (2 bytes - currently 100) + Flags0 (2 bytes - currently 0) + Flags1 (2 bytes - currently 0) + Color transform (1 byte) + + Although Adobe TN 5116 mentions Version = 101, all the Adobe files + now in circulation seem to use Version = 100, so that's what we write. + + We write the color transform byte as 1 if the JPEG color space is + YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with + whether the encoder performed a transformation, which is pretty useless. +} +begin + emit_marker(cinfo, M_APP14); + + emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); { length } + + emit_byte(cinfo, $41); { Identifier: ASCII "Adobe" } + emit_byte(cinfo, $64); + emit_byte(cinfo, $6F); + emit_byte(cinfo, $62); + emit_byte(cinfo, $65); + emit_2bytes(cinfo, 100); { Version } + emit_2bytes(cinfo, 0); { Flags0 } + emit_2bytes(cinfo, 0); { Flags1 } + case (cinfo^.jpeg_color_space) of + JCS_YCbCr: + emit_byte(cinfo, 1); { Color transform = 1 } + JCS_YCCK: + emit_byte(cinfo, 2); { Color transform = 2 } + else + emit_byte(cinfo, 0); { Color transform = 0 } + end; +end; + + +{ These routines allow writing an arbitrary marker with parameters. + The only intended use is to emit COM or APPn markers after calling + write_file_header and before calling write_frame_header. + Other uses are not guaranteed to produce desirable results. + Counting the parameter bytes properly is the caller's responsibility. } + +{METHODDEF} +procedure write_marker_header (cinfo : j_compress_ptr; + marker : int; + datalen : uint); +{ Emit an arbitrary marker header } +begin + if (datalen > uint(65533)) then { safety check } + ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH); + + emit_marker(cinfo, JPEG_MARKER(marker)); + + emit_2bytes(cinfo, int(datalen + 2)); { total length } +end; + +{METHODDEF} +procedure write_marker_byte (cinfo : j_compress_ptr; val : int); +{ Emit one byte of marker parameters following write_marker_header } +begin + emit_byte(cinfo, val); +end; + +{ Write datastream header. + This consists of an SOI and optional APPn markers. + We recommend use of the JFIF marker, but not the Adobe marker, + when using YCbCr or grayscale data. The JFIF marker should NOT + be used for any other JPEG colorspace. The Adobe marker is helpful + to distinguish RGB, CMYK, and YCCK colorspaces. + Note that an application can write additional header markers after + jpeg_start_compress returns. } + + +{METHODDEF} +procedure write_file_header (cinfo : j_compress_ptr); +var + marker : my_marker_ptr; +begin + marker := my_marker_ptr(cinfo^.marker); + + emit_marker(cinfo, M_SOI); { first the SOI } + + { SOI is defined to reset restart interval to 0 } + marker^.last_restart_interval := 0; + + if (cinfo^.write_JFIF_header) then { next an optional JFIF APP0 } + emit_jfif_app0(cinfo); + if (cinfo^.write_Adobe_marker) then { next an optional Adobe APP14 } + emit_adobe_app14(cinfo); +end; + + +{ Write frame header. + This consists of DQT and SOFn markers. + Note that we do not emit the SOF until we have emitted the DQT(s). + This avoids compatibility problems with incorrect implementations that + try to error-check the quant table numbers as soon as they see the SOF. } + + +{METHODDEF} +procedure write_frame_header (cinfo : j_compress_ptr); +var + ci, prec : int; + is_baseline : boolean; + compptr : jpeg_component_info_ptr; +begin + { Emit DQT for each quantization table. + Note that emit_dqt() suppresses any duplicate tables. } + + prec := 0; + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to Pred(cinfo^.num_components) do + begin + prec := prec + emit_dqt(cinfo, compptr^.quant_tbl_no); + Inc(compptr); + end; + { now prec is nonzero iff there are any 16-bit quant tables. } + + { Check for a non-baseline specification. + Note we assume that Huffman table numbers won't be changed later. } + + if (cinfo^.arith_code) or (cinfo^.progressive_mode) + or (cinfo^.data_precision <> 8) then + begin + is_baseline := FALSE; + end + else + begin + is_baseline := TRUE; + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to Pred(cinfo^.num_components) do + begin + if (compptr^.dc_tbl_no > 1) or (compptr^.ac_tbl_no > 1) then + is_baseline := FALSE; + Inc(compptr); + end; + if (prec <> 0) and (is_baseline) then + begin + is_baseline := FALSE; + { If it's baseline except for quantizer size, warn the user } + {$IFDEF DEBUG} + TRACEMS(j_common_ptr(cinfo), 0, JTRC_16BIT_TABLES); + {$ENDIF} + end; + end; + + { Emit the proper SOF marker } + if (cinfo^.arith_code) then + begin + emit_sof(cinfo, M_SOF9); { SOF code for arithmetic coding } + end + else + begin + if (cinfo^.progressive_mode) then + emit_sof(cinfo, M_SOF2) { SOF code for progressive Huffman } + else if (is_baseline) then + emit_sof(cinfo, M_SOF0) { SOF code for baseline implementation } + else + emit_sof(cinfo, M_SOF1); { SOF code for non-baseline Huffman file } + end; +end; + + +{ Write scan header. + This consists of DHT or DAC markers, optional DRI, and SOS. + Compressed data will be written following the SOS. } + +{METHODDEF} +procedure write_scan_header (cinfo : j_compress_ptr); +var + marker : my_marker_ptr; + i : int; + compptr : jpeg_component_info_ptr; +begin + marker := my_marker_ptr(cinfo^.marker); + if (cinfo^.arith_code) then + begin + { Emit arith conditioning info. We may have some duplication + if the file has multiple scans, but it's so small it's hardly + worth worrying about. } + emit_dac(cinfo); + end + else + begin + { Emit Huffman tables. + Note that emit_dht() suppresses any duplicate tables. } + for i := 0 to Pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[i]; + if (cinfo^.progressive_mode) then + begin + { Progressive mode: only DC or only AC tables are used in one scan } + if (cinfo^.Ss = 0) then + begin + if (cinfo^.Ah = 0) then { DC needs no table for refinement scan } + emit_dht(cinfo, compptr^.dc_tbl_no, FALSE); + end + else + begin + emit_dht(cinfo, compptr^.ac_tbl_no, TRUE); + end; + end + else + begin + { Sequential mode: need both DC and AC tables } + emit_dht(cinfo, compptr^.dc_tbl_no, FALSE); + emit_dht(cinfo, compptr^.ac_tbl_no, TRUE); + end; + end; + end; + + { Emit DRI if required --- note that DRI value could change for each scan. + We avoid wasting space with unnecessary DRIs, however. } + + if (cinfo^.restart_interval <> marker^.last_restart_interval) then + begin + emit_dri(cinfo); + marker^.last_restart_interval := cinfo^.restart_interval; + end; + + emit_sos(cinfo); +end; + + + +{ Write datastream trailer. } + + +{METHODDEF} +procedure write_file_trailer (cinfo : j_compress_ptr); +begin + emit_marker(cinfo, M_EOI); +end; + + +{ Write an abbreviated table-specification datastream. + This consists of SOI, DQT and DHT tables, and EOI. + Any table that is defined and not marked sent_table = TRUE will be + emitted. Note that all tables will be marked sent_table = TRUE at exit. } + + +{METHODDEF} +procedure write_tables_only (cinfo : j_compress_ptr); +var + i : int; +begin + emit_marker(cinfo, M_SOI); + + for i := 0 to Pred(NUM_QUANT_TBLS) do + begin + if (cinfo^.quant_tbl_ptrs[i] <> NIL) then + emit_dqt(cinfo, i); { dummy := ... } + end; + + if (not cinfo^.arith_code) then + begin + for i := 0 to Pred(NUM_HUFF_TBLS) do + begin + if (cinfo^.dc_huff_tbl_ptrs[i] <> NIL) then + emit_dht(cinfo, i, FALSE); + if (cinfo^.ac_huff_tbl_ptrs[i] <> NIL) then + emit_dht(cinfo, i, TRUE); + end; + end; + + emit_marker(cinfo, M_EOI); +end; + + +{ Initialize the marker writer module. } + +{GLOBAL} +procedure jinit_marker_writer (cinfo : j_compress_ptr); +var + marker : my_marker_ptr; +begin + { Create the subobject } + marker := my_marker_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_marker_writer)) ); + cinfo^.marker := jpeg_marker_writer_ptr(marker); + { Initialize method pointers } + marker^.pub.write_file_header := write_file_header; + marker^.pub.write_frame_header := write_frame_header; + marker^.pub.write_scan_header := write_scan_header; + marker^.pub.write_file_trailer := write_file_trailer; + marker^.pub.write_tables_only := write_tables_only; + marker^.pub.write_marker_header := write_marker_header; + marker^.pub.write_marker_byte := write_marker_byte; + { Initialize private state } + marker^.last_restart_interval := 0; +end; + + +end. diff --git a/src/lib/vampimg/JpegLib/imjcmaster.pas b/src/lib/vampimg/JpegLib/imjcmaster.pas new file mode 100644 index 0000000..1498398 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcmaster.pas @@ -0,0 +1,701 @@ +unit imjcmaster; + +{ This file contains master control logic for the JPEG compressor. + These routines are concerned with parameter validation, initial setup, + and inter-pass control (determining the number of passes and the work + to be done in each pass). } + +{ Original: jcmaster.c ; Copyright (C) 1991-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjutils, + imjpeglib; + +{ Initialize master compression control. } + +{GLOBAL} +procedure jinit_c_master_control (cinfo : j_compress_ptr; + transcode_only : boolean); + +implementation + +{ Private state } + +type + c_pass_type = ( + main_pass, { input data, also do first output step } + huff_opt_pass, { Huffman code optimization pass } + output_pass { data output pass } + ); + +type + my_master_ptr = ^my_comp_master; + my_comp_master = record + pub : jpeg_comp_master; { public fields } + + pass_type : c_pass_type; { the type of the current pass } + + pass_number : int; { # of passes completed } + total_passes : int; { total # of passes needed } + + scan_number : int; { current index in scan_info[] } + end; + + +{ Support routines that do various essential calculations. } + +{LOCAL} +procedure initial_setup (cinfo : j_compress_ptr); +{ Do computations that are needed before master selection phase } +var + ci : int; + compptr : jpeg_component_info_ptr; + samplesperrow : long; + jd_samplesperrow : JDIMENSION; +begin + + { Sanity check on image dimensions } + if (cinfo^.image_height <= 0) or (cinfo^.image_width <= 0) or + (cinfo^.num_components <= 0) or (cinfo^.input_components <= 0) then + ERREXIT(j_common_ptr(cinfo), JERR_EMPTY_IMAGE); + + { Make sure image isn't bigger than I can handle } + if ( long(cinfo^.image_height) > long(JPEG_MAX_DIMENSION)) or + ( long(cinfo^.image_width) > long(JPEG_MAX_DIMENSION)) then + ERREXIT1(j_common_ptr(cinfo), JERR_IMAGE_TOO_BIG, + uInt(JPEG_MAX_DIMENSION)); + + { Width of an input scanline must be representable as JDIMENSION. } + samplesperrow := long (cinfo^.image_width) * long (cinfo^.input_components); + jd_samplesperrow := JDIMENSION (samplesperrow); + if ( long(jd_samplesperrow) <> samplesperrow) then + ERREXIT(j_common_ptr(cinfo), JERR_WIDTH_OVERFLOW); + + { For now, precision must match compiled-in value... } + if (cinfo^.data_precision <> BITS_IN_JSAMPLE) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PRECISION, cinfo^.data_precision); + + { Check that number of components won't exceed internal array sizes } + if (cinfo^.num_components > MAX_COMPONENTS) then + ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.num_components, + MAX_COMPONENTS); + + { Compute maximum sampling factors; check factor validity } + cinfo^.max_h_samp_factor := 1; + cinfo^.max_v_samp_factor := 1; + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + if (compptr^.h_samp_factor<=0) or (compptr^.h_samp_factor>MAX_SAMP_FACTOR) + or (compptr^.v_samp_factor<=0) or (compptr^.v_samp_factor>MAX_SAMP_FACTOR) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_SAMPLING); + { MAX } + if cinfo^.max_h_samp_factor > compptr^.h_samp_factor then + cinfo^.max_h_samp_factor := cinfo^.max_h_samp_factor + else + cinfo^.max_h_samp_factor := compptr^.h_samp_factor; + { MAX } + if cinfo^.max_v_samp_factor > compptr^.v_samp_factor then + cinfo^.max_v_samp_factor := cinfo^.max_v_samp_factor + else + cinfo^.max_v_samp_factor := compptr^.v_samp_factor; + Inc(compptr); + end; + + { Compute dimensions of components } + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Fill in the correct component_index value; don't rely on application } + compptr^.component_index := ci; + { For compression, we never do DCT scaling. } + compptr^.DCT_scaled_size := DCTSIZE; + { Size in DCT blocks } + compptr^.width_in_blocks := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_width) * long (compptr^.h_samp_factor), + long (cinfo^.max_h_samp_factor * DCTSIZE)) ); + compptr^.height_in_blocks := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_height) * long (compptr^.v_samp_factor), + long (cinfo^.max_v_samp_factor * DCTSIZE)) ); + { Size in samples } + compptr^.downsampled_width := JDIMENSION ( + jdiv_round_up(long(cinfo^.image_width) * long(compptr^.h_samp_factor), + long(cinfo^.max_h_samp_factor)) ); + compptr^.downsampled_height := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_height) * long(compptr^.v_samp_factor), + long (cinfo^.max_v_samp_factor)) ); + { Mark component needed (this flag isn't actually used for compression) } + compptr^.component_needed := TRUE; + Inc(compptr); + end; + + { Compute number of fully interleaved MCU rows (number of times that + main controller will call coefficient controller). } + + cinfo^.total_iMCU_rows := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_height), + long (cinfo^.max_v_samp_factor*DCTSIZE)) ); +end; + + +{$ifdef C_MULTISCAN_FILES_SUPPORTED} + +{LOCAL} +procedure validate_script (cinfo : j_compress_ptr); +{ Verify that the scan script in cinfo^.scan_info[] is valid; also + determine whether it uses progressive JPEG, and set cinfo^.progressive_mode. } +type + IntRow = array[0..DCTSIZE2-1] of int; + introw_ptr = ^IntRow; +var + {const}scanptr : jpeg_scan_info_ptr; + scanno, ncomps, ci, coefi, thisi : int; + Ss, Se, Ah, Al : int; + component_sent : array[0..MAX_COMPONENTS-1] of boolean; +{$ifdef C_PROGRESSIVE_SUPPORTED} + last_bitpos_int_ptr : int_ptr; + last_bitpos_ptr : introw_ptr; + last_bitpos : array[0..MAX_COMPONENTS-1] of IntRow; + { -1 until that coefficient has been seen; then last Al for it } + { The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that + seems wrong: the upper bound ought to depend on data precision. + Perhaps they really meant 0..N+1 for N-bit precision. + Here we allow 0..10 for 8-bit data; Al larger than 10 results in + out-of-range reconstructed DC values during the first DC scan, + which might cause problems for some decoders. } +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + MAX_AH_AL = 10; +{$else} +const + MAX_AH_AL = 13; +{$endif} +{$endif} +begin + + if (cinfo^.num_scans <= 0) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, 0); + + { For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1; + for progressive JPEG, no scan can have this. } + + scanptr := cinfo^.scan_info; + if (scanptr^.Ss <> 0) or (scanptr^.Se <> DCTSIZE2-1) then + begin +{$ifdef C_PROGRESSIVE_SUPPORTED} + cinfo^.progressive_mode := TRUE; + last_bitpos_int_ptr := @(last_bitpos[0][0]); + for ci := 0 to pred(cinfo^.num_components) do + for coefi := 0 to pred(DCTSIZE2) do + begin + last_bitpos_int_ptr^ := -1; + Inc(last_bitpos_int_ptr); + end; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + begin + cinfo^.progressive_mode := FALSE; + for ci := 0 to pred(cinfo^.num_components) do + component_sent[ci] := FALSE; + end; + + for scanno := 1 to cinfo^.num_scans do + begin + { Validate component indexes } + ncomps := scanptr^.comps_in_scan; + if (ncomps <= 0) or (ncomps > MAX_COMPS_IN_SCAN) then + ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); + for ci := 0 to pred(ncomps) do + begin + thisi := scanptr^.component_index[ci]; + if (thisi < 0) or (thisi >= cinfo^.num_components) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, scanno); + { Components must appear in SOF order within each scan } + if (ci > 0) and (thisi <= scanptr^.component_index[ci-1]) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, scanno); + end; + { Validate progression parameters } + Ss := scanptr^.Ss; + Se := scanptr^.Se; + Ah := scanptr^.Ah; + Al := scanptr^.Al; + if (cinfo^.progressive_mode) then + begin +{$ifdef C_PROGRESSIVE_SUPPORTED} + if (Ss < 0) or (Ss >= DCTSIZE2) or (Se < Ss) or (Se >= DCTSIZE2) or + (Ah < 0) or (Ah > MAX_AH_AL) or (Al < 0) or (Al > MAX_AH_AL) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + + if (Ss < 0) or (Ss >= DCTSIZE2) or (Se < Ss) or (Se >= DCTSIZE2) + or (Ah < 0) or (Ah > MAX_AH_AL) or (Al < 0) or (Al > MAX_AH_AL) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + if (Ss = 0) then + begin + if (Se <> 0) then { DC and AC together not OK } + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + end + else + begin + if (ncomps <> 1) then { AC scans must be for only one component } + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + end; + for ci := 0 to pred(ncomps) do + begin + last_bitpos_ptr := @( last_bitpos[scanptr^.component_index[ci]]); + if (Ss <> 0) and (last_bitpos_ptr^[0] < 0) then { AC without prior DC scan } + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + for coefi := Ss to Se do + begin + if (last_bitpos_ptr^[coefi] < 0) then + begin + { first scan of this coefficient } + if (Ah <> 0) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + end + else + begin + { not first scan } + if (Ah <> last_bitpos_ptr^[coefi]) or (Al <> Ah-1) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + end; + last_bitpos_ptr^[coefi] := Al; + end; + end; +{$endif} + end + else + begin + { For sequential JPEG, all progression parameters must be these: } + if (Ss <> 0) or (Se <> DCTSIZE2-1) or (Ah <> 0) or (Al <> 0) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PROG_SCRIPT, scanno); + { Make sure components are not sent twice } + for ci := 0 to pred(ncomps) do + begin + thisi := scanptr^.component_index[ci]; + if (component_sent[thisi]) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_SCAN_SCRIPT, scanno); + component_sent[thisi] := TRUE; + end; + end; + Inc(scanptr); + end; + + { Now verify that everything got sent. } + if (cinfo^.progressive_mode) then + begin +{$ifdef C_PROGRESSIVE_SUPPORTED} + { For progressive mode, we only check that at least some DC data + got sent for each component; the spec does not require that all bits + of all coefficients be transmitted. Would it be wiser to enforce + transmission of all coefficient bits?? } + + for ci := 0 to pred(cinfo^.num_components) do + begin + if (last_bitpos[ci][0] < 0) then + ERREXIT(j_common_ptr(cinfo), JERR_MISSING_DATA); + end; +{$endif} + end + else + begin + for ci := 0 to pred(cinfo^.num_components) do + begin + if (not component_sent[ci]) then + ERREXIT(j_common_ptr(cinfo), JERR_MISSING_DATA); + end; + end; +end; + +{$endif} { C_MULTISCAN_FILES_SUPPORTED } + + +{LOCAL} +procedure select_scan_parameters (cinfo : j_compress_ptr); +{ Set up the scan parameters for the current scan } +var + master : my_master_ptr; + {const} scanptr : jpeg_scan_info_ptr; + ci : int; +var + comp_infos : jpeg_component_info_list_ptr; +begin +{$ifdef C_MULTISCAN_FILES_SUPPORTED} + if (cinfo^.scan_info <> NIL) then + begin + { Prepare for current scan --- the script is already validated } + master := my_master_ptr (cinfo^.master); + scanptr := cinfo^.scan_info; + Inc(scanptr, master^.scan_number); + + cinfo^.comps_in_scan := scanptr^.comps_in_scan; + comp_infos := cinfo^.comp_info; + for ci := 0 to pred(scanptr^.comps_in_scan) do + begin + cinfo^.cur_comp_info[ci] := + @(comp_infos^[scanptr^.component_index[ci]]); + end; + cinfo^.Ss := scanptr^.Ss; + cinfo^.Se := scanptr^.Se; + cinfo^.Ah := scanptr^.Ah; + cinfo^.Al := scanptr^.Al; + end + else +{$endif} + begin + { Prepare for single sequential-JPEG scan containing all components } + if (cinfo^.num_components > MAX_COMPS_IN_SCAN) then + ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.num_components, + MAX_COMPS_IN_SCAN); + cinfo^.comps_in_scan := cinfo^.num_components; + comp_infos := cinfo^.comp_info; + for ci := 0 to pred(cinfo^.num_components) do + begin + cinfo^.cur_comp_info[ci] := @(comp_infos^[ci]); + end; + cinfo^.Ss := 0; + cinfo^.Se := DCTSIZE2-1; + cinfo^.Ah := 0; + cinfo^.Al := 0; + end; +end; + + +{LOCAL} +procedure per_scan_setup (cinfo : j_compress_ptr); +{ Do computations that are needed before processing a JPEG scan } +{ cinfo^.comps_in_scan and cinfo^.cur_comp_info[] are already set } +var + ci, mcublks, tmp : int; + compptr : jpeg_component_info_ptr; + nominal : long; +begin + if (cinfo^.comps_in_scan = 1) then + begin + + { Noninterleaved (single-component) scan } + compptr := cinfo^.cur_comp_info[0]; + + { Overall image size in MCUs } + cinfo^.MCUs_per_row := compptr^.width_in_blocks; + cinfo^.MCU_rows_in_scan := compptr^.height_in_blocks; + + { For noninterleaved scan, always one block per MCU } + compptr^.MCU_width := 1; + compptr^.MCU_height := 1; + compptr^.MCU_blocks := 1; + compptr^.MCU_sample_width := DCTSIZE; + compptr^.last_col_width := 1; + { For noninterleaved scans, it is convenient to define last_row_height + as the number of block rows present in the last iMCU row. } + + tmp := int (compptr^.height_in_blocks) mod compptr^.v_samp_factor; + if (tmp = 0) then + tmp := compptr^.v_samp_factor; + compptr^.last_row_height := tmp; + + { Prepare array describing MCU composition } + cinfo^.blocks_in_MCU := 1; + cinfo^.MCU_membership[0] := 0; + + end + else + begin + + { Interleaved (multi-component) scan } + if (cinfo^.comps_in_scan <= 0) or + (cinfo^.comps_in_scan > MAX_COMPS_IN_SCAN) then + ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, + cinfo^.comps_in_scan, MAX_COMPS_IN_SCAN); + + { Overall image size in MCUs } + cinfo^.MCUs_per_row := JDIMENSION ( + jdiv_round_up( long (cinfo^.image_width), + long (cinfo^.max_h_samp_factor*DCTSIZE)) ); + cinfo^.MCU_rows_in_scan := JDIMENSION ( + jdiv_round_up( long (cinfo^.image_height), + long (cinfo^.max_v_samp_factor*DCTSIZE)) ); + + cinfo^.blocks_in_MCU := 0; + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + { Sampling factors give # of blocks of component in each MCU } + compptr^.MCU_width := compptr^.h_samp_factor; + compptr^.MCU_height := compptr^.v_samp_factor; + compptr^.MCU_blocks := compptr^.MCU_width * compptr^.MCU_height; + compptr^.MCU_sample_width := compptr^.MCU_width * DCTSIZE; + { Figure number of non-dummy blocks in last MCU column & row } + tmp := int (compptr^.width_in_blocks) mod compptr^.MCU_width; + if (tmp = 0) then + tmp := compptr^.MCU_width; + compptr^.last_col_width := tmp; + tmp := int (compptr^.height_in_blocks) mod compptr^.MCU_height; + if (tmp = 0) then + tmp := compptr^.MCU_height; + compptr^.last_row_height := tmp; + { Prepare array describing MCU composition } + mcublks := compptr^.MCU_blocks; + if (cinfo^.blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_MCU_SIZE); + while (mcublks > 0) do + begin + Dec(mcublks); + cinfo^.MCU_membership[cinfo^.blocks_in_MCU] := ci; + Inc(cinfo^.blocks_in_MCU); + end; + end; + + end; + + { Convert restart specified in rows to actual MCU count. } + { Note that count must fit in 16 bits, so we provide limiting. } + if (cinfo^.restart_in_rows > 0) then + begin + nominal := long(cinfo^.restart_in_rows) * long(cinfo^.MCUs_per_row); + if nominal < long(65535) then + cinfo^.restart_interval := uInt (nominal) + else + cinfo^.restart_interval := long(65535); + end; +end; + + +{ Per-pass setup. + This is called at the beginning of each pass. We determine which modules + will be active during this pass and give them appropriate start_pass calls. + We also set is_last_pass to indicate whether any more passes will be + required. } + +{METHODDEF} +procedure prepare_for_pass (cinfo : j_compress_ptr); +var + master : my_master_ptr; +var + fallthrough : boolean; +begin + master := my_master_ptr (cinfo^.master); + fallthrough := true; + + case (master^.pass_type) of + main_pass: + begin + { Initial pass: will collect input data, and do either Huffman + optimization or data output for the first scan. } + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (not cinfo^.raw_data_in) then + begin + cinfo^.cconvert^.start_pass (cinfo); + cinfo^.downsample^.start_pass (cinfo); + cinfo^.prep^.start_pass (cinfo, JBUF_PASS_THRU); + end; + cinfo^.fdct^.start_pass (cinfo); + cinfo^.entropy^.start_pass (cinfo, cinfo^.optimize_coding); + if master^.total_passes > 1 then + cinfo^.coef^.start_pass (cinfo, JBUF_SAVE_AND_PASS) + else + cinfo^.coef^.start_pass (cinfo, JBUF_PASS_THRU); + cinfo^.main^.start_pass (cinfo, JBUF_PASS_THRU); + if (cinfo^.optimize_coding) then + begin + { No immediate data output; postpone writing frame/scan headers } + master^.pub.call_pass_startup := FALSE; + end + else + begin + { Will write frame/scan headers at first jpeg_write_scanlines call } + master^.pub.call_pass_startup := TRUE; + end; + end; +{$ifdef ENTROPY_OPT_SUPPORTED} + huff_opt_pass, + output_pass: + begin + if (master^.pass_type = huff_opt_pass) then + begin + { Do Huffman optimization for a scan after the first one. } + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + if (cinfo^.Ss <> 0) or (cinfo^.Ah = 0) or (cinfo^.arith_code) then + begin + cinfo^.entropy^.start_pass (cinfo, TRUE); + cinfo^.coef^.start_pass (cinfo, JBUF_CRANK_DEST); + master^.pub.call_pass_startup := FALSE; + fallthrough := false; + end; + { Special case: Huffman DC refinement scans need no Huffman table + and therefore we can skip the optimization pass for them. } + if fallthrough then + begin + master^.pass_type := output_pass; + Inc(master^.pass_number); + {FALLTHROUGH} + end; + end; +{$else} + output_pass: + begin +{$endif} + if fallthrough then + begin + { Do a data-output pass. } + { We need not repeat per-scan setup if prior optimization pass did it. } + if (not cinfo^.optimize_coding) then + begin + select_scan_parameters(cinfo); + per_scan_setup(cinfo); + end; + cinfo^.entropy^.start_pass (cinfo, FALSE); + cinfo^.coef^.start_pass (cinfo, JBUF_CRANK_DEST); + { We emit frame/scan headers now } + if (master^.scan_number = 0) then + cinfo^.marker^.write_frame_header (cinfo); + cinfo^.marker^.write_scan_header (cinfo); + master^.pub.call_pass_startup := FALSE; + end; + end; + else + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); + end; + + master^.pub.is_last_pass := (master^.pass_number = master^.total_passes-1); + + { Set up progress monitor's pass info if present } + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.completed_passes := master^.pass_number; + cinfo^.progress^.total_passes := master^.total_passes; + end; +end; + + +{ Special start-of-pass hook. + This is called by jpeg_write_scanlines if call_pass_startup is TRUE. + In single-pass processing, we need this hook because we don't want to + write frame/scan headers during jpeg_start_compress; we want to let the + application write COM markers etc. between jpeg_start_compress and the + jpeg_write_scanlines loop. + In multi-pass processing, this routine is not used. } + +{METHODDEF} +procedure pass_startup (cinfo : j_compress_ptr); +begin + cinfo^.master^.call_pass_startup := FALSE; { reset flag so call only once } + + cinfo^.marker^.write_frame_header (cinfo); + cinfo^.marker^.write_scan_header (cinfo); +end; + + +{ Finish up at end of pass. } + +{METHODDEF} +procedure finish_pass_master (cinfo : j_compress_ptr); +var + master : my_master_ptr; +begin + master := my_master_ptr (cinfo^.master); + + { The entropy coder always needs an end-of-pass call, + either to analyze statistics or to flush its output buffer. } + cinfo^.entropy^.finish_pass (cinfo); + + { Update state for next pass } + case (master^.pass_type) of + main_pass: + begin + { next pass is either output of scan 0 (after optimization) + or output of scan 1 (if no optimization). } + + master^.pass_type := output_pass; + if (not cinfo^.optimize_coding) then + Inc(master^.scan_number); + end; + huff_opt_pass: + { next pass is always output of current scan } + master^.pass_type := output_pass; + output_pass: + begin + { next pass is either optimization or output of next scan } + if (cinfo^.optimize_coding) then + master^.pass_type := huff_opt_pass; + Inc(master^.scan_number); + end; + end; + + Inc(master^.pass_number); +end; + + +{ Initialize master compression control. } + +{GLOBAL} +procedure jinit_c_master_control (cinfo : j_compress_ptr; + transcode_only : boolean); +var + master : my_master_ptr; +begin + master := my_master_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_comp_master)) ); + cinfo^.master := jpeg_comp_master_ptr(master); + master^.pub.prepare_for_pass := prepare_for_pass; + master^.pub.pass_startup := pass_startup; + master^.pub.finish_pass := finish_pass_master; + master^.pub.is_last_pass := FALSE; + + { Validate parameters, determine derived values } + initial_setup(cinfo); + + if (cinfo^.scan_info <> NIL) then + begin +{$ifdef C_MULTISCAN_FILES_SUPPORTED} + validate_script(cinfo); +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + begin + cinfo^.progressive_mode := FALSE; + cinfo^.num_scans := 1; + end; + + if (cinfo^.progressive_mode) then { TEMPORARY HACK ??? } + cinfo^.optimize_coding := TRUE; { assume default tables no good for progressive mode } + + { Initialize my private state } + if (transcode_only) then + begin + { no main pass in transcoding } + if (cinfo^.optimize_coding) then + master^.pass_type := huff_opt_pass + else + master^.pass_type := output_pass; + end + else + begin + { for normal compression, first pass is always this type: } + master^.pass_type := main_pass; + end; + master^.scan_number := 0; + master^.pass_number := 0; + if (cinfo^.optimize_coding) then + master^.total_passes := cinfo^.num_scans * 2 + else + master^.total_passes := cinfo^.num_scans; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcomapi.pas b/src/lib/vampimg/JpegLib/imjcomapi.pas new file mode 100644 index 0000000..c58a7ae --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcomapi.pas @@ -0,0 +1,130 @@ +unit imjcomapi; + +{ This file contains application interface routines that are used for both + compression and decompression. } + +{ Original: jcomapi.c; Copyright (C) 1994-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib; + +{ Abort processing of a JPEG compression or decompression operation, + but don't destroy the object itself. } + +{GLOBAL} +procedure jpeg_abort (cinfo : j_common_ptr); + + +{ Destruction of a JPEG object. } + +{GLOBAL} +procedure jpeg_destroy (cinfo : j_common_ptr); + +{GLOBAL} +function jpeg_alloc_quant_table (cinfo : j_common_ptr) : JQUANT_TBL_PTR; + +{GLOBAL} +function jpeg_alloc_huff_table (cinfo : j_common_ptr) : JHUFF_TBL_PTR; + +implementation + +{ Abort processing of a JPEG compression or decompression operation, + but don't destroy the object itself. + + For this, we merely clean up all the nonpermanent memory pools. + Note that temp files (virtual arrays) are not allowed to belong to + the permanent pool, so we will be able to close all temp files here. + Closing a data source or destination, if necessary, is the application's + responsibility. } + + +{GLOBAL} +procedure jpeg_abort (cinfo : j_common_ptr); +var + pool : int; +begin + { Do nothing if called on a not-initialized or destroyed JPEG object. } + if (cinfo^.mem = NIL) then + exit; + + { Releasing pools in reverse order might help avoid fragmentation + with some (brain-damaged) malloc libraries. } + + for pool := JPOOL_NUMPOOLS-1 downto JPOOL_PERMANENT+1 do + begin + cinfo^.mem^.free_pool (cinfo, pool); + end; + + { Reset overall state for possible reuse of object } + if (cinfo^.is_decompressor) then + begin + cinfo^.global_state := DSTATE_START; + { Try to keep application from accessing now-deleted marker list. + A bit kludgy to do it here, but this is the most central place. } + j_decompress_ptr(cinfo)^.marker_list := NIL; + end + else + begin + cinfo^.global_state := CSTATE_START; + end; +end; + + +{ Destruction of a JPEG object. + + Everything gets deallocated except the master jpeg_compress_struct itself + and the error manager struct. Both of these are supplied by the application + and must be freed, if necessary, by the application. (Often they are on + the stack and so don't need to be freed anyway.) + Closing a data source or destination, if necessary, is the application's + responsibility. } + + +{GLOBAL} +procedure jpeg_destroy (cinfo : j_common_ptr); +begin + { We need only tell the memory manager to release everything. } + { NB: mem pointer is NIL if memory mgr failed to initialize. } + if (cinfo^.mem <> NIL) then + cinfo^.mem^.self_destruct (cinfo); + cinfo^.mem := NIL; { be safe if jpeg_destroy is called twice } + cinfo^.global_state := 0; { mark it destroyed } +end; + + +{ Convenience routines for allocating quantization and Huffman tables. + (Would jutils.c be a more reasonable place to put these?) } + + +{GLOBAL} +function jpeg_alloc_quant_table (cinfo : j_common_ptr) : JQUANT_TBL_PTR; +var + tbl : JQUANT_TBL_PTR; +begin + tbl := JQUANT_TBL_PTR( + cinfo^.mem^.alloc_small (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)) + ); + tbl^.sent_table := FALSE; { make sure this is false in any new table } + jpeg_alloc_quant_table := tbl; +end; + + +{GLOBAL} +function jpeg_alloc_huff_table (cinfo : j_common_ptr) : JHUFF_TBL_PTR; +var + tbl : JHUFF_TBL_PTR; +begin + tbl := JHUFF_TBL_PTR( + cinfo^.mem^.alloc_small (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)) + ); + tbl^.sent_table := FALSE; { make sure this is false in any new table } + jpeg_alloc_huff_table := tbl; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjconfig.inc b/src/lib/vampimg/JpegLib/imjconfig.inc new file mode 100644 index 0000000..70cf478 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjconfig.inc @@ -0,0 +1,125 @@ +{ ----------------------- JPEG_INTERNAL_OPTIONS ---------------------- } + + +{ These defines indicate whether to include various optional functions. + Undefining some of these symbols will produce a smaller but less capable + library. Note that you can leave certain source files out of the + compilation/linking process if you've #undef'd the corresponding symbols. + (You may HAVE to do that if your compiler doesn't like null source files.)} + + +{ Arithmetic coding is unsupported for legal reasons. Complaints to IBM. } + +{ Capability options common to encoder and decoder: } + +{$define DCT_ISLOW_SUPPORTED} { slow but accurate integer algorithm } +{$define DCT_IFAST_SUPPORTED} { faster, less accurate integer method } +{$define DCT_FLOAT_SUPPORTED} { floating-point: accurate, fast on fast HW } + +{ Encoder capability options: } + +{$undef C_ARITH_CODING_SUPPORTED} { Arithmetic coding back end? } +{$define C_MULTISCAN_FILES_SUPPORTED} { Multiple-scan JPEG files? } +{$define C_PROGRESSIVE_SUPPORTED} { Progressive JPEG? (Requires MULTISCAN)} +{$define ENTROPY_OPT_SUPPORTED} { Optimization of entropy coding parms? } +{ Note: if you selected 12-bit data precision, it is dangerous to turn off + ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit + precision, so jchuff.c normally uses entropy optimization to compute + usable tables for higher precision. If you don't want to do optimization, + you'll have to supply different default Huffman tables. + The exact same statements apply for progressive JPEG: the default tables + don't work for progressive mode. (This may get fixed, however.) } + +{$define INPUT_SMOOTHING_SUPPORTED} { Input image smoothing option? } + +{ Decoder capability options: } + +{$undef D_ARITH_CODING_SUPPORTED} { Arithmetic coding back end? } +{$define D_MULTISCAN_FILES_SUPPORTED} { Multiple-scan JPEG files? } +{$define D_PROGRESSIVE_SUPPORTED} { Progressive JPEG? (Requires MULTISCAN)} +{$define SAVE_MARKERS_SUPPORTED} { jpeg_save_markers() needed? } +{$define BLOCK_SMOOTHING_SUPPORTED} { Block smoothing? (Progressive only) } +{$define IDCT_SCALING_SUPPORTED} { Output rescaling via IDCT? } +{$undef UPSAMPLE_SCALING_SUPPORTED} { Output rescaling at upsample stage? } +{$define UPSAMPLE_MERGING_SUPPORTED} { Fast path for sloppy upsampling? } +{$define QUANT_1PASS_SUPPORTED} { 1-pass color quantization? } +{$define QUANT_2PASS_SUPPORTED} { 2-pass color quantization? } + +{ If you happen not to want the image transform support, disable it here } +{$define TRANSFORMS_SUPPORTED} + +{ more capability options later, no doubt } + +{$ifopt I+} {$define IOcheck} {$endif} + +{ ------------------------------------------------------------------------ } + +{$define USE_FMEM} { Borland has _fmemcpy() and _fmemset() } + +{$define FMEMCOPY} +{$define FMEMZERO} + +{$define DCTSIZE_IS_8} { e.g. unroll the inner loop } +{$define RIGHT_SHIFT_IS_UNSIGNED} +{$undef AVOID_TABLES} +{$undef FAST_DIVIDE} + +{$define BITS_IN_JSAMPLE_IS_8} + +{----------------------------------------------------------------} +{ for test of 12 bit JPEG code only. !! } +{-- $undef BITS_IN_JSAMPLE_IS_8} +{----------------------------------------------------------------} + +//{$define RGB_RED_IS_0} +{ !CHANGE: This must be defined for Delphi/Kylix/FPC } +{$define RGB_RED_IS_2} { RGB byte order } + + +{$define RGB_PIXELSIZE_IS_3} +{$define SLOW_SHIFT_32} +{$undef NO_ZERO_ROW_TEST} + +{$define USE_MSDOS_MEMMGR} { Define this if you use jmemdos.c } +{$define XMS_SUPPORTED} +{$define EMS_SUPPORTED} + +{$undef MEM_STATS} { Write out memory usage } +{$define AM_MEMORY_MANAGER} { we define jvirt_Xarray_control structs } + +{$undef FULL_MAIN_BUFFER_SUPPORTED} + +{$define PROGRESS_REPORT} +{$define TWO_FILE_COMMANDLINE} +{$undef BMP_SUPPORTED} +{$undef PPM_SUPPORTED} +{$undef GIF_SUPPORTED} +{$undef RLE_SUPPORTED} +{$undef TARGA_SUPPORTED} +{$define EXT_SWITCH} + +{$ifndef BITS_IN_JSAMPLE_IS_8} { for 12 bit samples } +{$undef BMP_SUPPORTED} +{$undef RLE_SUPPORTED} +{$undef TARGA_SUPPORTED} +{$endif} + + +{!CHANGE: Allowed only for Delphi} +{$undef BASM16} { for TP7 - use BASM for fast multiply } +{$ifdef Win32} + {$ifndef FPC} + {$define BASM} { jidctint with BASM for Delphi 2/3 } + {$undef RGB_RED_IS_0} { BGR byte order in JQUANT2 } + {$endif} +{$endif} + +{$ifdef FPC} + {$MODE DELPHI} +{$endif} + +{!CHANGE: Added this} +{$define Delphi_Stream} +{$Q-} +{$MINENUMSIZE 4} +{$ALIGN 8} diff --git a/src/lib/vampimg/JpegLib/imjcparam.pas b/src/lib/vampimg/JpegLib/imjcparam.pas new file mode 100644 index 0000000..66117ca --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcparam.pas @@ -0,0 +1,701 @@ +unit imjcparam; + +{ This file contains optional default-setting code for the JPEG compressor. + Applications do not have to use this file, but those that don't use it + must know a lot more about the innards of the JPEG code. } + +{ Original: jcparam.c ; Copyright (C) 1991-1998, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjcomapi, + imjpeglib; + +{ Quantization table setup routines } + +{GLOBAL} +procedure jpeg_add_quant_table (cinfo : j_compress_ptr; + which_tbl : int; + const basic_table : array of uInt; + scale_factor : int; + force_baseline : boolean); + +{GLOBAL} +procedure jpeg_set_linear_quality (cinfo : j_compress_ptr; + scale_factor : int; + force_baseline : boolean); +{ Set or change the 'quality' (quantization) setting, using default tables + and a straight percentage-scaling quality scale. In most cases it's better + to use jpeg_set_quality (below); this entry point is provided for + applications that insist on a linear percentage scaling. } + +{GLOBAL} +function jpeg_quality_scaling (quality : int) : int; +{ Convert a user-specified quality rating to a percentage scaling factor + for an underlying quantization table, using our recommended scaling curve. + The input 'quality' factor should be 0 (terrible) to 100 (very good). } + +{GLOBAL} +procedure jpeg_set_quality (cinfo : j_compress_ptr; + quality : int; + force_baseline : boolean); +{ Set or change the 'quality' (quantization) setting, using default tables. + This is the standard quality-adjusting entry point for typical user + interfaces; only those who want detailed control over quantization tables + would use the preceding three routines directly. } + +{GLOBAL} +procedure jpeg_set_defaults (cinfo : j_compress_ptr); + +{ Create a recommended progressive-JPEG script. + cinfo^.num_components and cinfo^.jpeg_color_space must be correct. } + +{ Set the JPEG colorspace, and choose colorspace-dependent default values. } + +{GLOBAL} +procedure jpeg_set_colorspace (cinfo : j_compress_ptr; + colorspace : J_COLOR_SPACE); + +{ Select an appropriate JPEG colorspace for in_color_space. } + +{GLOBAL} +procedure jpeg_default_colorspace (cinfo : j_compress_ptr); + +{GLOBAL} +procedure jpeg_simple_progression (cinfo : j_compress_ptr); + + +implementation + +{ Quantization table setup routines } + +{GLOBAL} +procedure jpeg_add_quant_table (cinfo : j_compress_ptr; + which_tbl : int; + const basic_table : array of uInt; + scale_factor : int; + force_baseline : boolean); +{ Define a quantization table equal to the basic_table times + a scale factor (given as a percentage). + If force_baseline is TRUE, the computed quantization table entries + are limited to 1..255 for JPEG baseline compatibility. } +var + qtblptr :^JQUANT_TBL_PTR; + i : int; + temp : long; +begin + { Safety check to ensure start_compress not called yet. } + if (cinfo^.global_state <> CSTATE_START) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + if (which_tbl < 0) or (which_tbl >= NUM_QUANT_TBLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_DQT_INDEX, which_tbl); + + qtblptr := @(cinfo^.quant_tbl_ptrs[which_tbl]); + + if (qtblptr^ = NIL) then + qtblptr^ := jpeg_alloc_quant_table(j_common_ptr(cinfo)); + + for i := 0 to pred(DCTSIZE2) do + begin + temp := (long(basic_table[i]) * scale_factor + long(50)) div long(100); + { limit the values to the valid range } + if (temp <= long(0)) then + temp := long(1); + if (temp > long(32767)) then + temp := long(32767); { max quantizer needed for 12 bits } + if (force_baseline) and (temp > long(255)) then + temp := long(255); { limit to baseline range if requested } + (qtblptr^)^.quantval[i] := UINT16 (temp); + end; + + { Initialize sent_table FALSE so table will be written to JPEG file. } + (qtblptr^)^.sent_table := FALSE; +end; + + +{GLOBAL} +procedure jpeg_set_linear_quality (cinfo : j_compress_ptr; + scale_factor : int; + force_baseline : boolean); +{ Set or change the 'quality' (quantization) setting, using default tables + and a straight percentage-scaling quality scale. In most cases it's better + to use jpeg_set_quality (below); this entry point is provided for + applications that insist on a linear percentage scaling. } + +{ These are the sample quantization tables given in JPEG spec section K.1. + The spec says that the values given produce "good" quality, and + when divided by 2, "very good" quality. } + +const + std_luminance_quant_tbl : array[0..DCTSIZE2-1] of uInt = + (16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99); + +const + std_chrominance_quant_tbl : array[0..DCTSIZE2-1] of uInt = + (17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99); +begin + { Set up two quantization tables using the specified scaling } + jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, + scale_factor, force_baseline); + jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, + scale_factor, force_baseline); +end; + + +{GLOBAL} +function jpeg_quality_scaling (quality : int) : int; +{ Convert a user-specified quality rating to a percentage scaling factor + for an underlying quantization table, using our recommended scaling curve. + The input 'quality' factor should be 0 (terrible) to 100 (very good). } +begin + { Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. } + if (quality <= 0) then + quality := 1; + if (quality > 100) then + quality := 100; + + { The basic table is used as-is (scaling 100) for a quality of 50. + Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + to make all the table entries 1 (hence, minimum quantization loss). + Qualities 1..50 are converted to scaling percentage 5000/Q. } + if (quality < 50) then + quality := 5000 div quality + else + quality := 200 - quality*2; + + jpeg_quality_scaling := quality; +end; + + +{GLOBAL} +procedure jpeg_set_quality (cinfo : j_compress_ptr; + quality : int; + force_baseline : boolean); +{ Set or change the 'quality' (quantization) setting, using default tables. + This is the standard quality-adjusting entry point for typical user + interfaces; only those who want detailed control over quantization tables + would use the preceding three routines directly. } +begin + { Convert user 0-100 rating to percentage scaling } + quality := jpeg_quality_scaling(quality); + + { Set up standard quality tables } + jpeg_set_linear_quality(cinfo, quality, force_baseline); +end; + + +{ Huffman table setup routines } + +{LOCAL} +procedure add_huff_table (cinfo : j_compress_ptr; + var htblptr : JHUFF_TBL_PTR; + var bits : array of UINT8; + var val : array of UINT8); +{ Define a Huffman table } +var + nsymbols, len : int; +begin + if (htblptr = NIL) then + htblptr := jpeg_alloc_huff_table(j_common_ptr(cinfo)); + + { Copy the number-of-symbols-of-each-code-length counts } + MEMCOPY(@htblptr^.bits, @bits, SIZEOF(htblptr^.bits)); + + + { Validate the counts. We do this here mainly so we can copy the right + number of symbols from the val[] array, without risking marching off + the end of memory. jchuff.c will do a more thorough test later. } + + nsymbols := 0; + for len := 1 to 16 do + Inc(nsymbols, bits[len]); + if (nsymbols < 1) or (nsymbols > 256) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + + MEMCOPY(@htblptr^.huffval, @val, nsymbols * SIZEOF(UINT8)); + + { Initialize sent_table FALSE so table will be written to JPEG file. } + (htblptr)^.sent_table := FALSE; +end; + + +{$J+} +{LOCAL} +procedure std_huff_tables (cinfo : j_compress_ptr); +{ Set up the standard Huffman tables (cf. JPEG standard section K.3) } +{ IMPORTANT: these are only valid for 8-bit data precision! } + const bits_dc_luminance : array[0..17-1] of UINT8 = + ({ 0-base } 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0); + const val_dc_luminance : array[0..11] of UINT8 = + (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + + const bits_dc_chrominance : array[0..17-1] of UINT8 = + ( { 0-base } 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + const val_dc_chrominance : array[0..11] of UINT8 = + ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ); + + const bits_ac_luminance : array[0..17-1] of UINT8 = + ( { 0-base } 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, $7d ); + const val_ac_luminance : array[0..161] of UINT8 = + ( $01, $02, $03, $00, $04, $11, $05, $12, + $21, $31, $41, $06, $13, $51, $61, $07, + $22, $71, $14, $32, $81, $91, $a1, $08, + $23, $42, $b1, $c1, $15, $52, $d1, $f0, + $24, $33, $62, $72, $82, $09, $0a, $16, + $17, $18, $19, $1a, $25, $26, $27, $28, + $29, $2a, $34, $35, $36, $37, $38, $39, + $3a, $43, $44, $45, $46, $47, $48, $49, + $4a, $53, $54, $55, $56, $57, $58, $59, + $5a, $63, $64, $65, $66, $67, $68, $69, + $6a, $73, $74, $75, $76, $77, $78, $79, + $7a, $83, $84, $85, $86, $87, $88, $89, + $8a, $92, $93, $94, $95, $96, $97, $98, + $99, $9a, $a2, $a3, $a4, $a5, $a6, $a7, + $a8, $a9, $aa, $b2, $b3, $b4, $b5, $b6, + $b7, $b8, $b9, $ba, $c2, $c3, $c4, $c5, + $c6, $c7, $c8, $c9, $ca, $d2, $d3, $d4, + $d5, $d6, $d7, $d8, $d9, $da, $e1, $e2, + $e3, $e4, $e5, $e6, $e7, $e8, $e9, $ea, + $f1, $f2, $f3, $f4, $f5, $f6, $f7, $f8, + $f9, $fa ); + + const bits_ac_chrominance : array[0..17-1] of UINT8 = + ( { 0-base } 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, $77 ); + const val_ac_chrominance : array[0..161] of UINT8 = + ( $00, $01, $02, $03, $11, $04, $05, $21, + $31, $06, $12, $41, $51, $07, $61, $71, + $13, $22, $32, $81, $08, $14, $42, $91, + $a1, $b1, $c1, $09, $23, $33, $52, $f0, + $15, $62, $72, $d1, $0a, $16, $24, $34, + $e1, $25, $f1, $17, $18, $19, $1a, $26, + $27, $28, $29, $2a, $35, $36, $37, $38, + $39, $3a, $43, $44, $45, $46, $47, $48, + $49, $4a, $53, $54, $55, $56, $57, $58, + $59, $5a, $63, $64, $65, $66, $67, $68, + $69, $6a, $73, $74, $75, $76, $77, $78, + $79, $7a, $82, $83, $84, $85, $86, $87, + $88, $89, $8a, $92, $93, $94, $95, $96, + $97, $98, $99, $9a, $a2, $a3, $a4, $a5, + $a6, $a7, $a8, $a9, $aa, $b2, $b3, $b4, + $b5, $b6, $b7, $b8, $b9, $ba, $c2, $c3, + $c4, $c5, $c6, $c7, $c8, $c9, $ca, $d2, + $d3, $d4, $d5, $d6, $d7, $d8, $d9, $da, + $e2, $e3, $e4, $e5, $e6, $e7, $e8, $e9, + $ea, $f2, $f3, $f4, $f5, $f6, $f7, $f8, + $f9, $fa ); +begin + add_huff_table(cinfo, cinfo^.dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(cinfo, cinfo^.ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(cinfo, cinfo^.dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(cinfo, cinfo^.ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +end; + + +{ Default parameter setup for compression. + + Applications that don't choose to use this routine must do their + own setup of all these parameters. Alternately, you can call this + to establish defaults and then alter parameters selectively. This + is the recommended approach since, if we add any new parameters, + your code will still work (they'll be set to reasonable defaults). } + +{GLOBAL} +procedure jpeg_set_defaults (cinfo : j_compress_ptr); +var + i : int; +begin + { Safety check to ensure start_compress not called yet. } + if (cinfo^.global_state <> CSTATE_START) then + ERREXIT1(J_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + { Allocate comp_info array large enough for maximum component count. + Array is made permanent in case application wants to compress + multiple images at same param settings. } + + if (cinfo^.comp_info = NIL) then + cinfo^.comp_info := jpeg_component_info_list_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT, + MAX_COMPONENTS * SIZEOF(jpeg_component_info)) ); + + { Initialize everything not dependent on the color space } + + cinfo^.data_precision := BITS_IN_JSAMPLE; + { Set up two quantization tables using default quality of 75 } + jpeg_set_quality(cinfo, 75, TRUE); + { Set up two Huffman tables } + std_huff_tables(cinfo); + + { Initialize default arithmetic coding conditioning } + for i := 0 to pred(NUM_ARITH_TBLS) do + begin + cinfo^.arith_dc_L[i] := 0; + cinfo^.arith_dc_U[i] := 1; + cinfo^.arith_ac_K[i] := 5; + end; + + { Default is no multiple-scan output } + cinfo^.scan_info := NIL; + cinfo^.num_scans := 0; + + { Expect normal source image, not raw downsampled data } + cinfo^.raw_data_in := FALSE; + + { Use Huffman coding, not arithmetic coding, by default } + cinfo^.arith_code := FALSE; + + { By default, don't do extra passes to optimize entropy coding } + cinfo^.optimize_coding := FALSE; + { The standard Huffman tables are only valid for 8-bit data precision. + If the precision is higher, force optimization on so that usable + tables will be computed. This test can be removed if default tables + are supplied that are valid for the desired precision. } + + if (cinfo^.data_precision > 8) then + cinfo^.optimize_coding := TRUE; + + { By default, use the simpler non-cosited sampling alignment } + cinfo^.CCIR601_sampling := FALSE; + + { No input smoothing } + cinfo^.smoothing_factor := 0; + + { DCT algorithm preference } + cinfo^.dct_method := JDCT_DEFAULT; + + { No restart markers } + cinfo^.restart_interval := 0; + cinfo^.restart_in_rows := 0; + + { Fill in default JFIF marker parameters. Note that whether the marker + will actually be written is determined by jpeg_set_colorspace. + + By default, the library emits JFIF version code 1.01. + An application that wants to emit JFIF 1.02 extension markers should set + JFIF_minor_version to 2. We could probably get away with just defaulting + to 1.02, but there may still be some decoders in use that will complain + about that; saying 1.01 should minimize compatibility problems. } + + cinfo^.JFIF_major_version := 1; { Default JFIF version = 1.01 } + cinfo^.JFIF_minor_version := 1; + cinfo^.density_unit := 0; { Pixel size is unknown by default } + cinfo^.X_density := 1; { Pixel aspect ratio is square by default } + cinfo^.Y_density := 1; + + { Choose JPEG colorspace based on input space, set defaults accordingly } + + jpeg_default_colorspace(cinfo); +end; + + +{ Select an appropriate JPEG colorspace for in_color_space. } + +{GLOBAL} +procedure jpeg_default_colorspace (cinfo : j_compress_ptr); +begin + case (cinfo^.in_color_space) of + JCS_GRAYSCALE: + jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); + JCS_RGB: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + JCS_YCbCr: + jpeg_set_colorspace(cinfo, JCS_YCbCr); + JCS_CMYK: + jpeg_set_colorspace(cinfo, JCS_CMYK); { By default, no translation } + JCS_YCCK: + jpeg_set_colorspace(cinfo, JCS_YCCK); + JCS_UNKNOWN: + jpeg_set_colorspace(cinfo, JCS_UNKNOWN); + else + ERREXIT(j_common_ptr(cinfo), JERR_BAD_IN_COLORSPACE); + end; +end; + + +{ Set the JPEG colorspace, and choose colorspace-dependent default values. } + +{GLOBAL} +procedure jpeg_set_colorspace (cinfo : j_compress_ptr; + colorspace : J_COLOR_SPACE); + { macro } + procedure SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl : int); + begin + with cinfo^.comp_info^[index] do + begin + component_id := (id); + h_samp_factor := (hsamp); + v_samp_factor := (vsamp); + quant_tbl_no := (quant); + dc_tbl_no := (dctbl); + ac_tbl_no := (actbl); + end; + end; + +var + ci : int; +begin + { Safety check to ensure start_compress not called yet. } + if (cinfo^.global_state <> CSTATE_START) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + { For all colorspaces, we use Q and Huff tables 0 for luminance components, + tables 1 for chrominance components. } + + cinfo^.jpeg_color_space := colorspace; + + cinfo^.write_JFIF_header := FALSE; { No marker for non-JFIF colorspaces } + cinfo^.write_Adobe_marker := FALSE; { write no Adobe marker by default } + + case (colorspace) of + JCS_GRAYSCALE: + begin + cinfo^.write_JFIF_header := TRUE; { Write a JFIF marker } + cinfo^.num_components := 1; + { JFIF specifies component ID 1 } + SET_COMP(0, 1, 1,1, 0, 0,0); + end; + JCS_RGB: + begin + cinfo^.write_Adobe_marker := TRUE; { write Adobe marker to flag RGB } + cinfo^.num_components := 3; + SET_COMP(0, $52 { 'R' }, 1,1, 0, 0,0); + SET_COMP(1, $47 { 'G' }, 1,1, 0, 0,0); + SET_COMP(2, $42 { 'B' }, 1,1, 0, 0,0); + end; + JCS_YCbCr: + begin + cinfo^.write_JFIF_header := TRUE; { Write a JFIF marker } + cinfo^.num_components := 3; + { JFIF specifies component IDs 1,2,3 } + { We default to 2x2 subsamples of chrominance } + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + end; + JCS_CMYK: + begin + cinfo^.write_Adobe_marker := TRUE; { write Adobe marker to flag CMYK } + cinfo^.num_components := 4; + SET_COMP(0, $43 { 'C' }, 1,1, 0, 0,0); + SET_COMP(1, $4D { 'M' }, 1,1, 0, 0,0); + SET_COMP(2, $59 { 'Y' }, 1,1, 0, 0,0); + SET_COMP(3, $4B { 'K' }, 1,1, 0, 0,0); + end; + JCS_YCCK: + begin + cinfo^.write_Adobe_marker := TRUE; { write Adobe marker to flag YCCK } + cinfo^.num_components := 4; + SET_COMP(0, 1, 2,2, 0, 0,0); + SET_COMP(1, 2, 1,1, 1, 1,1); + SET_COMP(2, 3, 1,1, 1, 1,1); + SET_COMP(3, 4, 2,2, 0, 0,0); + end; + JCS_UNKNOWN: + begin + cinfo^.num_components := cinfo^.input_components; + if (cinfo^.num_components < 1) + or (cinfo^.num_components > MAX_COMPONENTS) then + ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, + cinfo^.num_components, MAX_COMPONENTS); + for ci := 0 to pred(cinfo^.num_components) do + begin + SET_COMP(ci, ci, 1,1, 0, 0,0); + end; + end; + else + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + end; +end; + + +{$ifdef C_PROGRESSIVE_SUPPORTED} + +{LOCAL} +function fill_a_scan (scanptr : jpeg_scan_info_ptr; + ci : int; Ss : int; + Se : int; Ah : int; + Al : int) : jpeg_scan_info_ptr; +{ Support routine: generate one scan for specified component } +begin + scanptr^.comps_in_scan := 1; + scanptr^.component_index[0] := ci; + scanptr^.Ss := Ss; + scanptr^.Se := Se; + scanptr^.Ah := Ah; + scanptr^.Al := Al; + Inc(scanptr); + fill_a_scan := scanptr; +end; + +{LOCAL} +function fill_scans (scanptr : jpeg_scan_info_ptr; + ncomps : int; + Ss : int; Se : int; + Ah : int; Al : int) : jpeg_scan_info_ptr; +{ Support routine: generate one scan for each component } +var + ci : int; +begin + + for ci := 0 to pred(ncomps) do + begin + scanptr^.comps_in_scan := 1; + scanptr^.component_index[0] := ci; + scanptr^.Ss := Ss; + scanptr^.Se := Se; + scanptr^.Ah := Ah; + scanptr^.Al := Al; + Inc(scanptr); + end; + fill_scans := scanptr; +end; + +{LOCAL} +function fill_dc_scans (scanptr : jpeg_scan_info_ptr; + ncomps : int; + Ah : int; Al : int) : jpeg_scan_info_ptr; +{ Support routine: generate interleaved DC scan if possible, else N scans } +var + ci : int; +begin + + if (ncomps <= MAX_COMPS_IN_SCAN) then + begin + { Single interleaved DC scan } + scanptr^.comps_in_scan := ncomps; + for ci := 0 to pred(ncomps) do + scanptr^.component_index[ci] := ci; + scanptr^.Ss := 0; + scanptr^.Se := 0; + scanptr^.Ah := Ah; + scanptr^.Al := Al; + Inc(scanptr); + end + else + begin + { Noninterleaved DC scan for each component } + scanptr := fill_scans(scanptr, ncomps, 0, 0, Ah, Al); + end; + fill_dc_scans := scanptr; +end; + + +{ Create a recommended progressive-JPEG script. + cinfo^.num_components and cinfo^.jpeg_color_space must be correct. } + +{GLOBAL} +procedure jpeg_simple_progression (cinfo : j_compress_ptr); +var + ncomps : int; + nscans : int; + scanptr : jpeg_scan_info_ptr; +begin + ncomps := cinfo^.num_components; + + { Safety check to ensure start_compress not called yet. } + if (cinfo^.global_state <> CSTATE_START) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + { Figure space needed for script. Calculation must match code below! } + if (ncomps = 3) and (cinfo^.jpeg_color_space = JCS_YCbCr) then + begin + { Custom script for YCbCr color images. } + nscans := 10; + end + else + begin + { All-purpose script for other color spaces. } + if (ncomps > MAX_COMPS_IN_SCAN) then + nscans := 6 * ncomps { 2 DC + 4 AC scans per component } + else + nscans := 2 + 4 * ncomps; { 2 DC scans; 4 AC scans per component } + end; + + { Allocate space for script. + We need to put it in the permanent pool in case the application performs + multiple compressions without changing the settings. To avoid a memory + leak if jpeg_simple_progression is called repeatedly for the same JPEG + object, we try to re-use previously allocated space, and we allocate + enough space to handle YCbCr even if initially asked for grayscale. } + + if (cinfo^.script_space = NIL) or (cinfo^.script_space_size < nscans) then + begin + if nscans > 10 then + cinfo^.script_space_size := nscans + else + cinfo^.script_space_size := 10; + + cinfo^.script_space := jpeg_scan_info_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT, + cinfo^.script_space_size * SIZEOF(jpeg_scan_info)) ); + end; + scanptr := cinfo^.script_space; + + cinfo^.scan_info := scanptr; + cinfo^.num_scans := nscans; + + if (ncomps = 3) and (cinfo^.jpeg_color_space = JCS_YCbCr) then + begin + { Custom script for YCbCr color images. } + { Initial DC scan } + scanptr := fill_dc_scans(scanptr, ncomps, 0, 1); + { Initial AC scan: get some luma data out in a hurry } + scanptr := fill_a_scan(scanptr, 0, 1, 5, 0, 2); + { Chroma data is too small to be worth expending many scans on } + scanptr := fill_a_scan(scanptr, 2, 1, 63, 0, 1); + scanptr := fill_a_scan(scanptr, 1, 1, 63, 0, 1); + { Complete spectral selection for luma AC } + scanptr := fill_a_scan(scanptr, 0, 6, 63, 0, 2); + { Refine next bit of luma AC } + scanptr := fill_a_scan(scanptr, 0, 1, 63, 2, 1); + { Finish DC successive approximation } + scanptr := fill_dc_scans(scanptr, ncomps, 1, 0); + { Finish AC successive approximation } + scanptr := fill_a_scan(scanptr, 2, 1, 63, 1, 0); + scanptr := fill_a_scan(scanptr, 1, 1, 63, 1, 0); + { Luma bottom bit comes last since it's usually largest scan } + scanptr := fill_a_scan(scanptr, 0, 1, 63, 1, 0); + end + else + begin + { All-purpose script for other color spaces. } + { Successive approximation first pass } + scanptr := fill_dc_scans(scanptr, ncomps, 0, 1); + scanptr := fill_scans(scanptr, ncomps, 1, 5, 0, 2); + scanptr := fill_scans(scanptr, ncomps, 6, 63, 0, 2); + { Successive approximation second pass } + scanptr := fill_scans(scanptr, ncomps, 1, 63, 2, 1); + { Successive approximation final pass } + scanptr := fill_dc_scans(scanptr, ncomps, 1, 0); + scanptr := fill_scans(scanptr, ncomps, 1, 63, 1, 0); + end; +end; + +{$endif} +end. diff --git a/src/lib/vampimg/JpegLib/imjcphuff.pas b/src/lib/vampimg/JpegLib/imjcphuff.pas new file mode 100644 index 0000000..3c9dbf7 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcphuff.pas @@ -0,0 +1,962 @@ +unit imjcphuff; + +{ This file contains Huffman entropy encoding routines for progressive JPEG. + + We do not support output suspension in this module, since the library + currently does not allow multiple-scan files to be written with output + suspension. } + +{ Original: jcphuff.c; Copyright (C) 1995-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdeferr, + imjerror, + imjutils, + imjcomapi, + imjchuff; { Declarations shared with jchuff.c } + +{ Module initialization routine for progressive Huffman entropy encoding. } + +{GLOBAL} +procedure jinit_phuff_encoder (cinfo : j_compress_ptr); + +implementation + +{ Expanded entropy encoder object for progressive Huffman encoding. } +type + phuff_entropy_ptr = ^phuff_entropy_encoder; + phuff_entropy_encoder = record + pub : jpeg_entropy_encoder; { public fields } + + { Mode flag: TRUE for optimization, FALSE for actual data output } + gather_statistics : boolean; + + { Bit-level coding status. + next_output_byte/free_in_buffer are local copies of cinfo^.dest fields.} + + next_output_byte : JOCTETptr; { => next byte to write in buffer } + free_in_buffer : size_t; { # of byte spaces remaining in buffer } + put_buffer : INT32; { current bit-accumulation buffer } + put_bits : int; { # of bits now in it } + cinfo : j_compress_ptr; { link to cinfo (needed for dump_buffer) } + + { Coding status for DC components } + last_dc_val : array[0..MAX_COMPS_IN_SCAN-1] of int; + { last DC coef for each component } + + { Coding status for AC components } + ac_tbl_no : int; { the table number of the single component } + EOBRUN : uInt; { run length of EOBs } + BE : uInt; { # of buffered correction bits before MCU } + bit_buffer : JBytePtr; { buffer for correction bits (1 per char) } + { packing correction bits tightly would save some space but cost time... } + + restarts_to_go : uInt; { MCUs left in this restart interval } + next_restart_num : int; { next restart number to write (0-7) } + + { Pointers to derived tables (these workspaces have image lifespan). + Since any one scan codes only DC or only AC, we only need one set + of tables, not one for DC and one for AC. } + + derived_tbls : array[0..NUM_HUFF_TBLS-1] of c_derived_tbl_ptr; + + { Statistics tables for optimization; again, one set is enough } + count_ptrs : array[0..NUM_HUFF_TBLS-1] of TLongTablePtr; + end; + + +{ MAX_CORR_BITS is the number of bits the AC refinement correction-bit + buffer can hold. Larger sizes may slightly improve compression, but + 1000 is already well into the realm of overkill. + The minimum safe size is 64 bits. } + +const + MAX_CORR_BITS = 1000; { Max # of correction bits I can buffer } + + +{ Forward declarations } +{METHODDEF} +function encode_mcu_DC_first (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; + forward; +{METHODDEF} +function encode_mcu_AC_first (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; + forward; +{METHODDEF} +function encode_mcu_DC_refine (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; + forward; +{METHODDEF} +function encode_mcu_AC_refine (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; + forward; + +{METHODDEF} +procedure finish_pass_phuff (cinfo : j_compress_ptr); forward; + +{METHODDEF} +procedure finish_pass_gather_phuff (cinfo : j_compress_ptr); forward; + + +{ Initialize for a Huffman-compressed scan using progressive JPEG. } + +{METHODDEF} +procedure start_pass_phuff (cinfo : j_compress_ptr; + gather_statistics : boolean); +var + entropy : phuff_entropy_ptr; + is_DC_band : boolean; + ci, tbl : int; + compptr : jpeg_component_info_ptr; +begin + tbl := 0; + entropy := phuff_entropy_ptr (cinfo^.entropy); + + entropy^.cinfo := cinfo; + entropy^.gather_statistics := gather_statistics; + + is_DC_band := (cinfo^.Ss = 0); + + { We assume jcmaster.c already validated the scan parameters. } + + { Select execution routines } + if (cinfo^.Ah = 0) then + begin + if (is_DC_band) then + entropy^.pub.encode_mcu := encode_mcu_DC_first + else + entropy^.pub.encode_mcu := encode_mcu_AC_first; + end + else + begin + if (is_DC_band) then + entropy^.pub.encode_mcu := encode_mcu_DC_refine + else + begin + entropy^.pub.encode_mcu := encode_mcu_AC_refine; + { AC refinement needs a correction bit buffer } + if (entropy^.bit_buffer = NIL) then + entropy^.bit_buffer := JBytePtr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + MAX_CORR_BITS * SIZEOF(byte)) ); + end; + end; + if (gather_statistics) then + entropy^.pub.finish_pass := finish_pass_gather_phuff + else + entropy^.pub.finish_pass := finish_pass_phuff; + + { Only DC coefficients may be interleaved, so cinfo^.comps_in_scan = 1 + for AC coefficients. } + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + { Initialize DC predictions to 0 } + entropy^.last_dc_val[ci] := 0; + { Get table index } + if (is_DC_band) then + begin + if (cinfo^.Ah <> 0) then { DC refinement needs no table } + continue; + tbl := compptr^.dc_tbl_no; + end + else + begin + tbl := compptr^.ac_tbl_no; + entropy^.ac_tbl_no := tbl; + end; + if (gather_statistics) then + begin + { Check for invalid table index } + { (make_c_derived_tbl does this in the other path) } + if (tbl < 0) or (tbl >= NUM_HUFF_TBLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, tbl); + { Allocate and zero the statistics tables } + { Note that jpeg_gen_optimal_table expects 257 entries in each table! } + if (entropy^.count_ptrs[tbl] = NIL) then + entropy^.count_ptrs[tbl] := TLongTablePtr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + 257 * SIZEOF(long)) ); + MEMZERO(entropy^.count_ptrs[tbl], 257 * SIZEOF(long)); + end else + begin + { Compute derived values for Huffman table } + { We may do this more than once for a table, but it's not expensive } + jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, + entropy^.derived_tbls[tbl]); + end; + end; + + { Initialize AC stuff } + entropy^.EOBRUN := 0; + entropy^.BE := 0; + + { Initialize bit buffer to empty } + entropy^.put_buffer := 0; + entropy^.put_bits := 0; + + { Initialize restart stuff } + entropy^.restarts_to_go := cinfo^.restart_interval; + entropy^.next_restart_num := 0; +end; + + + + +{LOCAL} +procedure dump_buffer (entropy : phuff_entropy_ptr); +{ Empty the output buffer; we do not support suspension in this module. } +var + dest : jpeg_destination_mgr_ptr; +begin + dest := entropy^.cinfo^.dest; + + if (not dest^.empty_output_buffer (entropy^.cinfo)) then + ERREXIT(j_common_ptr(entropy^.cinfo), JERR_CANT_SUSPEND); + { After a successful buffer dump, must reset buffer pointers } + entropy^.next_output_byte := dest^.next_output_byte; + entropy^.free_in_buffer := dest^.free_in_buffer; +end; + + +{ Outputting bits to the file } + +{ Only the right 24 bits of put_buffer are used; the valid bits are + left-justified in this part. At most 16 bits can be passed to emit_bits + in one call, and we never retain more than 7 bits in put_buffer + between calls, so 24 bits are sufficient. } + + +{LOCAL} +procedure emit_bits (entropy : phuff_entropy_ptr; + code : uInt; + size : int); {INLINE} +{ Emit some bits, unless we are in gather mode } +var + {register} put_buffer : INT32; + {register} put_bits : int; +var + c : int; +begin + { This routine is heavily used, so it's worth coding tightly. } + put_buffer := INT32 (code); + put_bits := entropy^.put_bits; + + { if size is 0, caller used an invalid Huffman table entry } + if (size = 0) then + ERREXIT(j_common_ptr(entropy^.cinfo), JERR_HUFF_MISSING_CODE); + + if (entropy^.gather_statistics) then + exit; { do nothing if we're only getting stats } + + put_buffer := put_buffer and ((INT32(1) shl size) - 1); + { mask off any extra bits in code } + + Inc(put_bits, size); { new number of bits in buffer } + + put_buffer := put_buffer shl (24 - put_bits); { align incoming bits } + + put_buffer := put_buffer or entropy^.put_buffer; + { and merge with old buffer contents } + + while (put_bits >= 8) do + begin + c := int ((put_buffer shr 16) and $FF); + + {emit_byte(entropy, c);} + { Outputting bytes to the file. + NB: these must be called only when actually outputting, + that is, entropy^.gather_statistics = FALSE. } + { Emit a byte } + entropy^.next_output_byte^ := JOCTET(c); + Inc(entropy^.next_output_byte); + Dec(entropy^.free_in_buffer); + if (entropy^.free_in_buffer = 0) then + dump_buffer(entropy); + + if (c = $FF) then + begin { need to stuff a zero byte? } + {emit_byte(entropy, 0);} + entropy^.next_output_byte^ := JOCTET(0); + Inc(entropy^.next_output_byte); + Dec(entropy^.free_in_buffer); + if (entropy^.free_in_buffer = 0) then + dump_buffer(entropy); + end; + put_buffer := put_buffer shl 8; + Dec(put_bits, 8); + end; + + entropy^.put_buffer := put_buffer; { update variables } + entropy^.put_bits := put_bits; +end; + + +{LOCAL} +procedure flush_bits (entropy : phuff_entropy_ptr); +begin + emit_bits(entropy, $7F, 7); { fill any partial byte with ones } + entropy^.put_buffer := 0; { and reset bit-buffer to empty } + entropy^.put_bits := 0; +end; + +{ Emit (or just count) a Huffman symbol. } + + +{LOCAL} +procedure emit_symbol (entropy : phuff_entropy_ptr; + tbl_no : int; + symbol : int); {INLINE} +var + tbl : c_derived_tbl_ptr; +begin + if (entropy^.gather_statistics) then + Inc(entropy^.count_ptrs[tbl_no]^[symbol]) + else + begin + tbl := entropy^.derived_tbls[tbl_no]; + emit_bits(entropy, tbl^.ehufco[symbol], tbl^.ehufsi[symbol]); + end; +end; + + +{ Emit bits from a correction bit buffer. } + +{LOCAL} +procedure emit_buffered_bits (entropy : phuff_entropy_ptr; + bufstart : JBytePtr; + nbits : uInt); +var + bufptr : byteptr; +begin + if (entropy^.gather_statistics) then + exit; { no real work } + + bufptr := byteptr(bufstart); + while (nbits > 0) do + begin + emit_bits(entropy, uInt(bufptr^), 1); + Inc(bufptr); + Dec(nbits); + end; +end; + + +{ Emit any pending EOBRUN symbol. } + +{LOCAL} +procedure emit_eobrun (entropy : phuff_entropy_ptr); +var + {register} temp, nbits : int; +begin + if (entropy^.EOBRUN > 0) then + begin { if there is any pending EOBRUN } + temp := entropy^.EOBRUN; + nbits := 0; + temp := temp shr 1; + while (temp <> 0) do + begin + Inc(nbits); + temp := temp shr 1; + end; + + { safety check: shouldn't happen given limited correction-bit buffer } + if (nbits > 14) then + ERREXIT(j_common_ptr(entropy^.cinfo), JERR_HUFF_MISSING_CODE); + + emit_symbol(entropy, entropy^.ac_tbl_no, nbits shl 4); + if (nbits <> 0) then + emit_bits(entropy, entropy^.EOBRUN, nbits); + + entropy^.EOBRUN := 0; + + { Emit any buffered correction bits } + emit_buffered_bits(entropy, entropy^.bit_buffer, entropy^.BE); + entropy^.BE := 0; + end; +end; + + +{ Emit a restart marker & resynchronize predictions. } + +{LOCAL} +procedure emit_restart (entropy : phuff_entropy_ptr; + restart_num : int); +var + ci : int; +begin + emit_eobrun(entropy); + + if (not entropy^.gather_statistics) then + begin + flush_bits(entropy); + {emit_byte(entropy, $FF);} + { Outputting bytes to the file. + NB: these must be called only when actually outputting, + that is, entropy^.gather_statistics = FALSE. } + + entropy^.next_output_byte^ := JOCTET($FF); + Inc(entropy^.next_output_byte); + Dec(entropy^.free_in_buffer); + if (entropy^.free_in_buffer = 0) then + dump_buffer(entropy); + + {emit_byte(entropy, JPEG_RST0 + restart_num);} + entropy^.next_output_byte^ := JOCTET(JPEG_RST0 + restart_num); + Inc(entropy^.next_output_byte); + Dec(entropy^.free_in_buffer); + if (entropy^.free_in_buffer = 0) then + dump_buffer(entropy); + end; + + if (entropy^.cinfo^.Ss = 0) then + begin + { Re-initialize DC predictions to 0 } + for ci := 0 to pred(entropy^.cinfo^.comps_in_scan) do + entropy^.last_dc_val[ci] := 0; + end + else + begin + { Re-initialize all AC-related fields to 0 } + entropy^.EOBRUN := 0; + entropy^.BE := 0; + end; +end; + + +{ MCU encoding for DC initial scan (either spectral selection, + or first pass of successive approximation). } + +{METHODDEF} +function encode_mcu_DC_first (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; +var + entropy : phuff_entropy_ptr; + {register} temp, temp2 : int; + {register} nbits : int; + blkn, ci : int; + Al : int; + block : JBLOCK_PTR; + compptr : jpeg_component_info_ptr; + ishift_temp : int; +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + Al := cinfo^.Al; + + entropy^.next_output_byte := cinfo^.dest^.next_output_byte; + entropy^.free_in_buffer := cinfo^.dest^.free_in_buffer; + + { Emit restart marker if needed } + if (cinfo^.restart_interval <> 0) then + if (entropy^.restarts_to_go = 0) then + emit_restart(entropy, entropy^.next_restart_num); + + { Encode the MCU data blocks } + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + block := JBLOCK_PTR(MCU_data[blkn]); + ci := cinfo^.MCU_membership[blkn]; + compptr := cinfo^.cur_comp_info[ci]; + + { Compute the DC value after the required point transform by Al. + This is simply an arithmetic right shift. } + + {temp2 := IRIGHT_SHIFT( int(block^[0]), Al);} + {IRIGHT_SHIFT_IS_UNSIGNED} + ishift_temp := int(block^[0]); + if ishift_temp < 0 then + temp2 := (ishift_temp shr Al) or ((not 0) shl (16-Al)) + else + temp2 := ishift_temp shr Al; + + + { DC differences are figured on the point-transformed values. } + temp := temp2 - entropy^.last_dc_val[ci]; + entropy^.last_dc_val[ci] := temp2; + + { Encode the DC coefficient difference per section G.1.2.1 } + temp2 := temp; + if (temp < 0) then + begin + temp := -temp; { temp is abs value of input } + { For a negative input, want temp2 := bitwise complement of abs(input) } + { This code assumes we are on a two's complement machine } + Dec(temp2); + end; + + { Find the number of bits needed for the magnitude of the coefficient } + nbits := 0; + while (temp <> 0) do + begin + Inc(nbits); + temp := temp shr 1; + end; + + { Check for out-of-range coefficient values. + Since we're encoding a difference, the range limit is twice as much. } + + if (nbits > MAX_COEF_BITS+1) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_DCT_COEF); + + { Count/emit the Huffman-coded symbol for the number of bits } + emit_symbol(entropy, compptr^.dc_tbl_no, nbits); + + { Emit that number of bits of the value, if positive, } + { or the complement of its magnitude, if negative. } + if (nbits <> 0) then { emit_bits rejects calls with size 0 } + emit_bits(entropy, uInt(temp2), nbits); + end; + + cinfo^.dest^.next_output_byte := entropy^.next_output_byte; + cinfo^.dest^.free_in_buffer := entropy^.free_in_buffer; + + { Update restart-interval state too } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + begin + entropy^.restarts_to_go := cinfo^.restart_interval; + Inc(entropy^.next_restart_num); + with entropy^ do + next_restart_num := next_restart_num and 7; + end; + Dec(entropy^.restarts_to_go); + end; + + encode_mcu_DC_first := TRUE; +end; + + +{ MCU encoding for AC initial scan (either spectral selection, + or first pass of successive approximation). } + +{METHODDEF} +function encode_mcu_AC_first (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; +var + entropy : phuff_entropy_ptr; + {register} temp, temp2 : int; + {register} nbits : int; + {register} r, k : int; + Se : int; + Al : int; + block : JBLOCK_PTR; +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + Se := cinfo^.Se; + Al := cinfo^.Al; + + entropy^.next_output_byte := cinfo^.dest^.next_output_byte; + entropy^.free_in_buffer := cinfo^.dest^.free_in_buffer; + + { Emit restart marker if needed } + if (cinfo^.restart_interval <> 0) then + if (entropy^.restarts_to_go = 0) then + emit_restart(entropy, entropy^.next_restart_num); + + { Encode the MCU data block } + block := JBLOCK_PTR(MCU_data[0]); + + { Encode the AC coefficients per section G.1.2.2, fig. G.3 } + + r := 0; { r := run length of zeros } + + for k := cinfo^.Ss to Se do + begin + temp := (block^[jpeg_natural_order[k]]); + if (temp = 0) then + begin + Inc(r); + continue; + end; + { We must apply the point transform by Al. For AC coefficients this + is an integer division with rounding towards 0. To do this portably + in C, we shift after obtaining the absolute value; so the code is + interwoven with finding the abs value (temp) and output bits (temp2). } + + if (temp < 0) then + begin + temp := -temp; { temp is abs value of input } + temp := temp shr Al; { apply the point transform } + { For a negative coef, want temp2 := bitwise complement of abs(coef) } + temp2 := not temp; + end + else + begin + temp := temp shr Al; { apply the point transform } + temp2 := temp; + end; + { Watch out for case that nonzero coef is zero after point transform } + if (temp = 0) then + begin + Inc(r); + continue; + end; + + { Emit any pending EOBRUN } + if (entropy^.EOBRUN > 0) then + emit_eobrun(entropy); + { if run length > 15, must emit special run-length-16 codes ($F0) } + while (r > 15) do + begin + emit_symbol(entropy, entropy^.ac_tbl_no, $F0); + Dec(r, 16); + end; + + { Find the number of bits needed for the magnitude of the coefficient } + nbits := 0; { there must be at least one 1 bit } + repeat + Inc(nbits); + temp := temp shr 1; + until (temp = 0); + + { Check for out-of-range coefficient values } + if (nbits > MAX_COEF_BITS) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_DCT_COEF); + + { Count/emit Huffman symbol for run length / number of bits } + emit_symbol(entropy, entropy^.ac_tbl_no, (r shl 4) + nbits); + + { Emit that number of bits of the value, if positive, } + { or the complement of its magnitude, if negative. } + emit_bits(entropy, uInt(temp2), nbits); + + r := 0; { reset zero run length } + end; + + if (r > 0) then + begin { If there are trailing zeroes, } + Inc(entropy^.EOBRUN); { count an EOB } + if (entropy^.EOBRUN = $7FFF) then + emit_eobrun(entropy); { force it out to avoid overflow } + end; + + cinfo^.dest^.next_output_byte := entropy^.next_output_byte; + cinfo^.dest^.free_in_buffer := entropy^.free_in_buffer; + + { Update restart-interval state too } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + begin + entropy^.restarts_to_go := cinfo^.restart_interval; + Inc(entropy^.next_restart_num); + with entropy^ do + next_restart_num := next_restart_num and 7; + end; + Dec(entropy^.restarts_to_go); + end; + + encode_mcu_AC_first := TRUE; +end; + + +{ MCU encoding for DC successive approximation refinement scan. + Note: we assume such scans can be multi-component, although the spec + is not very clear on the point. } + +{METHODDEF} +function encode_mcu_DC_refine (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; +var + entropy : phuff_entropy_ptr; + {register} temp : int; + blkn : int; + Al : int; + block : JBLOCK_PTR; +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + Al := cinfo^.Al; + + entropy^.next_output_byte := cinfo^.dest^.next_output_byte; + entropy^.free_in_buffer := cinfo^.dest^.free_in_buffer; + + { Emit restart marker if needed } + if (cinfo^.restart_interval <> 0) then + if (entropy^.restarts_to_go = 0) then + emit_restart(entropy, entropy^.next_restart_num); + + { Encode the MCU data blocks } + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + block := JBLOCK_PTR(MCU_data[blkn]); + + { We simply emit the Al'th bit of the DC coefficient value. } + temp := block^[0]; + emit_bits(entropy, uInt(temp shr Al), 1); + end; + + cinfo^.dest^.next_output_byte := entropy^.next_output_byte; + cinfo^.dest^.free_in_buffer := entropy^.free_in_buffer; + + { Update restart-interval state too } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + begin + entropy^.restarts_to_go := cinfo^.restart_interval; + Inc(entropy^.next_restart_num); + with entropy^ do + next_restart_num := next_restart_num and 7; + end; + Dec(entropy^.restarts_to_go); + end; + + encode_mcu_DC_refine := TRUE; +end; + + +{ MCU encoding for AC successive approximation refinement scan. } + +{METHODDEF} +function encode_mcu_AC_refine (cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; + +var + entropy : phuff_entropy_ptr; + {register} temp : int; + {register} r, k : int; + EOB : int; + BR_buffer : JBytePtr; + BR : uInt; + Se : int; + Al : int; + block : JBLOCK_PTR; + absvalues : array[0..DCTSIZE2-1] of int; +begin + entropy := phuff_entropy_ptr(cinfo^.entropy); + Se := cinfo^.Se; + Al := cinfo^.Al; + + entropy^.next_output_byte := cinfo^.dest^.next_output_byte; + entropy^.free_in_buffer := cinfo^.dest^.free_in_buffer; + + { Emit restart marker if needed } + if (cinfo^.restart_interval <> 0) then + if (entropy^.restarts_to_go = 0) then + emit_restart(entropy, entropy^.next_restart_num); + + { Encode the MCU data block } + block := JBLOCK_PTR(MCU_data[0]); + + { It is convenient to make a pre-pass to determine the transformed + coefficients' absolute values and the EOB position. } + + EOB := 0; + for k := cinfo^.Ss to Se do + begin + temp := block^[jpeg_natural_order[k]]; + { We must apply the point transform by Al. For AC coefficients this + is an integer division with rounding towards 0. To do this portably + in C, we shift after obtaining the absolute value. } + + if (temp < 0) then + temp := -temp; { temp is abs value of input } + temp := temp shr Al; { apply the point transform } + absvalues[k] := temp; { save abs value for main pass } + if (temp = 1) then + EOB := k; { EOB := index of last newly-nonzero coef } + end; + + { Encode the AC coefficients per section G.1.2.3, fig. G.7 } + + r := 0; { r := run length of zeros } + BR := 0; { BR := count of buffered bits added now } + BR_buffer := JBytePtr(@(entropy^.bit_buffer^[entropy^.BE])); + { Append bits to buffer } + + for k := cinfo^.Ss to Se do + begin + temp := absvalues[k]; + if (temp = 0) then + begin + Inc(r); + continue; + end; + + { Emit any required ZRLs, but not if they can be folded into EOB } + while (r > 15) and (k <= EOB) do + begin + { emit any pending EOBRUN and the BE correction bits } + emit_eobrun(entropy); + { Emit ZRL } + emit_symbol(entropy, entropy^.ac_tbl_no, $F0); + Dec(r, 16); + { Emit buffered correction bits that must be associated with ZRL } + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer := entropy^.bit_buffer; { BE bits are gone now } + BR := 0; + end; + + { If the coef was previously nonzero, it only needs a correction bit. + NOTE: a straight translation of the spec's figure G.7 would suggest + that we also need to test r > 15. But if r > 15, we can only get here + if k > EOB, which implies that this coefficient is not 1. } + if (temp > 1) then + begin + { The correction bit is the next bit of the absolute value. } + BR_buffer^[BR] := byte (temp and 1); + Inc(BR); + continue; + end; + + { Emit any pending EOBRUN and the BE correction bits } + emit_eobrun(entropy); + + { Count/emit Huffman symbol for run length / number of bits } + emit_symbol(entropy, entropy^.ac_tbl_no, (r shl 4) + 1); + + { Emit output bit for newly-nonzero coef } + if (block^[jpeg_natural_order[k]] < 0) then + temp := 0 + else + temp := 1; + emit_bits(entropy, uInt(temp), 1); + + { Emit buffered correction bits that must be associated with this code } + emit_buffered_bits(entropy, BR_buffer, BR); + BR_buffer := entropy^.bit_buffer; { BE bits are gone now } + BR := 0; + r := 0; { reset zero run length } + end; + + if (r > 0) or (BR > 0) then + begin { If there are trailing zeroes, } + Inc(entropy^.EOBRUN); { count an EOB } + Inc(entropy^.BE, BR); { concat my correction bits to older ones } + { We force out the EOB if we risk either: + 1. overflow of the EOB counter; + 2. overflow of the correction bit buffer during the next MCU. } + + if (entropy^.EOBRUN = $7FFF) or + (entropy^.BE > (MAX_CORR_BITS-DCTSIZE2+1)) then + emit_eobrun(entropy); + end; + + cinfo^.dest^.next_output_byte := entropy^.next_output_byte; + cinfo^.dest^.free_in_buffer := entropy^.free_in_buffer; + + { Update restart-interval state too } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + begin + entropy^.restarts_to_go := cinfo^.restart_interval; + Inc(entropy^.next_restart_num); + with entropy^ do + next_restart_num := next_restart_num and 7; + end; + Dec(entropy^.restarts_to_go); + end; + + encode_mcu_AC_refine := TRUE; +end; + + +{ Finish up at the end of a Huffman-compressed progressive scan. } + +{METHODDEF} +procedure finish_pass_phuff (cinfo : j_compress_ptr); +var + entropy : phuff_entropy_ptr; +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + + entropy^.next_output_byte := cinfo^.dest^.next_output_byte; + entropy^.free_in_buffer := cinfo^.dest^.free_in_buffer; + + { Flush out any buffered data } + emit_eobrun(entropy); + flush_bits(entropy); + + cinfo^.dest^.next_output_byte := entropy^.next_output_byte; + cinfo^.dest^.free_in_buffer := entropy^.free_in_buffer; +end; + + +{ Finish up a statistics-gathering pass and create the new Huffman tables. } + +{METHODDEF} +procedure finish_pass_gather_phuff (cinfo : j_compress_ptr); +var + entropy : phuff_entropy_ptr; + is_DC_band : boolean; + ci, tbl : int; + compptr : jpeg_component_info_ptr; + htblptr : ^JHUFF_TBL_PTR; + did : array[0..NUM_HUFF_TBLS-1] of boolean; +begin + tbl := 0; + entropy := phuff_entropy_ptr (cinfo^.entropy); + + { Flush out buffered data (all we care about is counting the EOB symbol) } + emit_eobrun(entropy); + + is_DC_band := (cinfo^.Ss = 0); + + { It's important not to apply jpeg_gen_optimal_table more than once + per table, because it clobbers the input frequency counts! } + + MEMZERO(@did, SIZEOF(did)); + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + if (is_DC_band) then + begin + if (cinfo^.Ah <> 0) then { DC refinement needs no table } + continue; + tbl := compptr^.dc_tbl_no; + end + else + begin + tbl := compptr^.ac_tbl_no; + end; + if (not did[tbl]) then + begin + if (is_DC_band) then + htblptr := @(cinfo^.dc_huff_tbl_ptrs[tbl]) + else + htblptr := @(cinfo^.ac_huff_tbl_ptrs[tbl]); + if (htblptr^ = NIL) then + htblptr^ := jpeg_alloc_huff_table(j_common_ptr(cinfo)); + jpeg_gen_optimal_table(cinfo, htblptr^, entropy^.count_ptrs[tbl]^); + did[tbl] := TRUE; + end; + end; +end; + + +{ Module initialization routine for progressive Huffman entropy encoding. } + +{GLOBAL} +procedure jinit_phuff_encoder (cinfo : j_compress_ptr); +var + entropy : phuff_entropy_ptr; + i : int; +begin + entropy := phuff_entropy_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(phuff_entropy_encoder)) ); + cinfo^.entropy := jpeg_entropy_encoder_ptr(entropy); + entropy^.pub.start_pass := start_pass_phuff; + + { Mark tables unallocated } + for i := 0 to pred(NUM_HUFF_TBLS) do + begin + entropy^.derived_tbls[i] := NIL; + entropy^.count_ptrs[i] := NIL; + end; + entropy^.bit_buffer := NIL; { needed only in AC refinement scan } +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcprepct.pas b/src/lib/vampimg/JpegLib/imjcprepct.pas new file mode 100644 index 0000000..9f21e51 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcprepct.pas @@ -0,0 +1,406 @@ +unit imjcprepct; + +{ Original : jcprepct.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +{ This file contains the compression preprocessing controller. + This controller manages the color conversion, downsampling, + and edge expansion steps. + + Most of the complexity here is associated with buffering input rows + as required by the downsampler. See the comments at the head of + jcsample.c for the downsampler's needs. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjpeglib, + imjdeferr, + imjerror, + imjinclude, + imjutils; + +{GLOBAL} +procedure jinit_c_prep_controller (cinfo : j_compress_ptr; + need_full_buffer : boolean); + +implementation + + +{ At present, jcsample.c can request context rows only for smoothing. + In the future, we might also need context rows for CCIR601 sampling + or other more-complex downsampling procedures. The code to support + context rows should be compiled only if needed. } + +{$ifdef INPUT_SMOOTHING_SUPPORTED} + {$define CONTEXT_ROWS_SUPPORTED} +{$endif} + + +{ For the simple (no-context-row) case, we just need to buffer one + row group's worth of pixels for the downsampling step. At the bottom of + the image, we pad to a full row group by replicating the last pixel row. + The downsampler's last output row is then replicated if needed to pad + out to a full iMCU row. + + When providing context rows, we must buffer three row groups' worth of + pixels. Three row groups are physically allocated, but the row pointer + arrays are made five row groups high, with the extra pointers above and + below "wrapping around" to point to the last and first real row groups. + This allows the downsampler to access the proper context rows. + At the top and bottom of the image, we create dummy context rows by + copying the first or last real pixel row. This copying could be avoided + by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the + trouble on the compression side. } + + +{ Private buffer controller object } + +type + my_prep_ptr = ^my_prep_controller; + my_prep_controller = record + pub : jpeg_c_prep_controller; { public fields } + + { Downsampling input buffer. This buffer holds color-converted data + until we have enough to do a downsample step. } + + color_buf : array[0..MAX_COMPONENTS-1] of JSAMPARRAY; + + rows_to_go : JDIMENSION; { counts rows remaining in source image } + next_buf_row : int; { index of next row to store in color_buf } + + {$ifdef CONTEXT_ROWS_SUPPORTED} { only needed for context case } + this_row_group : int; { starting row index of group to process } + next_buf_stop : int; { downsample when we reach this index } + {$endif} + end; {my_prep_controller;} + + +{ Initialize for a processing pass. } + +{METHODDEF} +procedure start_pass_prep (cinfo : j_compress_ptr; + pass_mode : J_BUF_MODE ); +var + prep : my_prep_ptr; +begin + prep := my_prep_ptr (cinfo^.prep); + + if (pass_mode <> JBUF_PASS_THRU) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + + { Initialize total-height counter for detecting bottom of image } + prep^.rows_to_go := cinfo^.image_height; + { Mark the conversion buffer empty } + prep^.next_buf_row := 0; +{$ifdef CONTEXT_ROWS_SUPPORTED} + { Preset additional state variables for context mode. + These aren't used in non-context mode, so we needn't test which mode. } + prep^.this_row_group := 0; + { Set next_buf_stop to stop after two row groups have been read in. } + prep^.next_buf_stop := 2 * cinfo^.max_v_samp_factor; +{$endif} +end; + + +{ Expand an image vertically from height input_rows to height output_rows, + by duplicating the bottom row. } + +{LOCAL} +procedure expand_bottom_edge (image_data : JSAMPARRAY; + num_cols : JDIMENSION; + input_rows : int; + output_rows : int); +var + {register} row : int; +begin + for row := input_rows to pred(output_rows) do + begin + jcopy_sample_rows(image_data, input_rows-1, image_data, row, + 1, num_cols); + end; +end; + + +{ Process some data in the simple no-context case. + + Preprocessor output data is counted in "row groups". A row group + is defined to be v_samp_factor sample rows of each component. + Downsampling will produce this much data from each max_v_samp_factor + input rows. } + +{METHODDEF} +procedure pre_process_data (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr : JDIMENSION; + in_rows_avail : JDIMENSION; + output_buf : JSAMPIMAGE; + var out_row_group_ctr : JDIMENSION; + out_row_groups_avail : JDIMENSION); +var + prep : my_prep_ptr; + numrows, ci : int; + inrows : JDIMENSION; + compptr : jpeg_component_info_ptr; +var + local_input_buf : JSAMPARRAY; +begin + prep := my_prep_ptr (cinfo^.prep); + + while (in_row_ctr < in_rows_avail) and + (out_row_group_ctr < out_row_groups_avail) do + begin + { Do color conversion to fill the conversion buffer. } + inrows := in_rows_avail - in_row_ctr; + numrows := cinfo^.max_v_samp_factor - prep^.next_buf_row; + {numrows := int( MIN(JDIMENSION(numrows), inrows) );} + if inrows < JDIMENSION(numrows) then + numrows := int(inrows); + local_input_buf := JSAMPARRAY(@(input_buf^[in_row_ctr])); + cinfo^.cconvert^.color_convert (cinfo, local_input_buf, + JSAMPIMAGE(@prep^.color_buf), + JDIMENSION(prep^.next_buf_row), + numrows); + Inc(in_row_ctr, numrows); + Inc(prep^.next_buf_row, numrows); + Dec(prep^.rows_to_go, numrows); + { If at bottom of image, pad to fill the conversion buffer. } + if (prep^.rows_to_go = 0) and + (prep^.next_buf_row < cinfo^.max_v_samp_factor) then + begin + for ci := 0 to pred(cinfo^.num_components) do + begin + expand_bottom_edge(prep^.color_buf[ci], cinfo^.image_width, + prep^.next_buf_row, cinfo^.max_v_samp_factor); + end; + prep^.next_buf_row := cinfo^.max_v_samp_factor; + end; + { If we've filled the conversion buffer, empty it. } + if (prep^.next_buf_row = cinfo^.max_v_samp_factor) then + begin + cinfo^.downsample^.downsample (cinfo, + JSAMPIMAGE(@prep^.color_buf), + JDIMENSION (0), + output_buf, + out_row_group_ctr); + prep^.next_buf_row := 0; + Inc(out_row_group_ctr);; + end; + { If at bottom of image, pad the output to a full iMCU height. + Note we assume the caller is providing a one-iMCU-height output buffer! } + if (prep^.rows_to_go = 0) and + (out_row_group_ctr < out_row_groups_avail) then + begin + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + expand_bottom_edge(output_buf^[ci], + compptr^.width_in_blocks * DCTSIZE, + int (out_row_group_ctr) * compptr^.v_samp_factor, + int (out_row_groups_avail) * compptr^.v_samp_factor); + Inc(compptr); + end; + out_row_group_ctr := out_row_groups_avail; + break; { can exit outer loop without test } + end; + end; +end; + + +{$ifdef CONTEXT_ROWS_SUPPORTED} + +{ Process some data in the context case. } + +{METHODDEF} +procedure pre_process_context (cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr : JDIMENSION; + in_rows_avail : JDIMENSION; + output_buf : JSAMPIMAGE; + var out_row_group_ctr : JDIMENSION; + out_row_groups_avail : JDIMENSION); +var + prep : my_prep_ptr; + numrows, ci : int; + buf_height : int; + inrows : JDIMENSION; +var + row : int; + +begin + prep := my_prep_ptr (cinfo^.prep); + buf_height := cinfo^.max_v_samp_factor * 3; + + while (out_row_group_ctr < out_row_groups_avail) do + begin + if (in_row_ctr < in_rows_avail) then + begin + { Do color conversion to fill the conversion buffer. } + inrows := in_rows_avail - in_row_ctr; + numrows := prep^.next_buf_stop - prep^.next_buf_row; + {numrows := int ( MIN( JDIMENSION(numrows), inrows) );} + if inrows < JDIMENSION(numrows) then + numrows := int(inrows); + cinfo^.cconvert^.color_convert (cinfo, + JSAMPARRAY(@input_buf^[in_row_ctr]), + JSAMPIMAGE(@prep^.color_buf), + JDIMENSION (prep^.next_buf_row), + numrows); + { Pad at top of image, if first time through } + if (prep^.rows_to_go = cinfo^.image_height) then + begin + for ci := 0 to pred(cinfo^.num_components) do + begin + for row := 1 to cinfo^.max_v_samp_factor do + begin + jcopy_sample_rows(prep^.color_buf[ci], 0, + prep^.color_buf[ci], -row, + 1, cinfo^.image_width); + end; + end; + end; + Inc(in_row_ctr, numrows); + Inc(prep^.next_buf_row, numrows); + Dec(prep^.rows_to_go, numrows); + end + else + begin + { Return for more data, unless we are at the bottom of the image. } + if (prep^.rows_to_go <> 0) then + break; + { When at bottom of image, pad to fill the conversion buffer. } + if (prep^.next_buf_row < prep^.next_buf_stop) then + begin + for ci := 0 to pred(cinfo^.num_components) do + begin + expand_bottom_edge(prep^.color_buf[ci], cinfo^.image_width, + prep^.next_buf_row, prep^.next_buf_stop); + end; + prep^.next_buf_row := prep^.next_buf_stop; + end; + end; + { If we've gotten enough data, downsample a row group. } + if (prep^.next_buf_row = prep^.next_buf_stop) then + begin + cinfo^.downsample^.downsample (cinfo, + JSAMPIMAGE(@prep^.color_buf), + JDIMENSION(prep^.this_row_group), + output_buf, + out_row_group_ctr); + Inc(out_row_group_ctr); + { Advance pointers with wraparound as necessary. } + Inc(prep^.this_row_group, cinfo^.max_v_samp_factor); + if (prep^.this_row_group >= buf_height) then + prep^.this_row_group := 0; + if (prep^.next_buf_row >= buf_height) then + prep^.next_buf_row := 0; + prep^.next_buf_stop := prep^.next_buf_row + cinfo^.max_v_samp_factor; + end; + end; +end; + + +{ Create the wrapped-around downsampling input buffer needed for context mode. } + +{LOCAL} +procedure create_context_buffer (cinfo : j_compress_ptr); +var + prep : my_prep_ptr; + rgroup_height : int; + ci, i : int; + compptr : jpeg_component_info_ptr; + true_buffer, fake_buffer : JSAMPARRAY; +begin + prep := my_prep_ptr (cinfo^.prep); + rgroup_height := cinfo^.max_v_samp_factor; + { Grab enough space for fake row pointers for all the components; + we need five row groups' worth of pointers for each component. } + + fake_buffer := JSAMPARRAY( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + (cinfo^.num_components * 5 * rgroup_height) * + SIZEOF(JSAMPROW)) ); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Allocate the actual buffer space (3 row groups) for this component. + We make the buffer wide enough to allow the downsampler to edge-expand + horizontally within the buffer, if it so chooses. } + true_buffer := cinfo^.mem^.alloc_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, + JDIMENSION (( long(compptr^.width_in_blocks) * DCTSIZE * + cinfo^.max_h_samp_factor) div compptr^.h_samp_factor), + JDIMENSION (3 * rgroup_height)); + { Copy true buffer row pointers into the middle of the fake row array } + MEMCOPY(JSAMPARRAY(@ fake_buffer^[rgroup_height]), true_buffer, + 3 * rgroup_height * SIZEOF(JSAMPROW)); + { Fill in the above and below wraparound pointers } + for i := 0 to pred(rgroup_height) do + begin + fake_buffer^[i] := true_buffer^[2 * rgroup_height + i]; + fake_buffer^[4 * rgroup_height + i] := true_buffer^[i]; + end; + prep^.color_buf[ci] := JSAMPARRAY(@ fake_buffer^[rgroup_height]); + Inc(JSAMPROW_PTR(fake_buffer), 5 * rgroup_height); { point to space for next component } + Inc(compptr); + end; +end; + +{$endif} { CONTEXT_ROWS_SUPPORTED } + + +{ Initialize preprocessing controller. } + +{GLOBAL} +procedure jinit_c_prep_controller (cinfo : j_compress_ptr; + need_full_buffer : boolean); +var + prep : my_prep_ptr; + ci : int; + compptr : jpeg_component_info_ptr; +begin + + if (need_full_buffer) then { safety check } + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + + prep := my_prep_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_prep_controller)) ); + cinfo^.prep := jpeg_c_prep_controller_ptr(prep); + prep^.pub.start_pass := start_pass_prep; + + { Allocate the color conversion buffer. + We make the buffer wide enough to allow the downsampler to edge-expand + horizontally within the buffer, if it so chooses. } + + if (cinfo^.downsample^.need_context_rows) then + begin + { Set up to provide context rows } +{$ifdef CONTEXT_ROWS_SUPPORTED} + prep^.pub.pre_process_data := pre_process_context; + create_context_buffer(cinfo); +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + begin + { No context, just make it tall enough for one row group } + prep^.pub.pre_process_data := pre_process_data; + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + prep^.color_buf[ci] := cinfo^.mem^.alloc_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, + JDIMENSION (( long(compptr^.width_in_blocks) * DCTSIZE * + cinfo^.max_h_samp_factor) div compptr^.h_samp_factor), + JDIMENSION(cinfo^.max_v_samp_factor) ); + Inc(compptr); + end; + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjcsample.pas b/src/lib/vampimg/JpegLib/imjcsample.pas new file mode 100644 index 0000000..48ea3d8 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjcsample.pas @@ -0,0 +1,631 @@ +unit imjcsample; + +{ This file contains downsampling routines. + + Downsampling input data is counted in "row groups". A row group + is defined to be max_v_samp_factor pixel rows of each component, + from which the downsampler produces v_samp_factor sample rows. + A single row group is processed in each call to the downsampler module. + + The downsampler is responsible for edge-expansion of its output data + to fill an integral number of DCT blocks horizontally. The source buffer + may be modified if it is helpful for this purpose (the source buffer is + allocated wide enough to correspond to the desired output width). + The caller (the prep controller) is responsible for vertical padding. + + The downsampler may request "context rows" by setting need_context_rows + during startup. In this case, the input arrays will contain at least + one row group's worth of pixels above and below the passed-in data; + the caller will create dummy rows at image top and bottom by replicating + the first or last real pixel row. + + An excellent reference for image resampling is + Digital Image Warping, George Wolberg, 1990. + Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. + + The downsampling algorithm used here is a simple average of the source + pixels covered by the output pixel. The hi-falutin sampling literature + refers to this as a "box filter". In general the characteristics of a box + filter are not very good, but for the specific cases we normally use (1:1 + and 2:1 ratios) the box is equivalent to a "triangle filter" which is not + nearly so bad. If you intend to use other sampling ratios, you'd be well + advised to improve this code. + + A simple input-smoothing capability is provided. This is mainly intended + for cleaning up color-dithered GIF input files (if you find it inadequate, + we suggest using an external filtering program such as pnmconvol). When + enabled, each input pixel P is replaced by a weighted sum of itself and its + eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, + where SF := (smoothing_factor / 1024). + Currently, smoothing is only supported for 2h2v sampling factors. } + +{ Original: jcsample.c ; Copyright (C) 1991-1996, Thomas G. Lane. } + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjutils, + imjdeferr, + imjerror, + imjpeglib; + + +{ Module initialization routine for downsampling. + Note that we must select a routine for each component. } + +{GLOBAL} +procedure jinit_downsampler (cinfo : j_compress_ptr); + +implementation + +{ Pointer to routine to downsample a single component } +type + downsample1_ptr = procedure(cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + output_data : JSAMPARRAY); + +{ Private subobject } + +type + my_downsample_ptr = ^my_downsampler; + my_downsampler = record + pub : jpeg_downsampler; { public fields } + + { Downsampling method pointers, one per component } + methods : array[0..MAX_COMPONENTS-1] of downsample1_ptr; + end; + +{ Initialize for a downsampling pass. } + +{METHODDEF} +procedure start_pass_downsample (cinfo : j_compress_ptr); +begin + { no work for now } +end; + + +{ Expand a component horizontally from width input_cols to width output_cols, + by duplicating the rightmost samples. } + +{LOCAL} +procedure expand_right_edge (image_data : JSAMPARRAY; + num_rows : int; + input_cols : JDIMENSION; + output_cols : JDIMENSION); +var + {register} ptr : JSAMPLE_PTR; + {register} pixval : JSAMPLE; + {register} count : int; + row : int; + numcols : int; +begin + numcols := int (output_cols - input_cols); + + if (numcols > 0) then + begin + for row := 0 to pred(num_rows) do + begin + ptr := JSAMPLE_PTR(@(image_data^[row]^[input_cols-1])); + pixval := ptr^; { don't need GETJSAMPLE() here } + for count := pred(numcols) downto 0 do + begin + Inc(ptr); + ptr^ := pixval; + end; + end; + end; +end; + + +{ Do downsampling for a whole row group (all components). + + In this version we simply downsample each component independently. } + +{METHODDEF} +procedure sep_downsample (cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE; + in_row_index : JDIMENSION; + output_buf : JSAMPIMAGE; + out_row_group_index : JDIMENSION); +var + downsample : my_downsample_ptr; + ci : int; + compptr : jpeg_component_info_ptr; + in_ptr, out_ptr : JSAMPARRAY; +begin + downsample := my_downsample_ptr (cinfo^.downsample); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + in_ptr := JSAMPARRAY(@ input_buf^[ci]^[in_row_index]); + out_ptr := JSAMPARRAY(@ output_buf^[ci]^ + [out_row_group_index * JDIMENSION(compptr^.v_samp_factor)]); + downsample^.methods[ci] (cinfo, compptr, in_ptr, out_ptr); + Inc(compptr); + end; +end; + + +{ Downsample pixel values of a single component. + One row group is processed per call. + This version handles arbitrary integral sampling ratios, without smoothing. + Note that this version is not actually used for customary sampling ratios. } + +{METHODDEF} +procedure int_downsample (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + output_data : JSAMPARRAY); +var + inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v : int; + outcol, outcol_h : JDIMENSION; { outcol_h = outcol*h_expand } + output_cols : JDIMENSION; + inptr, + outptr : JSAMPLE_PTR; + outvalue : INT32; +begin + output_cols := compptr^.width_in_blocks * DCTSIZE; + + h_expand := cinfo^.max_h_samp_factor div compptr^.h_samp_factor; + v_expand := cinfo^.max_v_samp_factor div compptr^.v_samp_factor; + numpix := h_expand * v_expand; + numpix2 := numpix div 2; + + { Expand input data enough to let all the output samples be generated + by the standard loop. Special-casing padded output would be more + efficient. } + + expand_right_edge(input_data, cinfo^.max_v_samp_factor, + cinfo^.image_width, output_cols * JDIMENSION(h_expand)); + + inrow := 0; + for outrow := 0 to pred(compptr^.v_samp_factor) do + begin + outptr := JSAMPLE_PTR(output_data^[outrow]); + outcol_h := 0; + for outcol := 0 to pred(output_cols) do + begin + outvalue := 0; + for v := 0 to pred(v_expand) do + begin + inptr := @(input_data^[inrow+v]^[outcol_h]); + for h := 0 to pred(h_expand) do + begin + Inc(outvalue, INT32 (GETJSAMPLE(inptr^)) ); + Inc(inptr); + end; + end; + outptr^ := JSAMPLE ((outvalue + numpix2) div numpix); + Inc(outptr); + Inc(outcol_h, h_expand); + end; + Inc(inrow, v_expand); + end; +end; + + +{ Downsample pixel values of a single component. + This version handles the special case of a full-size component, + without smoothing. } + +{METHODDEF} +procedure fullsize_downsample (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + output_data : JSAMPARRAY); +begin + { Copy the data } + jcopy_sample_rows(input_data, 0, output_data, 0, + cinfo^.max_v_samp_factor, cinfo^.image_width); + { Edge-expand } + expand_right_edge(output_data, cinfo^.max_v_samp_factor, + cinfo^.image_width, compptr^.width_in_blocks * DCTSIZE); +end; + + +{ Downsample pixel values of a single component. + This version handles the common case of 2:1 horizontal and 1:1 vertical, + without smoothing. + + A note about the "bias" calculations: when rounding fractional values to + integer, we do not want to always round 0.5 up to the next integer. + If we did that, we'd introduce a noticeable bias towards larger values. + Instead, this code is arranged so that 0.5 will be rounded up or down at + alternate pixel locations (a simple ordered dither pattern). } + +{METHODDEF} +procedure h2v1_downsample (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + output_data : JSAMPARRAY); +var + outrow : int; + outcol : JDIMENSION; + output_cols : JDIMENSION; + {register} inptr, outptr : JSAMPLE_PTR; + {register} bias : int; +begin + output_cols := compptr^.width_in_blocks * DCTSIZE; + + { Expand input data enough to let all the output samples be generated + by the standard loop. Special-casing padded output would be more + efficient. } + + expand_right_edge(input_data, cinfo^.max_v_samp_factor, + cinfo^.image_width, output_cols * 2); + + for outrow := 0 to pred(compptr^.v_samp_factor) do + begin + outptr := JSAMPLE_PTR(output_data^[outrow]); + inptr := JSAMPLE_PTR(input_data^[outrow]); + bias := 0; { bias := 0,1,0,1,... for successive samples } + for outcol := 0 to pred(output_cols) do + begin + outptr^ := JSAMPLE ((GETJSAMPLE(inptr^) + + GETJSAMPLE(JSAMPROW(inptr)^[1]) + bias) shr 1); + Inc(outptr); + bias := bias xor 1; { 0=>1, 1=>0 } + Inc(inptr, 2); + end; + end; +end; + + +{ Downsample pixel values of a single component. + This version handles the standard case of 2:1 horizontal and 2:1 vertical, + without smoothing. } + +{METHODDEF} +procedure h2v2_downsample (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + output_data : JSAMPARRAY); +var + inrow, outrow : int; + outcol : JDIMENSION; + output_cols : JDIMENSION; + {register} inptr0, inptr1, outptr : JSAMPLE_PTR; + {register} bias : int; +begin + output_cols := compptr^.width_in_blocks * DCTSIZE; + + { Expand input data enough to let all the output samples be generated + by the standard loop. Special-casing padded output would be more + efficient. } + + expand_right_edge(input_data, cinfo^.max_v_samp_factor, + cinfo^.image_width, output_cols * 2); + + inrow := 0; + for outrow := 0 to pred(compptr^.v_samp_factor) do + begin + outptr := JSAMPLE_PTR(output_data^[outrow]); + inptr0 := JSAMPLE_PTR(input_data^[inrow]); + inptr1 := JSAMPLE_PTR(input_data^[inrow+1]); + bias := 1; { bias := 1,2,1,2,... for successive samples } + for outcol := 0 to pred(output_cols) do + begin + outptr^ := JSAMPLE ((GETJSAMPLE(inptr0^) + + GETJSAMPLE(JSAMPROW(inptr0)^[1]) + + GETJSAMPLE(inptr1^) + + GETJSAMPLE(JSAMPROW(inptr1)^[1]) + bias) shr 2); + Inc(outptr); + bias := bias xor 3; { 1=>2, 2=>1 } + Inc(inptr0, 2); + Inc(inptr1, 2); + end; + Inc(inrow, 2); + end; +end; + + +{$ifdef INPUT_SMOOTHING_SUPPORTED} + +{ Downsample pixel values of a single component. + This version handles the standard case of 2:1 horizontal and 2:1 vertical, + with smoothing. One row of context is required. } + +{METHODDEF} +procedure h2v2_smooth_downsample (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + output_data : JSAMPARRAY); +var + inrow, outrow : int; + colctr : JDIMENSION; + output_cols : JDIMENSION; + {register} inptr0, inptr1, above_ptr, below_ptr, outptr : JSAMPLE_PTR; + membersum, neighsum, memberscale, neighscale : INT32; +var + prev_input_data : JSAMPARRAY; + prev_inptr0, prev_inptr1, prev_above_ptr, prev_below_ptr : JSAMPLE_PTR; +begin + output_cols := compptr^.width_in_blocks * DCTSIZE; + + { Expand input data enough to let all the output samples be generated + by the standard loop. Special-casing padded output would be more + efficient. } + + prev_input_data := input_data; + Dec(JSAMPROW_PTR(prev_input_data)); + expand_right_edge(prev_input_data, cinfo^.max_v_samp_factor + 2, + cinfo^.image_width, output_cols * 2); + + { We don't bother to form the individual "smoothed" input pixel values; + we can directly compute the output which is the average of the four + smoothed values. Each of the four member pixels contributes a fraction + (1-8*SF) to its own smoothed image and a fraction SF to each of the three + other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final + output. The four corner-adjacent neighbor pixels contribute a fraction + SF to just one smoothed pixel, or SF/4 to the final output; while the + eight edge-adjacent neighbors contribute SF to each of two smoothed + pixels, or SF/2 overall. In order to use integer arithmetic, these + factors are scaled by 2^16 := 65536. + Also recall that SF := smoothing_factor / 1024. } + + memberscale := 16384 - cinfo^.smoothing_factor * 80; { scaled (1-5*SF)/4 } + neighscale := cinfo^.smoothing_factor * 16; { scaled SF/4 } + + inrow := 0; + for outrow := 0 to pred(compptr^.v_samp_factor) do + begin + outptr := JSAMPLE_PTR(output_data^[outrow]); + inptr0 := JSAMPLE_PTR(input_data^[inrow]); + inptr1 := JSAMPLE_PTR(input_data^[inrow+1]); + above_ptr := JSAMPLE_PTR(input_data^[inrow-1]); + below_ptr := JSAMPLE_PTR(input_data^[inrow+2]); + + { Special case for first column: pretend column -1 is same as column 0 } + membersum := GETJSAMPLE(inptr0^) + GETJSAMPLE(JSAMPROW(inptr0)^[1]) + + GETJSAMPLE(inptr1^) + GETJSAMPLE(JSAMPROW(inptr1)^[1]); + neighsum := GETJSAMPLE(above_ptr^) + GETJSAMPLE(JSAMPROW(above_ptr)^[1]) + + GETJSAMPLE(below_ptr^) + GETJSAMPLE(JSAMPROW(below_ptr)^[1]) + + GETJSAMPLE(inptr0^) + GETJSAMPLE(JSAMPROW(inptr0)^[2]) + + GETJSAMPLE(inptr1^) + GETJSAMPLE(JSAMPROW(inptr1)^[2]); + Inc(neighsum, neighsum); + Inc(neighsum, GETJSAMPLE(above_ptr^) + + GETJSAMPLE(JSAMPROW(above_ptr)^[2]) + + GETJSAMPLE(below_ptr^) + + GETJSAMPLE(JSAMPROW(below_ptr)^[2]) ); + membersum := membersum * memberscale + neighsum * neighscale; + outptr^ := JSAMPLE ((membersum + 32768) shr 16); + Inc(outptr); + prev_inptr0 := inptr0; + prev_inptr1 := inptr1; + Inc(prev_inptr0); + Inc(prev_inptr1); + Inc(inptr0, 2); + Inc(inptr1, 2); + prev_above_ptr := above_ptr; + prev_below_ptr := below_ptr; + Inc(above_ptr, 2); + Inc(below_ptr, 2); + Inc(prev_above_ptr, 1); + Inc(prev_below_ptr, 1); + + for colctr := pred(output_cols - 2) downto 0 do + begin + { sum of pixels directly mapped to this output element } + membersum := GETJSAMPLE(inptr0^) + GETJSAMPLE(JSAMPROW(inptr0)^[1]) + + GETJSAMPLE(inptr1^) + GETJSAMPLE(JSAMPROW(inptr1)^[1]); + { sum of edge-neighbor pixels } + neighsum := GETJSAMPLE(above_ptr^) + GETJSAMPLE(JSAMPROW(above_ptr)^[1]) + + GETJSAMPLE(below_ptr^) + GETJSAMPLE(JSAMPROW(below_ptr)^[1]) + + GETJSAMPLE(prev_inptr0^) + GETJSAMPLE(JSAMPROW(inptr0)^[2]) + + GETJSAMPLE(prev_inptr1^) + GETJSAMPLE(JSAMPROW(inptr1)^[2]); + { The edge-neighbors count twice as much as corner-neighbors } + Inc(neighsum, neighsum); + { Add in the corner-neighbors } + Inc(neighsum, GETJSAMPLE(prev_above_ptr^) + + GETJSAMPLE(JSAMPROW(above_ptr)^[2]) + + GETJSAMPLE(prev_below_ptr^) + + GETJSAMPLE(JSAMPROW(below_ptr)^[2]) ); + { form final output scaled up by 2^16 } + membersum := membersum * memberscale + neighsum * neighscale; + { round, descale and output it } + outptr^ := JSAMPLE ((membersum + 32768) shr 16); + Inc(outptr); + Inc(inptr0, 2); + Inc(inptr1, 2); + Inc(prev_inptr0, 2); + Inc(prev_inptr1, 2); + Inc(above_ptr, 2); + Inc(below_ptr, 2); + Inc(prev_above_ptr, 2); + Inc(prev_below_ptr, 2); + end; + + { Special case for last column } + membersum := GETJSAMPLE(inptr0^) + GETJSAMPLE(JSAMPROW(inptr0)^[1]) + + GETJSAMPLE(inptr1^) + GETJSAMPLE(JSAMPROW(inptr1)^[1]); + neighsum := GETJSAMPLE(above_ptr^) + GETJSAMPLE(JSAMPROW(above_ptr)^[1]) + + GETJSAMPLE(below_ptr^) + GETJSAMPLE(JSAMPROW(below_ptr)^[1]) + + GETJSAMPLE(prev_inptr0^) + GETJSAMPLE(JSAMPROW(inptr0)^[1]) + + GETJSAMPLE(prev_inptr1^) + GETJSAMPLE(JSAMPROW(inptr1)^[1]); + Inc(neighsum, neighsum); + Inc(neighsum, GETJSAMPLE(prev_above_ptr^) + + GETJSAMPLE(JSAMPROW(above_ptr)^[1]) + + GETJSAMPLE(prev_below_ptr^) + + GETJSAMPLE(JSAMPROW(below_ptr)^[1]) ); + membersum := membersum * memberscale + neighsum * neighscale; + outptr^ := JSAMPLE ((membersum + 32768) shr 16); + + Inc(inrow, 2); + end; +end; + + +{ Downsample pixel values of a single component. + This version handles the special case of a full-size component, + with smoothing. One row of context is required. } + +{METHODDEF} +procedure fullsize_smooth_downsample (cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + output_data : JSAMPARRAY); +var + outrow : int; + colctr : JDIMENSION; + output_cols : JDIMENSION; + {register} inptr, above_ptr, below_ptr, outptr : JSAMPLE_PTR; + membersum, neighsum, memberscale, neighscale : INT32; + colsum, lastcolsum, nextcolsum : int; +var + prev_input_data : JSAMPARRAY; +begin + output_cols := compptr^.width_in_blocks * DCTSIZE; + + { Expand input data enough to let all the output samples be generated + by the standard loop. Special-casing padded output would be more + efficient. } + + prev_input_data := input_data; + Dec(JSAMPROW_PTR(prev_input_data)); + expand_right_edge(prev_input_data, cinfo^.max_v_samp_factor + 2, + cinfo^.image_width, output_cols); + + { Each of the eight neighbor pixels contributes a fraction SF to the + smoothed pixel, while the main pixel contributes (1-8*SF). In order + to use integer arithmetic, these factors are multiplied by 2^16 := 65536. + Also recall that SF := smoothing_factor / 1024. } + + memberscale := long(65536) - cinfo^.smoothing_factor * long(512); { scaled 1-8*SF } + neighscale := cinfo^.smoothing_factor * 64; { scaled SF } + + for outrow := 0 to pred(compptr^.v_samp_factor) do + begin + outptr := JSAMPLE_PTR(output_data^[outrow]); + inptr := JSAMPLE_PTR(input_data^[outrow]); + above_ptr := JSAMPLE_PTR(input_data^[outrow-1]); + below_ptr := JSAMPLE_PTR(input_data^[outrow+1]); + + { Special case for first column } + colsum := GETJSAMPLE(above_ptr^) + GETJSAMPLE(below_ptr^) + + GETJSAMPLE(inptr^); + Inc(above_ptr); + Inc(below_ptr); + membersum := GETJSAMPLE(inptr^); + Inc(inptr); + nextcolsum := GETJSAMPLE(above_ptr^) + GETJSAMPLE(below_ptr^) + + GETJSAMPLE(inptr^); + neighsum := colsum + (colsum - membersum) + nextcolsum; + membersum := membersum * memberscale + neighsum * neighscale; + outptr^ := JSAMPLE ((membersum + 32768) shr 16); + Inc(outptr); + lastcolsum := colsum; colsum := nextcolsum; + + for colctr := pred(output_cols - 2) downto 0 do + begin + membersum := GETJSAMPLE(inptr^); + Inc(inptr); + Inc(above_ptr); + Inc(below_ptr); + nextcolsum := GETJSAMPLE(above_ptr^) + GETJSAMPLE(below_ptr^) + + GETJSAMPLE(inptr^); + neighsum := lastcolsum + (colsum - membersum) + nextcolsum; + membersum := membersum * memberscale + neighsum * neighscale; + outptr^ := JSAMPLE ((membersum + 32768) shr 16); + Inc(outptr); + lastcolsum := colsum; colsum := nextcolsum; + end; + + { Special case for last column } + membersum := GETJSAMPLE(inptr^); + neighsum := lastcolsum + (colsum - membersum) + colsum; + membersum := membersum * memberscale + neighsum * neighscale; + outptr^ := JSAMPLE ((membersum + 32768) shr 16); + end; +end; + +{$endif} { INPUT_SMOOTHING_SUPPORTED } + + +{ Module initialization routine for downsampling. + Note that we must select a routine for each component. } + +{GLOBAL} +procedure jinit_downsampler (cinfo : j_compress_ptr); +var + downsample : my_downsample_ptr; + ci : int; + compptr : jpeg_component_info_ptr; + smoothok : boolean; +begin + smoothok := TRUE; + + downsample := my_downsample_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_downsampler)) ); + cinfo^.downsample := jpeg_downsampler_ptr (downsample); + downsample^.pub.start_pass := start_pass_downsample; + downsample^.pub.downsample := sep_downsample; + downsample^.pub.need_context_rows := FALSE; + + if (cinfo^.CCIR601_sampling) then + ERREXIT(j_common_ptr(cinfo), JERR_CCIR601_NOTIMPL); + + { Verify we can handle the sampling factors, and set up method pointers } + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + if (compptr^.h_samp_factor = cinfo^.max_h_samp_factor) and + (compptr^.v_samp_factor = cinfo^.max_v_samp_factor) then + begin +{$ifdef INPUT_SMOOTHING_SUPPORTED} + if (cinfo^.smoothing_factor <> 0) then + begin + downsample^.methods[ci] := fullsize_smooth_downsample; + downsample^.pub.need_context_rows := TRUE; + end + else +{$endif} + downsample^.methods[ci] := fullsize_downsample; + end + else + if (compptr^.h_samp_factor * 2 = cinfo^.max_h_samp_factor) and + (compptr^.v_samp_factor = cinfo^.max_v_samp_factor) then + begin + smoothok := FALSE; + downsample^.methods[ci] := h2v1_downsample; + end + else + if (compptr^.h_samp_factor * 2 = cinfo^.max_h_samp_factor) and + (compptr^.v_samp_factor * 2 = cinfo^.max_v_samp_factor) then + begin + {$ifdef INPUT_SMOOTHING_SUPPORTED} + if (cinfo^.smoothing_factor <> 0) then + begin + downsample^.methods[ci] := h2v2_smooth_downsample; + downsample^.pub.need_context_rows := TRUE; + end + else + {$endif} + downsample^.methods[ci] := h2v2_downsample; + end + else + if ((cinfo^.max_h_samp_factor mod compptr^.h_samp_factor) = 0) and + ((cinfo^.max_v_samp_factor mod compptr^.v_samp_factor) = 0) then + begin + smoothok := FALSE; + downsample^.methods[ci] := int_downsample; + end + else + ERREXIT(j_common_ptr(cinfo), JERR_FRACT_SAMPLE_NOTIMPL); + Inc(compptr); + end; + +{$ifdef INPUT_SMOOTHING_SUPPORTED} + if (cinfo^.smoothing_factor <> 0) and (not smoothok) then + TRACEMS(j_common_ptr(cinfo), 0, JTRC_SMOOTH_NOTIMPL); +{$endif} +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdapimin.pas b/src/lib/vampimg/JpegLib/imjdapimin.pas new file mode 100644 index 0000000..726d798 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdapimin.pas @@ -0,0 +1,505 @@ +unit imjdapimin; + +{$N+} { Nomssi: cinfo^.output_gamma } + +{ This file contains application interface code for the decompression half + of the JPEG library. These are the "minimum" API routines that may be + needed in either the normal full-decompression case or the + transcoding-only case. + + Most of the routines intended to be called directly by an application + are in this file or in jdapistd.c. But also see jcomapi.c for routines + shared by compression and decompression, and jdtrans.c for the transcoding + case. } + +{ Original : jdapimin.c ; Copyright (C) 1994-1998, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib, + imjmemmgr, imjdmarker, imjdinput, imjcomapi; + +{ Nomssi } +procedure jpeg_create_decompress(cinfo : j_decompress_ptr); + +{ Initialization of a JPEG decompression object. + The error manager must already be set up (in case memory manager fails). } + +{GLOBAL} +procedure jpeg_CreateDecompress (cinfo : j_decompress_ptr; + version : int; + structsize : size_t); + +{ Destruction of a JPEG decompression object } + +{GLOBAL} +procedure jpeg_destroy_decompress (cinfo : j_decompress_ptr); + + +{ Decompression startup: read start of JPEG datastream to see what's there. + Need only initialize JPEG object and supply a data source before calling. + + This routine will read as far as the first SOS marker (ie, actual start of + compressed data), and will save all tables and parameters in the JPEG + object. It will also initialize the decompression parameters to default + values, and finally return JPEG_HEADER_OK. On return, the application may + adjust the decompression parameters and then call jpeg_start_decompress. + (Or, if the application only wanted to determine the image parameters, + the data need not be decompressed. In that case, call jpeg_abort or + jpeg_destroy to release any temporary space.) + If an abbreviated (tables only) datastream is presented, the routine will + return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + re-use the JPEG object to read the abbreviated image datastream(s). + It is unnecessary (but OK) to call jpeg_abort in this case. + The JPEG_SUSPENDED return code only occurs if the data source module + requests suspension of the decompressor. In this case the application + should load more source data and then re-call jpeg_read_header to resume + processing. + If a non-suspending data source is used and require_image is TRUE, then the + return code need not be inspected since only JPEG_HEADER_OK is possible. + + This routine is now just a front end to jpeg_consume_input, with some + extra error checking. } + +{GLOBAL} +function jpeg_read_header (cinfo : j_decompress_ptr; + require_image : boolean) : int; + +{ Consume data in advance of what the decompressor requires. + This can be called at any time once the decompressor object has + been created and a data source has been set up. + + This routine is essentially a state machine that handles a couple + of critical state-transition actions, namely initial setup and + transition from header scanning to ready-for-start_decompress. + All the actual input is done via the input controller's consume_input + method. } + +{GLOBAL} +function jpeg_consume_input (cinfo : j_decompress_ptr) : int; + +{ Have we finished reading the input file? } + +{GLOBAL} +function jpeg_input_complete (cinfo : j_decompress_ptr) : boolean; + +{ Is there more than one scan? } + +{GLOBAL} +function jpeg_has_multiple_scans (cinfo : j_decompress_ptr) : boolean; + + +{ Finish JPEG decompression. + + This will normally just verify the file trailer and release temp storage. + + Returns FALSE if suspended. The return value need be inspected only if + a suspending data source is used. } + +{GLOBAL} +function jpeg_finish_decompress (cinfo : j_decompress_ptr) : boolean; + +implementation + +procedure jpeg_create_decompress(cinfo : j_decompress_ptr); +begin + jpeg_CreateDecompress(cinfo, JPEG_LIB_VERSION, + size_t(sizeof(jpeg_decompress_struct))); +end; + +{ Initialization of a JPEG decompression object. + The error manager must already be set up (in case memory manager fails). } + +{GLOBAL} +procedure jpeg_CreateDecompress (cinfo : j_decompress_ptr; + version : int; + structsize : size_t); +var + i : int; +var + err : jpeg_error_mgr_ptr; + client_data : voidp; +begin + { Guard against version mismatches between library and caller. } + cinfo^.mem := NIL; { so jpeg_destroy knows mem mgr not called } + if (version <> JPEG_LIB_VERSION) then + ERREXIT2(j_common_ptr(cinfo), JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); + if (structsize <> SIZEOF(jpeg_decompress_struct)) then + ERREXIT2(j_common_ptr(cinfo), JERR_BAD_STRUCT_SIZE, + int(SIZEOF(jpeg_decompress_struct)), int(structsize)); + + { For debugging purposes, we zero the whole master structure. + But the application has already set the err pointer, and may have set + client_data, so we have to save and restore those fields. + Note: if application hasn't set client_data, tools like Purify may + complain here. } + begin + err := cinfo^.err; + client_data := cinfo^.client_data; { ignore Purify complaint here } + MEMZERO(j_common_ptr(cinfo), SIZEOF(jpeg_decompress_struct)); + cinfo^.err := err; + cinfo^.client_data := client_data; + end; + cinfo^.is_decompressor := TRUE; + + { Initialize a memory manager instance for this object } + jinit_memory_mgr(j_common_ptr(cinfo)); + + { Zero out pointers to permanent structures. } + cinfo^.progress := NIL; + cinfo^.src := NIL; + + for i := 0 to pred(NUM_QUANT_TBLS) do + cinfo^.quant_tbl_ptrs[i] := NIL; + + for i := 0 to pred(NUM_HUFF_TBLS) do + begin + cinfo^.dc_huff_tbl_ptrs[i] := NIL; + cinfo^.ac_huff_tbl_ptrs[i] := NIL; + end; + + { Initialize marker processor so application can override methods + for COM, APPn markers before calling jpeg_read_header. } + cinfo^.marker_list := NIL; + jinit_marker_reader(cinfo); + + { And initialize the overall input controller. } + jinit_input_controller(cinfo); + + { OK, I'm ready } + cinfo^.global_state := DSTATE_START; +end; + + +{ Destruction of a JPEG decompression object } + +{GLOBAL} +procedure jpeg_destroy_decompress (cinfo : j_decompress_ptr); +begin + jpeg_destroy(j_common_ptr(cinfo)); { use common routine } +end; + + +{ Abort processing of a JPEG decompression operation, + but don't destroy the object itself. } + +{GLOBAL} +procedure jpeg_abort_decompress (cinfo : j_decompress_ptr); +begin + jpeg_abort(j_common_ptr(cinfo)); { use common routine } +end; + + +{ Set default decompression parameters. } + +{LOCAL} +procedure default_decompress_parms (cinfo : j_decompress_ptr); +var + cid0 : int; + cid1 : int; + cid2 : int; +begin + { Guess the input colorspace, and set output colorspace accordingly. } + { (Wish JPEG committee had provided a real way to specify this...) } + { Note application may override our guesses. } + case (cinfo^.num_components) of + 1: begin + cinfo^.jpeg_color_space := JCS_GRAYSCALE; + cinfo^.out_color_space := JCS_GRAYSCALE; + end; + + 3: begin + if (cinfo^.saw_JFIF_marker) then + begin + cinfo^.jpeg_color_space := JCS_YCbCr; { JFIF implies YCbCr } + end + else + if (cinfo^.saw_Adobe_marker) then + begin + case (cinfo^.Adobe_transform) of + 0: cinfo^.jpeg_color_space := JCS_RGB; + 1: cinfo^.jpeg_color_space := JCS_YCbCr; + else + begin + WARNMS1(j_common_ptr(cinfo), JWRN_ADOBE_XFORM, cinfo^.Adobe_transform); + cinfo^.jpeg_color_space := JCS_YCbCr; { assume it's YCbCr } + end; + end; + end + else + begin + { Saw no special markers, try to guess from the component IDs } + cid0 := cinfo^.comp_info^[0].component_id; + cid1 := cinfo^.comp_info^[1].component_id; + cid2 := cinfo^.comp_info^[2].component_id; + + if (cid0 = 1) and (cid1 = 2) and (cid2 = 3) then + cinfo^.jpeg_color_space := JCS_YCbCr { assume JFIF w/out marker } + else + if (cid0 = 82) and (cid1 = 71) and (cid2 = 66) then + cinfo^.jpeg_color_space := JCS_RGB { ASCII 'R', 'G', 'B' } + else + begin + {$IFDEF DEBUG} + TRACEMS3(j_common_ptr(cinfo), 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); + {$ENDIF} + cinfo^.jpeg_color_space := JCS_YCbCr; { assume it's YCbCr } + end; + end; + { Always guess RGB is proper output colorspace. } + cinfo^.out_color_space := JCS_RGB; + end; + + 4: begin + if (cinfo^.saw_Adobe_marker) then + begin + case (cinfo^.Adobe_transform) of + 0: cinfo^.jpeg_color_space := JCS_CMYK; + 2: cinfo^.jpeg_color_space := JCS_YCCK; + else + begin + WARNMS1(j_common_ptr(cinfo), JWRN_ADOBE_XFORM, cinfo^.Adobe_transform); + cinfo^.jpeg_color_space := JCS_YCCK; { assume it's YCCK } + end; + end; + end + else + begin + { No special markers, assume straight CMYK. } + cinfo^.jpeg_color_space := JCS_CMYK; + end; + cinfo^.out_color_space := JCS_CMYK; + end; + + else + begin + cinfo^.jpeg_color_space := JCS_UNKNOWN; + cinfo^.out_color_space := JCS_UNKNOWN; + end; + end; + + { Set defaults for other decompression parameters. } + cinfo^.scale_num := 1; { 1:1 scaling } + cinfo^.scale_denom := 1; + cinfo^.output_gamma := 1.0; + cinfo^.buffered_image := FALSE; + cinfo^.raw_data_out := FALSE; + cinfo^.dct_method := JDCT_DEFAULT; + cinfo^.do_fancy_upsampling := TRUE; + cinfo^.do_block_smoothing := TRUE; + cinfo^.quantize_colors := FALSE; + { We set these in case application only sets quantize_colors. } + cinfo^.dither_mode := JDITHER_FS; +{$ifdef QUANT_2PASS_SUPPORTED} + cinfo^.two_pass_quantize := TRUE; +{$else} + cinfo^.two_pass_quantize := FALSE; +{$endif} + cinfo^.desired_number_of_colors := 256; + cinfo^.colormap := NIL; + { Initialize for no mode change in buffered-image mode. } + cinfo^.enable_1pass_quant := FALSE; + cinfo^.enable_external_quant := FALSE; + cinfo^.enable_2pass_quant := FALSE; +end; + + +{ Decompression startup: read start of JPEG datastream to see what's there. + Need only initialize JPEG object and supply a data source before calling. + + This routine will read as far as the first SOS marker (ie, actual start of + compressed data), and will save all tables and parameters in the JPEG + object. It will also initialize the decompression parameters to default + values, and finally return JPEG_HEADER_OK. On return, the application may + adjust the decompression parameters and then call jpeg_start_decompress. + (Or, if the application only wanted to determine the image parameters, + the data need not be decompressed. In that case, call jpeg_abort or + jpeg_destroy to release any temporary space.) + If an abbreviated (tables only) datastream is presented, the routine will + return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then + re-use the JPEG object to read the abbreviated image datastream(s). + It is unnecessary (but OK) to call jpeg_abort in this case. + The JPEG_SUSPENDED return code only occurs if the data source module + requests suspension of the decompressor. In this case the application + should load more source data and then re-call jpeg_read_header to resume + processing. + If a non-suspending data source is used and require_image is TRUE, then the + return code need not be inspected since only JPEG_HEADER_OK is possible. + + This routine is now just a front end to jpeg_consume_input, with some + extra error checking. } + +{GLOBAL} +function jpeg_read_header (cinfo : j_decompress_ptr; + require_image : boolean) : int; +var + retcode : int; +begin + if (cinfo^.global_state <> DSTATE_START) and + (cinfo^.global_state <> DSTATE_INHEADER) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + retcode := jpeg_consume_input(cinfo); + + case (retcode) of + JPEG_REACHED_SOS: + retcode := JPEG_HEADER_OK; + JPEG_REACHED_EOI: + begin + if (require_image) then { Complain if application wanted an image } + ERREXIT(j_common_ptr(cinfo), JERR_NO_IMAGE); + { Reset to start state; it would be safer to require the application to + call jpeg_abort, but we can't change it now for compatibility reasons. + A side effect is to free any temporary memory (there shouldn't be any). } + + jpeg_abort(j_common_ptr(cinfo)); { sets state := DSTATE_START } + retcode := JPEG_HEADER_TABLES_ONLY; + end; + JPEG_SUSPENDED: ; { no work } + end; + + jpeg_read_header := retcode; +end; + + +{ Consume data in advance of what the decompressor requires. + This can be called at any time once the decompressor object has + been created and a data source has been set up. + + This routine is essentially a state machine that handles a couple + of critical state-transition actions, namely initial setup and + transition from header scanning to ready-for-start_decompress. + All the actual input is done via the input controller's consume_input + method. } + +{GLOBAL} +function jpeg_consume_input (cinfo : j_decompress_ptr) : int; +var + retcode : int; +begin + retcode := JPEG_SUSPENDED; + + { NB: every possible DSTATE value should be listed in this switch } + + if (cinfo^.global_state) = DSTATE_START then + begin {work around the FALLTHROUGH} + { Start-of-datastream actions: reset appropriate modules } + cinfo^.inputctl^.reset_input_controller (cinfo); + { Initialize application's data source module } + cinfo^.src^.init_source (cinfo); + cinfo^.global_state := DSTATE_INHEADER; + end; + + case (cinfo^.global_state) of + DSTATE_START, + DSTATE_INHEADER: + begin + retcode := cinfo^.inputctl^.consume_input (cinfo); + if (retcode = JPEG_REACHED_SOS) then + begin { Found SOS, prepare to decompress } + { Set up default parameters based on header data } + default_decompress_parms(cinfo); + { Set global state: ready for start_decompress } + cinfo^.global_state := DSTATE_READY; + end; + end; + DSTATE_READY: + { Can't advance past first SOS until start_decompress is called } + retcode := JPEG_REACHED_SOS; + + DSTATE_PRELOAD, + DSTATE_PRESCAN, + DSTATE_SCANNING, + DSTATE_RAW_OK, + DSTATE_BUFIMAGE, + DSTATE_BUFPOST, + DSTATE_STOPPING: + retcode := cinfo^.inputctl^.consume_input (cinfo); + else + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + end; + jpeg_consume_input := retcode; +end; + + +{ Have we finished reading the input file? } + +{GLOBAL} +function jpeg_input_complete (cinfo : j_decompress_ptr) : boolean; +begin + { Check for valid jpeg object } + if (cinfo^.global_state < DSTATE_START) or + (cinfo^.global_state > DSTATE_STOPPING) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + jpeg_input_complete := cinfo^.inputctl^.eoi_reached; +end; + + +{ Is there more than one scan? } + +{GLOBAL} +function jpeg_has_multiple_scans (cinfo : j_decompress_ptr) : boolean; +begin + { Only valid after jpeg_read_header completes } + if (cinfo^.global_state < DSTATE_READY) or + (cinfo^.global_state > DSTATE_STOPPING) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + jpeg_has_multiple_scans := cinfo^.inputctl^.has_multiple_scans; +end; + + +{ Finish JPEG decompression. + + This will normally just verify the file trailer and release temp storage. + + Returns FALSE if suspended. The return value need be inspected only if + a suspending data source is used. } + +{GLOBAL} +function jpeg_finish_decompress (cinfo : j_decompress_ptr) : boolean; +begin + if ((cinfo^.global_state = DSTATE_SCANNING) or + (cinfo^.global_state = DSTATE_RAW_OK) and (not cinfo^.buffered_image)) then + begin + { Terminate final pass of non-buffered mode } + if (cinfo^.output_scanline < cinfo^.output_height) then + ERREXIT(j_common_ptr(cinfo), JERR_TOO_LITTLE_DATA); + cinfo^.master^.finish_output_pass (cinfo); + cinfo^.global_state := DSTATE_STOPPING; + end + else + if (cinfo^.global_state = DSTATE_BUFIMAGE) then + begin + { Finishing after a buffered-image operation } + cinfo^.global_state := DSTATE_STOPPING; + end + else + if (cinfo^.global_state <> DSTATE_STOPPING) then + begin + { STOPPING := repeat call after a suspension, anything else is error } + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + end; + { Read until EOI } + while (not cinfo^.inputctl^.eoi_reached) do + begin + if (cinfo^.inputctl^.consume_input (cinfo) = JPEG_SUSPENDED) then + begin + jpeg_finish_decompress := FALSE; { Suspend, come back later } + exit; + end; + end; + { Do final cleanup } + cinfo^.src^.term_source (cinfo); + { We can use jpeg_abort to release memory and reset global_state } + jpeg_abort(j_common_ptr(cinfo)); + jpeg_finish_decompress := TRUE; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdapistd.pas b/src/lib/vampimg/JpegLib/imjdapistd.pas new file mode 100644 index 0000000..04afd11 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdapistd.pas @@ -0,0 +1,376 @@ +unit imjdapistd; + +{ Original : jdapistd.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +{ This file is part of the Independent JPEG Group's software. + For conditions of distribution and use, see the accompanying README file. + + This file contains application interface code for the decompression half + of the JPEG library. These are the "standard" API routines that are + used in the normal full-decompression case. They are not used by a + transcoding-only application. Note that if an application links in + jpeg_start_decompress, it will end up linking in the entire decompressor. + We thus must separate this file from jdapimin.c to avoid linking the + whole decompression library into a transcoder. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib, + imjdmaster; + +{ Read some scanlines of data from the JPEG decompressor. + + The return value will be the number of lines actually read. + This may be less than the number requested in several cases, + including bottom of image, data source suspension, and operating + modes that emit multiple scanlines at a time. + + Note: we warn about excess calls to jpeg_read_scanlines() since + this likely signals an application programmer error. However, + an oversize buffer (max_lines > scanlines remaining) is not an error. } + +{GLOBAL} +function jpeg_read_scanlines (cinfo : j_decompress_ptr; + scanlines : JSAMPARRAY; + max_lines : JDIMENSION) : JDIMENSION; + + +{ Alternate entry point to read raw data. + Processes exactly one iMCU row per call, unless suspended. } + +{GLOBAL} +function jpeg_read_raw_data (cinfo : j_decompress_ptr; + data : JSAMPIMAGE; + max_lines : JDIMENSION) : JDIMENSION; + +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + +{ Initialize for an output pass in buffered-image mode. } + +{GLOBAL} +function jpeg_start_output (cinfo : j_decompress_ptr; + scan_number : int) : boolean; + +{ Finish up after an output pass in buffered-image mode. + + Returns FALSE if suspended. The return value need be inspected only if + a suspending data source is used. } + +{GLOBAL} +function jpeg_finish_output (cinfo : j_decompress_ptr) : boolean; + +{$endif} { D_MULTISCAN_FILES_SUPPORTED } + +{ Decompression initialization. + jpeg_read_header must be completed before calling this. + + If a multipass operating mode was selected, this will do all but the + last pass, and thus may take a great deal of time. + + Returns FALSE if suspended. The return value need be inspected only if + a suspending data source is used. } + +{GLOBAL} +function jpeg_start_decompress (cinfo : j_decompress_ptr) : boolean; + + +implementation + +{ Forward declarations } +{LOCAL} +function output_pass_setup (cinfo : j_decompress_ptr) : boolean; forward; + +{ Decompression initialization. + jpeg_read_header must be completed before calling this. + + If a multipass operating mode was selected, this will do all but the + last pass, and thus may take a great deal of time. + + Returns FALSE if suspended. The return value need be inspected only if + a suspending data source is used. } + +{GLOBAL} +function jpeg_start_decompress (cinfo : j_decompress_ptr) : boolean; +var + retcode : int; +begin + if (cinfo^.global_state = DSTATE_READY) then + begin + { First call: initialize master control, select active modules } + jinit_master_decompress(cinfo); + if (cinfo^.buffered_image) then + begin + { No more work here; expecting jpeg_start_output next } + cinfo^.global_state := DSTATE_BUFIMAGE; + jpeg_start_decompress := TRUE; + exit; + end; + cinfo^.global_state := DSTATE_PRELOAD; + end; + if (cinfo^.global_state = DSTATE_PRELOAD) then + begin + { If file has multiple scans, absorb them all into the coef buffer } + if (cinfo^.inputctl^.has_multiple_scans) then + begin +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + while TRUE do + begin + + { Call progress monitor hook if present } + if (cinfo^.progress <> NIL) then + cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); + { Absorb some more input } + retcode := cinfo^.inputctl^.consume_input (cinfo); + if (retcode = JPEG_SUSPENDED) then + begin + jpeg_start_decompress := FALSE; + exit; + end; + if (retcode = JPEG_REACHED_EOI) then + break; + { Advance progress counter if appropriate } + if (cinfo^.progress <> NIL) and + ((retcode = JPEG_ROW_COMPLETED) or (retcode = JPEG_REACHED_SOS)) then + begin + Inc(cinfo^.progress^.pass_counter); + if (cinfo^.progress^.pass_counter >= cinfo^.progress^.pass_limit) then + begin + { jdmaster underestimated number of scans; ratchet up one scan } + Inc(cinfo^.progress^.pass_limit, long(cinfo^.total_iMCU_rows)); + end; + end; + end; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} { D_MULTISCAN_FILES_SUPPORTED } + end; + cinfo^.output_scan_number := cinfo^.input_scan_number; + end + else + if (cinfo^.global_state <> DSTATE_PRESCAN) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + { Perform any dummy output passes, and set up for the final pass } + jpeg_start_decompress := output_pass_setup(cinfo); +end; + + +{ Set up for an output pass, and perform any dummy pass(es) needed. + Common subroutine for jpeg_start_decompress and jpeg_start_output. + Entry: global_state := DSTATE_PRESCAN only if previously suspended. + Exit: If done, returns TRUE and sets global_state for proper output mode. + If suspended, returns FALSE and sets global_state := DSTATE_PRESCAN. } + +{LOCAL} +function output_pass_setup (cinfo : j_decompress_ptr) : boolean; +var + last_scanline : JDIMENSION; +begin + if (cinfo^.global_state <> DSTATE_PRESCAN) then + begin + { First call: do pass setup } + cinfo^.master^.prepare_for_output_pass (cinfo); + cinfo^.output_scanline := 0; + cinfo^.global_state := DSTATE_PRESCAN; + end; + { Loop over any required dummy passes } + while (cinfo^.master^.is_dummy_pass) do + begin +{$ifdef QUANT_2PASS_SUPPORTED} + { Crank through the dummy pass } + while (cinfo^.output_scanline < cinfo^.output_height) do + begin + { Call progress monitor hook if present } + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.pass_counter := long (cinfo^.output_scanline); + cinfo^.progress^.pass_limit := long (cinfo^.output_height); + cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); + end; + { Process some data } + last_scanline := cinfo^.output_scanline; + cinfo^.main^.process_data (cinfo, JSAMPARRAY(NIL), + cinfo^.output_scanline, {var} + JDIMENSION(0)); + if (cinfo^.output_scanline = last_scanline) then + begin + output_pass_setup := FALSE; { No progress made, must suspend } + exit; + end; + end; + { Finish up dummy pass, and set up for another one } + cinfo^.master^.finish_output_pass (cinfo); + cinfo^.master^.prepare_for_output_pass (cinfo); + cinfo^.output_scanline := 0; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} { QUANT_2PASS_SUPPORTED } + end; + { Ready for application to drive output pass through + jpeg_read_scanlines or jpeg_read_raw_data. } + if cinfo^.raw_data_out then + cinfo^.global_state := DSTATE_RAW_OK + else + cinfo^.global_state := DSTATE_SCANNING; + output_pass_setup := TRUE; +end; + + +{ Read some scanlines of data from the JPEG decompressor. + + The return value will be the number of lines actually read. + This may be less than the number requested in several cases, + including bottom of image, data source suspension, and operating + modes that emit multiple scanlines at a time. + + Note: we warn about excess calls to jpeg_read_scanlines() since + this likely signals an application programmer error. However, + an oversize buffer (max_lines > scanlines remaining) is not an error. } + +{GLOBAL} +function jpeg_read_scanlines (cinfo : j_decompress_ptr; + scanlines : JSAMPARRAY; + max_lines : JDIMENSION) : JDIMENSION; +var + row_ctr : JDIMENSION; +begin + if (cinfo^.global_state <> DSTATE_SCANNING) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + if (cinfo^.output_scanline >= cinfo^.output_height) then + begin + WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA); + jpeg_read_scanlines := 0; + exit; + end; + + { Call progress monitor hook if present } + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.pass_counter := long (cinfo^.output_scanline); + cinfo^.progress^.pass_limit := long (cinfo^.output_height); + cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); + end; + + { Process some data } + row_ctr := 0; + cinfo^.main^.process_data (cinfo, scanlines, {var}row_ctr, max_lines); + Inc(cinfo^.output_scanline, row_ctr); + jpeg_read_scanlines := row_ctr; +end; + + +{ Alternate entry point to read raw data. + Processes exactly one iMCU row per call, unless suspended. } + +{GLOBAL} +function jpeg_read_raw_data (cinfo : j_decompress_ptr; + data : JSAMPIMAGE; + max_lines : JDIMENSION) : JDIMENSION; +var + lines_per_iMCU_row : JDIMENSION; +begin + if (cinfo^.global_state <> DSTATE_RAW_OK) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + if (cinfo^.output_scanline >= cinfo^.output_height) then + begin + WARNMS(j_common_ptr(cinfo), JWRN_TOO_MUCH_DATA); + jpeg_read_raw_data := 0; + exit; + end; + + { Call progress monitor hook if present } + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.pass_counter := long (cinfo^.output_scanline); + cinfo^.progress^.pass_limit := long (cinfo^.output_height); + cinfo^.progress^.progress_monitor (j_common_ptr(cinfo)); + end; + + { Verify that at least one iMCU row can be returned. } + lines_per_iMCU_row := cinfo^.max_v_samp_factor * cinfo^.min_DCT_scaled_size; + if (max_lines < lines_per_iMCU_row) then + ERREXIT(j_common_ptr(cinfo), JERR_BUFFER_SIZE); + + { Decompress directly into user's buffer. } + if (cinfo^.coef^.decompress_data (cinfo, data) = 0) then + begin + jpeg_read_raw_data := 0; { suspension forced, can do nothing more } + exit; + end; + + { OK, we processed one iMCU row. } + Inc(cinfo^.output_scanline, lines_per_iMCU_row); + jpeg_read_raw_data := lines_per_iMCU_row; +end; + + +{ Additional entry points for buffered-image mode. } + +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + +{ Initialize for an output pass in buffered-image mode. } + +{GLOBAL} +function jpeg_start_output (cinfo : j_decompress_ptr; + scan_number : int) : boolean; +begin + if (cinfo^.global_state <> DSTATE_BUFIMAGE) and + (cinfo^.global_state <> DSTATE_PRESCAN) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + { Limit scan number to valid range } + if (scan_number <= 0) then + scan_number := 1; + if (cinfo^.inputctl^.eoi_reached) and + (scan_number > cinfo^.input_scan_number) then + scan_number := cinfo^.input_scan_number; + cinfo^.output_scan_number := scan_number; + { Perform any dummy output passes, and set up for the real pass } + jpeg_start_output := output_pass_setup(cinfo); +end; + + +{ Finish up after an output pass in buffered-image mode. + + Returns FALSE if suspended. The return value need be inspected only if + a suspending data source is used. } + +{GLOBAL} +function jpeg_finish_output (cinfo : j_decompress_ptr) : boolean; +begin + if ((cinfo^.global_state = DSTATE_SCANNING) or + (cinfo^.global_state = DSTATE_RAW_OK) and cinfo^.buffered_image) then + begin + { Terminate this pass. } + { We do not require the whole pass to have been completed. } + cinfo^.master^.finish_output_pass (cinfo); + cinfo^.global_state := DSTATE_BUFPOST; + end + else + if (cinfo^.global_state <> DSTATE_BUFPOST) then + begin + { BUFPOST := repeat call after a suspension, anything else is error } + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + end; + { Read markers looking for SOS or EOI } + while (cinfo^.input_scan_number <= cinfo^.output_scan_number) and + (not cinfo^.inputctl^.eoi_reached) do + begin + if (cinfo^.inputctl^.consume_input (cinfo) = JPEG_SUSPENDED) then + begin + jpeg_finish_output := FALSE; { Suspend, come back later } + exit; + end; + end; + cinfo^.global_state := DSTATE_BUFIMAGE; + jpeg_finish_output := TRUE; +end; + +{$endif} { D_MULTISCAN_FILES_SUPPORTED } + +end. diff --git a/src/lib/vampimg/JpegLib/imjdcoefct.pas b/src/lib/vampimg/JpegLib/imjdcoefct.pas new file mode 100644 index 0000000..5024786 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdcoefct.pas @@ -0,0 +1,895 @@ +unit imjdcoefct; + +{ This file contains the coefficient buffer controller for decompression. + This controller is the top level of the JPEG decompressor proper. + The coefficient buffer lies between entropy decoding and inverse-DCT steps. + + In buffered-image mode, this controller is the interface between + input-oriented processing and output-oriented processing. + Also, the input side (only) is used when reading a file for transcoding. } + +{ Original: jdcoefct.c ; Copyright (C) 1994-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjutils, + imjpeglib; + +{GLOBAL} +procedure jinit_d_coef_controller (cinfo : j_decompress_ptr; + need_full_buffer : boolean); + + +implementation + + +{ Block smoothing is only applicable for progressive JPEG, so: } +{$ifndef D_PROGRESSIVE_SUPPORTED} +{$undef BLOCK_SMOOTHING_SUPPORTED} +{$endif} + +{ Private buffer controller object } + +{$ifdef BLOCK_SMOOTHING_SUPPORTED} +const + SAVED_COEFS = 6; { we save coef_bits[0..5] } +type + Latch = array[0..SAVED_COEFS-1] of int; + Latch_ptr = ^Latch; +{$endif} + +type + my_coef_ptr = ^my_coef_controller; + my_coef_controller = record + pub : jpeg_d_coef_controller; { public fields } + + { These variables keep track of the current location of the input side. } + { cinfo^.input_iMCU_row is also used for this. } + MCU_ctr : JDIMENSION; { counts MCUs processed in current row } + MCU_vert_offset : int; { counts MCU rows within iMCU row } + MCU_rows_per_iMCU_row : int; { number of such rows needed } + + { The output side's location is represented by cinfo^.output_iMCU_row. } + + { In single-pass modes, it's sufficient to buffer just one MCU. + We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks, + and let the entropy decoder write into that workspace each time. + (On 80x86, the workspace is FAR even though it's not really very big; + this is to keep the module interfaces unchanged when a large coefficient + buffer is necessary.) + In multi-pass modes, this array points to the current MCU's blocks + within the virtual arrays; it is used only by the input side. } + + MCU_buffer : array[0..D_MAX_BLOCKS_IN_MCU-1] of JBLOCKROW; + + {$ifdef D_MULTISCAN_FILES_SUPPORTED} + { In multi-pass modes, we need a virtual block array for each component. } + whole_image : jvirt_barray_tbl; + {$endif} + + {$ifdef BLOCK_SMOOTHING_SUPPORTED} + { When doing block smoothing, we latch coefficient Al values here } + coef_bits_latch : Latch_Ptr; + {$endif} + end; + +{ Forward declarations } +{METHODDEF} +function decompress_onepass (cinfo : j_decompress_ptr; + output_buf : JSAMPIMAGE) : int; forward; +{$ifdef D_MULTISCAN_FILES_SUPPORTED} +{METHODDEF} +function decompress_data (cinfo : j_decompress_ptr; + output_buf : JSAMPIMAGE) : int; forward; +{$endif} +{$ifdef BLOCK_SMOOTHING_SUPPORTED} +{LOCAL} +function smoothing_ok (cinfo : j_decompress_ptr) : boolean; forward; + +{METHODDEF} +function decompress_smooth_data (cinfo : j_decompress_ptr; + output_buf : JSAMPIMAGE) : int; forward; +{$endif} + + +{LOCAL} +procedure start_iMCU_row (cinfo : j_decompress_ptr); +{ Reset within-iMCU-row counters for a new row (input side) } +var + coef : my_coef_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + + { In an interleaved scan, an MCU row is the same as an iMCU row. + In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. + But at the bottom of the image, process only what's left. } + + if (cinfo^.comps_in_scan > 1) then + begin + coef^.MCU_rows_per_iMCU_row := 1; + end + else + begin + if (cinfo^.input_iMCU_row < (cinfo^.total_iMCU_rows-1)) then + coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.v_samp_factor + else + coef^.MCU_rows_per_iMCU_row := cinfo^.cur_comp_info[0]^.last_row_height; + end; + + coef^.MCU_ctr := 0; + coef^.MCU_vert_offset := 0; +end; + + +{ Initialize for an input processing pass. } + +{METHODDEF} +procedure start_input_pass (cinfo : j_decompress_ptr); +begin + cinfo^.input_iMCU_row := 0; + start_iMCU_row(cinfo); +end; + + +{ Initialize for an output processing pass. } + +{METHODDEF} +procedure start_output_pass (cinfo : j_decompress_ptr); +var + coef : my_coef_ptr; +begin +{$ifdef BLOCK_SMOOTHING_SUPPORTED} + coef := my_coef_ptr (cinfo^.coef); + + { If multipass, check to see whether to use block smoothing on this pass } + if (coef^.pub.coef_arrays <> NIL) then + begin + if (cinfo^.do_block_smoothing) and smoothing_ok(cinfo) then + coef^.pub.decompress_data := decompress_smooth_data + else + coef^.pub.decompress_data := decompress_data; + end; +{$endif} + cinfo^.output_iMCU_row := 0; +end; + + +{ Decompress and return some data in the single-pass case. + Always attempts to emit one fully interleaved MCU row ("iMCU" row). + Input and output must run in lockstep since we have only a one-MCU buffer. + Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + + NB: output_buf contains a plane for each component in image, + which we index according to the component's SOF position.} + +{METHODDEF} +function decompress_onepass (cinfo : j_decompress_ptr; + output_buf : JSAMPIMAGE) : int; +var + coef : my_coef_ptr; + MCU_col_num : JDIMENSION; { index of current MCU within row } + last_MCU_col : JDIMENSION; + last_iMCU_row : JDIMENSION; + blkn, ci, xindex, yindex, yoffset, useful_width : int; + output_ptr : JSAMPARRAY; + start_col, output_col : JDIMENSION; + compptr : jpeg_component_info_ptr; + inverse_DCT : inverse_DCT_method_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + last_MCU_col := cinfo^.MCUs_per_row - 1; + last_iMCU_row := cinfo^.total_iMCU_rows - 1; + + { Loop to process as much as one whole iMCU row } + for yoffset := coef^.MCU_vert_offset to pred(coef^.MCU_rows_per_iMCU_row) do + begin + for MCU_col_num := coef^.MCU_ctr to last_MCU_col do + begin + { Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. } + jzero_far( coef^.MCU_buffer[0], + size_t (cinfo^.blocks_in_MCU * SIZEOF(JBLOCK))); + if (not cinfo^.entropy^.decode_mcu (cinfo, coef^.MCU_buffer)) then + begin + { Suspension forced; update state counters and exit } + coef^.MCU_vert_offset := yoffset; + coef^.MCU_ctr := MCU_col_num; + decompress_onepass := JPEG_SUSPENDED; + exit; + end; + { Determine where data should go in output_buf and do the IDCT thing. + We skip dummy blocks at the right and bottom edges (but blkn gets + incremented past them!). Note the inner loop relies on having + allocated the MCU_buffer[] blocks sequentially. } + + blkn := 0; { index of current DCT block within MCU } + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + { Don't bother to IDCT an uninteresting component. } + if (not compptr^.component_needed) then + begin + Inc(blkn, compptr^.MCU_blocks); + continue; + end; + inverse_DCT := cinfo^.idct^.inverse_DCT[compptr^.component_index]; + if (MCU_col_num < last_MCU_col) then + useful_width := compptr^.MCU_width + else + useful_width := compptr^.last_col_width; + + output_ptr := JSAMPARRAY(@ output_buf^[compptr^.component_index]^ + [yoffset * compptr^.DCT_scaled_size]); + start_col := LongInt(MCU_col_num) * compptr^.MCU_sample_width; + for yindex := 0 to pred(compptr^.MCU_height) do + begin + if (cinfo^.input_iMCU_row < last_iMCU_row) or + (yoffset+yindex < compptr^.last_row_height) then + begin + output_col := start_col; + for xindex := 0 to pred(useful_width) do + begin + inverse_DCT (cinfo, compptr, + JCOEFPTR(coef^.MCU_buffer[blkn+xindex]), + output_ptr, output_col); + Inc(output_col, compptr^.DCT_scaled_size); + end; + end; + Inc(blkn, compptr^.MCU_width); + Inc(JSAMPROW_PTR(output_ptr), compptr^.DCT_scaled_size); + end; + end; + end; + { Completed an MCU row, but perhaps not an iMCU row } + coef^.MCU_ctr := 0; + end; + { Completed the iMCU row, advance counters for next one } + Inc(cinfo^.output_iMCU_row); + + Inc(cinfo^.input_iMCU_row); + if (cinfo^.input_iMCU_row < cinfo^.total_iMCU_rows) then + begin + start_iMCU_row(cinfo); + decompress_onepass := JPEG_ROW_COMPLETED; + exit; + end; + { Completed the scan } + cinfo^.inputctl^.finish_input_pass (cinfo); + decompress_onepass := JPEG_SCAN_COMPLETED; +end; + +{ Dummy consume-input routine for single-pass operation. } + +{METHODDEF} +function dummy_consume_data (cinfo : j_decompress_ptr) : int; +begin + dummy_consume_data := JPEG_SUSPENDED; { Always indicate nothing was done } +end; + + +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + +{ Consume input data and store it in the full-image coefficient buffer. + We read as much as one fully interleaved MCU row ("iMCU" row) per call, + ie, v_samp_factor block rows for each component in the scan. + Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.} + +{METHODDEF} +function consume_data (cinfo : j_decompress_ptr) : int; +var + coef : my_coef_ptr; + MCU_col_num : JDIMENSION; { index of current MCU within row } + blkn, ci, xindex, yindex, yoffset : int; + start_col : JDIMENSION; + buffer : array[0..MAX_COMPS_IN_SCAN-1] of JBLOCKARRAY; + buffer_ptr : JBLOCKROW; + compptr : jpeg_component_info_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + + { Align the virtual buffers for the components used in this scan. } + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + buffer[ci] := cinfo^.mem^.access_virt_barray + (j_common_ptr (cinfo), coef^.whole_image[compptr^.component_index], + LongInt(cinfo^.input_iMCU_row) * compptr^.v_samp_factor, + JDIMENSION (compptr^.v_samp_factor), TRUE); + { Note: entropy decoder expects buffer to be zeroed, + but this is handled automatically by the memory manager + because we requested a pre-zeroed array. } + + end; + + { Loop to process one whole iMCU row } + for yoffset := coef^.MCU_vert_offset to pred(coef^.MCU_rows_per_iMCU_row) do + begin + for MCU_col_num := coef^.MCU_ctr to pred(cinfo^.MCUs_per_row) do + begin + { Construct list of pointers to DCT blocks belonging to this MCU } + blkn := 0; { index of current DCT block within MCU } + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + start_col := LongInt(MCU_col_num) * compptr^.MCU_width; + for yindex := 0 to pred(compptr^.MCU_height) do + begin + buffer_ptr := JBLOCKROW(@ buffer[ci]^[yindex+yoffset]^[start_col]); + for xindex := 0 to pred(compptr^.MCU_width) do + begin + coef^.MCU_buffer[blkn] := buffer_ptr; + Inc(blkn); + Inc(JBLOCK_PTR(buffer_ptr)); + end; + end; + end; + { Try to fetch the MCU. } + if (not cinfo^.entropy^.decode_mcu (cinfo, coef^.MCU_buffer)) then + begin + { Suspension forced; update state counters and exit } + coef^.MCU_vert_offset := yoffset; + coef^.MCU_ctr := MCU_col_num; + consume_data := JPEG_SUSPENDED; + exit; + end; + end; + { Completed an MCU row, but perhaps not an iMCU row } + coef^.MCU_ctr := 0; + end; + { Completed the iMCU row, advance counters for next one } + Inc(cinfo^.input_iMCU_row); + if (cinfo^.input_iMCU_row < cinfo^.total_iMCU_rows) then + begin + start_iMCU_row(cinfo); + consume_data := JPEG_ROW_COMPLETED; + exit; + end; + { Completed the scan } + cinfo^.inputctl^.finish_input_pass (cinfo); + consume_data := JPEG_SCAN_COMPLETED; +end; + + +{ Decompress and return some data in the multi-pass case. + Always attempts to emit one fully interleaved MCU row ("iMCU" row). + Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED. + + NB: output_buf contains a plane for each component in image. } + +{METHODDEF} +function decompress_data (cinfo : j_decompress_ptr; + output_buf : JSAMPIMAGE) : int; +var + coef : my_coef_ptr; + last_iMCU_row : JDIMENSION; + block_num : JDIMENSION; + ci, block_row, block_rows : int; + buffer : JBLOCKARRAY; + buffer_ptr : JBLOCKROW; + output_ptr : JSAMPARRAY; + output_col : JDIMENSION; + compptr : jpeg_component_info_ptr; + inverse_DCT : inverse_DCT_method_ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + last_iMCU_row := cinfo^.total_iMCU_rows - 1; + + { Force some input to be done if we are getting ahead of the input. } + while (cinfo^.input_scan_number < cinfo^.output_scan_number) or + ((cinfo^.input_scan_number = cinfo^.output_scan_number) and + (LongInt(cinfo^.input_iMCU_row) <= cinfo^.output_iMCU_row)) do + begin + if (cinfo^.inputctl^.consume_input(cinfo) = JPEG_SUSPENDED) then + begin + decompress_data := JPEG_SUSPENDED; + exit; + end; + end; + + { OK, output from the virtual arrays. } + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Don't bother to IDCT an uninteresting component. } + if (not compptr^.component_needed) then + continue; + { Align the virtual buffer for this component. } + buffer := cinfo^.mem^.access_virt_barray + (j_common_ptr (cinfo), coef^.whole_image[ci], + cinfo^.output_iMCU_row * compptr^.v_samp_factor, + JDIMENSION (compptr^.v_samp_factor), FALSE); + { Count non-dummy DCT block rows in this iMCU row. } + if (cinfo^.output_iMCU_row < LongInt(last_iMCU_row)) then + block_rows := compptr^.v_samp_factor + else + begin + { NB: can't use last_row_height here; it is input-side-dependent! } + block_rows := int(LongInt(compptr^.height_in_blocks) mod compptr^.v_samp_factor); + if (block_rows = 0) then + block_rows := compptr^.v_samp_factor; + end; + inverse_DCT := cinfo^.idct^.inverse_DCT[ci]; + output_ptr := output_buf^[ci]; + { Loop over all DCT blocks to be processed. } + for block_row := 0 to pred(block_rows) do + begin + buffer_ptr := buffer^[block_row]; + output_col := 0; + for block_num := 0 to pred(compptr^.width_in_blocks) do + begin + inverse_DCT (cinfo, compptr, JCOEFPTR (buffer_ptr), + output_ptr, output_col); + Inc(JBLOCK_PTR(buffer_ptr)); + Inc(output_col, compptr^.DCT_scaled_size); + end; + Inc(JSAMPROW_PTR(output_ptr), compptr^.DCT_scaled_size); + end; + Inc(compptr); + end; + + Inc(cinfo^.output_iMCU_row); + if (cinfo^.output_iMCU_row < LongInt(cinfo^.total_iMCU_rows)) then + begin + decompress_data := JPEG_ROW_COMPLETED; + exit; + end; + decompress_data := JPEG_SCAN_COMPLETED; +end; + +{$endif} { D_MULTISCAN_FILES_SUPPORTED } + + +{$ifdef BLOCK_SMOOTHING_SUPPORTED} + +{ This code applies interblock smoothing as described by section K.8 + of the JPEG standard: the first 5 AC coefficients are estimated from + the DC values of a DCT block and its 8 neighboring blocks. + We apply smoothing only for progressive JPEG decoding, and only if + the coefficients it can estimate are not yet known to full precision. } + +{ Natural-order array positions of the first 5 zigzag-order coefficients } +const + Q01_POS = 1; + Q10_POS = 8; + Q20_POS = 16; + Q11_POS = 9; + Q02_POS = 2; + +{ Determine whether block smoothing is applicable and safe. + We also latch the current states of the coef_bits[] entries for the + AC coefficients; otherwise, if the input side of the decompressor + advances into a new scan, we might think the coefficients are known + more accurately than they really are. } + +{LOCAL} +function smoothing_ok (cinfo : j_decompress_ptr) : boolean; +var + coef : my_coef_ptr; + smoothing_useful : boolean; + ci, coefi : int; + compptr : jpeg_component_info_ptr; + qtable : JQUANT_TBL_PTR; + coef_bits : coef_bits_ptr; + coef_bits_latch : Latch_Ptr; +begin + coef := my_coef_ptr (cinfo^.coef); + smoothing_useful := FALSE; + + if (not cinfo^.progressive_mode) or (cinfo^.coef_bits = NIL) then + begin + smoothing_ok := FALSE; + exit; + end; + + { Allocate latch area if not already done } + if (coef^.coef_bits_latch = NIL) then + coef^.coef_bits_latch := Latch_Ptr( + cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE, + cinfo^.num_components * + (SAVED_COEFS * SIZEOF(int))) ); + coef_bits_latch := (coef^.coef_bits_latch); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { All components' quantization values must already be latched. } + qtable := compptr^.quant_table; + if (qtable = NIL) then + begin + smoothing_ok := FALSE; + exit; + end; + { Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. } + if (qtable^.quantval[0] = 0) or + (qtable^.quantval[Q01_POS] = 0) or + (qtable^.quantval[Q10_POS] = 0) or + (qtable^.quantval[Q20_POS] = 0) or + (qtable^.quantval[Q11_POS] = 0) or + (qtable^.quantval[Q02_POS] = 0) then + begin + smoothing_ok := FALSE; + exit; + end; + { DC values must be at least partly known for all components. } + coef_bits := @cinfo^.coef_bits^[ci]; { Nomssi } + if (coef_bits^[0] < 0) then + begin + smoothing_ok := FALSE; + exit; + end; + { Block smoothing is helpful if some AC coefficients remain inaccurate. } + for coefi := 1 to 5 do + begin + coef_bits_latch^[coefi] := coef_bits^[coefi]; + if (coef_bits^[coefi] <> 0) then + smoothing_useful := TRUE; + end; + Inc(coef_bits_latch {SAVED_COEFS}); + Inc(compptr); + end; + + smoothing_ok := smoothing_useful; +end; + + +{ Variant of decompress_data for use when doing block smoothing. } + +{METHODDEF} +function decompress_smooth_data (cinfo : j_decompress_ptr; + output_buf : JSAMPIMAGE) : int; +var + coef : my_coef_ptr; + last_iMCU_row : JDIMENSION; + block_num, last_block_column : JDIMENSION; + ci, block_row, block_rows, access_rows : int; + buffer : JBLOCKARRAY; + buffer_ptr, prev_block_row, next_block_row : JBLOCKROW; + output_ptr : JSAMPARRAY; + output_col : JDIMENSION; + compptr : jpeg_component_info_ptr; + inverse_DCT : inverse_DCT_method_ptr; + first_row, last_row : boolean; + workspace : JBLOCK; + coef_bits : Latch_Ptr; { coef_bits_ptr; } + quanttbl : JQUANT_TBL_PTR; + Q00,Q01,Q02,Q10,Q11,Q20, num : INT32; + DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9 : int; + Al, pred : int; +var + delta : JDIMENSION; +begin + coef := my_coef_ptr (cinfo^.coef); + last_iMCU_row := cinfo^.total_iMCU_rows - 1; + + { Force some input to be done if we are getting ahead of the input. } + while (cinfo^.input_scan_number <= cinfo^.output_scan_number) and + (not cinfo^.inputctl^.eoi_reached) do + begin + if (cinfo^.input_scan_number = cinfo^.output_scan_number) then + begin + { If input is working on current scan, we ordinarily want it to + have completed the current row. But if input scan is DC, + we want it to keep one row ahead so that next block row's DC + values are up to date. } + + if (cinfo^.Ss = 0) then + delta := 1 + else + delta := 0; + if (LongInt(cinfo^.input_iMCU_row) > cinfo^.output_iMCU_row+LongInt(delta)) then + break; + end; + if (cinfo^.inputctl^.consume_input(cinfo) = JPEG_SUSPENDED) then + begin + decompress_smooth_data := JPEG_SUSPENDED; + exit; + end; + end; + + { OK, output from the virtual arrays. } + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to (cinfo^.num_components-1) do + begin + { Don't bother to IDCT an uninteresting component. } + if (not compptr^.component_needed) then + continue; + { Count non-dummy DCT block rows in this iMCU row. } + if (cinfo^.output_iMCU_row < LongInt(last_iMCU_row)) then + begin + block_rows := compptr^.v_samp_factor; + access_rows := block_rows * 2; { this and next iMCU row } + last_row := FALSE; + end + else + begin + { NB: can't use last_row_height here; it is input-side-dependent! } + block_rows := int (compptr^.height_in_blocks) mod compptr^.v_samp_factor; + if (block_rows = 0) then + block_rows := compptr^.v_samp_factor; + access_rows := block_rows; { this iMCU row only } + last_row := TRUE; + end; + { Align the virtual buffer for this component. } + if (cinfo^.output_iMCU_row > 0) then + begin + Inc(access_rows, compptr^.v_samp_factor); { prior iMCU row too } + buffer := cinfo^.mem^.access_virt_barray + (j_common_ptr (cinfo), coef^.whole_image[ci], + (cinfo^.output_iMCU_row - 1) * compptr^.v_samp_factor, + JDIMENSION (access_rows), FALSE); + Inc(JBLOCKROW_PTR(buffer), compptr^.v_samp_factor); { point to current iMCU row } + first_row := FALSE; + end + else + begin + buffer := cinfo^.mem^.access_virt_barray + (j_common_ptr (cinfo), coef^.whole_image[ci], + JDIMENSION (0), JDIMENSION (access_rows), FALSE); + first_row := TRUE; + end; + { Fetch component-dependent info } + coef_bits := coef^.coef_bits_latch; + Inc(coef_bits, ci); { ci * SAVED_COEFS} + quanttbl := compptr^.quant_table; + Q00 := quanttbl^.quantval[0]; + Q01 := quanttbl^.quantval[Q01_POS]; + Q10 := quanttbl^.quantval[Q10_POS]; + Q20 := quanttbl^.quantval[Q20_POS]; + Q11 := quanttbl^.quantval[Q11_POS]; + Q02 := quanttbl^.quantval[Q02_POS]; + inverse_DCT := cinfo^.idct^.inverse_DCT[ci]; + output_ptr := output_buf^[ci]; + { Loop over all DCT blocks to be processed. } + for block_row := 0 to (block_rows-1) do + begin + buffer_ptr := buffer^[block_row]; + if (first_row) and (block_row = 0) then + prev_block_row := buffer_ptr + else + prev_block_row := buffer^[block_row-1]; + if (last_row) and (block_row = block_rows-1) then + next_block_row := buffer_ptr + else + next_block_row := buffer^[block_row+1]; + { We fetch the surrounding DC values using a sliding-register approach. + Initialize all nine here so as to do the right thing on narrow pics.} + + DC3 := int(prev_block_row^[0][0]); + DC2 := DC3; + DC1 := DC2; + DC6 := int(buffer_ptr^[0][0]); + DC5 := DC6; + DC4 := DC5; + DC9 := int(next_block_row^[0][0]); + DC8 := DC9; + DC7 := DC8 ; + output_col := 0; + last_block_column := compptr^.width_in_blocks - 1; + for block_num := 0 to last_block_column do + begin + { Fetch current DCT block into workspace so we can modify it. } + jcopy_block_row(buffer_ptr, JBLOCKROW (@workspace), JDIMENSION(1)); + { Update DC values } + if (block_num < last_block_column) then + begin + DC3 := int (prev_block_row^[1][0]); + DC6 := int (buffer_ptr^[1][0]); + DC9 := int (next_block_row^[1][0]); + end; + { Compute coefficient estimates per K.8. + An estimate is applied only if coefficient is still zero, + and is not known to be fully accurate. } + + { AC01 } + Al := coef_bits^[1]; + if (Al <> 0) and (workspace[1] = 0) then + begin + num := 36 * Q00 * (DC4 - DC6); + if (num >= 0) then + begin + pred := int (((Q01 shl 7) + num) div (Q01 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + end + else + begin + pred := int (((Q01 shl 7) - num) div (Q01 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + pred := -pred; + end; + workspace[1] := JCOEF (pred); + end; + { AC10 } + Al := coef_bits^[2]; + if (Al <> 0) and (workspace[8] = 0) then + begin + num := 36 * Q00 * (DC2 - DC8); + if (num >= 0) then + begin + pred := int (((Q10 shl 7) + num) div (Q10 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + end + else + begin + pred := int (((Q10 shl 7) - num) div (Q10 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + pred := -pred; + end; + workspace[8] := JCOEF (pred); + end; + { AC20 } + Al := coef_bits^[3]; + if (Al <> 0) and (workspace[16] = 0) then + begin + num := 9 * Q00 * (DC2 + DC8 - 2*DC5); + if (num >= 0) then + begin + pred := int (((Q20 shl 7) + num) div (Q20 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + end + else + begin + pred := int (((Q20 shl 7) - num) div (Q20 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + pred := -pred; + end; + workspace[16] := JCOEF (pred); + end; + { AC11 } + Al := coef_bits^[4]; + if (Al <> 0) and (workspace[9] = 0) then + begin + num := 5 * Q00 * (DC1 - DC3 - DC7 + DC9); + if (num >= 0) then + begin + pred := int (((Q11 shl 7) + num) div (Q11 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + end + else + begin + pred := int (((Q11 shl 7) - num) div (Q11 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + pred := -pred; + end; + workspace[9] := JCOEF (pred); + end; + { AC02 } + Al := coef_bits^[5]; + if (Al <> 0) and (workspace[2] = 0) then + begin + num := 9 * Q00 * (DC4 + DC6 - 2*DC5); + if (num >= 0) then + begin + pred := int (((Q02 shl 7) + num) div (Q02 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + end + else + begin + pred := int (((Q02 shl 7) - num) div (Q02 shl 8)); + if (Al > 0) and (pred >= (1 shl Al)) then + pred := (1 shl Al)-1; + pred := -pred; + end; + workspace[2] := JCOEF (pred); + end; + { OK, do the IDCT } + inverse_DCT (cinfo, compptr, JCOEFPTR (@workspace), + output_ptr, output_col); + { Advance for next column } + DC1 := DC2; DC2 := DC3; + DC4 := DC5; DC5 := DC6; + DC7 := DC8; DC8 := DC9; + Inc(JBLOCK_PTR(buffer_ptr)); + Inc(JBLOCK_PTR(prev_block_row)); + Inc(JBLOCK_PTR(next_block_row)); + Inc(output_col, compptr^.DCT_scaled_size); + end; + Inc(JSAMPROW_PTR(output_ptr), compptr^.DCT_scaled_size); + end; + Inc(compptr); + end; + + Inc(cinfo^.output_iMCU_row); + if (cinfo^.output_iMCU_row < LongInt(cinfo^.total_iMCU_rows)) then + begin + decompress_smooth_data := JPEG_ROW_COMPLETED; + exit; + end; + decompress_smooth_data := JPEG_SCAN_COMPLETED; +end; + +{$endif} { BLOCK_SMOOTHING_SUPPORTED } + + +{ Initialize coefficient buffer controller. } + +{GLOBAL} +procedure jinit_d_coef_controller (cinfo : j_decompress_ptr; + need_full_buffer : boolean); +var + coef : my_coef_ptr; +{$ifdef D_MULTISCAN_FILES_SUPPORTED} +var + ci, access_rows : int; + compptr : jpeg_component_info_ptr; +{$endif} +var + buffer : JBLOCK_PTR; + i : int; +begin + coef := my_coef_ptr( + cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE, + SIZEOF(my_coef_controller)) ); + cinfo^.coef := jpeg_d_coef_controller_ptr(coef); + coef^.pub.start_input_pass := start_input_pass; + coef^.pub.start_output_pass := start_output_pass; +{$ifdef BLOCK_SMOOTHING_SUPPORTED} + coef^.coef_bits_latch := NIL; +{$endif} + + { Create the coefficient buffer. } + if (need_full_buffer) then + begin +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + { Allocate a full-image virtual array for each component, } + { padded to a multiple of samp_factor DCT blocks in each direction. } + { Note we ask for a pre-zeroed array. } + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + access_rows := compptr^.v_samp_factor; +{$ifdef BLOCK_SMOOTHING_SUPPORTED} + { If block smoothing could be used, need a bigger window } + if (cinfo^.progressive_mode) then + access_rows := access_rows * 3; +{$endif} + coef^.whole_image[ci] := cinfo^.mem^.request_virt_barray + (j_common_ptr (cinfo), JPOOL_IMAGE, TRUE, + JDIMENSION (jround_up( long(compptr^.width_in_blocks), + long(compptr^.h_samp_factor) )), + JDIMENSION (jround_up( long(compptr^.height_in_blocks), + long(compptr^.v_samp_factor) )), + JDIMENSION (access_rows)); + Inc(compptr); + end; + coef^.pub.consume_data := consume_data; + coef^.pub.decompress_data := decompress_data; + coef^.pub.coef_arrays := @(coef^.whole_image); + { link to virtual arrays } +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + begin + { We only need a single-MCU buffer. } + buffer := JBLOCK_PTR ( + cinfo^.mem^.alloc_large (j_common_ptr (cinfo), JPOOL_IMAGE, + D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)) ); + for i := 0 to pred(D_MAX_BLOCKS_IN_MCU) do + begin + coef^.MCU_buffer[i] := JBLOCKROW(buffer); + Inc(buffer); + end; + coef^.pub.consume_data := dummy_consume_data; + coef^.pub.decompress_data := decompress_onepass; + coef^.pub.coef_arrays := NIL; { flag for no virtual arrays } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdcolor.pas b/src/lib/vampimg/JpegLib/imjdcolor.pas new file mode 100644 index 0000000..f27fa5c --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdcolor.pas @@ -0,0 +1,501 @@ +unit imjdcolor; + +{ This file contains output colorspace conversion routines. } + +{ Original: jdcolor.c ; Copyright (C) 1991-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjutils, + imjdeferr, + imjerror, + imjpeglib; + +{ Module initialization routine for output colorspace conversion. } + +{GLOBAL} +procedure jinit_color_deconverter (cinfo : j_decompress_ptr); + +implementation + +{ Private subobject } +type + int_Color_Table = array[0..MAXJSAMPLE+1-1] of int; + int_table_ptr = ^int_Color_Table; + INT32_Color_Table = array[0..MAXJSAMPLE+1-1] of INT32; + INT32_table_ptr = ^INT32_Color_Table; +type + my_cconvert_ptr = ^my_color_deconverter; + my_color_deconverter = record + pub : jpeg_color_deconverter; { public fields } + + { Private state for YCC^.RGB conversion } + Cr_r_tab : int_table_ptr; { => table for Cr to R conversion } + Cb_b_tab : int_table_ptr; { => table for Cb to B conversion } + Cr_g_tab : INT32_table_ptr; { => table for Cr to G conversion } + Cb_g_tab : INT32_table_ptr; { => table for Cb to G conversion } + end; + + + + +{*************** YCbCr ^. RGB conversion: most common case *************} + +{ YCbCr is defined per CCIR 601-1, except that Cb and Cr are + normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + The conversion equations to be implemented are therefore + R = Y + 1.40200 * Cr + G = Y - 0.34414 * Cb - 0.71414 * Cr + B = Y + 1.77200 * Cb + where Cb and Cr represent the incoming values less CENTERJSAMPLE. + (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) + + To avoid floating-point arithmetic, we represent the fractional constants + as integers scaled up by 2^16 (about 4 digits precision); we have to divide + the products by 2^16, with appropriate rounding, to get the correct answer. + Notice that Y, being an integral input, does not contribute any fraction + so it need not participate in the rounding. + + For even more speed, we avoid doing any multiplications in the inner loop + by precalculating the constants times Cb and Cr for all possible values. + For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); + for 12-bit samples it is still acceptable. It's not very reasonable for + 16-bit samples, but if you want lossless storage you shouldn't be changing + colorspace anyway. + The Cr=>R and Cb=>B values can be rounded to integers in advance; the + values for the G calculation are left scaled up, since we must add them + together before rounding. } + +const + SCALEBITS = 16; { speediest right-shift on some machines } + ONE_HALF = (INT32(1) shl (SCALEBITS-1)); + + +{ Initialize tables for YCC->RGB colorspace conversion. } + +{LOCAL} +procedure build_ycc_rgb_table (cinfo : j_decompress_ptr); +const + FIX_1_40200 = INT32(Round( 1.40200 * (1 shl SCALEBITS))); + FIX_1_77200 = INT32(Round( 1.77200 * (1 shl SCALEBITS))); + FIX_0_71414 = INT32(Round( 0.71414 * (1 shl SCALEBITS))); + FIX_0_34414 = INT32(Round( 0.34414 * (1 shl SCALEBITS))); + +var + cconvert : my_cconvert_ptr; + i : int; + x : INT32; +var + shift_temp : INT32; +begin + cconvert := my_cconvert_ptr (cinfo^.cconvert); + + + cconvert^.Cr_r_tab := int_table_ptr( + cinfo^.mem^.alloc_small ( j_common_ptr(cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)) ); + cconvert^.Cb_b_tab := int_table_ptr ( + cinfo^.mem^.alloc_small ( j_common_ptr(cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)) ); + cconvert^.Cr_g_tab := INT32_table_ptr ( + cinfo^.mem^.alloc_small ( j_common_ptr(cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)) ); + cconvert^.Cb_g_tab := INT32_table_ptr ( + cinfo^.mem^.alloc_small ( j_common_ptr(cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)) ); + + + x := -CENTERJSAMPLE; + for i := 0 to MAXJSAMPLE do + begin + { i is the actual input pixel value, in the range 0..MAXJSAMPLE } + { The Cb or Cr value we are thinking of is x := i - CENTERJSAMPLE } + { Cr=>R value is nearest int to 1.40200 * x } + + shift_temp := FIX_1_40200 * x + ONE_HALF; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + cconvert^.Cr_r_tab^[i] := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + cconvert^.Cr_r_tab^[i] := int(shift_temp shr SCALEBITS); + + { Cb=>B value is nearest int to 1.77200 * x } + shift_temp := FIX_1_77200 * x + ONE_HALF; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + cconvert^.Cb_b_tab^[i] := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + cconvert^.Cb_b_tab^[i] := int(shift_temp shr SCALEBITS); + + { Cr=>G value is scaled-up -0.71414 * x } + cconvert^.Cr_g_tab^[i] := (- FIX_0_71414 ) * x; + { Cb=>G value is scaled-up -0.34414 * x } + { We also add in ONE_HALF so that need not do it in inner loop } + cconvert^.Cb_g_tab^[i] := (- FIX_0_34414 ) * x + ONE_HALF; + Inc(x); + end; +end; + + +{ Convert some rows of samples to the output colorspace. + + Note that we change from noninterleaved, one-plane-per-component format + to interleaved-pixel format. The output buffer is therefore three times + as wide as the input buffer. + A starting row offset is provided only for the input buffer. The caller + can easily adjust the passed output_buf value to accommodate any row + offset required on that side. } + +{METHODDEF} +procedure ycc_rgb_convert (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + input_row : JDIMENSION; + output_buf : JSAMPARRAY; + num_rows : int); +var + cconvert : my_cconvert_ptr; + {register} y, cb, cr : int; + {register} outptr : JSAMPROW; + {register} inptr0, inptr1, inptr2 : JSAMPROW; + {register} col : JDIMENSION; + num_cols : JDIMENSION; + { copy these pointers into registers if possible } + {register} range_limit : range_limit_table_ptr; + {register} Crrtab : int_table_ptr; + {register} Cbbtab : int_table_ptr; + {register} Crgtab : INT32_table_ptr; + {register} Cbgtab : INT32_table_ptr; +var + shift_temp : INT32; +begin + cconvert := my_cconvert_ptr (cinfo^.cconvert); + num_cols := cinfo^.output_width; + range_limit := cinfo^.sample_range_limit; + Crrtab := cconvert^.Cr_r_tab; + Cbbtab := cconvert^.Cb_b_tab; + Crgtab := cconvert^.Cr_g_tab; + Cbgtab := cconvert^.Cb_g_tab; + + while (num_rows > 0) do + begin + Dec(num_rows); + inptr0 := input_buf^[0]^[input_row]; + inptr1 := input_buf^[1]^[input_row]; + inptr2 := input_buf^[2]^[input_row]; + Inc(input_row); + outptr := output_buf^[0]; + Inc(JSAMPROW_PTR(output_buf)); + for col := 0 to pred(num_cols) do + begin + y := GETJSAMPLE(inptr0^[col]); + cb := GETJSAMPLE(inptr1^[col]); + cr := GETJSAMPLE(inptr2^[col]); + { Range-limiting is essential due to noise introduced by DCT losses. } + outptr^[RGB_RED] := range_limit^[y + Crrtab^[cr]]; + shift_temp := Cbgtab^[cb] + Crgtab^[cr]; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + outptr^[RGB_GREEN] := range_limit^[y + int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS)))] + else + outptr^[RGB_GREEN] := range_limit^[y + int(shift_temp shr SCALEBITS)]; + + outptr^[RGB_BLUE] := range_limit^[y + Cbbtab^[cb]]; + Inc(JSAMPLE_PTR(outptr), RGB_PIXELSIZE); + end; + end; +end; + + +{*************** Cases other than YCbCr -> RGB *************} + + +{ Color conversion for no colorspace change: just copy the data, + converting from separate-planes to interleaved representation. } + +{METHODDEF} +procedure null_convert (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + input_row : JDIMENSION; + output_buf : JSAMPARRAY; + num_rows : int); +var + {register} inptr, + outptr : JSAMPLE_PTR; + {register} count : JDIMENSION; + {register} num_components : int; + num_cols : JDIMENSION; + ci : int; +begin + num_components := cinfo^.num_components; + num_cols := cinfo^.output_width; + + while (num_rows > 0) do + begin + Dec(num_rows); + for ci := 0 to pred(num_components) do + begin + inptr := JSAMPLE_PTR(input_buf^[ci]^[input_row]); + outptr := JSAMPLE_PTR(@(output_buf^[0]^[ci])); + + for count := pred(num_cols) downto 0 do + begin + outptr^ := inptr^; { needn't bother with GETJSAMPLE() here } + Inc(inptr); + Inc(outptr, num_components); + end; + end; + Inc(input_row); + Inc(JSAMPROW_PTR(output_buf)); + end; +end; + + +{ Color conversion for grayscale: just copy the data. + This also works for YCbCr -> grayscale conversion, in which + we just copy the Y (luminance) component and ignore chrominance. } + +{METHODDEF} +procedure grayscale_convert (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + input_row : JDIMENSION; + output_buf : JSAMPARRAY; + num_rows : int); +begin + jcopy_sample_rows(input_buf^[0], int(input_row), output_buf, 0, + num_rows, cinfo^.output_width); +end; + +{ Convert grayscale to RGB: just duplicate the graylevel three times. + This is provided to support applications that don't want to cope + with grayscale as a separate case. } + +{METHODDEF} +procedure gray_rgb_convert (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + input_row : JDIMENSION; + output_buf : JSAMPARRAY; + num_rows : int); +var + {register} inptr, outptr : JSAMPLE_PTR; + {register} col : JDIMENSION; + num_cols : JDIMENSION; +begin + num_cols := cinfo^.output_width; + while (num_rows > 0) do + begin + inptr := JSAMPLE_PTR(input_buf^[0]^[input_row]); + Inc(input_row); + outptr := JSAMPLE_PTR(@output_buf^[0]); + Inc(JSAMPROW_PTR(output_buf)); + for col := 0 to pred(num_cols) do + begin + { We can dispense with GETJSAMPLE() here } + JSAMPROW(outptr)^[RGB_RED] := inptr^; + JSAMPROW(outptr)^[RGB_GREEN] := inptr^; + JSAMPROW(outptr)^[RGB_BLUE] := inptr^; + Inc(inptr); + Inc(outptr, RGB_PIXELSIZE); + end; + Dec(num_rows); + end; +end; + + +{ Adobe-style YCCK -> CMYK conversion. + We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same + conversion as above, while passing K (black) unchanged. + We assume build_ycc_rgb_table has been called. } + +{METHODDEF} +procedure ycck_cmyk_convert (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + input_row : JDIMENSION; + output_buf : JSAMPARRAY; + num_rows : int); +var + cconvert : my_cconvert_ptr; + {register} y, cb, cr : int; + {register} outptr : JSAMPROW; + {register} inptr0, inptr1, inptr2, inptr3 : JSAMPROW; + {register} col : JDIMENSION; + num_cols : JDIMENSION; + { copy these pointers into registers if possible } + {register} range_limit : range_limit_table_ptr; + {register} Crrtab : int_table_ptr; + {register} Cbbtab : int_table_ptr; + {register} Crgtab : INT32_table_ptr; + {register} Cbgtab : INT32_table_ptr; +var + shift_temp : INT32; +begin + cconvert := my_cconvert_ptr (cinfo^.cconvert); + num_cols := cinfo^.output_width; + { copy these pointers into registers if possible } + range_limit := cinfo^.sample_range_limit; + Crrtab := cconvert^.Cr_r_tab; + Cbbtab := cconvert^.Cb_b_tab; + Crgtab := cconvert^.Cr_g_tab; + Cbgtab := cconvert^.Cb_g_tab; + + while (num_rows > 0) do + begin + Dec(num_rows); + inptr0 := input_buf^[0]^[input_row]; + inptr1 := input_buf^[1]^[input_row]; + inptr2 := input_buf^[2]^[input_row]; + inptr3 := input_buf^[3]^[input_row]; + Inc(input_row); + outptr := output_buf^[0]; + Inc(JSAMPROW_PTR(output_buf)); + for col := 0 to pred(num_cols) do + begin + y := GETJSAMPLE(inptr0^[col]); + cb := GETJSAMPLE(inptr1^[col]); + cr := GETJSAMPLE(inptr2^[col]); + { Range-limiting is essential due to noise introduced by DCT losses. } + outptr^[0] := range_limit^[MAXJSAMPLE - (y + Crrtab^[cr])]; { red } + shift_temp := Cbgtab^[cb] + Crgtab^[cr]; + if shift_temp < 0 then + outptr^[1] := range_limit^[MAXJSAMPLE - (y + int( + (shift_temp shr SCALEBITS) or ((not INT32(0)) shl (32-SCALEBITS)) + ) )] + else + outptr^[1] := range_limit^[MAXJSAMPLE - { green } + (y + int(shift_temp shr SCALEBITS) )]; + outptr^[2] := range_limit^[MAXJSAMPLE - (y + Cbbtab^[cb])]; { blue } + { K passes through unchanged } + outptr^[3] := inptr3^[col]; { don't need GETJSAMPLE here } + Inc(JSAMPLE_PTR(outptr), 4); + end; + end; +end; + + +{ Empty method for start_pass. } + +{METHODDEF} +procedure start_pass_dcolor (cinfo : j_decompress_ptr); +begin + { no work needed } +end; + + +{ Module initialization routine for output colorspace conversion. } + +{GLOBAL} +procedure jinit_color_deconverter (cinfo : j_decompress_ptr); +var + cconvert : my_cconvert_ptr; + ci : int; +begin + cconvert := my_cconvert_ptr ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_color_deconverter)) ); + cinfo^.cconvert := jpeg_color_deconverter_ptr (cconvert); + cconvert^.pub.start_pass := start_pass_dcolor; + + { Make sure num_components agrees with jpeg_color_space } + case (cinfo^.jpeg_color_space) of + JCS_GRAYSCALE: + if (cinfo^.num_components <> 1) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + + JCS_RGB, + JCS_YCbCr: + if (cinfo^.num_components <> 3) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + + JCS_CMYK, + JCS_YCCK: + if (cinfo^.num_components <> 4) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + + else { JCS_UNKNOWN can be anything } + if (cinfo^.num_components < 1) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_J_COLORSPACE); + end; + + { Set out_color_components and conversion method based on requested space. + Also clear the component_needed flags for any unused components, + so that earlier pipeline stages can avoid useless computation. } + + case (cinfo^.out_color_space) of + JCS_GRAYSCALE: + begin + cinfo^.out_color_components := 1; + if (cinfo^.jpeg_color_space = JCS_GRAYSCALE) + or (cinfo^.jpeg_color_space = JCS_YCbCr) then + begin + cconvert^.pub.color_convert := grayscale_convert; + { For color -> grayscale conversion, only the + Y (0) component is needed } + for ci := 1 to pred(cinfo^.num_components) do + cinfo^.comp_info^[ci].component_needed := FALSE; + end + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + JCS_RGB: + begin + cinfo^.out_color_components := RGB_PIXELSIZE; + if (cinfo^.jpeg_color_space = JCS_YCbCr) then + begin + cconvert^.pub.color_convert := ycc_rgb_convert; + build_ycc_rgb_table(cinfo); + end + else + if (cinfo^.jpeg_color_space = JCS_GRAYSCALE) then + begin + cconvert^.pub.color_convert := gray_rgb_convert; + end + else + if (cinfo^.jpeg_color_space = JCS_RGB) and (RGB_PIXELSIZE = 3) then + begin + cconvert^.pub.color_convert := null_convert; + end + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + JCS_CMYK: + begin + cinfo^.out_color_components := 4; + if (cinfo^.jpeg_color_space = JCS_YCCK) then + begin + cconvert^.pub.color_convert := ycck_cmyk_convert; + build_ycc_rgb_table(cinfo); + end + else + if (cinfo^.jpeg_color_space = JCS_CMYK) then + begin + cconvert^.pub.color_convert := null_convert; + end + else + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + + else + begin { Permit null conversion to same output space } + if (cinfo^.out_color_space = cinfo^.jpeg_color_space) then + begin + cinfo^.out_color_components := cinfo^.num_components; + cconvert^.pub.color_convert := null_convert; + end + else { unsupported non-null conversion } + ERREXIT(j_common_ptr(cinfo), JERR_CONVERSION_NOTIMPL); + end; + end; + + if (cinfo^.quantize_colors) then + cinfo^.output_components := 1 { single colormapped output component } + else + cinfo^.output_components := cinfo^.out_color_components; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdct.pas b/src/lib/vampimg/JpegLib/imjdct.pas new file mode 100644 index 0000000..30d3356 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdct.pas @@ -0,0 +1,109 @@ +unit imjdct; + +{ Orignal: jdct.h; Copyright (C) 1994-1996, Thomas G. Lane. } + +{ This include file contains common declarations for the forward and + inverse DCT modules. These declarations are private to the DCT managers + (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. + The individual DCT algorithms are kept in separate files to ease + machine-dependent tuning (e.g., assembly coding). } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg; + + +{ A forward DCT routine is given a pointer to a work area of type DCTELEM[]; + the DCT is to be performed in-place in that buffer. Type DCTELEM is int + for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT + implementations use an array of type FAST_FLOAT, instead.) + The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). + The DCT outputs are returned scaled up by a factor of 8; they therefore + have a range of +-8K for 8-bit data, +-128K for 12-bit data. This + convention improves accuracy in integer implementations and saves some + work in floating-point ones. + Quantization of the output coefficients is done by jcdctmgr.c. } + + +{$ifdef BITS_IN_JSAMPLE_IS_8} +type + DCTELEM = int; { 16 or 32 bits is fine } +{$else} +type { must have 32 bits } + DCTELEM = INT32; +{$endif} +type + jTDctElem = 0..(MaxInt div SizeOf(DCTELEM))-1; + DCTELEM_FIELD = array[jTDctElem] of DCTELEM; + DCTELEM_FIELD_PTR = ^DCTELEM_FIELD; + DCTELEMPTR = ^DCTELEM; + +type + forward_DCT_method_ptr = procedure(var data : array of DCTELEM); + float_DCT_method_ptr = procedure(var data : array of FAST_FLOAT); + + +{ An inverse DCT routine is given a pointer to the input JBLOCK and a pointer + to an output sample array. The routine must dequantize the input data as + well as perform the IDCT; for dequantization, it uses the multiplier table + pointed to by compptr->dct_table. The output data is to be placed into the + sample array starting at a specified column. (Any row offset needed will + be applied to the array pointer before it is passed to the IDCT code.) + Note that the number of samples emitted by the IDCT routine is + DCT_scaled_size * DCT_scaled_size. } + + +{ typedef inverse_DCT_method_ptr is declared in jpegint.h } + + +{ Each IDCT routine has its own ideas about the best dct_table element type. } + + +type + ISLOW_MULT_TYPE = MULTIPLIER; { short or int, whichever is faster } + +{$ifdef BITS_IN_JSAMPLE_IS_8} +type + IFAST_MULT_TYPE = MULTIPLIER; { 16 bits is OK, use short if faster } +const + IFAST_SCALE_BITS = 2; { fractional bits in scale factors } +{$else} +type + IFAST_MULT_TYPE = INT32; { need 32 bits for scaled quantizers } +const + IFAST_SCALE_BITS = 13; { fractional bits in scale factors } +{$endif} +type + FLOAT_MULT_TYPE = FAST_FLOAT; { preferred floating type } + +const + RANGE_MASK = (MAXJSAMPLE * 4 + 3); { 2 bits wider than legal samples } + +type + jTMultType = 0..(MaxInt div SizeOf(ISLOW_MULT_TYPE))-1; + ISLOW_MULT_TYPE_FIELD = array[jTMultType] of ISLOW_MULT_TYPE; + ISLOW_MULT_TYPE_FIELD_PTR = ^ISLOW_MULT_TYPE_FIELD; + ISLOW_MULT_TYPE_PTR = ^ISLOW_MULT_TYPE; + + jTFloatType = 0..(MaxInt div SizeOf(FLOAT_MULT_TYPE))-1; + FLOAT_MULT_TYPE_FIELD = array[jTFloatType] of FLOAT_MULT_TYPE; + FLOAT_MULT_TYPE_FIELD_PTR = ^FLOAT_MULT_TYPE_FIELD; + FLOAT_MULT_TYPE_PTR = ^FLOAT_MULT_TYPE; + + jTFastType = 0..(MaxInt div SizeOf(IFAST_MULT_TYPE))-1; + IFAST_MULT_TYPE_FIELD = array[jTFastType] of IFAST_MULT_TYPE; + IFAST_MULT_TYPE_FIELD_PTR = ^IFAST_MULT_TYPE_FIELD; + IFAST_MULT_TYPE_PTR = ^IFAST_MULT_TYPE; + +type + jTFastFloat = 0..(MaxInt div SizeOf(FAST_FLOAT))-1; + FAST_FLOAT_FIELD = array[jTFastFloat] of FAST_FLOAT; + FAST_FLOAT_FIELD_PTR = ^FAST_FLOAT_FIELD; + FAST_FLOAT_PTR = ^FAST_FLOAT; + +implementation + +end. diff --git a/src/lib/vampimg/JpegLib/imjddctmgr.pas b/src/lib/vampimg/JpegLib/imjddctmgr.pas new file mode 100644 index 0000000..42ae295 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjddctmgr.pas @@ -0,0 +1,330 @@ +unit imjddctmgr; + +{ Original : jddctmgr.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +{ This file contains the inverse-DCT management logic. + This code selects a particular IDCT implementation to be used, + and it performs related housekeeping chores. No code in this file + is executed per IDCT step, only during output pass setup. + + Note that the IDCT routines are responsible for performing coefficient + dequantization as well as the IDCT proper. This module sets up the + dequantization multiplier table needed by the IDCT routine. } + +interface + +{$I imjconfig.inc} + +{$N+} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib, + imjdct, { Private declarations for DCT subsystem } + imjidctfst, + {$IFDEF BASM} + imjidctasm, + {$ELSE} + imjidctint, + {$ENDIF} + imjidctflt, + imjidctred; + + + +{ Initialize IDCT manager. } + +{GLOBAL} +procedure jinit_inverse_dct (cinfo : j_decompress_ptr); + + +implementation + +{ The decompressor input side (jdinput.c) saves away the appropriate + quantization table for each component at the start of the first scan + involving that component. (This is necessary in order to correctly + decode files that reuse Q-table slots.) + When we are ready to make an output pass, the saved Q-table is converted + to a multiplier table that will actually be used by the IDCT routine. + The multiplier table contents are IDCT-method-dependent. To support + application changes in IDCT method between scans, we can remake the + multiplier tables if necessary. + In buffered-image mode, the first output pass may occur before any data + has been seen for some components, and thus before their Q-tables have + been saved away. To handle this case, multiplier tables are preset + to zeroes; the result of the IDCT will be a neutral gray level. } + + +{ Private subobject for this module } + +type + my_idct_ptr = ^my_idct_controller; + my_idct_controller = record + pub : jpeg_inverse_dct; { public fields } + + { This array contains the IDCT method code that each multiplier table + is currently set up for, or -1 if it's not yet set up. + The actual multiplier tables are pointed to by dct_table in the + per-component comp_info structures. } + + cur_method : array[0..MAX_COMPONENTS-1] of int; + end; {my_idct_controller;} + + +{ Allocated multiplier tables: big enough for any supported variant } + +type + multiplier_table = record + case byte of + 0:(islow_array : array[0..DCTSIZE2-1] of ISLOW_MULT_TYPE); + {$ifdef DCT_IFAST_SUPPORTED} + 1:(ifast_array : array[0..DCTSIZE2-1] of IFAST_MULT_TYPE); + {$endif} + {$ifdef DCT_FLOAT_SUPPORTED} + 2:(float_array : array[0..DCTSIZE2-1] of FLOAT_MULT_TYPE); + {$endif} + end; + + +{ The current scaled-IDCT routines require ISLOW-style multiplier tables, + so be sure to compile that code if either ISLOW or SCALING is requested. } + +{$ifdef DCT_ISLOW_SUPPORTED} + {$define PROVIDE_ISLOW_TABLES} +{$else} + {$ifdef IDCT_SCALING_SUPPORTED} + {$define PROVIDE_ISLOW_TABLES} + {$endif} +{$endif} + + +{ Prepare for an output pass. + Here we select the proper IDCT routine for each component and build + a matching multiplier table. } + +{METHODDEF} +procedure start_pass (cinfo : j_decompress_ptr); +var + idct : my_idct_ptr; + ci, i : int; + compptr : jpeg_component_info_ptr; + method : J_DCT_METHOD; + method_ptr : inverse_DCT_method_ptr; + qtbl : JQUANT_TBL_PTR; +{$ifdef PROVIDE_ISLOW_TABLES} +var + ismtbl : ISLOW_MULT_TYPE_FIELD_PTR; +{$endif} +{$ifdef DCT_IFAST_SUPPORTED} +const + CONST_BITS = 14; +const + aanscales : array[0..DCTSIZE2-1] of INT16 = + ({ precomputed values scaled up by 14 bits } + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247); +var + ifmtbl : IFAST_MULT_TYPE_FIELD_PTR; + {SHIFT_TEMPS} + + { Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + + function DESCALE(x : INT32; n : int) : INT32; + var + shift_temp : INT32; + begin + {$ifdef RIGHT_SHIFT_IS_UNSIGNED} + shift_temp := x + (INT32(1) shl (n-1)); + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else + Descale := (shift_temp shr n); + {$else} + Descale := (x + (INT32(1) shl (n-1)) shr n; + {$endif} + end; + +{$endif} +{$ifdef DCT_FLOAT_SUPPORTED} +const + aanscalefactor : array[0..DCTSIZE-1] of double = + (1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379); +var + fmtbl : FLOAT_MULT_TYPE_FIELD_PTR; + row, col : int; +{$endif} +begin + idct := my_idct_ptr (cinfo^.idct); + method := J_DCT_METHOD(0); + method_ptr := NIL; + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + + for ci := 0 to pred(cinfo^.num_components) do + begin + { Select the proper IDCT routine for this component's scaling } + case (compptr^.DCT_scaled_size) of +{$ifdef IDCT_SCALING_SUPPORTED} + 1:begin + method_ptr := jpeg_idct_1x1; + method := JDCT_ISLOW; { jidctred uses islow-style table } + end; + 2:begin + method_ptr := jpeg_idct_2x2; + method := JDCT_ISLOW; { jidctred uses islow-style table } + end; + 4:begin + method_ptr := jpeg_idct_4x4; + method := JDCT_ISLOW; { jidctred uses islow-style table } + end; +{$endif} + DCTSIZE: + case (cinfo^.dct_method) of +{$ifdef DCT_ISLOW_SUPPORTED} + JDCT_ISLOW: + begin + method_ptr := @jpeg_idct_islow; + method := JDCT_ISLOW; + end; +{$endif} +{$ifdef DCT_IFAST_SUPPORTED} + JDCT_IFAST: + begin + method_ptr := @jpeg_idct_ifast; + method := JDCT_IFAST; + end; +{$endif} +{$ifdef DCT_FLOAT_SUPPORTED} + JDCT_FLOAT: + begin + method_ptr := @jpeg_idct_float; + method := JDCT_FLOAT; + end; +{$endif} + else + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); + end; + else + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_DCTSIZE, compptr^.DCT_scaled_size); + end; + idct^.pub.inverse_DCT[ci] := method_ptr; + { Create multiplier table from quant table. + However, we can skip this if the component is uninteresting + or if we already built the table. Also, if no quant table + has yet been saved for the component, we leave the + multiplier table all-zero; we'll be reading zeroes from the + coefficient controller's buffer anyway. } + + if (not compptr^.component_needed) or (idct^.cur_method[ci] = int(method)) then + continue; + qtbl := compptr^.quant_table; + if (qtbl = NIL) then { happens if no data yet for component } + continue; + idct^.cur_method[ci] := int(method); + case (method) of +{$ifdef PROVIDE_ISLOW_TABLES} + JDCT_ISLOW: + begin + { For LL&M IDCT method, multipliers are equal to raw quantization + coefficients, but are stored as ints to ensure access efficiency. } + + ismtbl := ISLOW_MULT_TYPE_FIELD_PTR (compptr^.dct_table); + for i := 0 to pred(DCTSIZE2) do + begin + ismtbl^[i] := ISLOW_MULT_TYPE (qtbl^.quantval[i]); + end; + end; +{$endif} +{$ifdef DCT_IFAST_SUPPORTED} + JDCT_IFAST: + begin + { For AA&N IDCT method, multipliers are equal to quantization + coefficients scaled by scalefactor[row]*scalefactor[col], where + scalefactor[0] := 1 + scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7 + For integer operation, the multiplier table is to be scaled by + IFAST_SCALE_BITS. } + + ifmtbl := IFAST_MULT_TYPE_FIELD_PTR (compptr^.dct_table); + + for i := 0 to pred(DCTSIZE2) do + begin + ifmtbl^[i] := IFAST_MULT_TYPE( + DESCALE( INT32 (qtbl^.quantval[i]) * INT32 (aanscales[i]), + CONST_BITS-IFAST_SCALE_BITS) ); + end; + end; +{$endif} +{$ifdef DCT_FLOAT_SUPPORTED} + JDCT_FLOAT: + begin + { For float AA&N IDCT method, multipliers are equal to quantization + coefficients scaled by scalefactor[row]*scalefactor[col], where + scalefactor[0] := 1 + scalefactor[k] := cos(k*PI/16) * sqrt(2) for k=1..7 } + + fmtbl := FLOAT_MULT_TYPE_FIELD_PTR(compptr^.dct_table); + + i := 0; + for row := 0 to pred(DCTSIZE) do + begin + for col := 0 to pred(DCTSIZE) do + begin + fmtbl^[i] := {FLOAT_MULT_TYPE} ( + {double} qtbl^.quantval[i] * + aanscalefactor[row] * aanscalefactor[col] ); + Inc(i); + end; + end; + end; +{$endif} + else + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); + break; + end; + Inc(compptr); + end; +end; + + +{ Initialize IDCT manager. } + +{GLOBAL} +procedure jinit_inverse_dct (cinfo : j_decompress_ptr); +var + idct : my_idct_ptr; + ci : int; + compptr : jpeg_component_info_ptr; +begin + idct := my_idct_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_idct_controller)) ); + cinfo^.idct := jpeg_inverse_dct_ptr (idct); + idct^.pub.start_pass := start_pass; + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Allocate and pre-zero a multiplier table for each component } + compptr^.dct_table := + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(multiplier_table)); + MEMZERO(compptr^.dct_table, SIZEOF(multiplier_table)); + { Mark multiplier table not yet set up for any method } + idct^.cur_method[ci] := -1; + Inc(compptr); + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdeferr.pas b/src/lib/vampimg/JpegLib/imjdeferr.pas new file mode 100644 index 0000000..61fe305 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdeferr.pas @@ -0,0 +1,497 @@ +unit imjdeferr; + +{ This file defines the error and message codes for the cjpeg/djpeg + applications. These strings are not needed as part of the JPEG library + proper. + Edit this file to add new codes, or to translate the message strings to + some other language. } + +{ Original cderror.h ; Copyright (C) 1994, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +{ To define the enum list of message codes, include this file without + defining macro JMESSAGE. To create a message string table, include it + again with a suitable JMESSAGE definition (see jerror.c for an example). } + + +{ Original: jversion.h ; Copyright (C) 1991-1996, Thomas G. Lane. } +{ This file contains software version identification. } + +const + JVERSION = '6a 7-Feb-96'; + + JCOPYRIGHT = 'Copyright (C) 1996, Thomas G. Lane'; + + JNOTICE = 'Pascal Translation, Copyright (C) 1996, Jacques Nomssi Nzali'; + +{ Create the message string table. + We do this from the master message list in jerror.h by re-reading + jerror.h with a suitable definition for macro JMESSAGE. + The message table is made an external symbol just in case any applications + want to refer to it directly. } + +type + J_MESSAGE_CODE =( + JMSG_NOMESSAGE, + JERR_ARITH_NOTIMPL, + JERR_BAD_ALIGN_TYPE, + JERR_BAD_ALLOC_CHUNK, + JERR_BAD_BUFFER_MODE, + JERR_BAD_COMPONENT_ID, + JERR_BAD_DCT_COEF, + JERR_BAD_DCTSIZE, + JERR_BAD_HUFF_TABLE, + JERR_BAD_IN_COLORSPACE, + JERR_BAD_J_COLORSPACE, + JERR_BAD_LENGTH, + JERR_BAD_LIB_VERSION, + JERR_BAD_MCU_SIZE, + JERR_BAD_POOL_ID, + JERR_BAD_PRECISION, + JERR_BAD_PROGRESSION, + JERR_BAD_PROG_SCRIPT, + JERR_BAD_SAMPLING, + JERR_BAD_SCAN_SCRIPT, + JERR_BAD_STATE, + JERR_BAD_STRUCT_SIZE, + JERR_BAD_VIRTUAL_ACCESS, + JERR_BUFFER_SIZE, + JERR_CANT_SUSPEND, + JERR_CCIR601_NOTIMPL, + JERR_COMPONENT_COUNT, + JERR_CONVERSION_NOTIMPL, + JERR_DAC_INDEX, + JERR_DAC_VALUE, + JERR_DHT_COUNTS, + JERR_DHT_INDEX, + JERR_DQT_INDEX, + JERR_EMPTY_IMAGE, + JERR_EMS_READ, + JERR_EMS_WRITE, + JERR_EOI_EXPECTED, + JERR_FILE_READ, + JERR_FILE_WRITE, + JERR_FRACT_SAMPLE_NOTIMPL, + JERR_HUFF_CLEN_OVERFLOW, + JERR_HUFF_MISSING_CODE, + JERR_IMAGE_TOO_BIG, + JERR_INPUT_EMPTY, + JERR_INPUT_EOF, + JERR_MISMATCHED_QUANT_TABLE, + JERR_MISSING_DATA, + JERR_MODE_CHANGE, + JERR_NOTIMPL, + JERR_NOT_COMPILED, + JERR_NO_BACKING_STORE, + JERR_NO_HUFF_TABLE, + JERR_NO_IMAGE, + JERR_NO_QUANT_TABLE, + JERR_NO_SOI, + JERR_OUT_OF_MEMORY, + JERR_QUANT_COMPONENTS, + JERR_QUANT_FEW_COLORS, + JERR_QUANT_MANY_COLORS, + JERR_SOF_DUPLICATE, + JERR_SOF_NO_SOS, + JERR_SOF_UNSUPPORTED, + JERR_SOI_DUPLICATE, + JERR_SOS_NO_SOF, + JERR_TFILE_CREATE, + JERR_TFILE_READ, + JERR_TFILE_SEEK, + JERR_TFILE_WRITE, + JERR_TOO_LITTLE_DATA, + JERR_UNKNOWN_MARKER, + JERR_VIRTUAL_BUG, + JERR_WIDTH_OVERFLOW, + JERR_XMS_READ, + JERR_XMS_WRITE, + JMSG_COPYRIGHT, + JMSG_VERSION, + JTRC_16BIT_TABLES, + JTRC_ADOBE, + JTRC_APP0, + JTRC_APP14, + JTRC_DAC, + JTRC_DHT, + JTRC_DQT, + JTRC_DRI, + JTRC_EMS_CLOSE, + JTRC_EMS_OPEN, + JTRC_EOI, + JTRC_HUFFBITS, + JTRC_JFIF, + JTRC_JFIF_BADTHUMBNAILSIZE, + JTRC_JFIF_EXTENSION, + JTRC_JFIF_THUMBNAIL, + JTRC_MISC_MARKER, + JTRC_PARMLESS_MARKER, + JTRC_QUANTVALS, + JTRC_QUANT_3_NCOLORS, + JTRC_QUANT_NCOLORS, + JTRC_QUANT_SELECTED, + JTRC_RECOVERY_ACTION, + JTRC_RST, + JTRC_SMOOTH_NOTIMPL, + JTRC_SOF, + JTRC_SOF_COMPONENT, + JTRC_SOI, + JTRC_SOS, + JTRC_SOS_COMPONENT, + JTRC_SOS_PARAMS, + JTRC_TFILE_CLOSE, + JTRC_TFILE_OPEN, + JTRC_THUMB_JPEG, + JTRC_THUMB_PALETTE, + JTRC_THUMB_RGB, + JTRC_UNKNOWN_IDS, + JTRC_XMS_CLOSE, + JTRC_XMS_OPEN, + JWRN_ADOBE_XFORM, + JWRN_BOGUS_PROGRESSION, + JWRN_EXTRANEOUS_DATA, + JWRN_HIT_MARKER, + JWRN_HUFF_BAD_CODE, + JWRN_JFIF_MAJOR, + JWRN_JPEG_EOF, + JWRN_MUST_RESYNC, + JWRN_NOT_SEQUENTIAL, + JWRN_TOO_MUCH_DATA, + + + JMSG_FIRSTADDONCODE, { Must be first entry! } + + {$ifdef BMP_SUPPORTED} + JERR_BMP_BADCMAP, { Unsupported BMP colormap format } + JERR_BMP_BADDEPTH, { Only 8- and 24-bit BMP files are supported } + JERR_BMP_BADHEADER, { Invalid BMP file: bad header length } + JERR_BMP_BADPLANES, { Invalid BMP file: biPlanes not equal to 1 } + JERR_BMP_COLORSPACE, { BMP output must be grayscale or RGB } + JERR_BMP_COMPRESSED, { Sorry, compressed BMPs not yet supported } + JERR_BMP_NOT, { Not a BMP file - does not start with BM } + JTRC_BMP, { %dx%d 24-bit BMP image } + JTRC_BMP_MAPPED, { %dx%d 8-bit colormapped BMP image } + JTRC_BMP_OS2, { %dx%d 24-bit OS2 BMP image } + JTRC_BMP_OS2_MAPPED, { %dx%d 8-bit colormapped OS2 BMP image } + {$endif} { BMP_SUPPORTED } + + {$ifdef GIF_SUPPORTED} + JERR_GIF_BUG, { GIF output got confused } + JERR_GIF_CODESIZE, { Bogus GIF codesize %d } + JERR_GIF_COLORSPACE, { GIF output must be grayscale or RGB } + JERR_GIF_IMAGENOTFOUND, { Too few images in GIF file } + JERR_GIF_NOT, { Not a GIF file } + JTRC_GIF, { %dx%dx%d GIF image } + JTRC_GIF_BADVERSION, + { Warning: unexpected GIF version number '%c%c%c' } + JTRC_GIF_EXTENSION, { Ignoring GIF extension block of type 0x%02x } + JTRC_GIF_NONSQUARE, { Caution: nonsquare pixels in input } + JWRN_GIF_BADDATA, { Corrupt data in GIF file } + JWRN_GIF_CHAR, { Bogus char 0x%02x in GIF file, ignoring } + JWRN_GIF_ENDCODE, { Premature end of GIF image } + JWRN_GIF_NOMOREDATA, { Ran out of GIF bits } + {$endif} { GIF_SUPPORTED } + + {$ifdef PPM_SUPPORTED} + JERR_PPM_COLORSPACE, { PPM output must be grayscale or RGB } + JERR_PPM_NONNUMERIC, { Nonnumeric data in PPM file } + JERR_PPM_NOT, { Not a PPM file } + JTRC_PGM, { %dx%d PGM image } + JTRC_PGM_TEXT, { %dx%d text PGM image } + JTRC_PPM, { %dx%d PPM image } + JTRC_PPM_TEXT, { %dx%d text PPM image } + {$endif} { PPM_SUPPORTED } + + {$ifdef RLE_SUPPORTED} + JERR_RLE_BADERROR, { Bogus error code from RLE library } + JERR_RLE_COLORSPACE, { RLE output must be grayscale or RGB } + JERR_RLE_DIMENSIONS, { Image dimensions (%dx%d) too large for RLE } + JERR_RLE_EMPTY, { Empty RLE file } + JERR_RLE_EOF, { Premature EOF in RLE header } + JERR_RLE_MEM, { Insufficient memory for RLE header } + JERR_RLE_NOT, { Not an RLE file } + JERR_RLE_TOOMANYCHANNELS, { Cannot handle %d output channels for RLE } + JERR_RLE_UNSUPPORTED, { Cannot handle this RLE setup } + JTRC_RLE, { %dx%d full-color RLE file } + JTRC_RLE_FULLMAP, { %dx%d full-color RLE file with map of length %d } + JTRC_RLE_GRAY, { %dx%d grayscale RLE file } + JTRC_RLE_MAPGRAY, { %dx%d grayscale RLE file with map of length %d } + JTRC_RLE_MAPPED, { %dx%d colormapped RLE file with map of length %d } + {$endif} { RLE_SUPPORTED } + + {$ifdef TARGA_SUPPORTED} + JERR_TGA_BADCMAP, { Unsupported Targa colormap format } + JERR_TGA_BADPARMS, { Invalid or unsupported Targa file } + JERR_TGA_COLORSPACE, { Targa output must be grayscale or RGB } + JTRC_TGA, { %dx%d RGB Targa image } + JTRC_TGA_GRAY, { %dx%d grayscale Targa image } + JTRC_TGA_MAPPED, { %dx%d colormapped Targa image } + {$else} + JERR_TGA_NOTCOMP, { Targa support was not compiled } + {$endif} { TARGA_SUPPORTED } + + JERR_BAD_CMAP_FILE, + { Color map file is invalid or of unsupported format } + JERR_TOO_MANY_COLORS, + { Output file format cannot handle %d colormap entries } + JERR_UNGETC_FAILED, { ungetc failed } + {$ifdef TARGA_SUPPORTED} + JERR_UNKNOWN_FORMAT, + { Unrecognized input file format --- perhaps you need -targa } + {$else} + JERR_UNKNOWN_FORMAT, { Unrecognized input file format } + {$endif} + JERR_UNSUPPORTED_FORMAT, { Unsupported output file format } + + JMSG_LASTADDONCODE + ); + + +const + JMSG_LASTMSGCODE : J_MESSAGE_CODE = JMSG_LASTADDONCODE; + +type + msg_table = Array[J_MESSAGE_CODE] of string[80]; +const + jpeg_std_message_table : msg_table = ( + + { JMSG_NOMESSAGE } 'Bogus message code %d', { Must be first entry! } + +{ For maintenance convenience, list is alphabetical by message code name } + { JERR_ARITH_NOTIMPL } + 'Sorry, there are legal restrictions on arithmetic coding', + { JERR_BAD_ALIGN_TYPE } 'ALIGN_TYPE is wrong, please fix', + { JERR_BAD_ALLOC_CHUNK } 'MAX_ALLOC_CHUNK is wrong, please fix', + { JERR_BAD_BUFFER_MODE } 'Bogus buffer control mode', + { JERR_BAD_COMPONENT_ID } 'Invalid component ID %d in SOS', + { JERR_BAD_DCT_COEF } 'DCT coefficient out of range', + { JERR_BAD_DCTSIZE } 'IDCT output block size %d not supported', + { JERR_BAD_HUFF_TABLE } 'Bogus Huffman table definition', + { JERR_BAD_IN_COLORSPACE } 'Bogus input colorspace', + { JERR_BAD_J_COLORSPACE } 'Bogus JPEG colorspace', + { JERR_BAD_LENGTH } 'Bogus marker length', + { JERR_BAD_LIB_VERSION } + 'Wrong JPEG library version: library is %d, caller expects %d', + { JERR_BAD_MCU_SIZE } 'Sampling factors too large for interleaved scan', + { JERR_BAD_POOL_ID } 'Invalid memory pool code %d', + { JERR_BAD_PRECISION } 'Unsupported JPEG data precision %d', + { JERR_BAD_PROGRESSION } + 'Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d', + { JERR_BAD_PROG_SCRIPT } + 'Invalid progressive parameters at scan script entry %d', + { JERR_BAD_SAMPLING } 'Bogus sampling factors', + { JERR_BAD_SCAN_SCRIPT } 'Invalid scan script at entry %d', + { JERR_BAD_STATE } 'Improper call to JPEG library in state %d', + { JERR_BAD_STRUCT_SIZE } + 'JPEG parameter struct mismatch: library thinks size is %d, caller expects %d', + { JERR_BAD_VIRTUAL_ACCESS } 'Bogus virtual array access', + { JERR_BUFFER_SIZE } 'Buffer passed to JPEG library is too small', + { JERR_CANT_SUSPEND } 'Suspension not allowed here', + { JERR_CCIR601_NOTIMPL } 'CCIR601 sampling not implemented yet', + { JERR_COMPONENT_COUNT } 'Too many color components: %d, max %d', + { JERR_CONVERSION_NOTIMPL } 'Unsupported color conversion request', + { JERR_DAC_INDEX } 'Bogus DAC index %d', + { JERR_DAC_VALUE } 'Bogus DAC value $%x', + { JERR_DHT_COUNTS } 'Bogus DHT counts', + { JERR_DHT_INDEX } 'Bogus DHT index %d', + { JERR_DQT_INDEX } 'Bogus DQT index %d', + { JERR_EMPTY_IMAGE } 'Empty JPEG image (DNL not supported)', + { JERR_EMS_READ } 'Read from EMS failed', + { JERR_EMS_WRITE } 'Write to EMS failed', + { JERR_EOI_EXPECTED } 'Didn''t expect more than one scan', + { JERR_FILE_READ } 'Input file read error', + { JERR_FILE_WRITE } 'Output file write error --- out of disk space?', + { JERR_FRACT_SAMPLE_NOTIMPL } 'Fractional sampling not implemented yet', + { JERR_HUFF_CLEN_OVERFLOW } 'Huffman code size table overflow', + { JERR_HUFF_MISSING_CODE } 'Missing Huffman code table entry', + { JERR_IMAGE_TOO_BIG } 'Maximum supported image dimension is %d pixels', + { JERR_INPUT_EMPTY } 'Empty input file', + { JERR_INPUT_EOF } 'Premature end of input file', + { JERR_MISMATCHED_QUANT_TABLE } + 'Cannot transcode due to multiple use of quantization table %d', + { JERR_MISSING_DATA } 'Scan script does not transmit all data', + { JERR_MODE_CHANGE } 'Invalid color quantization mode change', + { JERR_NOTIMPL } 'Not implemented yet', + { JERR_NOT_COMPILED } 'Requested feature was omitted at compile time', + { JERR_NO_BACKING_STORE } 'Backing store not supported', + { JERR_NO_HUFF_TABLE } 'Huffman table $%02x was not defined', + { JERR_NO_IMAGE } 'JPEG datastream contains no image', + { JERR_NO_QUANT_TABLE } 'Quantization table $%02x was not defined', + { JERR_NO_SOI } 'Not a JPEG file: starts with $%02x $%02x', + { JERR_OUT_OF_MEMORY } 'Insufficient memory (case %d)', + { JERR_QUANT_COMPONENTS } + 'Cannot quantize more than %d color components', + { JERR_QUANT_FEW_COLORS } 'Cannot quantize to fewer than %d colors', + { JERR_QUANT_MANY_COLORS } 'Cannot quantize to more than %d colors', + { JERR_SOF_DUPLICATE } 'Invalid JPEG file structure: two SOF markers', + { JERR_SOF_NO_SOS } 'Invalid JPEG file structure: missing SOS marker', + { JERR_SOF_UNSUPPORTED } 'Unsupported JPEG process: SOF type $%02x', + { JERR_SOI_DUPLICATE } 'Invalid JPEG file structure: two SOI markers', + { JERR_SOS_NO_SOF } 'Invalid JPEG file structure: SOS before SOF', + { JERR_TFILE_CREATE } 'Failed to create temporary file %s', + { JERR_TFILE_READ } 'Read failed on temporary file', + { JERR_TFILE_SEEK } 'Seek failed on temporary file', + { JERR_TFILE_WRITE } + 'Write failed on temporary file --- out of disk space?', + { JERR_TOO_LITTLE_DATA } 'Application transferred too few scanlines', + { JERR_UNKNOWN_MARKER } 'Unsupported marker type $%02x', + { JERR_VIRTUAL_BUG } 'Virtual array controller messed up', + { JERR_WIDTH_OVERFLOW } 'Image too wide for this implementation', + { JERR_XMS_READ } 'Read from XMS failed', + { JERR_XMS_WRITE } 'Write to XMS failed', + { JMSG_COPYRIGHT } JCOPYRIGHT, + { JMSG_VERSION } JVERSION, + { JTRC_16BIT_TABLES } + 'Caution: quantization tables are too coarse for baseline JPEG', + { JTRC_ADOBE } + 'Adobe APP14 marker: version %d, flags $%04x $%04x, transform %d', + { JTRC_APP0 } 'Unknown APP0 marker (not JFIF), length %d', + { JTRC_APP14 } 'Unknown APP14 marker (not Adobe), length %d', + { JTRC_DAC } 'Define Arithmetic Table $%02x: $%02x', + { JTRC_DHT } 'Define Huffman Table $%02x', + { JTRC_DQT } 'Define Quantization Table %d precision %d', + { JTRC_DRI } 'Define Restart Interval %d', + { JTRC_EMS_CLOSE } 'Freed EMS handle %d', + { JTRC_EMS_OPEN } 'Obtained EMS handle %d', + { JTRC_EOI } 'End Of Image', + { JTRC_HUFFBITS } ' %3d %3d %3d %3d %3d %3d %3d %3d', + { JTRC_JFIF } 'JFIF APP0 marker, density %dx%d %d', + { JTRC_JFIF_BADTHUMBNAILSIZE } + 'Warning: thumbnail image size does not match data length %d', + { JTRC_JFIF_EXTENSION } 'JFIF extension marker: type 0x%02x, length %u', + { JTRC_JFIF_THUMBNAIL } ' with %d x %d thumbnail image', + { JTRC_MISC_MARKER } 'Skipping marker $%02x, length %d', + { JTRC_PARMLESS_MARKER } 'Unexpected marker $%02x', + { JTRC_QUANTVALS } ' %4d %4d %4d %4d %4d %4d %4d %4d', + { JTRC_QUANT_3_NCOLORS } 'Quantizing to %d = %d*%d*%d colors', + { JTRC_QUANT_NCOLORS } 'Quantizing to %d colors', + { JTRC_QUANT_SELECTED } 'Selected %d colors for quantization', + { JTRC_RECOVERY_ACTION } 'At marker $%02x, recovery action %d', + { JTRC_RST } 'RST%d', + { JTRC_SMOOTH_NOTIMPL } + 'Smoothing not supported with nonstandard sampling ratios', + { JTRC_SOF } 'Start Of Frame $%02x: width=%d, height=%d, components=%d', + { JTRC_SOF_COMPONENT } ' Component %d: %dhx%dv q=%d', + { JTRC_SOI } 'Start of Image', + { JTRC_SOS } 'Start Of Scan: %d components', + { JTRC_SOS_COMPONENT } ' Component %d: dc=%d ac=%d', + { JTRC_SOS_PARAMS } ' Ss=%d, Se=%d, Ah=%d, Al=%d', + { JTRC_TFILE_CLOSE } 'Closed temporary file %s', + { JTRC_TFILE_OPEN } 'Opened temporary file %s', + { JTRC_THUMB_JPEG } + 'JFIF extension marker: JPEG-compressed thumbnail image, length %u', + { JMESSAGE(JTRC_THUMB_PALETTE } + 'JFIF extension marker: palette thumbnail image, length %u', + { JMESSAGE(JTRC_THUMB_RGB } + 'JFIF extension marker: RGB thumbnail image, length %u', + { JTRC_UNKNOWN_IDS } + 'Unrecognized component IDs %d %d %d, assuming YCbCr', + { JTRC_XMS_CLOSE } 'Freed XMS handle %d', + { JTRC_XMS_OPEN } 'Obtained XMS handle %d', + { JWRN_ADOBE_XFORM } 'Unknown Adobe color transform code %d', + { JWRN_BOGUS_PROGRESSION } + 'Inconsistent progression sequence for component %d coefficient %d', + { JWRN_EXTRANEOUS_DATA } + 'Corrupt JPEG data: %d extraneous bytes before marker $%02x', + { JWRN_HIT_MARKER } 'Corrupt JPEG data: premature end of data segment', + { JWRN_HUFF_BAD_CODE } 'Corrupt JPEG data: bad Huffman code', + { JWRN_JFIF_MAJOR } 'Warning: unknown JFIF revision number %d.%02d', + { JWRN_JPEG_EOF } 'Premature end of JPEG file', + { JWRN_MUST_RESYNC } + 'Corrupt JPEG data: found marker $%02x instead of RST%d', + { JWRN_NOT_SEQUENTIAL } 'Invalid SOS parameters for sequential JPEG', + { JWRN_TOO_MUCH_DATA } 'Application transferred too many scanlines', + + { JMSG_FIRSTADDONCODE } '', { Must be first entry! } + +{$ifdef BMP_SUPPORTED} + { JERR_BMP_BADCMAP } 'Unsupported BMP colormap format', + { JERR_BMP_BADDEPTH } 'Only 8- and 24-bit BMP files are supported', + { JERR_BMP_BADHEADER } 'Invalid BMP file: bad header length', + { JERR_BMP_BADPLANES } 'Invalid BMP file: biPlanes not equal to 1', + { JERR_BMP_COLORSPACE } 'BMP output must be grayscale or RGB', + { JERR_BMP_COMPRESSED } 'Sorry, compressed BMPs not yet supported', + { JERR_BMP_NOT } 'Not a BMP file - does not start with BM', + { JTRC_BMP } '%dx%d 24-bit BMP image', + { JTRC_BMP_MAPPED } '%dx%d 8-bit colormapped BMP image', + { JTRC_BMP_OS2 } '%dx%d 24-bit OS2 BMP image', + { JTRC_BMP_OS2_MAPPED } '%dx%d 8-bit colormapped OS2 BMP image', +{$endif} { BMP_SUPPORTED } + +{$ifdef GIF_SUPPORTED} + { JERR_GIF_BUG } 'GIF output got confused', + { JERR_GIF_CODESIZE } 'Bogus GIF codesize %d', + { JERR_GIF_COLORSPACE } 'GIF output must be grayscale or RGB', + { JERR_GIF_IMAGENOTFOUND } 'Too few images in GIF file', + { JERR_GIF_NOT } 'Not a GIF file', + { JTRC_GIF } '%dx%dx%d GIF image', + { JTRC_GIF_BADVERSION } + 'Warning: unexpected GIF version number "%c%c%c"', + { JTRC_GIF_EXTENSION } 'Ignoring GIF extension block of type 0x%02x', + { JTRC_GIF_NONSQUARE } 'Caution: nonsquare pixels in input', + { JWRN_GIF_BADDATA } 'Corrupt data in GIF file', + { JWRN_GIF_CHAR } 'Bogus char 0x%02x in GIF file, ignoring', + { JWRN_GIF_ENDCODE } 'Premature end of GIF image', + { JWRN_GIF_NOMOREDATA } 'Ran out of GIF bits', +{$endif} { GIF_SUPPORTED } + +{$ifdef PPM_SUPPORTED} + { JERR_PPM_COLORSPACE } 'PPM output must be grayscale or RGB', + { JERR_PPM_NONNUMERIC } 'Nonnumeric data in PPM file', + { JERR_PPM_NOT } 'Not a PPM file', + { JTRC_PGM } '%dx%d PGM image', + { JTRC_PGM_TEXT } '%dx%d text PGM image', + { JTRC_PPM } '%dx%d PPM image', + { JTRC_PPM_TEXT } '%dx%d text PPM image', +{$endif} { PPM_SUPPORTED } + +{$ifdef RLE_SUPPORTED} + { JERR_RLE_BADERROR } 'Bogus error code from RLE library', + { JERR_RLE_COLORSPACE } 'RLE output must be grayscale or RGB', + { JERR_RLE_DIMENSIONS } 'Image dimensions (%dx%d) too large for RLE', + { JERR_RLE_EMPTY } 'Empty RLE file', + { JERR_RLE_EOF } 'Premature EOF in RLE header', + { JERR_RLE_MEM } 'Insufficient memory for RLE header', + { JERR_RLE_NOT } 'Not an RLE file', + { JERR_RLE_TOOMANYCHANNELS } 'Cannot handle %d output channels for RLE', + { JERR_RLE_UNSUPPORTED } 'Cannot handle this RLE setup', + { JTRC_RLE } '%dx%d full-color RLE file', + { JTRC_RLE_FULLMAP } '%dx%d full-color RLE file with map of length %d', + { JTRC_RLE_GRAY } '%dx%d grayscale RLE file', + { JTRC_RLE_MAPGRAY } '%dx%d grayscale RLE file with map of length %d', + { JTRC_RLE_MAPPED } '%dx%d colormapped RLE file with map of length %d', +{$endif} { RLE_SUPPORTED } + +{$ifdef TARGA_SUPPORTED} + { JERR_TGA_BADCMAP } 'Unsupported Targa colormap format', + { JERR_TGA_BADPARMS } 'Invalid or unsupported Targa file', + { JERR_TGA_COLORSPACE } 'Targa output must be grayscale or RGB', + { JTRC_TGA } '%dx%d RGB Targa image', + { JTRC_TGA_GRAY } '%dx%d grayscale Targa image', + { JTRC_TGA_MAPPED } '%dx%d colormapped Targa image', +{$else} + { JERR_TGA_NOTCOMP } 'Targa support was not compiled', +{$endif} { TARGA_SUPPORTED } + + { JERR_BAD_CMAP_FILE } + 'Color map file is invalid or of unsupported format', + { JERR_TOO_MANY_COLORS } + 'Output file format cannot handle %d colormap entries', + { JERR_UNGETC_FAILED } 'ungetc failed', +{$ifdef TARGA_SUPPORTED} + { JERR_UNKNOWN_FORMAT } + 'Unrecognized input file format --- perhaps you need -targa', +{$else} + { JERR_UNKNOWN_FORMAT } 'Unrecognized input file format', +{$endif} + { JERR_UNSUPPORTED_FORMAT } 'Unsupported output file format', + + + { JMSG_LASTADDONCODE } ''); + +implementation + +end. diff --git a/src/lib/vampimg/JpegLib/imjdhuff.pas b/src/lib/vampimg/JpegLib/imjdhuff.pas new file mode 100644 index 0000000..09f0e66 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdhuff.pas @@ -0,0 +1,1204 @@ +unit imjdhuff; + +{ This file contains declarations for Huffman entropy decoding routines + that are shared between the sequential decoder (jdhuff.c) and the + progressive decoder (jdphuff.c). No other modules need to see these. } + +{ This file contains Huffman entropy decoding routines. + + Much of the complexity here has to do with supporting input suspension. + If the data source module demands suspension, we want to be able to back + up to the start of the current MCU. To do this, we copy state variables + into local working storage, and update them back to the permanent + storage only upon successful completion of an MCU. } + +{ Original: jdhuff.h+jdhuff.c; Copyright (C) 1991-1997, Thomas G. Lane. } + + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjutils, + imjpeglib; + + +{ Declarations shared with jdphuff.c } + + + +{ Derived data constructed for each Huffman table } + +const + HUFF_LOOKAHEAD = 8; { # of bits of lookahead } + +type + d_derived_tbl_ptr = ^d_derived_tbl; + d_derived_tbl = record + { Basic tables: (element [0] of each array is unused) } + maxcode : array[0..18-1] of INT32; { largest code of length k (-1 if none) } + { (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) } + valoffset : array[0..17-1] of INT32; { huffval[] offset for codes of length k } + { valoffset[k] = huffval[] index of 1st symbol of code length k, less + the smallest code of length k; so given a code of length k, the + corresponding symbol is huffval[code + valoffset[k]] } + + { Link to public Huffman table (needed only in jpeg_huff_decode) } + pub : JHUFF_TBL_PTR; + + { Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of + the input data stream. If the next Huffman code is no more + than HUFF_LOOKAHEAD bits long, we can obtain its length and + the corresponding symbol directly from these tables. } + + look_nbits : array[0..(1 shl HUFF_LOOKAHEAD)-1] of int; + { # bits, or 0 if too long } + look_sym : array[0..(1 shl HUFF_LOOKAHEAD)-1] of UINT8; + { symbol, or unused } + end; + +{ Fetching the next N bits from the input stream is a time-critical operation + for the Huffman decoders. We implement it with a combination of inline + macros and out-of-line subroutines. Note that N (the number of bits + demanded at one time) never exceeds 15 for JPEG use. + + We read source bytes into get_buffer and dole out bits as needed. + If get_buffer already contains enough bits, they are fetched in-line + by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough + bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer + as full as possible (not just to the number of bits needed; this + prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer). + Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension. + On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains + at least the requested number of bits --- dummy zeroes are inserted if + necessary. } + + +type + bit_buf_type = INT32 ; { type of bit-extraction buffer } +const + BIT_BUF_SIZE = 32; { size of buffer in bits } + +{ If long is > 32 bits on your machine, and shifting/masking longs is + reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE + appropriately should be a win. Unfortunately we can't define the size + with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8) + because not all machines measure sizeof in 8-bit bytes. } + +type + bitread_perm_state = record { Bitreading state saved across MCUs } + get_buffer : bit_buf_type; { current bit-extraction buffer } + bits_left : int; { # of unused bits in it } + end; + +type + bitread_working_state = record + { Bitreading working state within an MCU } + { current data source location } + { We need a copy, rather than munging the original, in case of suspension } + next_input_byte : JOCTETptr; { => next byte to read from source } + bytes_in_buffer : size_t; { # of bytes remaining in source buffer } + { Bit input buffer --- note these values are kept in register variables, + not in this struct, inside the inner loops. } + + get_buffer : bit_buf_type; { current bit-extraction buffer } + bits_left : int; { # of unused bits in it } + { Pointer needed by jpeg_fill_bit_buffer } + cinfo : j_decompress_ptr; { back link to decompress master record } + end; + +{ Module initialization routine for Huffman entropy decoding. } + +{GLOBAL} +procedure jinit_huff_decoder (cinfo : j_decompress_ptr); + +{GLOBAL} +function jpeg_huff_decode(var state : bitread_working_state; + get_buffer : bit_buf_type; {register} + bits_left : int; {register} + htbl : d_derived_tbl_ptr; + min_bits : int) : int; + +{ Compute the derived values for a Huffman table. + Note this is also used by jdphuff.c. } + +{GLOBAL} +procedure jpeg_make_d_derived_tbl (cinfo : j_decompress_ptr; + isDC : boolean; + tblno : int; + var pdtbl : d_derived_tbl_ptr); + +{ Load up the bit buffer to a depth of at least nbits } + +function jpeg_fill_bit_buffer (var state : bitread_working_state; + get_buffer : bit_buf_type; {register} + bits_left : int; {register} + nbits : int) : boolean; + +implementation + +{$IFDEF MACRO} + +{ Macros to declare and load/save bitread local variables. } +{$define BITREAD_STATE_VARS} + get_buffer : bit_buf_type ; {register} + bits_left : int; {register} + br_state : bitread_working_state; + +{$define BITREAD_LOAD_STATE(cinfop,permstate)} + br_state.cinfo := cinfop; + br_state.next_input_byte := cinfop^.src^.next_input_byte; + br_state.bytes_in_buffer := cinfop^.src^.bytes_in_buffer; + get_buffer := permstate.get_buffer; + bits_left := permstate.bits_left; + +{$define BITREAD_SAVE_STATE(cinfop,permstate) } + cinfop^.src^.next_input_byte := br_state.next_input_byte; + cinfop^.src^.bytes_in_buffer := br_state.bytes_in_buffer; + permstate.get_buffer := get_buffer; + permstate.bits_left := bits_left; + + +{ These macros provide the in-line portion of bit fetching. + Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer + before using GET_BITS, PEEK_BITS, or DROP_BITS. + The variables get_buffer and bits_left are assumed to be locals, + but the state struct might not be (jpeg_huff_decode needs this). + CHECK_BIT_BUFFER(state,n,action); + Ensure there are N bits in get_buffer; if suspend, take action. + val = GET_BITS(n); + Fetch next N bits. + val = PEEK_BITS(n); + Fetch next N bits without removing them from the buffer. + DROP_BITS(n); + Discard next N bits. + The value N should be a simple variable, not an expression, because it + is evaluated multiple times. } + + +{$define CHECK_BIT_BUFFER(state,nbits,action)} + if (bits_left < (nbits)) then + begin + if (not jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) then + begin + action; + exit; + end; + get_buffer := state.get_buffer; + bits_left := state.bits_left; + end; + + +{$define GET_BITS(nbits)} + Dec(bits_left, (nbits)); + ( (int(get_buffer shr bits_left)) and ( pred(1 shl (nbits)) ) ) + +{$define PEEK_BITS(nbits)} + int(get_buffer shr (bits_left - (nbits))) and pred(1 shl (nbits)) + +{$define DROP_BITS(nbits)} + Dec(bits_left, nbits); + + + + +{ Code for extracting next Huffman-coded symbol from input bit stream. + Again, this is time-critical and we make the main paths be macros. + + We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits + without looping. Usually, more than 95% of the Huffman codes will be 8 + or fewer bits long. The few overlength codes are handled with a loop, + which need not be inline code. + + Notes about the HUFF_DECODE macro: + 1. Near the end of the data segment, we may fail to get enough bits + for a lookahead. In that case, we do it the hard way. + 2. If the lookahead table contains no entry, the next code must be + more than HUFF_LOOKAHEAD bits long. + 3. jpeg_huff_decode returns -1 if forced to suspend. } + + + + +macro HUFF_DECODE(s,br_state,htbl,return FALSE,slowlabel); +label showlabel; +var + nb, look : int; {register} +begin + if (bits_left < HUFF_LOOKAHEAD) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) then + begin + decode_mcu := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + if (bits_left < HUFF_LOOKAHEAD) then + begin + nb := 1; + goto slowlabel; + end; + end; + {look := PEEK_BITS(HUFF_LOOKAHEAD);} + look := int(get_buffer shr (bits_left - HUFF_LOOKAHEAD)) and + pred(1 shl HUFF_LOOKAHEAD); + + nb := htbl^.look_nbits[look]; + if (nb <> 0) then + begin + {DROP_BITS(nb);} + Dec(bits_left, nb); + + s := htbl^.look_sym[look]; + end + else + begin + nb := HUFF_LOOKAHEAD+1; +slowlabel: + s := jpeg_huff_decode(br_state,get_buffer,bits_left,htbl,nb)); + if (s < 0) then + begin + result := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; +end; + + +{$ENDIF} {MACRO} + +{ Expanded entropy decoder object for Huffman decoding. + + The savable_state subrecord contains fields that change within an MCU, + but must not be updated permanently until we complete the MCU. } + +type + savable_state = record + last_dc_val : array[0..MAX_COMPS_IN_SCAN-1] of int; { last DC coef for each component } + end; + + +type + huff_entropy_ptr = ^huff_entropy_decoder; + huff_entropy_decoder = record + pub : jpeg_entropy_decoder; { public fields } + + { These fields are loaded into local variables at start of each MCU. + In case of suspension, we exit WITHOUT updating them. } + + bitstate : bitread_perm_state; { Bit buffer at start of MCU } + saved : savable_state; { Other state at start of MCU } + + { These fields are NOT loaded into local working state. } + restarts_to_go : uInt; { MCUs left in this restart interval } + + { Pointers to derived tables (these workspaces have image lifespan) } + dc_derived_tbls : array[0..NUM_HUFF_TBLS] of d_derived_tbl_ptr; + ac_derived_tbls : array[0..NUM_HUFF_TBLS] of d_derived_tbl_ptr; + + { Precalculated info set up by start_pass for use in decode_mcu: } + + { Pointers to derived tables to be used for each block within an MCU } + dc_cur_tbls : array[0..D_MAX_BLOCKS_IN_MCU-1] of d_derived_tbl_ptr; + ac_cur_tbls : array[0..D_MAX_BLOCKS_IN_MCU-1] of d_derived_tbl_ptr; + { Whether we care about the DC and AC coefficient values for each block } + dc_needed : array[0..D_MAX_BLOCKS_IN_MCU-1] of boolean; + ac_needed : array[0..D_MAX_BLOCKS_IN_MCU-1] of boolean; + end; + + + +{ Initialize for a Huffman-compressed scan. } + +{METHODDEF} +procedure start_pass_huff_decoder (cinfo : j_decompress_ptr); +var + entropy : huff_entropy_ptr; + ci, blkn, dctbl, actbl : int; + compptr : jpeg_component_info_ptr; +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + + { Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG. + This ought to be an error condition, but we make it a warning because + there are some baseline files out there with all zeroes in these bytes. } + + if (cinfo^.Ss <> 0) or (cinfo^.Se <> DCTSIZE2-1) or + (cinfo^.Ah <> 0) or (cinfo^.Al <> 0) then + WARNMS(j_common_ptr(cinfo), JWRN_NOT_SEQUENTIAL); + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + dctbl := compptr^.dc_tbl_no; + actbl := compptr^.ac_tbl_no; + { Compute derived values for Huffman tables } + { We may do this more than once for a table, but it's not expensive } + jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl, + entropy^.dc_derived_tbls[dctbl]); + jpeg_make_d_derived_tbl(cinfo, FALSE, actbl, + entropy^.ac_derived_tbls[actbl]); + { Initialize DC predictions to 0 } + entropy^.saved.last_dc_val[ci] := 0; + end; + + { Precalculate decoding info for each block in an MCU of this scan } + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + ci := cinfo^.MCU_membership[blkn]; + compptr := cinfo^.cur_comp_info[ci]; + { Precalculate which table to use for each block } + entropy^.dc_cur_tbls[blkn] := entropy^.dc_derived_tbls[compptr^.dc_tbl_no]; + entropy^.ac_cur_tbls[blkn] := entropy^.ac_derived_tbls[compptr^.ac_tbl_no]; + { Decide whether we really care about the coefficient values } + if (compptr^.component_needed) then + begin + entropy^.dc_needed[blkn] := TRUE; + { we don't need the ACs if producing a 1/8th-size image } + entropy^.ac_needed[blkn] := (compptr^.DCT_scaled_size > 1); + end + else + begin + entropy^.ac_needed[blkn] := FALSE; + entropy^.dc_needed[blkn] := FALSE; + end; + end; + + { Initialize bitread state variables } + entropy^.bitstate.bits_left := 0; + entropy^.bitstate.get_buffer := 0; { unnecessary, but keeps Purify quiet } + entropy^.pub.insufficient_data := FALSE; + + { Initialize restart counter } + entropy^.restarts_to_go := cinfo^.restart_interval; +end; + + +{ Compute the derived values for a Huffman table. + This routine also performs some validation checks on the table. + + Note this is also used by jdphuff.c. } + +{GLOBAL} +procedure jpeg_make_d_derived_tbl (cinfo : j_decompress_ptr; + isDC : boolean; + tblno : int; + var pdtbl : d_derived_tbl_ptr); +var + htbl : JHUFF_TBL_PTR; + dtbl : d_derived_tbl_ptr; + p, i, l, si, numsymbols : int; + lookbits, ctr : int; + huffsize : array[0..257-1] of byte; + huffcode : array[0..257-1] of uInt; + code : uInt; +var + sym : int; +begin + { Note that huffsize[] and huffcode[] are filled in code-length order, + paralleling the order of the symbols themselves in htbl^.huffval[]. } + + { Find the input Huffman table } + if (tblno < 0) or (tblno >= NUM_HUFF_TBLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, tblno); + if isDC then + htbl := cinfo^.dc_huff_tbl_ptrs[tblno] + else + htbl := cinfo^.ac_huff_tbl_ptrs[tblno]; + if (htbl = NIL) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_HUFF_TABLE, tblno); + + { Allocate a workspace if we haven't already done so. } + if (pdtbl = NIL) then + pdtbl := d_derived_tbl_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(d_derived_tbl)) ); + dtbl := pdtbl; + dtbl^.pub := htbl; { fill in back link } + + { Figure C.1: make table of Huffman code length for each symbol } + + p := 0; + for l := 1 to 16 do + begin + i := int(htbl^.bits[l]); + if (i < 0) or (p + i > 256) then { protect against table overrun } + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + while (i > 0) do + begin + huffsize[p] := byte(l); + Inc(p); + Dec(i); + end; + end; + huffsize[p] := 0; + numsymbols := p; + + { Figure C.2: generate the codes themselves } + { We also validate that the counts represent a legal Huffman code tree. } + + code := 0; + si := huffsize[0]; + p := 0; + while (huffsize[p] <> 0) do + begin + while (( int (huffsize[p]) ) = si) do + begin + huffcode[p] := code; + Inc(p); + Inc(code); + end; + { code is now 1 more than the last code used for codelength si; but + it must still fit in si bits, since no code is allowed to be all ones. } + + if (INT32(code) >= (INT32(1) shl si)) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + + code := code shl 1; + Inc(si); + end; + + { Figure F.15: generate decoding tables for bit-sequential decoding } + + p := 0; + for l := 1 to 16 do + begin + if (htbl^.bits[l] <> 0) then + begin + { valoffset[l] = huffval[] index of 1st symbol of code length l, + minus the minimum code of length l } + + dtbl^.valoffset[l] := INT32(p) - INT32(huffcode[p]); + Inc(p, htbl^.bits[l]); + dtbl^.maxcode[l] := huffcode[p-1]; { maximum code of length l } + end + else + begin + dtbl^.maxcode[l] := -1; { -1 if no codes of this length } + end; + end; + dtbl^.maxcode[17] := long($FFFFF); { ensures jpeg_huff_decode terminates } + + { Compute lookahead tables to speed up decoding. + First we set all the table entries to 0, indicating "too long"; + then we iterate through the Huffman codes that are short enough and + fill in all the entries that correspond to bit sequences starting + with that code. } + + MEMZERO(@dtbl^.look_nbits, SIZEOF(dtbl^.look_nbits)); + + p := 0; + for l := 1 to HUFF_LOOKAHEAD do + begin + for i := 1 to int (htbl^.bits[l]) do + begin + { l := current code's length, p := its index in huffcode[] & huffval[]. } + { Generate left-justified code followed by all possible bit sequences } + lookbits := huffcode[p] shl (HUFF_LOOKAHEAD-l); + for ctr := pred(1 shl (HUFF_LOOKAHEAD-l)) downto 0 do + begin + dtbl^.look_nbits[lookbits] := l; + dtbl^.look_sym[lookbits] := htbl^.huffval[p]; + Inc(lookbits); + end; + Inc(p); + end; + end; + + { Validate symbols as being reasonable. + For AC tables, we make no check, but accept all byte values 0..255. + For DC tables, we require the symbols to be in range 0..15. + (Tighter bounds could be applied depending on the data depth and mode, + but this is sufficient to ensure safe decoding.) } + + if (isDC) then + begin + for i := 0 to pred(numsymbols) do + begin + sym := htbl^.huffval[i]; + if (sym < 0) or (sym > 15) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + end; + end; +end; + + +{ Out-of-line code for bit fetching (shared with jdphuff.c). + See jdhuff.h for info about usage. + Note: current values of get_buffer and bits_left are passed as parameters, + but are returned in the corresponding fields of the state struct. + + On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width + of get_buffer to be used. (On machines with wider words, an even larger + buffer could be used.) However, on some machines 32-bit shifts are + quite slow and take time proportional to the number of places shifted. + (This is true with most PC compilers, for instance.) In this case it may + be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the + average shift distance at the cost of more calls to jpeg_fill_bit_buffer. } + +{$ifdef SLOW_SHIFT_32} +const + MIN_GET_BITS = 15; { minimum allowable value } +{$else} +const + MIN_GET_BITS = (BIT_BUF_SIZE-7); +{$endif} + + +{GLOBAL} +function jpeg_fill_bit_buffer (var state : bitread_working_state; + {register} get_buffer : bit_buf_type; + {register} bits_left : int; + nbits : int) : boolean; +label + no_more_bytes; +{ Load up the bit buffer to a depth of at least nbits } +var + { Copy heavily used state fields into locals (hopefully registers) } + {register} next_input_byte : {const} JOCTETptr; + {register} bytes_in_buffer : size_t; +var + {register} c : int; +var + cinfo : j_decompress_ptr; +begin + next_input_byte := state.next_input_byte; + bytes_in_buffer := state.bytes_in_buffer; + cinfo := state.cinfo; + + { Attempt to load at least MIN_GET_BITS bits into get_buffer. } + { (It is assumed that no request will be for more than that many bits.) } + { We fail to do so only if we hit a marker or are forced to suspend. } + + if (cinfo^.unread_marker = 0) then { cannot advance past a marker } + begin + while (bits_left < MIN_GET_BITS) do + begin + { Attempt to read a byte } + if (bytes_in_buffer = 0) then + begin + if not cinfo^.src^.fill_input_buffer(cinfo) then + begin + jpeg_fill_bit_buffer := FALSE; + exit; + end; + next_input_byte := cinfo^.src^.next_input_byte; + bytes_in_buffer := cinfo^.src^.bytes_in_buffer; + end; + Dec(bytes_in_buffer); + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + + { If it's $FF, check and discard stuffed zero byte } + if (c = $FF) then + begin + { Loop here to discard any padding FF's on terminating marker, + so that we can save a valid unread_marker value. NOTE: we will + accept multiple FF's followed by a 0 as meaning a single FF data + byte. This data pattern is not valid according to the standard. } + + repeat + if (bytes_in_buffer = 0) then + begin + if (not state.cinfo^.src^.fill_input_buffer (state.cinfo)) then + begin + jpeg_fill_bit_buffer := FALSE; + exit; + end; + next_input_byte := state.cinfo^.src^.next_input_byte; + bytes_in_buffer := state.cinfo^.src^.bytes_in_buffer; + end; + Dec(bytes_in_buffer); + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + Until (c <> $FF); + + if (c = 0) then + begin + { Found FF/00, which represents an FF data byte } + c := $FF; + end + else + begin + { Oops, it's actually a marker indicating end of compressed data. + Save the marker code for later use. + Fine point: it might appear that we should save the marker into + bitread working state, not straight into permanent state. But + once we have hit a marker, we cannot need to suspend within the + current MCU, because we will read no more bytes from the data + source. So it is OK to update permanent state right away. } + + cinfo^.unread_marker := c; + { See if we need to insert some fake zero bits. } + goto no_more_bytes; + end; + end; + + { OK, load c into get_buffer } + get_buffer := (get_buffer shl 8) or c; + Inc(bits_left, 8); + end { end while } + end + else + begin + no_more_bytes: + { We get here if we've read the marker that terminates the compressed + data segment. There should be enough bits in the buffer register + to satisfy the request; if so, no problem. } + + if (nbits > bits_left) then + begin + { Uh-oh. Report corrupted data to user and stuff zeroes into + the data stream, so that we can produce some kind of image. + We use a nonvolatile flag to ensure that only one warning message + appears per data segment. } + + if not cinfo^.entropy^.insufficient_data then + begin + WARNMS(j_common_ptr(cinfo), JWRN_HIT_MARKER); + cinfo^.entropy^.insufficient_data := TRUE; + end; + { Fill the buffer with zero bits } + get_buffer := get_buffer shl (MIN_GET_BITS - bits_left); + bits_left := MIN_GET_BITS; + end; + end; + + { Unload the local registers } + state.next_input_byte := next_input_byte; + state.bytes_in_buffer := bytes_in_buffer; + state.get_buffer := get_buffer; + state.bits_left := bits_left; + + jpeg_fill_bit_buffer := TRUE; +end; + + +{ Out-of-line code for Huffman code decoding. + See jdhuff.h for info about usage. } + +{GLOBAL} +function jpeg_huff_decode (var state : bitread_working_state; + {register} get_buffer : bit_buf_type; + {register} bits_left : int; + htbl : d_derived_tbl_ptr; + min_bits : int) : int; +var + {register} l : int; + {register} code : INT32; +begin + l := min_bits; + + { HUFF_DECODE has determined that the code is at least min_bits } + { bits long, so fetch that many bits in one swoop. } + + {CHECK_BIT_BUFFER(state, l, return -1);} + if (bits_left < l) then + begin + if (not jpeg_fill_bit_buffer(state, get_buffer, bits_left, l)) then + begin + jpeg_huff_decode := -1; + exit; + end; + get_buffer := state.get_buffer; + bits_left := state.bits_left; + end; + + {code := GET_BITS(l);} + Dec(bits_left, l); + code := (int(get_buffer shr bits_left)) and ( pred(1 shl l) ); + + { Collect the rest of the Huffman code one bit at a time. } + { This is per Figure F.16 in the JPEG spec. } + + while (code > htbl^.maxcode[l]) do + begin + code := code shl 1; + {CHECK_BIT_BUFFER(state, 1, return -1);} + if (bits_left < 1) then + begin + if (not jpeg_fill_bit_buffer(state, get_buffer, bits_left, 1)) then + begin + jpeg_huff_decode := -1; + exit; + end; + get_buffer := state.get_buffer; + bits_left := state.bits_left; + end; + + {code := code or GET_BITS(1);} + Dec(bits_left); + code := code or ( (int(get_buffer shr bits_left)) and pred(1 shl 1) ); + + Inc(l); + end; + + { Unload the local registers } + state.get_buffer := get_buffer; + state.bits_left := bits_left; + + { With garbage input we may reach the sentinel value l := 17. } + + if (l > 16) then + begin + WARNMS(j_common_ptr(state.cinfo), JWRN_HUFF_BAD_CODE); + jpeg_huff_decode := 0; { fake a zero as the safest result } + exit; + end; + + jpeg_huff_decode := htbl^.pub^.huffval[ int (code + htbl^.valoffset[l]) ]; +end; + + +{ Figure F.12: extend sign bit. + On some machines, a shift and add will be faster than a table lookup. } + +{$ifdef AVOID_TABLES} + +#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) + +{$else} + +{$define HUFF_EXTEND(x,s) + if (x < extend_test[s]) then + := x + extend_offset[s] + else + x;} + +const + extend_test : array[0..16-1] of int = { entry n is 2**(n-1) } + ($0000, $0001, $0002, $0004, $0008, $0010, $0020, $0040, + $0080, $0100, $0200, $0400, $0800, $1000, $2000, $4000); + +const + extend_offset : array[0..16-1] of int = { entry n is (-1 << n) + 1 } +(0, ((-1) shl 1) + 1, ((-1) shl 2) + 1, ((-1) shl 3) + 1, ((-1) shl 4) + 1, + ((-1) shl 5) + 1, ((-1) shl 6) + 1, ((-1) shl 7) + 1, ((-1) shl 8) + 1, + ((-1) shl 9) + 1, ((-1) shl 10) + 1, ((-1) shl 11) + 1,((-1) shl 12) + 1, + ((-1) shl 13) + 1, ((-1) shl 14) + 1, ((-1) shl 15) + 1); + +{$endif} { AVOID_TABLES } + + +{ Check for a restart marker & resynchronize decoder. + Returns FALSE if must suspend. } + +{LOCAL} +function process_restart (cinfo : j_decompress_ptr) : boolean; +var + entropy : huff_entropy_ptr; + ci : int; +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + + { Throw away any unused bits remaining in bit buffer; } + { include any full bytes in next_marker's count of discarded bytes } + Inc(cinfo^.marker^.discarded_bytes, entropy^.bitstate.bits_left div 8); + entropy^.bitstate.bits_left := 0; + + { Advance past the RSTn marker } + if (not cinfo^.marker^.read_restart_marker (cinfo)) then + begin + process_restart := FALSE; + exit; + end; + + { Re-initialize DC predictions to 0 } + for ci := 0 to pred(cinfo^.comps_in_scan) do + entropy^.saved.last_dc_val[ci] := 0; + + { Reset restart counter } + entropy^.restarts_to_go := cinfo^.restart_interval; + + { Reset out-of-data flag, unless read_restart_marker left us smack up + against a marker. In that case we will end up treating the next data + segment as empty, and we can avoid producing bogus output pixels by + leaving the flag set. } + + if (cinfo^.unread_marker = 0) then + entropy^.pub.insufficient_data := FALSE; + + process_restart := TRUE; +end; + + +{ Decode and return one MCU's worth of Huffman-compressed coefficients. + The coefficients are reordered from zigzag order into natural array order, + but are not dequantized. + + The i'th block of the MCU is stored into the block pointed to by + MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. + (Wholesale zeroing is usually a little faster than retail...) + + Returns FALSE if data source requested suspension. In that case no + changes have been made to permanent state. (Exception: some output + coefficients may already have been assigned. This is harmless for + this module, since we'll just re-assign them on the next call.) } + +{METHODDEF} +function decode_mcu (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; +label + label1, label2, label3; +var + entropy : huff_entropy_ptr; + {register} s, k, r : int; + blkn, ci : int; + block : JBLOCK_PTR; + {BITREAD_STATE_VARS} + get_buffer : bit_buf_type ; {register} + bits_left : int; {register} + br_state : bitread_working_state; + + state : savable_state; + dctbl : d_derived_tbl_ptr; + actbl : d_derived_tbl_ptr; +var + nb, look : int; {register} +begin + entropy := huff_entropy_ptr (cinfo^.entropy); + + { Process restart marker if needed; may have to suspend } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + if (not process_restart(cinfo)) then + begin + decode_mcu := FALSE; + exit; + end; + end; + + { If we've run out of data, just leave the MCU set to zeroes. + This way, we return uniform gray for the remainder of the segment. } + + if not entropy^.pub.insufficient_data then + begin + + { Load up working state } + {BITREAD_LOAD_STATE(cinfo,entropy^.bitstate);} + br_state.cinfo := cinfo; + br_state.next_input_byte := cinfo^.src^.next_input_byte; + br_state.bytes_in_buffer := cinfo^.src^.bytes_in_buffer; + get_buffer := entropy^.bitstate.get_buffer; + bits_left := entropy^.bitstate.bits_left; + + {ASSIGN_STATE(state, entropy^.saved);} + state := entropy^.saved; + + { Outer loop handles each block in the MCU } + + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + block := JBLOCK_PTR(MCU_data[blkn]); + dctbl := entropy^.dc_cur_tbls[blkn]; + actbl := entropy^.ac_cur_tbls[blkn]; + + { Decode a single block's worth of coefficients } + + { Section F.2.2.1: decode the DC coefficient difference } + {HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);} + if (bits_left < HUFF_LOOKAHEAD) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) then + begin + decode_mcu := False; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + if (bits_left < HUFF_LOOKAHEAD) then + begin + nb := 1; + goto label1; + end; + end; + {look := PEEK_BITS(HUFF_LOOKAHEAD);} + look := int(get_buffer shr (bits_left - HUFF_LOOKAHEAD)) and + pred(1 shl HUFF_LOOKAHEAD); + + nb := dctbl^.look_nbits[look]; + if (nb <> 0) then + begin + {DROP_BITS(nb);} + Dec(bits_left, nb); + + s := dctbl^.look_sym[look]; + end + else + begin + nb := HUFF_LOOKAHEAD+1; + label1: + s := jpeg_huff_decode(br_state,get_buffer,bits_left,dctbl,nb); + if (s < 0) then + begin + decode_mcu := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + if (s <> 0) then + begin + {CHECK_BIT_BUFFER(br_state, s, return FALSE);} + if (bits_left < s) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) then + begin + decode_mcu := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {r := GET_BITS(s);} + Dec(bits_left, s); + r := ( int(get_buffer shr bits_left)) and ( pred(1 shl s) ); + + {s := HUFF_EXTEND(r, s);} + if (r < extend_test[s]) then + s := r + extend_offset[s] + else + s := r; + end; + + if (entropy^.dc_needed[blkn]) then + begin + { Convert DC difference to actual value, update last_dc_val } + ci := cinfo^.MCU_membership[blkn]; + Inc(s, state.last_dc_val[ci]); + state.last_dc_val[ci] := s; + { Output the DC coefficient (assumes jpeg_natural_order[0] := 0) } + block^[0] := JCOEF (s); + end; + + if (entropy^.ac_needed[blkn]) then + begin + + { Section F.2.2.2: decode the AC coefficients } + { Since zeroes are skipped, output area must be cleared beforehand } + k := 1; + while (k < DCTSIZE2) do { Nomssi: k is incr. in the loop } + begin + {HUFF_DECODE(s, br_state, actbl, return FALSE, label2);} + if (bits_left < HUFF_LOOKAHEAD) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) then + begin + decode_mcu := False; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + if (bits_left < HUFF_LOOKAHEAD) then + begin + nb := 1; + goto label2; + end; + end; + {look := PEEK_BITS(HUFF_LOOKAHEAD);} + look := int(get_buffer shr (bits_left - HUFF_LOOKAHEAD)) and + pred(1 shl HUFF_LOOKAHEAD); + + nb := actbl^.look_nbits[look]; + if (nb <> 0) then + begin + {DROP_BITS(nb);} + Dec(bits_left, nb); + + s := actbl^.look_sym[look]; + end + else + begin + nb := HUFF_LOOKAHEAD+1; + label2: + s := jpeg_huff_decode(br_state,get_buffer,bits_left,actbl,nb); + if (s < 0) then + begin + decode_mcu := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + r := s shr 4; + s := s and 15; + + if (s <> 0) then + begin + Inc(k, r); + {CHECK_BIT_BUFFER(br_state, s, return FALSE);} + if (bits_left < s) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) then + begin + decode_mcu := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {r := GET_BITS(s);} + Dec(bits_left, s); + r := (int(get_buffer shr bits_left)) and ( pred(1 shl s) ); + + {s := HUFF_EXTEND(r, s);} + if (r < extend_test[s]) then + s := r + extend_offset[s] + else + s := r; + { Output coefficient in natural (dezigzagged) order. + Note: the extra entries in jpeg_natural_order[] will save us + if k >= DCTSIZE2, which could happen if the data is corrupted. } + + block^[jpeg_natural_order[k]] := JCOEF (s); + end + else + begin + if (r <> 15) then + break; + Inc(k, 15); + end; + Inc(k); + end; + end + else + begin + + { Section F.2.2.2: decode the AC coefficients } + { In this path we just discard the values } + k := 1; + while (k < DCTSIZE2) do + begin + {HUFF_DECODE(s, br_state, actbl, return FALSE, label3);} + if (bits_left < HUFF_LOOKAHEAD) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) then + begin + decode_mcu := False; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + if (bits_left < HUFF_LOOKAHEAD) then + begin + nb := 1; + goto label3; + end; + end; + {look := PEEK_BITS(HUFF_LOOKAHEAD);} + look := int(get_buffer shr (bits_left - HUFF_LOOKAHEAD)) and + pred(1 shl HUFF_LOOKAHEAD); + + nb := actbl^.look_nbits[look]; + if (nb <> 0) then + begin + {DROP_BITS(nb);} + Dec(bits_left, nb); + + s := actbl^.look_sym[look]; + end + else + begin + nb := HUFF_LOOKAHEAD+1; + label3: + s := jpeg_huff_decode(br_state,get_buffer,bits_left,actbl,nb); + if (s < 0) then + begin + decode_mcu := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + r := s shr 4; + s := s and 15; + + if (s <> 0) then + begin + Inc(k, r); + {CHECK_BIT_BUFFER(br_state, s, return FALSE);} + if (bits_left < s) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) then + begin + decode_mcu := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {DROP_BITS(s);} + Dec(bits_left, s); + end + else + begin + if (r <> 15) then + break; + Inc(k, 15); + end; + Inc(k); + end; + + end; + end; + + { Completed MCU, so update state } + {BITREAD_SAVE_STATE(cinfo,entropy^.bitstate);} + cinfo^.src^.next_input_byte := br_state.next_input_byte; + cinfo^.src^.bytes_in_buffer := br_state.bytes_in_buffer; + entropy^.bitstate.get_buffer := get_buffer; + entropy^.bitstate.bits_left := bits_left; + + {ASSIGN_STATE(entropy^.saved, state);} + entropy^.saved := state; + + end; + + { Account for restart interval (no-op if not using restarts) } + Dec(entropy^.restarts_to_go); + + decode_mcu := TRUE; +end; + + +{ Module initialization routine for Huffman entropy decoding. } + +{GLOBAL} +procedure jinit_huff_decoder (cinfo : j_decompress_ptr); +var + entropy : huff_entropy_ptr; + i : int; +begin + entropy := huff_entropy_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(huff_entropy_decoder)) ); + cinfo^.entropy := jpeg_entropy_decoder_ptr (entropy); + entropy^.pub.start_pass := start_pass_huff_decoder; + entropy^.pub.decode_mcu := decode_mcu; + + { Mark tables unallocated } + for i := 0 to pred(NUM_HUFF_TBLS) do + begin + entropy^.dc_derived_tbls[i] := NIL; + entropy^.ac_derived_tbls[i] := NIL; + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdinput.pas b/src/lib/vampimg/JpegLib/imjdinput.pas new file mode 100644 index 0000000..98347d2 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdinput.pas @@ -0,0 +1,416 @@ +unit imjdinput; + +{ Original: jdinput.c ; Copyright (C) 1991-1997, Thomas G. Lane. } + +{ This file is part of the Independent JPEG Group's software. + For conditions of distribution and use, see the accompanying README file. + + This file contains input control logic for the JPEG decompressor. + These routines are concerned with controlling the decompressor's input + processing (marker reading and coefficient decoding). The actual input + reading is done in jdmarker.c, jdhuff.c, and jdphuff.c. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjpeglib, + imjdeferr, + imjerror, + imjinclude, imjutils; + +{ Initialize the input controller module. + This is called only once, when the decompression object is created. } + +{GLOBAL} +procedure jinit_input_controller (cinfo : j_decompress_ptr); + +implementation + +{ Private state } + +type + my_inputctl_ptr = ^my_input_controller; + my_input_controller = record + pub : jpeg_input_controller; { public fields } + + inheaders : boolean; { TRUE until first SOS is reached } + end; {my_input_controller;} + + + +{ Forward declarations } +{METHODDEF} +function consume_markers (cinfo : j_decompress_ptr) : int; forward; + + +{ Routines to calculate various quantities related to the size of the image. } + +{LOCAL} +procedure initial_setup (cinfo : j_decompress_ptr); +{ Called once, when first SOS marker is reached } +var + ci : int; + compptr : jpeg_component_info_ptr; +begin + { Make sure image isn't bigger than I can handle } + if (long(cinfo^.image_height) > long (JPEG_MAX_DIMENSION)) or + (long(cinfo^.image_width) > long(JPEG_MAX_DIMENSION)) then + ERREXIT1(j_common_ptr(cinfo), JERR_IMAGE_TOO_BIG, uInt(JPEG_MAX_DIMENSION)); + + { For now, precision must match compiled-in value... } + if (cinfo^.data_precision <> BITS_IN_JSAMPLE) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_PRECISION, cinfo^.data_precision); + + { Check that number of components won't exceed internal array sizes } + if (cinfo^.num_components > MAX_COMPONENTS) then + ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.num_components, + MAX_COMPONENTS); + + { Compute maximum sampling factors; check factor validity } + cinfo^.max_h_samp_factor := 1; + cinfo^.max_v_samp_factor := 1; + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + if (compptr^.h_samp_factor<=0) or (compptr^.h_samp_factor>MAX_SAMP_FACTOR) or + (compptr^.v_samp_factor<=0) or (compptr^.v_samp_factor>MAX_SAMP_FACTOR) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_SAMPLING); + {cinfo^.max_h_samp_factor := MAX(cinfo^.max_h_samp_factor, + compptr^.h_samp_factor); + cinfo^.max_v_samp_factor := MAX(cinfo^.max_v_samp_factor, + compptr^.v_samp_factor);} + if cinfo^.max_h_samp_factor < compptr^.h_samp_factor then + cinfo^.max_h_samp_factor := compptr^.h_samp_factor; + if cinfo^.max_v_samp_factor < compptr^.v_samp_factor then + cinfo^.max_v_samp_factor := compptr^.v_samp_factor; + Inc(compptr); + end; + + { We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE. + In the full decompressor, this will be overridden by jdmaster.c; + but in the transcoder, jdmaster.c is not used, so we must do it here. } + + cinfo^.min_DCT_scaled_size := DCTSIZE; + + { Compute dimensions of components } + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + compptr^.DCT_scaled_size := DCTSIZE; + { Size in DCT blocks } + compptr^.width_in_blocks := JDIMENSION( + jdiv_round_up( long(cinfo^.image_width) * long(compptr^.h_samp_factor), + long(cinfo^.max_h_samp_factor * DCTSIZE)) ); + compptr^.height_in_blocks := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_height) * long(compptr^.v_samp_factor), + long (cinfo^.max_v_samp_factor * DCTSIZE)) ); + { downsampled_width and downsampled_height will also be overridden by + jdmaster.c if we are doing full decompression. The transcoder library + doesn't use these values, but the calling application might. } + + { Size in samples } + compptr^.downsampled_width := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_width) * long(compptr^.h_samp_factor), + long (cinfo^.max_h_samp_factor)) ); + compptr^.downsampled_height := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_height) * long(compptr^.v_samp_factor), + long (cinfo^.max_v_samp_factor)) ); + { Mark component needed, until color conversion says otherwise } + compptr^.component_needed := TRUE; + { Mark no quantization table yet saved for component } + compptr^.quant_table := NIL; + Inc(compptr); + end; + + { Compute number of fully interleaved MCU rows. } + cinfo^.total_iMCU_rows := JDIMENSION( + jdiv_round_up(long(cinfo^.image_height), + long(cinfo^.max_v_samp_factor*DCTSIZE)) ); + + { Decide whether file contains multiple scans } + if (cinfo^.comps_in_scan < cinfo^.num_components) or + (cinfo^.progressive_mode) then + cinfo^.inputctl^.has_multiple_scans := TRUE + else + cinfo^.inputctl^.has_multiple_scans := FALSE; +end; + + +{LOCAL} +procedure per_scan_setup (cinfo : j_decompress_ptr); +{ Do computations that are needed before processing a JPEG scan } +{ cinfo^.comps_in_scan and cinfo^.cur_comp_info[] were set from SOS marker } +var + ci, mcublks, tmp : int; + compptr : jpeg_component_info_ptr; +begin + if (cinfo^.comps_in_scan = 1) then + begin + { Noninterleaved (single-component) scan } + compptr := cinfo^.cur_comp_info[0]; + + { Overall image size in MCUs } + cinfo^.MCUs_per_row := compptr^.width_in_blocks; + cinfo^.MCU_rows_in_scan := compptr^.height_in_blocks; + + { For noninterleaved scan, always one block per MCU } + compptr^.MCU_width := 1; + compptr^.MCU_height := 1; + compptr^.MCU_blocks := 1; + compptr^.MCU_sample_width := compptr^.DCT_scaled_size; + compptr^.last_col_width := 1; + { For noninterleaved scans, it is convenient to define last_row_height + as the number of block rows present in the last iMCU row. } + + tmp := int (LongInt(compptr^.height_in_blocks) mod compptr^.v_samp_factor); + if (tmp = 0) then + tmp := compptr^.v_samp_factor; + compptr^.last_row_height := tmp; + + { Prepare array describing MCU composition } + cinfo^.blocks_in_MCU := 1; + cinfo^.MCU_membership[0] := 0; + + end + else + begin + + { Interleaved (multi-component) scan } + if (cinfo^.comps_in_scan <= 0) or (cinfo^.comps_in_scan > MAX_COMPS_IN_SCAN) then + ERREXIT2(j_common_ptr(cinfo), JERR_COMPONENT_COUNT, cinfo^.comps_in_scan, + MAX_COMPS_IN_SCAN); + + { Overall image size in MCUs } + cinfo^.MCUs_per_row := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_width), + long (cinfo^.max_h_samp_factor*DCTSIZE)) ); + cinfo^.MCU_rows_in_scan := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_height), + long (cinfo^.max_v_samp_factor*DCTSIZE)) ); + + cinfo^.blocks_in_MCU := 0; + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + { Sampling factors give # of blocks of component in each MCU } + compptr^.MCU_width := compptr^.h_samp_factor; + compptr^.MCU_height := compptr^.v_samp_factor; + compptr^.MCU_blocks := compptr^.MCU_width * compptr^.MCU_height; + compptr^.MCU_sample_width := compptr^.MCU_width * compptr^.DCT_scaled_size; + { Figure number of non-dummy blocks in last MCU column & row } + tmp := int (LongInt(compptr^.width_in_blocks) mod compptr^.MCU_width); + if (tmp = 0) then + tmp := compptr^.MCU_width; + compptr^.last_col_width := tmp; + tmp := int (LongInt(compptr^.height_in_blocks) mod compptr^.MCU_height); + if (tmp = 0) then + tmp := compptr^.MCU_height; + compptr^.last_row_height := tmp; + { Prepare array describing MCU composition } + mcublks := compptr^.MCU_blocks; + if (LongInt(cinfo^.blocks_in_MCU) + mcublks > D_MAX_BLOCKS_IN_MCU) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_MCU_SIZE); + while (mcublks > 0) do + begin + Dec(mcublks); + cinfo^.MCU_membership[cinfo^.blocks_in_MCU] := ci; + Inc(cinfo^.blocks_in_MCU); + end; + end; + + end; +end; + + +{ Save away a copy of the Q-table referenced by each component present + in the current scan, unless already saved during a prior scan. + + In a multiple-scan JPEG file, the encoder could assign different components + the same Q-table slot number, but change table definitions between scans + so that each component uses a different Q-table. (The IJG encoder is not + currently capable of doing this, but other encoders might.) Since we want + to be able to dequantize all the components at the end of the file, this + means that we have to save away the table actually used for each component. + We do this by copying the table at the start of the first scan containing + the component. + The JPEG spec prohibits the encoder from changing the contents of a Q-table + slot between scans of a component using that slot. If the encoder does so + anyway, this decoder will simply use the Q-table values that were current + at the start of the first scan for the component. + + The decompressor output side looks only at the saved quant tables, + not at the current Q-table slots. } + +{LOCAL} +procedure latch_quant_tables (cinfo : j_decompress_ptr); +var + ci, qtblno : int; + compptr : jpeg_component_info_ptr; + qtbl : JQUANT_TBL_PTR; +begin + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + { No work if we already saved Q-table for this component } + if (compptr^.quant_table <> NIL) then + continue; + { Make sure specified quantization table is present } + qtblno := compptr^.quant_tbl_no; + if (qtblno < 0) or (qtblno >= NUM_QUANT_TBLS) or + (cinfo^.quant_tbl_ptrs[qtblno] = NIL) then + ERREXIT1(j_common_ptr(cinfo), JERR_NO_QUANT_TABLE, qtblno); + { OK, save away the quantization table } + qtbl := JQUANT_TBL_PTR( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(JQUANT_TBL)) ); + MEMCOPY(qtbl, cinfo^.quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL)); + compptr^.quant_table := qtbl; + end; +end; + + +{ Initialize the input modules to read a scan of compressed data. + The first call to this is done by jdmaster.c after initializing + the entire decompressor (during jpeg_start_decompress). + Subsequent calls come from consume_markers, below. } + +{METHODDEF} +procedure start_input_pass (cinfo : j_decompress_ptr); +begin + per_scan_setup(cinfo); + latch_quant_tables(cinfo); + cinfo^.entropy^.start_pass (cinfo); + cinfo^.coef^.start_input_pass (cinfo); + cinfo^.inputctl^.consume_input := cinfo^.coef^.consume_data; +end; + + +{ Finish up after inputting a compressed-data scan. + This is called by the coefficient controller after it's read all + the expected data of the scan. } + +{METHODDEF} +procedure finish_input_pass (cinfo : j_decompress_ptr); +begin + cinfo^.inputctl^.consume_input := consume_markers; +end; + + +{ Read JPEG markers before, between, or after compressed-data scans. + Change state as necessary when a new scan is reached. + Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. + + The consume_input method pointer points either here or to the + coefficient controller's consume_data routine, depending on whether + we are reading a compressed data segment or inter-segment markers. } + +{METHODDEF} +function consume_markers (cinfo : j_decompress_ptr) : int; +var + val : int; + inputctl : my_inputctl_ptr; +begin + inputctl := my_inputctl_ptr (cinfo^.inputctl); + + if (inputctl^.pub.eoi_reached) then { After hitting EOI, read no further } + begin + consume_markers := JPEG_REACHED_EOI; + exit; + end; + + val := cinfo^.marker^.read_markers (cinfo); + + case (val) of + JPEG_REACHED_SOS: { Found SOS } + begin + if (inputctl^.inheaders) then + begin { 1st SOS } + initial_setup(cinfo); + inputctl^.inheaders := FALSE; + { Note: start_input_pass must be called by jdmaster.c + before any more input can be consumed. jdapimin.c is + responsible for enforcing this sequencing. } + end + else + begin { 2nd or later SOS marker } + if (not inputctl^.pub.has_multiple_scans) then + ERREXIT(j_common_ptr(cinfo), JERR_EOI_EXPECTED); { Oops, I wasn't expecting this! } + start_input_pass(cinfo); + end; + end; + JPEG_REACHED_EOI: { Found EOI } + begin + inputctl^.pub.eoi_reached := TRUE; + if (inputctl^.inheaders) then + begin { Tables-only datastream, apparently } + if (cinfo^.marker^.saw_SOF) then + ERREXIT(j_common_ptr(cinfo), JERR_SOF_NO_SOS); + end + else + begin + { Prevent infinite loop in coef ctlr's decompress_data routine + if user set output_scan_number larger than number of scans. } + + if (cinfo^.output_scan_number > cinfo^.input_scan_number) then + cinfo^.output_scan_number := cinfo^.input_scan_number; + end; + end; + JPEG_SUSPENDED:; + end; + + consume_markers := val; +end; + + +{ Reset state to begin a fresh datastream. } + +{METHODDEF} +procedure reset_input_controller (cinfo : j_decompress_ptr); +var + inputctl : my_inputctl_ptr; +begin + inputctl := my_inputctl_ptr (cinfo^.inputctl); + + inputctl^.pub.consume_input := consume_markers; + inputctl^.pub.has_multiple_scans := FALSE; { "unknown" would be better } + inputctl^.pub.eoi_reached := FALSE; + inputctl^.inheaders := TRUE; + { Reset other modules } + cinfo^.err^.reset_error_mgr (j_common_ptr(cinfo)); + cinfo^.marker^.reset_marker_reader (cinfo); + { Reset progression state -- would be cleaner if entropy decoder did this } + cinfo^.coef_bits := NIL; +end; + + +{ Initialize the input controller module. + This is called only once, when the decompression object is created. } + +{GLOBAL} +procedure jinit_input_controller (cinfo : j_decompress_ptr); +var + inputctl : my_inputctl_ptr; +begin + { Create subobject in permanent pool } + inputctl := my_inputctl_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT, + SIZEOF(my_input_controller)) ); + cinfo^.inputctl := jpeg_input_controller_ptr(inputctl); + { Initialize method pointers } + inputctl^.pub.consume_input := consume_markers; + inputctl^.pub.reset_input_controller := reset_input_controller; + inputctl^.pub.start_input_pass := start_input_pass; + inputctl^.pub.finish_input_pass := finish_input_pass; + { Initialize state: can't use reset_input_controller since we don't + want to try to reset other modules yet. } + + inputctl^.pub.has_multiple_scans := FALSE; { "unknown" would be better } + inputctl^.pub.eoi_reached := FALSE; + inputctl^.inheaders := TRUE; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdmainct.pas b/src/lib/vampimg/JpegLib/imjdmainct.pas new file mode 100644 index 0000000..037f099 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdmainct.pas @@ -0,0 +1,610 @@ +unit imjdmainct; + + +{ This file is part of the Independent JPEG Group's software. + For conditions of distribution and use, see the accompanying README file. + + This file contains the main buffer controller for decompression. + The main buffer lies between the JPEG decompressor proper and the + post-processor; it holds downsampled data in the JPEG colorspace. + + Note that this code is bypassed in raw-data mode, since the application + supplies the equivalent of the main buffer in that case. } + +{ Original: jdmainct.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + + +{ In the current system design, the main buffer need never be a full-image + buffer; any full-height buffers will be found inside the coefficient or + postprocessing controllers. Nonetheless, the main controller is not + trivial. Its responsibility is to provide context rows for upsampling/ + rescaling, and doing this in an efficient fashion is a bit tricky. + + Postprocessor input data is counted in "row groups". A row group + is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + sample rows of each component. (We require DCT_scaled_size values to be + chosen such that these numbers are integers. In practice DCT_scaled_size + values will likely be powers of two, so we actually have the stronger + condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) + Upsampling will typically produce max_v_samp_factor pixel rows from each + row group (times any additional scale factor that the upsampler is + applying). + + The coefficient controller will deliver data to us one iMCU row at a time; + each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or + exactly min_DCT_scaled_size row groups. (This amount of data corresponds + to one row of MCUs when the image is fully interleaved.) Note that the + number of sample rows varies across components, but the number of row + groups does not. Some garbage sample rows may be included in the last iMCU + row at the bottom of the image. + + Depending on the vertical scaling algorithm used, the upsampler may need + access to the sample row(s) above and below its current input row group. + The upsampler is required to set need_context_rows TRUE at global + selection + time if so. When need_context_rows is FALSE, this controller can simply + obtain one iMCU row at a time from the coefficient controller and dole it + out as row groups to the postprocessor. + + When need_context_rows is TRUE, this controller guarantees that the buffer + passed to postprocessing contains at least one row group's worth of samples + above and below the row group(s) being processed. Note that the context + rows "above" the first passed row group appear at negative row offsets in + the passed buffer. At the top and bottom of the image, the required + context rows are manufactured by duplicating the first or last real sample + row; this avoids having special cases in the upsampling inner loops. + + The amount of context is fixed at one row group just because that's a + convenient number for this controller to work with. The existing + upsamplers really only need one sample row of context. An upsampler + supporting arbitrary output rescaling might wish for more than one row + group of context when shrinking the image; tough, we don't handle that. + (This is justified by the assumption that downsizing will be handled mostly + by adjusting the DCT_scaled_size values, so that the actual scale factor at + the upsample step needn't be much less than one.) + + To provide the desired context, we have to retain the last two row groups + of one iMCU row while reading in the next iMCU row. (The last row group + can't be processed until we have another row group for its below-context, + and so we have to save the next-to-last group too for its above-context.) + We could do this most simply by copying data around in our buffer, but + that'd be very slow. We can avoid copying any data by creating a rather + strange pointer structure. Here's how it works. We allocate a workspace + consisting of M+2 row groups (where M = min_DCT_scaled_size is the number + of row groups per iMCU row). We create two sets of redundant pointers to + the workspace. Labeling the physical row groups 0 to M+1, the synthesized + pointer lists look like this: + M+1 M-1 + master pointer --> 0 master pointer --> 0 + 1 1 + ... ... + M-3 M-3 + M-2 M + M-1 M+1 + M M-2 + M+1 M-1 + 0 0 + We read alternate iMCU rows using each master pointer; thus the last two + row groups of the previous iMCU row remain un-overwritten in the workspace. + The pointer lists are set up so that the required context rows appear to + be adjacent to the proper places when we pass the pointer lists to the + upsampler. + + The above pictures describe the normal state of the pointer lists. + At top and bottom of the image, we diddle the pointer lists to duplicate + the first or last sample row as necessary (this is cheaper than copying + sample rows around). + + This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that + situation each iMCU row provides only one row group so the buffering logic + must be different (eg, we must read two iMCU rows before we can emit the + first row group). For now, we simply do not support providing context + rows when min_DCT_scaled_size is 1. That combination seems unlikely to + be worth providing --- if someone wants a 1/8th-size preview, they probably + want it quick and dirty, so a context-free upsampler is sufficient. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, +{$ifdef QUANT_2PASS_SUPPORTED} + imjquant2, +{$endif} + imjdeferr, + imjerror, + imjpeglib; + + +{GLOBAL} +procedure jinit_d_main_controller (cinfo : j_decompress_ptr; + need_full_buffer : boolean); + + +implementation + +{ Private buffer controller object } + +type + my_main_ptr = ^my_main_controller; + my_main_controller = record + pub : jpeg_d_main_controller; { public fields } + + { Pointer to allocated workspace (M or M+2 row groups). } + buffer : array[0..MAX_COMPONENTS-1] of JSAMPARRAY; + + buffer_full : boolean; { Have we gotten an iMCU row from decoder? } + rowgroup_ctr : JDIMENSION ; { counts row groups output to postprocessor } + + { Remaining fields are only used in the context case. } + + { These are the master pointers to the funny-order pointer lists. } + xbuffer : array[0..2-1] of JSAMPIMAGE; { pointers to weird pointer lists } + + whichptr : int; { indicates which pointer set is now in use } + context_state : int; { process_data state machine status } + rowgroups_avail : JDIMENSION; { row groups available to postprocessor } + iMCU_row_ctr : JDIMENSION; { counts iMCU rows to detect image top/bot } + end; { my_main_controller; } + + +{ context_state values: } +const + CTX_PREPARE_FOR_IMCU = 0; { need to prepare for MCU row } + CTX_PROCESS_IMCU = 1; { feeding iMCU to postprocessor } + CTX_POSTPONED_ROW = 2; { feeding postponed row group } + + +{ Forward declarations } +{METHODDEF} +procedure process_data_simple_main(cinfo : j_decompress_ptr; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); forward; +{METHODDEF} +procedure process_data_context_main (cinfo : j_decompress_ptr; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); forward; + +{$ifdef QUANT_2PASS_SUPPORTED} +{METHODDEF} +procedure process_data_crank_post (cinfo : j_decompress_ptr; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); forward; +{$endif} + + +{LOCAL} +procedure alloc_funny_pointers (cinfo : j_decompress_ptr); +{ Allocate space for the funny pointer lists. + This is done only once, not once per pass. } +var + main : my_main_ptr; + ci, rgroup : int; + M : int; + compptr : jpeg_component_info_ptr; + xbuf : JSAMPARRAY; +begin + main := my_main_ptr (cinfo^.main); + M := cinfo^.min_DCT_scaled_size; + + { Get top-level space for component array pointers. + We alloc both arrays with one call to save a few cycles. } + + main^.xbuffer[0] := JSAMPIMAGE ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + cinfo^.num_components * 2 * SIZEOF(JSAMPARRAY)) ); + main^.xbuffer[1] := JSAMPIMAGE(@( main^.xbuffer[0]^[cinfo^.num_components] )); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + rgroup := (compptr^.v_samp_factor * compptr^.DCT_scaled_size) div + cinfo^.min_DCT_scaled_size; { height of a row group of component } + { Get space for pointer lists --- M+4 row groups in each list. + We alloc both pointer lists with one call to save a few cycles. } + + xbuf := JSAMPARRAY ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)) ); + Inc(JSAMPROW_PTR(xbuf), rgroup); { want one row group at negative offsets } + main^.xbuffer[0]^[ci] := xbuf; + Inc(JSAMPROW_PTR(xbuf), rgroup * (M + 4)); + main^.xbuffer[1]^[ci] := xbuf; + Inc(compptr); + end; +end; + +{LOCAL} +procedure make_funny_pointers (cinfo : j_decompress_ptr); +{ Create the funny pointer lists discussed in the comments above. + The actual workspace is already allocated (in main^.buffer), + and the space for the pointer lists is allocated too. + This routine just fills in the curiously ordered lists. + This will be repeated at the beginning of each pass. } +var + main : my_main_ptr; + ci, i, rgroup : int; + M : int; + compptr : jpeg_component_info_ptr; + buf, xbuf0, xbuf1 : JSAMPARRAY; +var + help_xbuf0 : JSAMPARRAY; { work around negative offsets } +begin + main := my_main_ptr (cinfo^.main); + M := cinfo^.min_DCT_scaled_size; + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + rgroup := (compptr^.v_samp_factor * compptr^.DCT_scaled_size) div + cinfo^.min_DCT_scaled_size; { height of a row group of component } + xbuf0 := main^.xbuffer[0]^[ci]; + xbuf1 := main^.xbuffer[1]^[ci]; + { First copy the workspace pointers as-is } + buf := main^.buffer[ci]; + for i := 0 to pred(rgroup * (M + 2)) do + begin + xbuf0^[i] := buf^[i]; + xbuf1^[i] := buf^[i]; + end; + { In the second list, put the last four row groups in swapped order } + for i := 0 to pred(rgroup * 2) do + begin + xbuf1^[rgroup*(M-2) + i] := buf^[rgroup*M + i]; + xbuf1^[rgroup*M + i] := buf^[rgroup*(M-2) + i]; + end; + { The wraparound pointers at top and bottom will be filled later + (see set_wraparound_pointers, below). Initially we want the "above" + pointers to duplicate the first actual data line. This only needs + to happen in xbuffer[0]. } + + help_xbuf0 := xbuf0; + Dec(JSAMPROW_PTR(help_xbuf0), rgroup); + + for i := 0 to pred(rgroup) do + begin + {xbuf0^[i - rgroup] := xbuf0^[0];} + help_xbuf0^[i] := xbuf0^[0]; + end; + Inc(compptr); + end; +end; + + +{LOCAL} +procedure set_wraparound_pointers (cinfo : j_decompress_ptr); +{ Set up the "wraparound" pointers at top and bottom of the pointer lists. + This changes the pointer list state from top-of-image to the normal state. } +var + main : my_main_ptr; + ci, i, rgroup : int; + M : int; + compptr : jpeg_component_info_ptr; + xbuf0, xbuf1 : JSAMPARRAY; +var + help_xbuf0, + help_xbuf1 : JSAMPARRAY; { work around negative offsets } +begin + main := my_main_ptr (cinfo^.main); + M := cinfo^.min_DCT_scaled_size; + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + rgroup := (compptr^.v_samp_factor * compptr^.DCT_scaled_size) div + cinfo^.min_DCT_scaled_size; { height of a row group of component } + xbuf0 := main^.xbuffer[0]^[ci]; + xbuf1 := main^.xbuffer[1]^[ci]; + + help_xbuf0 := xbuf0; + Dec(JSAMPROW_PTR(help_xbuf0), rgroup); + help_xbuf1 := xbuf1; + Dec(JSAMPROW_PTR(help_xbuf1), rgroup); + + for i := 0 to pred(rgroup) do + begin + {xbuf0^[i - rgroup] := xbuf0^[rgroup*(M+1) + i]; + xbuf1^[i - rgroup] := xbuf1^[rgroup*(M+1) + i];} + + help_xbuf0^[i] := xbuf0^[rgroup*(M+1) + i]; + help_xbuf1^[i] := xbuf1^[rgroup*(M+1) + i]; + + xbuf0^[rgroup*(M+2) + i] := xbuf0^[i]; + xbuf1^[rgroup*(M+2) + i] := xbuf1^[i]; + end; + Inc(compptr); + end; +end; + + +{LOCAL} +procedure set_bottom_pointers (cinfo : j_decompress_ptr); +{ Change the pointer lists to duplicate the last sample row at the bottom + of the image. whichptr indicates which xbuffer holds the final iMCU row. + Also sets rowgroups_avail to indicate number of nondummy row groups in row. } +var + main : my_main_ptr; + ci, i, rgroup, iMCUheight, rows_left : int; + compptr : jpeg_component_info_ptr; + xbuf : JSAMPARRAY; +begin + main := my_main_ptr (cinfo^.main); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Count sample rows in one iMCU row and in one row group } + iMCUheight := compptr^.v_samp_factor * compptr^.DCT_scaled_size; + rgroup := iMCUheight div cinfo^.min_DCT_scaled_size; + { Count nondummy sample rows remaining for this component } + rows_left := int (compptr^.downsampled_height mod JDIMENSION (iMCUheight)); + if (rows_left = 0) then + rows_left := iMCUheight; + { Count nondummy row groups. Should get same answer for each component, + so we need only do it once. } + if (ci = 0) then + begin + main^.rowgroups_avail := JDIMENSION ((rows_left-1) div rgroup + 1); + end; + { Duplicate the last real sample row rgroup*2 times; this pads out the + last partial rowgroup and ensures at least one full rowgroup of context. } + + xbuf := main^.xbuffer[main^.whichptr]^[ci]; + for i := 0 to pred(rgroup * 2) do + begin + xbuf^[rows_left + i] := xbuf^[rows_left-1]; + end; + Inc(compptr); + end; +end; + + +{ Initialize for a processing pass. } + +{METHODDEF} +procedure start_pass_main (cinfo : j_decompress_ptr; + pass_mode : J_BUF_MODE); +var + main : my_main_ptr; +begin + main := my_main_ptr (cinfo^.main); + + case (pass_mode) of + JBUF_PASS_THRU: + begin + if (cinfo^.upsample^.need_context_rows) then + begin + main^.pub.process_data := process_data_context_main; + make_funny_pointers(cinfo); { Create the xbuffer[] lists } + main^.whichptr := 0; { Read first iMCU row into xbuffer[0] } + main^.context_state := CTX_PREPARE_FOR_IMCU; + main^.iMCU_row_ctr := 0; + end + else + begin + { Simple case with no context needed } + main^.pub.process_data := process_data_simple_main; + end; + main^.buffer_full := FALSE; { Mark buffer empty } + main^.rowgroup_ctr := 0; + end; +{$ifdef QUANT_2PASS_SUPPORTED} + JBUF_CRANK_DEST: + { For last pass of 2-pass quantization, just crank the postprocessor } + main^.pub.process_data := process_data_crank_post; +{$endif} + else + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + end; +end; + + +{ Process some data. + This handles the simple case where no context is required. } + +{METHODDEF} +procedure process_data_simple_main (cinfo : j_decompress_ptr; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +var + main : my_main_ptr; + rowgroups_avail : JDIMENSION; +var + main_buffer_ptr : JSAMPIMAGE; +begin + main := my_main_ptr (cinfo^.main); + main_buffer_ptr := JSAMPIMAGE(@(main^.buffer)); + + { Read input data if we haven't filled the main buffer yet } + if (not main^.buffer_full) then + begin + if (cinfo^.coef^.decompress_data (cinfo, main_buffer_ptr)=0) then + exit; { suspension forced, can do nothing more } + main^.buffer_full := TRUE; { OK, we have an iMCU row to work with } + end; + + { There are always min_DCT_scaled_size row groups in an iMCU row. } + rowgroups_avail := JDIMENSION (cinfo^.min_DCT_scaled_size); + { Note: at the bottom of the image, we may pass extra garbage row groups + to the postprocessor. The postprocessor has to check for bottom + of image anyway (at row resolution), so no point in us doing it too. } + + { Feed the postprocessor } + cinfo^.post^.post_process_data (cinfo, main_buffer_ptr, + main^.rowgroup_ctr, rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + + { Has postprocessor consumed all the data yet? If so, mark buffer empty } + if (main^.rowgroup_ctr >= rowgroups_avail) then + begin + main^.buffer_full := FALSE; + main^.rowgroup_ctr := 0; + end; +end; + + +{ Process some data. + This handles the case where context rows must be provided. } + +{METHODDEF} +procedure process_data_context_main (cinfo : j_decompress_ptr; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +var + main : my_main_ptr; +begin + main := my_main_ptr (cinfo^.main); + + { Read input data if we haven't filled the main buffer yet } + if (not main^.buffer_full) then + begin + if (cinfo^.coef^.decompress_data (cinfo, + main^.xbuffer[main^.whichptr])=0) then + exit; { suspension forced, can do nothing more } + main^.buffer_full := TRUE; { OK, we have an iMCU row to work with } + Inc(main^.iMCU_row_ctr); { count rows received } + end; + + { Postprocessor typically will not swallow all the input data it is handed + in one call (due to filling the output buffer first). Must be prepared + to exit and restart. This switch lets us keep track of how far we got. + Note that each case falls through to the next on successful completion. } + + case (main^.context_state) of + CTX_POSTPONED_ROW: + begin + { Call postprocessor using previously set pointers for postponed row } + cinfo^.post^.post_process_data (cinfo, main^.xbuffer[main^.whichptr], + main^.rowgroup_ctr, main^.rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main^.rowgroup_ctr < main^.rowgroups_avail) then + exit; { Need to suspend } + main^.context_state := CTX_PREPARE_FOR_IMCU; + if (out_row_ctr >= out_rows_avail) then + exit; { Postprocessor exactly filled output buf } + end; + end; + case (main^.context_state) of + CTX_POSTPONED_ROW, + CTX_PREPARE_FOR_IMCU: {FALLTHROUGH} + begin + { Prepare to process first M-1 row groups of this iMCU row } + main^.rowgroup_ctr := 0; + main^.rowgroups_avail := JDIMENSION (cinfo^.min_DCT_scaled_size - 1); + { Check for bottom of image: if so, tweak pointers to "duplicate" + the last sample row, and adjust rowgroups_avail to ignore padding rows. } + + if (main^.iMCU_row_ctr = cinfo^.total_iMCU_rows) then + set_bottom_pointers(cinfo); + main^.context_state := CTX_PROCESS_IMCU; + + end; + end; + case (main^.context_state) of + CTX_POSTPONED_ROW, + CTX_PREPARE_FOR_IMCU, {FALLTHROUGH} + CTX_PROCESS_IMCU: + begin + { Call postprocessor using previously set pointers } + cinfo^.post^.post_process_data (cinfo, main^.xbuffer[main^.whichptr], + main^.rowgroup_ctr, main^.rowgroups_avail, + output_buf, out_row_ctr, out_rows_avail); + if (main^.rowgroup_ctr < main^.rowgroups_avail) then + exit; { Need to suspend } + { After the first iMCU, change wraparound pointers to normal state } + if (main^.iMCU_row_ctr = 1) then + set_wraparound_pointers(cinfo); + { Prepare to load new iMCU row using other xbuffer list } + main^.whichptr := main^.whichptr xor 1; { 0=>1 or 1=>0 } + main^.buffer_full := FALSE; + { Still need to process last row group of this iMCU row, } + { which is saved at index M+1 of the other xbuffer } + main^.rowgroup_ctr := JDIMENSION (cinfo^.min_DCT_scaled_size + 1); + main^.rowgroups_avail := JDIMENSION (cinfo^.min_DCT_scaled_size + 2); + main^.context_state := CTX_POSTPONED_ROW; + end; + end; +end; + + +{ Process some data. + Final pass of two-pass quantization: just call the postprocessor. + Source data will be the postprocessor controller's internal buffer. } + +{$ifdef QUANT_2PASS_SUPPORTED} + +{METHODDEF} +procedure process_data_crank_post (cinfo : j_decompress_ptr; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +var + in_row_group_ctr : JDIMENSION; +begin + in_row_group_ctr := 0; + cinfo^.post^.post_process_data (cinfo, JSAMPIMAGE (NIL), + in_row_group_ctr, + JDIMENSION(0), + output_buf, + out_row_ctr, + out_rows_avail); +end; + +{$endif} { QUANT_2PASS_SUPPORTED } + + +{ Initialize main buffer controller. } + +{GLOBAL} +procedure jinit_d_main_controller (cinfo : j_decompress_ptr; + need_full_buffer : boolean); +var + main : my_main_ptr; + ci, rgroup, ngroups : int; + compptr : jpeg_component_info_ptr; +begin + main := my_main_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_main_controller)) ); + cinfo^.main := jpeg_d_main_controller_ptr(main); + main^.pub.start_pass := start_pass_main; + + if (need_full_buffer) then { shouldn't happen } + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + + { Allocate the workspace. + ngroups is the number of row groups we need.} + + if (cinfo^.upsample^.need_context_rows) then + begin + if (cinfo^.min_DCT_scaled_size < 2) then { unsupported, see comments above } + ERREXIT(j_common_ptr(cinfo), JERR_NOTIMPL); + alloc_funny_pointers(cinfo); { Alloc space for xbuffer[] lists } + ngroups := cinfo^.min_DCT_scaled_size + 2; + end + else + begin + ngroups := cinfo^.min_DCT_scaled_size; + end; + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + rgroup := (compptr^.v_samp_factor * compptr^.DCT_scaled_size) div + cinfo^.min_DCT_scaled_size; { height of a row group of component } + main^.buffer[ci] := cinfo^.mem^.alloc_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, + compptr^.width_in_blocks * LongWord(compptr^.DCT_scaled_size), + JDIMENSION (rgroup * ngroups)); + Inc(compptr); + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdmarker.pas b/src/lib/vampimg/JpegLib/imjdmarker.pas new file mode 100644 index 0000000..b87a3dd --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdmarker.pas @@ -0,0 +1,2648 @@ +unit imjdmarker; + +{ This file contains routines to decode JPEG datastream markers. + Most of the complexity arises from our desire to support input + suspension: if not all of the data for a marker is available; + we must exit back to the application. On resumption; we reprocess + the marker. } + +{ Original: jdmarker.c; Copyright (C) 1991-1998; Thomas G. Lane. } +{ History + 9.7.96 Conversion to pascal started jnn + 22.3.98 updated to 6b jnn } + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjcomapi, + imjpeglib; + +const { JPEG marker codes } + M_SOF0 = $c0; + M_SOF1 = $c1; + M_SOF2 = $c2; + M_SOF3 = $c3; + + M_SOF5 = $c5; + M_SOF6 = $c6; + M_SOF7 = $c7; + + M_JPG = $c8; + M_SOF9 = $c9; + M_SOF10 = $ca; + M_SOF11 = $cb; + + M_SOF13 = $cd; + M_SOF14 = $ce; + M_SOF15 = $cf; + + M_DHT = $c4; + + M_DAC = $cc; + + M_RST0 = $d0; + M_RST1 = $d1; + M_RST2 = $d2; + M_RST3 = $d3; + M_RST4 = $d4; + M_RST5 = $d5; + M_RST6 = $d6; + M_RST7 = $d7; + + M_SOI = $d8; + M_EOI = $d9; + M_SOS = $da; + M_DQT = $db; + M_DNL = $dc; + M_DRI = $dd; + M_DHP = $de; + M_EXP = $df; + + M_APP0 = $e0; + M_APP1 = $e1; + M_APP2 = $e2; + M_APP3 = $e3; + M_APP4 = $e4; + M_APP5 = $e5; + M_APP6 = $e6; + M_APP7 = $e7; + M_APP8 = $e8; + M_APP9 = $e9; + M_APP10 = $ea; + M_APP11 = $eb; + M_APP12 = $ec; + M_APP13 = $ed; + M_APP14 = $ee; + M_APP15 = $ef; + + M_JPG0 = $f0; + M_JPG13 = $fd; + M_COM = $fe; + + M_TEM = $01; + + M_ERROR = $100; + +type + JPEG_MARKER = uint; { JPEG marker codes } + +{ Private state } + +type + my_marker_ptr = ^my_marker_reader; + my_marker_reader = record + pub : jpeg_marker_reader; { public fields } + + { Application-overridable marker processing methods } + process_COM : jpeg_marker_parser_method; + process_APPn : array[0..16-1] of jpeg_marker_parser_method; + + { Limit on marker data length to save for each marker type } + length_limit_COM : uint; + length_limit_APPn : array[0..16-1] of uint; + + { Status of COM/APPn marker saving } + cur_marker : jpeg_saved_marker_ptr; { NIL if not processing a marker } + bytes_read : uint; { data bytes read so far in marker } + { Note: cur_marker is not linked into marker_list until it's all read. } + end; + +{GLOBAL} +function jpeg_resync_to_restart(cinfo : j_decompress_ptr; + desired : int) : boolean; +{GLOBAL} +procedure jinit_marker_reader (cinfo : j_decompress_ptr); + +{$ifdef SAVE_MARKERS_SUPPORTED} + +{GLOBAL} +procedure jpeg_save_markers (cinfo : j_decompress_ptr; + marker_code : int; + length_limit : uint); +{$ENDIF} + +{GLOBAL} +procedure jpeg_set_marker_processor (cinfo : j_decompress_ptr; + marker_code : int; + routine : jpeg_marker_parser_method); + +implementation + +uses + imjutils; + +{ At all times, cinfo1.src.next_input_byte and .bytes_in_buffer reflect + the current restart point; we update them only when we have reached a + suitable place to restart if a suspension occurs. } + + +{ Routines to process JPEG markers. + + Entry condition: JPEG marker itself has been read and its code saved + in cinfo^.unread_marker; input restart point is just after the marker. + + Exit: if return TRUE, have read and processed any parameters, and have + updated the restart point to point after the parameters. + If return FALSE, was forced to suspend before reaching end of + marker parameters; restart point has not been moved. Same routine + will be called again after application supplies more input data. + + This approach to suspension assumes that all of a marker's parameters + can fit into a single input bufferload. This should hold for "normal" + markers. Some COM/APPn markers might have large parameter segments + that might not fit. If we are simply dropping such a marker, we use + skip_input_data to get past it, and thereby put the problem on the + source manager's shoulders. If we are saving the marker's contents + into memory, we use a slightly different convention: when forced to + suspend, the marker processor updates the restart point to the end of + what it's consumed (ie, the end of the buffer) before returning FALSE. + On resumption, cinfo->unread_marker still contains the marker code, + but the data source will point to the next chunk of marker data. + The marker processor must retain internal state to deal with this. + + Note that we don't bother to avoid duplicate trace messages if a + suspension occurs within marker parameters. Other side effects + require more care. } + +{LOCAL} +function get_soi (cinfo : j_decompress_ptr) : boolean; +{ Process an SOI marker } +var + i : int; +begin + {$IFDEF DEBUG} + TRACEMS(j_common_ptr(cinfo), 1, JTRC_SOI); + {$ENDIF} + + if (cinfo^.marker^.saw_SOI) then + ERREXIT(j_common_ptr(cinfo), JERR_SOI_DUPLICATE); + + { Reset all parameters that are defined to be reset by SOI } + + for i := 0 to Pred(NUM_ARITH_TBLS) do + with cinfo^ do + begin + arith_dc_L[i] := 0; + arith_dc_U[i] := 1; + arith_ac_K[i] := 5; + end; + cinfo^.restart_interval := 0; + + { Set initial assumptions for colorspace etc } + + with cinfo^ do + begin + jpeg_color_space := JCS_UNKNOWN; + CCIR601_sampling := FALSE; { Assume non-CCIR sampling??? } + + saw_JFIF_marker := FALSE; + JFIF_major_version := 1; { set default JFIF APP0 values } + JFIF_minor_version := 1; + density_unit := 0; + X_density := 1; + Y_density := 1; + saw_Adobe_marker := FALSE; + Adobe_transform := 0; + + marker^.saw_SOI := TRUE; + end; + get_soi := TRUE; +end; { get_soi } + + +{LOCAL} +function get_sof(cinfo : j_decompress_ptr; + is_prog : boolean; + is_arith : boolean) : boolean; +{ Process a SOFn marker } +var + length : INT32; + c, ci : int; + compptr : jpeg_component_info_ptr; +{ Declare and initialize local copies of input pointer/count } +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; +{} + cinfo^.progressive_mode := is_prog; + cinfo^.arith_code := is_arith; + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + + { Read a byte into variable cinfo^.data_precision. + If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + cinfo^.data_precision := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + +{ Read two bytes interpreted as an unsigned 16-bit integer. + cinfo^.image_height should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + cinfo^.image_height := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( cinfo^.image_height, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + +{ Read two bytes interpreted as an unsigned 16-bit integer. + cinfo^.image_width should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + cinfo^.image_width := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( cinfo^.image_width, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + { Read a byte into variable cinfo^.num_components. + If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + cinfo^.num_components := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + Dec(length, 8); + + {$IFDEF DEBUG} + TRACEMS4(j_common_ptr(cinfo), 1, JTRC_SOF, cinfo^.unread_marker, + int(cinfo^.image_width), int(cinfo^.image_height), + cinfo^.num_components); + {$ENDIF} + + if (cinfo^.marker^.saw_SOF) then + ERREXIT(j_common_ptr(cinfo), JERR_SOF_DUPLICATE); + + { We don't support files in which the image height is initially specified } + { as 0 and is later redefined by DNL. As long as we have to check that, } + { might as well have a general sanity check. } + if (cinfo^.image_height <= 0) or (cinfo^.image_width <= 0) + or (cinfo^.num_components <= 0) then + ERREXIT(j_common_ptr(cinfo), JERR_EMPTY_IMAGE); + + if (length <> (cinfo^.num_components * 3)) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH); + + if (cinfo^.comp_info = NIL) then { do only once, even if suspend } + cinfo^.comp_info := jpeg_component_info_list_ptr( + cinfo^.mem^.alloc_small(j_common_ptr(cinfo), JPOOL_IMAGE, + cinfo^.num_components * SIZEOF(jpeg_component_info))); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + compptr^.component_index := ci; + + { Read a byte into variable compptr^.component_id. + If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + compptr^.component_id := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + compptr^.h_samp_factor := (c shr 4) and 15; + compptr^.v_samp_factor := (c ) and 15; + + { Read a byte into variable compptr^.quant_tbl_no. + If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sof := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + compptr^.quant_tbl_no := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + {$IFDEF DEBUG} + TRACEMS4(j_common_ptr(cinfo), 1, JTRC_SOF_COMPONENT, + compptr^.component_id, compptr^.h_samp_factor, + compptr^.v_samp_factor, compptr^.quant_tbl_no); + {$ENDIF} + + Inc(compptr); + end; + + cinfo^.marker^.saw_SOF := TRUE; + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + get_sof := TRUE; +end; { get_sof } + + +{LOCAL} +function get_sos (cinfo : j_decompress_ptr) : boolean; +{ Process a SOS marker } +label + id_found; +var + length : INT32; + i, ci, n, c, cc : int; + compptr : jpeg_component_info_ptr; +{ Declare and initialize local copies of input pointer/count } +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; { Array[] of JOCTET; } + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + +{} + + if not cinfo^.marker^.saw_SOF then + ERREXIT(j_common_ptr(cinfo), JERR_SOS_NO_SOF); + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + + { Read a byte into variable n (Number of components). + If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + n := GETJOCTET(next_input_byte^); { Number of components } + Inc(next_input_byte); + + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_SOS, n); + {$ENDIF} + + if ((length <> (n * 2 + 6)) or (n < 1) or (n > MAX_COMPS_IN_SCAN)) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH); + + cinfo^.comps_in_scan := n; + + { Collect the component-spec parameters } + + for i := 0 to Pred(n) do + begin + { Read a byte into variable cc. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + cc := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to Pred(cinfo^.num_components) do + begin + if (cc = compptr^.component_id) then + goto id_found; + Inc(compptr); + end; + + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_COMPONENT_ID, cc); + + id_found: + + cinfo^.cur_comp_info[i] := compptr; + compptr^.dc_tbl_no := (c shr 4) and 15; + compptr^.ac_tbl_no := (c ) and 15; + + {$IFDEF DEBUG} + TRACEMS3(j_common_ptr(cinfo), 1, JTRC_SOS_COMPONENT, cc, + compptr^.dc_tbl_no, compptr^.ac_tbl_no); + {$ENDIF} + end; + + { Collect the additional scan parameters Ss, Se, Ah/Al. } + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + cinfo^.Ss := c; + + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + cinfo^.Se := c; + + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_sos := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + cinfo^.Ah := (c shr 4) and 15; + cinfo^.Al := (c ) and 15; + + {$IFDEF DEBUG} + TRACEMS4(j_common_ptr(cinfo), 1, JTRC_SOS_PARAMS, cinfo^.Ss, cinfo^.Se, + cinfo^.Ah, cinfo^.Al); + {$ENDIF} + + { Prepare to scan data & restart markers } + cinfo^.marker^.next_restart_num := 0; + + { Count another SOS marker } + Inc( cinfo^.input_scan_number ); + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + get_sos := TRUE; +end; { get_sos } + + +{METHODDEF} +function skip_variable (cinfo : j_decompress_ptr) : boolean; +{ Skip over an unknown or uninteresting variable-length marker } +var + length : INT32; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; { Array[] of JOCTET; } + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + skip_variable := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := uint(GETJOCTET(next_input_byte^)) shl 8; + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + skip_variable := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET(next_input_byte^)); + Inc( next_input_byte ); + + Dec(length, 2); + + {$IFDEF DEBUG} + TRACEMS2(j_common_ptr(cinfo), 1, JTRC_MISC_MARKER, + cinfo^.unread_marker, int(length)); + {$ENDIF} + + { Unload the local copies --- do this only at a restart boundary } + { do before skip_input_data } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + if (length > 0) then + cinfo^.src^.skip_input_data(cinfo, long(length)); + + skip_variable := TRUE; +end; { skip_variable } + + +{$IFDEF D_ARITH_CODING_SUPPORTED} + +{LOCAL} +function get_dac (cinfo : j_decompress_ptr) : boolean; +{ Process a DAC marker } +var + length : INT32; + index, val : int; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dac := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dac := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + Dec(length, 2); + + while (length > 0) do + begin + { Read a byte into variable index. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dac := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + index := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + { Read a byte into variable val. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dac := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + val := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + Dec( length, 2); + + {$IFDEF DEBUG} + TRACEMS2(j_common_ptr(cinfo), 1, JTRC_DAC, index, val); + {$ENDIF} + + if (index < 0) or (index >= (2*NUM_ARITH_TBLS)) then + ERREXIT1(j_common_ptr(cinfo) , JERR_DAC_INDEX, index); + + if (index >= NUM_ARITH_TBLS) then + begin { define AC table } + cinfo^.arith_ac_K[index-NUM_ARITH_TBLS] := UINT8(val); + end + else + begin { define DC table } + cinfo^.arith_dc_L[index] := UINT8(val and $0F); + cinfo^.arith_dc_U[index] := UINT8(val shr 4); + if (cinfo^.arith_dc_L[index] > cinfo^.arith_dc_U[index]) then + ERREXIT1(j_common_ptr(cinfo) , JERR_DAC_VALUE, val); + end; + end; + + if (length <> 0) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH); + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + get_dac := TRUE; +end; { get_dac } + +{$ELSE} + +{LOCAL} +function get_dac (cinfo : j_decompress_ptr) : boolean; +begin + get_dac := skip_variable(cinfo); +end; + +{$ENDIF} + +{LOCAL} +function get_dht (cinfo : j_decompress_ptr) : boolean; +{ Process a DHT marker } +var + length : INT32; + bits : Array[0..17-1] of UINT8; + huffval : Array[0..256-1] of UINT8; + i, index, count : int; + htblptr : ^JHUFF_TBL_PTR; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dht := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dht := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + Dec(length, 2); + + while (length > 16) do + begin + { Read a byte into variable index. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dht := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + index := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_DHT, index); + {$ENDIF} + + bits[0] := 0; + count := 0; + for i := 1 to 16 do + begin + { Read a byte into variable bits[i]. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dht := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + bits[i] := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + Inc( count, bits[i] ); + end; + + Dec( length, (1 + 16) ); + + {$IFDEF DEBUG} + TRACEMS8(j_common_ptr(cinfo), 2, JTRC_HUFFBITS, + bits[1], bits[2], bits[3], bits[4], + bits[5], bits[6], bits[7], bits[8]); + TRACEMS8(j_common_ptr(cinfo), 2, JTRC_HUFFBITS, + bits[9], bits[10], bits[11], bits[12], + bits[13], bits[14], bits[15], bits[16]); + {$ENDIF} + + { Here we just do minimal validation of the counts to avoid walking + off the end of our table space. jdhuff.c will check more carefully. } + + if (count > 256) or (INT32(count) > length) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_HUFF_TABLE); + + for i := 0 to Pred(count) do + begin + { Read a byte into variable huffval[i]. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dht := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + huffval[i] := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + end; + + Dec( length, count ); + + if (index and $10)<>0 then + begin { AC table definition } + Dec( index, $10 ); + htblptr := @cinfo^.ac_huff_tbl_ptrs[index]; + end + else + begin { DC table definition } + htblptr := @cinfo^.dc_huff_tbl_ptrs[index]; + end; + + if (index < 0) or (index >= NUM_HUFF_TBLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_DHT_INDEX, index); + + if (htblptr^ = NIL) then + htblptr^ := jpeg_alloc_huff_table(j_common_ptr(cinfo)); + + MEMCOPY(@(htblptr^)^.bits, @bits, SIZEOF((htblptr^)^.bits)); + MEMCOPY(@(htblptr^)^.huffval, @huffval, SIZEOF((htblptr^)^.huffval)); + end; + + if (length <> 0) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH); + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + get_dht := TRUE; +end; { get_dht } + + +{LOCAL} +function get_dqt (cinfo : j_decompress_ptr) : boolean; +{ Process a DQT marker } +var + length : INT32; + n, i, prec : int; + tmp : uint; + quant_ptr : JQUANT_TBL_PTR; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dqt := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dqt := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + Dec( length, 2 ); + + while (length > 0) do + begin + { Read a byte into variable n. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dqt := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + n := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + prec := n shr 4; + n := n and $0F; + + {$IFDEF DEBUG} + TRACEMS2(j_common_ptr(cinfo), 1, JTRC_DQT, n, prec); + {$ENDIF} + + if (n >= NUM_QUANT_TBLS) then + ERREXIT1(j_common_ptr(cinfo) , JERR_DQT_INDEX, n); + + if (cinfo^.quant_tbl_ptrs[n] = NIL) then + cinfo^.quant_tbl_ptrs[n] := jpeg_alloc_quant_table(j_common_ptr(cinfo)); + quant_ptr := cinfo^.quant_tbl_ptrs[n]; + + for i := 0 to Pred(DCTSIZE2) do + begin + if (prec <> 0) then + begin + { Read two bytes interpreted as an unsigned 16-bit integer. + tmp should be declared unsigned int or perhaps INT32. } + + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dqt := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + tmp := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dqt := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( tmp, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + end + else + begin + { Read a byte into variable tmp. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dqt := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + tmp := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + end; + + { We convert the zigzag-order table to natural array order. } + quant_ptr^.quantval[jpeg_natural_order[i]] := UINT16(tmp); + end; + + if (cinfo^.err^.trace_level >= 2) then + begin + i := 0; + while i < Pred(DCTSIZE2) do + begin + {$IFDEF DEBUG} + TRACEMS8(j_common_ptr(cinfo), 2, JTRC_QUANTVALS, + quant_ptr^.quantval[i], quant_ptr^.quantval[i+1], + quant_ptr^.quantval[i+2], quant_ptr^.quantval[i+3], + quant_ptr^.quantval[i+4], quant_ptr^.quantval[i+5], + quant_ptr^.quantval[i+6], quant_ptr^.quantval[i+7]); + {$ENDIF} + Inc(i, 8); + end; + end; + + Dec( length, DCTSIZE2+1 ); + if (prec <> 0) then + Dec( length, DCTSIZE2 ); + end; + + if (length <> 0) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH); + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + get_dqt := TRUE; +end; { get_dqt } + + +{LOCAL} +function get_dri (cinfo : j_decompress_ptr) : boolean; +{ Process a DRI marker } +var + length : INT32; + tmp : uint; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dri := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dri := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + if (length <> 4) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_LENGTH); + +{ Read two bytes interpreted as an unsigned 16-bit integer. + tmp should be declared unsigned int or perhaps INT32. } + +{ make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dri := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + tmp := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_dri := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( tmp, GETJOCTET( next_input_byte^)); + Inc( next_input_byte ); + + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_DRI, tmp); + {$ENDIF} + + cinfo^.restart_interval := tmp; + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + get_dri := TRUE; +end; { get_dri } + + +{ Routines for processing APPn and COM markers. + These are either saved in memory or discarded, per application request. + APP0 and APP14 are specially checked to see if they are + JFIF and Adobe markers, respectively. } + +const + APP0_DATA_LEN = 14; { Length of interesting data in APP0 } + APP14_DATA_LEN = 12; { Length of interesting data in APP14 } + APPN_DATA_LEN = 14; { Must be the largest of the above!! } + + +{LOCAL} +procedure examine_app0 (cinfo : j_decompress_ptr; + var data : array of JOCTET; + datalen : uint; + remaining : INT32); + +{ Examine first few bytes from an APP0. + Take appropriate action if it is a JFIF marker. + datalen is # of bytes at data[], remaining is length of rest of marker data. +} +{$IFDEF DEBUG} +var + totallen : INT32; +{$ENDIF} +begin + {$IFDEF DEBUG} + totallen := INT32(datalen) + remaining; + {$ENDIF} + if (datalen >= APP0_DATA_LEN) and + (GETJOCTET(data[0]) = $4A) and + (GETJOCTET(data[1]) = $46) and + (GETJOCTET(data[2]) = $49) and + (GETJOCTET(data[3]) = $46) and + (GETJOCTET(data[4]) = 0) then + begin + { Found JFIF APP0 marker: save info } + cinfo^.saw_JFIF_marker := TRUE; + cinfo^.JFIF_major_version := GETJOCTET(data[5]); + cinfo^.JFIF_minor_version := GETJOCTET(data[6]); + cinfo^.density_unit := GETJOCTET(data[7]); + cinfo^.X_density := (GETJOCTET(data[8]) shl 8) + GETJOCTET(data[9]); + cinfo^.Y_density := (GETJOCTET(data[10]) shl 8) + GETJOCTET(data[11]); + { Check version. + Major version must be 1, anything else signals an incompatible change. + (We used to treat this as an error, but now it's a nonfatal warning, + because some bozo at Hijaak couldn't read the spec.) + Minor version should be 0..2, but process anyway if newer. } + + if (cinfo^.JFIF_major_version <> 1) then + WARNMS2(j_common_ptr(cinfo), JWRN_JFIF_MAJOR, + cinfo^.JFIF_major_version, cinfo^.JFIF_minor_version); + { Generate trace messages } + {$IFDEF DEBUG} + TRACEMS5(j_common_ptr(cinfo), 1, JTRC_JFIF, + cinfo^.JFIF_major_version, cinfo^.JFIF_minor_version, + cinfo^.X_density, cinfo^.Y_density, cinfo^.density_unit); + { Validate thumbnail dimensions and issue appropriate messages } + if (GETJOCTET(data[12]) or GETJOCTET(data[13])) <> 0 then + TRACEMS2(j_common_ptr(cinfo), 1, JTRC_JFIF_THUMBNAIL, + GETJOCTET(data[12]), GETJOCTET(data[13])); + Dec(totallen, APP0_DATA_LEN); + if (totallen <> + ( INT32(GETJOCTET(data[12])) * INT32(GETJOCTET(data[13])) * INT32(3) )) then + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_JFIF_BADTHUMBNAILSIZE, int(totallen)); + {$ENDIF} + end + else + if (datalen >= 6) and + (GETJOCTET(data[0]) = $4A) and + (GETJOCTET(data[1]) = $46) and + (GETJOCTET(data[2]) = $58) and + (GETJOCTET(data[3]) = $58) and + (GETJOCTET(data[4]) = 0) then + begin + { Found JFIF "JFXX" extension APP0 marker } + { The library doesn't actually do anything with these, + but we try to produce a helpful trace message. } + {$IFDEF DEBUG} + case (GETJOCTET(data[5])) of + $10: + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_THUMB_JPEG, int(totallen)); + $11: + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_THUMB_PALETTE, int(totallen)); + $13: + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_THUMB_RGB, int(totallen)); + else + TRACEMS2(j_common_ptr(cinfo), 1, JTRC_JFIF_EXTENSION, + GETJOCTET(data[5]), int(totallen)); + end; + {$ENDIF} + end + else + begin + { Start of APP0 does not match "JFIF" or "JFXX", or too short } + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_APP0, int(totallen)); + {$ENDIF} + end; +end; + + +{LOCAL} +procedure examine_app14 (cinfo : j_decompress_ptr; + var data : array of JOCTET; + datalen : uint; + remaining : INT32); +{ Examine first few bytes from an APP14. + Take appropriate action if it is an Adobe marker. + datalen is # of bytes at data[], remaining is length of rest of marker data. + } +var + {$IFDEF DEBUG} + version, flags0, flags1, + {$ENDIF} + transform : uint; +begin + if (datalen >= APP14_DATA_LEN) and + (GETJOCTET(data[0]) = $41) and + (GETJOCTET(data[1]) = $64) and + (GETJOCTET(data[2]) = $6F) and + (GETJOCTET(data[3]) = $62) and + (GETJOCTET(data[4]) = $65) then + begin + { Found Adobe APP14 marker } + {$IFDEF DEBUG} + version := (GETJOCTET(data[5]) shl 8) + GETJOCTET(data[6]); + flags0 := (GETJOCTET(data[7]) shl 8) + GETJOCTET(data[8]); + flags1 := (GETJOCTET(data[9]) shl 8) + GETJOCTET(data[10]); + {$ENDIF} + transform := GETJOCTET(data[11]); + {$IFDEF DEBUG} + TRACEMS4(j_common_ptr(cinfo), 1, JTRC_ADOBE, version, flags0, flags1, transform); + {$ENDIF} + cinfo^.saw_Adobe_marker := TRUE; + cinfo^.Adobe_transform := UINT8 (transform); + end + else + begin + { Start of APP14 does not match "Adobe", or too short } + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_APP14, int (datalen + remaining)); + {$ENDIF} + end; +end; + + +{METHODDEF} +function get_interesting_appn (cinfo : j_decompress_ptr) : boolean; +{ Process an APP0 or APP14 marker without saving it } +var + length : INT32; + b : array[0..APPN_DATA_LEN-1] of JOCTET; + i, numtoread: uint; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + +{ Read two bytes interpreted as an unsigned 16-bit integer. + length should be declared unsigned int or perhaps INT32. } + + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_interesting_appn := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_interesting_appn := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET(next_input_byte^)); + Inc( next_input_byte ); + + Dec(length, 2); + + { get the interesting part of the marker data } + if (length >= APPN_DATA_LEN) then + numtoread := APPN_DATA_LEN + else + if (length > 0) then + numtoread := uint(length) + else + numtoread := 0; + + if numtoread > 0 then + begin + for i := 0 to numtoread-1 do + begin + { Read a byte into b[i]. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + get_interesting_appn := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + b[i] := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + end; + end; + + Dec(length, numtoread); + + { process it } + case (cinfo^.unread_marker) of + M_APP0: + examine_app0(cinfo, b, numtoread, length); + M_APP14: + examine_app14(cinfo, b, numtoread, length); + else + { can't get here unless jpeg_save_markers chooses wrong processor } + ERREXIT1(j_common_ptr(cinfo), JERR_UNKNOWN_MARKER, cinfo^.unread_marker); + end; + + { skip any remaining data -- could be lots } + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + if (length > 0) then + cinfo^.src^.skip_input_data(cinfo, long(length)); + + get_interesting_appn := TRUE; +end; + +{$ifdef SAVE_MARKERS_SUPPORTED} + +{METHODDEF} +function save_marker (cinfo : j_decompress_ptr) : boolean; +{ Save an APPn or COM marker into the marker list } +var + marker : my_marker_ptr; + cur_marker : jpeg_saved_marker_ptr; + bytes_read, data_length : uint; + data : JOCTET_FIELD_PTR; + length : INT32; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +var + limit : uint; +var + prev : jpeg_saved_marker_ptr; +begin + { local copies of input pointer/count } + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + + marker := my_marker_ptr(cinfo^.marker); + cur_marker := marker^.cur_marker; + length := 0; + + if (cur_marker = NIL) then + begin + { begin reading a marker } + { Read two bytes interpreted as an unsigned 16-bit integer. } + + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + save_marker := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + length := (uint( GETJOCTET(next_input_byte^)) shl 8); + Inc( next_input_byte ); + + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + save_marker := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + Inc( length, GETJOCTET(next_input_byte^)); + Inc( next_input_byte ); + + Dec(length, 2); + if (length >= 0) then + begin { watch out for bogus length word } + { figure out how much we want to save } + + if (cinfo^.unread_marker = int(M_COM)) then + limit := marker^.length_limit_COM + else + limit := marker^.length_limit_APPn[cinfo^.unread_marker - int(M_APP0)]; + if (uint(length) < limit) then + limit := uint(length); + { allocate and initialize the marker item } + cur_marker := jpeg_saved_marker_ptr( + cinfo^.mem^.alloc_large (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(jpeg_marker_struct) + limit) ); + cur_marker^.next := NIL; + cur_marker^.marker := UINT8 (cinfo^.unread_marker); + cur_marker^.original_length := uint(length); + cur_marker^.data_length := limit; + { data area is just beyond the jpeg_marker_struct } + cur_marker^.data := JOCTET_FIELD_PTR(cur_marker); + Inc(jpeg_saved_marker_ptr(cur_marker^.data)); + data := cur_marker^.data; + + marker^.cur_marker := cur_marker; + marker^.bytes_read := 0; + bytes_read := 0; + data_length := limit; + end + else + begin + { deal with bogus length word } + data_length := 0; + bytes_read := 0; + data := NIL; + end + end + else + begin + { resume reading a marker } + bytes_read := marker^.bytes_read; + data_length := cur_marker^.data_length; + data := cur_marker^.data; + Inc(data, bytes_read); + end; + + while (bytes_read < data_length) do + begin + { move the restart point to here } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + marker^.bytes_read := bytes_read; + { If there's not at least one byte in buffer, suspend } + if (bytes_in_buffer = 0) then + begin + if not datasrc^.fill_input_buffer (cinfo) then + begin + save_marker := FALSE; + exit; + end; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + + { Copy bytes with reasonable rapidity } + while (bytes_read < data_length) and (bytes_in_buffer > 0) do + begin + JOCTETPTR(data)^ := next_input_byte^; + Inc(JOCTETPTR(data)); + Inc(next_input_byte); + Dec(bytes_in_buffer); + Inc(bytes_read); + end; + end; + + { Done reading what we want to read } + if (cur_marker <> NIL) then + begin { will be NIL if bogus length word } + { Add new marker to end of list } + if (cinfo^.marker_list = NIL) then + begin + cinfo^.marker_list := cur_marker + end + else + begin + prev := cinfo^.marker_list; + while (prev^.next <> NIL) do + prev := prev^.next; + prev^.next := cur_marker; + end; + { Reset pointer & calc remaining data length } + data := cur_marker^.data; + length := cur_marker^.original_length - data_length; + end; + { Reset to initial state for next marker } + marker^.cur_marker := NIL; + + { Process the marker if interesting; else just make a generic trace msg } + case (cinfo^.unread_marker) of + M_APP0: + examine_app0(cinfo, data^, data_length, length); + M_APP14: + examine_app14(cinfo, data^, data_length, length); + else + {$IFDEF DEBUG} + TRACEMS2(j_common_ptr(cinfo), 1, JTRC_MISC_MARKER, cinfo^.unread_marker, + int(data_length + length)); + {$ENDIF} + end; + + { skip any remaining data -- could be lots } + { do before skip_input_data } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + if (length > 0) then + cinfo^.src^.skip_input_data (cinfo, long(length) ); + + save_marker := TRUE; +end; + +{$endif} { SAVE_MARKERS_SUPPORTED } + + +{ Find the next JPEG marker, save it in cinfo^.unread_marker. + Returns FALSE if had to suspend before reaching a marker; + in that case cinfo^.unread_marker is unchanged. + + Note that the result might not be a valid marker code, + but it will never be 0 or FF. } + +{LOCAL} +function next_marker (cinfo : j_decompress_ptr) : boolean; +var + c : int; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + + {while TRUE do} + repeat + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + next_marker := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + { Skip any non-FF bytes. + This may look a bit inefficient, but it will not occur in a valid file. + We sync after each discarded byte so that a suspending data source + can discard the byte from its buffer. } + + while (c <> $FF) do + begin + Inc(cinfo^.marker^.discarded_bytes); + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + next_marker := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + end; + { This loop swallows any duplicate FF bytes. Extra FFs are legal as + pad bytes, so don't count them in discarded_bytes. We assume there + will not be so many consecutive FF bytes as to overflow a suspending + data source's input buffer. } + + repeat + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + next_marker := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + Until (c <> $FF); + if (c <> 0) then + break; { found a valid marker, exit loop } + { Reach here if we found a stuffed-zero data sequence (FF/00). + Discard it and loop back to try again. } + + Inc(cinfo^.marker^.discarded_bytes, 2); + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + Until False; + + if (cinfo^.marker^.discarded_bytes <> 0) then + begin + WARNMS2(j_common_ptr(cinfo), JWRN_EXTRANEOUS_DATA, + cinfo^.marker^.discarded_bytes, c); + cinfo^.marker^.discarded_bytes := 0; + end; + + cinfo^.unread_marker := c; + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + next_marker := TRUE; +end; { next_marker } + + +{LOCAL} +function first_marker (cinfo : j_decompress_ptr) : boolean; +{ Like next_marker, but used to obtain the initial SOI marker. } +{ For this marker, we do not allow preceding garbage or fill; otherwise, + we might well scan an entire input file before realizing it ain't JPEG. + If an application wants to process non-JFIF files, it must seek to the + SOI before calling the JPEG library. } +var + c, c2 : int; +var + datasrc : jpeg_source_mgr_ptr; + next_input_byte : JOCTETptr; + bytes_in_buffer : size_t; +begin + datasrc := cinfo^.src; + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + + { Read a byte into variable c. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + first_marker := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + { Read a byte into variable c2. If must suspend, return FALSE. } + { make a byte available. + Note we do *not* do INPUT_SYNC before calling fill_input_buffer, + but we must reload the local copies after a successful fill. } + if (bytes_in_buffer = 0) then + begin + if (not datasrc^.fill_input_buffer(cinfo)) then + begin + first_marker := FALSE; + exit; + end; + { Reload the local copies } + next_input_byte := datasrc^.next_input_byte; + bytes_in_buffer := datasrc^.bytes_in_buffer; + end; + Dec( bytes_in_buffer ); + + c2 := GETJOCTET(next_input_byte^); + Inc(next_input_byte); + + if (c <> $FF) or (c2 <> int(M_SOI)) then + ERREXIT2(j_common_ptr(cinfo), JERR_NO_SOI, c, c2); + + cinfo^.unread_marker := c2; + + { Unload the local copies --- do this only at a restart boundary } + datasrc^.next_input_byte := next_input_byte; + datasrc^.bytes_in_buffer := bytes_in_buffer; + + first_marker := TRUE; +end; { first_marker } + + +{ Read markers until SOS or EOI. + + Returns same codes as are defined for jpeg_consume_input: + JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. } + +{METHODDEF} +function read_markers (cinfo : j_decompress_ptr) : int; +begin + { Outer loop repeats once for each marker. } + repeat + { Collect the marker proper, unless we already did. } + { NB: first_marker() enforces the requirement that SOI appear first. } + if (cinfo^.unread_marker = 0) then + begin + if not cinfo^.marker^.saw_SOI then + begin + if not first_marker(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + end + else + begin + if not next_marker(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + end; + end; + { At this point cinfo^.unread_marker contains the marker code and the + input point is just past the marker proper, but before any parameters. + A suspension will cause us to return with this state still true. } + + case (cinfo^.unread_marker) of + M_SOI: + if not get_soi(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_SOF0, { Baseline } + M_SOF1: { Extended sequential, Huffman } + if not get_sof(cinfo, FALSE, FALSE) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + M_SOF2: { Progressive, Huffman } + if not get_sof(cinfo, TRUE, FALSE) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_SOF9: { Extended sequential, arithmetic } + if not get_sof(cinfo, FALSE, TRUE) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_SOF10: { Progressive, arithmetic } + if not get_sof(cinfo, TRUE, TRUE) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + { Currently unsupported SOFn types } + M_SOF3, { Lossless, Huffman } + M_SOF5, { Differential sequential, Huffman } + M_SOF6, { Differential progressive, Huffman } + M_SOF7, { Differential lossless, Huffman } + M_JPG, { Reserved for JPEG extensions } + M_SOF11, { Lossless, arithmetic } + M_SOF13, { Differential sequential, arithmetic } + M_SOF14, { Differential progressive, arithmetic } + M_SOF15: { Differential lossless, arithmetic } + ERREXIT1(j_common_ptr(cinfo), JERR_SOF_UNSUPPORTED, cinfo^.unread_marker); + + M_SOS: + begin + if not get_sos(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + cinfo^.unread_marker := 0; { processed the marker } + read_markers := JPEG_REACHED_SOS; + exit; + end; + + M_EOI: + begin + {$IFDEF DEBUG} + TRACEMS(j_common_ptr(cinfo), 1, JTRC_EOI); + {$ENDIF} + cinfo^.unread_marker := 0; { processed the marker } + read_markers := JPEG_REACHED_EOI; + exit; + end; + + M_DAC: + if not get_dac(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_DHT: + if not get_dht(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_DQT: + if not get_dqt(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_DRI: + if not get_dri(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_APP0, + M_APP1, + M_APP2, + M_APP3, + M_APP4, + M_APP5, + M_APP6, + M_APP7, + M_APP8, + M_APP9, + M_APP10, + M_APP11, + M_APP12, + M_APP13, + M_APP14, + M_APP15: + if not my_marker_ptr(cinfo^.marker)^. + process_APPn[cinfo^.unread_marker - int(M_APP0)](cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_COM: + if not my_marker_ptr(cinfo^.marker)^.process_COM (cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + M_RST0, { these are all parameterless } + M_RST1, + M_RST2, + M_RST3, + M_RST4, + M_RST5, + M_RST6, + M_RST7, + M_TEM: + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_PARMLESS_MARKER, + cinfo^.unread_marker) + {$ENDIF} + ; + + M_DNL: { Ignore DNL ... perhaps the wrong thing } + if not skip_variable(cinfo) then + begin + read_markers := JPEG_SUSPENDED; + exit; + end; + + else { must be DHP, EXP, JPGn, or RESn } + { For now, we treat the reserved markers as fatal errors since they are + likely to be used to signal incompatible JPEG Part 3 extensions. + Once the JPEG 3 version-number marker is well defined, this code + ought to change! } + ERREXIT1(j_common_ptr(cinfo) , JERR_UNKNOWN_MARKER, + cinfo^.unread_marker); + end; { end of case } + { Successfully processed marker, so reset state variable } + cinfo^.unread_marker := 0; + Until false; +end; { read_markers } + + +{ Read a restart marker, which is expected to appear next in the datastream; + if the marker is not there, take appropriate recovery action. + Returns FALSE if suspension is required. + + This is called by the entropy decoder after it has read an appropriate + number of MCUs. cinfo^.unread_marker may be nonzero if the entropy decoder + has already read a marker from the data source. Under normal conditions + cinfo^.unread_marker will be reset to 0 before returning; if not reset, + it holds a marker which the decoder will be unable to read past. } + +{METHODDEF} +function read_restart_marker (cinfo : j_decompress_ptr) :boolean; +begin + { Obtain a marker unless we already did. } + { Note that next_marker will complain if it skips any data. } + if (cinfo^.unread_marker = 0) then + begin + if not next_marker(cinfo) then + begin + read_restart_marker := FALSE; + exit; + end; + end; + + if (cinfo^.unread_marker = (int(M_RST0) + cinfo^.marker^.next_restart_num)) then + begin + { Normal case --- swallow the marker and let entropy decoder continue } + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 3, JTRC_RST, + cinfo^.marker^.next_restart_num); + {$ENDIF} + cinfo^.unread_marker := 0; + end + else + begin + { Uh-oh, the restart markers have been messed up. } + { Let the data source manager determine how to resync. } + if not cinfo^.src^.resync_to_restart(cinfo, + cinfo^.marker^.next_restart_num) then + begin + read_restart_marker := FALSE; + exit; + end; + end; + + { Update next-restart state } + with cinfo^.marker^ do + next_restart_num := (next_restart_num + 1) and 7; + + read_restart_marker := TRUE; +end; { read_restart_marker } + + +{ This is the default resync_to_restart method for data source managers + to use if they don't have any better approach. Some data source managers + may be able to back up, or may have additional knowledge about the data + which permits a more intelligent recovery strategy; such managers would + presumably supply their own resync method. + + read_restart_marker calls resync_to_restart if it finds a marker other than + the restart marker it was expecting. (This code is *not* used unless + a nonzero restart interval has been declared.) cinfo^.unread_marker is + the marker code actually found (might be anything, except 0 or FF). + The desired restart marker number (0..7) is passed as a parameter. + This routine is supposed to apply whatever error recovery strategy seems + appropriate in order to position the input stream to the next data segment. + Note that cinfo^.unread_marker is treated as a marker appearing before + the current data-source input point; usually it should be reset to zero + before returning. + Returns FALSE if suspension is required. + + This implementation is substantially constrained by wanting to treat the + input as a data stream; this means we can't back up. Therefore, we have + only the following actions to work with: + 1. Simply discard the marker and let the entropy decoder resume at next + byte of file. + 2. Read forward until we find another marker, discarding intervening + data. (In theory we could look ahead within the current bufferload, + without having to discard data if we don't find the desired marker. + This idea is not implemented here, in part because it makes behavior + dependent on buffer size and chance buffer-boundary positions.) + 3. Leave the marker unread (by failing to zero cinfo^.unread_marker). + This will cause the entropy decoder to process an empty data segment, + inserting dummy zeroes, and then we will reprocess the marker. + + #2 is appropriate if we think the desired marker lies ahead, while #3 is + appropriate if the found marker is a future restart marker (indicating + that we have missed the desired restart marker, probably because it got + corrupted). + We apply #2 or #3 if the found marker is a restart marker no more than + two counts behind or ahead of the expected one. We also apply #2 if the + found marker is not a legal JPEG marker code (it's certainly bogus data). + If the found marker is a restart marker more than 2 counts away, we do #1 + (too much risk that the marker is erroneous; with luck we will be able to + resync at some future point). + For any valid non-restart JPEG marker, we apply #3. This keeps us from + overrunning the end of a scan. An implementation limited to single-scan + files might find it better to apply #2 for markers other than EOI, since + any other marker would have to be bogus data in that case. } + + +{GLOBAL} +function jpeg_resync_to_restart(cinfo : j_decompress_ptr; + desired : int) : boolean; +var + marker : int; + action : int; +begin + marker := cinfo^.unread_marker; + //action := 1; { never used } + { Always put up a warning. } + WARNMS2(j_common_ptr(cinfo), JWRN_MUST_RESYNC, marker, desired); + + { Outer loop handles repeated decision after scanning forward. } + repeat + if (marker < int(M_SOF0)) then + action := 2 { invalid marker } + else + if (marker < int(M_RST0)) or (marker > int(M_RST7)) then + action := 3 { valid non-restart marker } + else + begin + if (marker = (int(M_RST0) + ((desired+1) and 7))) or + (marker = (int(M_RST0) + ((desired+2) and 7))) then + action := 3 { one of the next two expected restarts } + else + if (marker = (int(M_RST0) + ((desired-1) and 7))) or + (marker = (int(M_RST0) + ((desired-2) and 7))) then + action := 2 { a prior restart, so advance } + else + action := 1; { desired restart or too far away } + end; + + {$IFDEF DEBUG} + TRACEMS2(j_common_ptr(cinfo), 4, JTRC_RECOVERY_ACTION, marker, action); + {$ENDIF} + case action of + 1: + { Discard marker and let entropy decoder resume processing. } + begin + cinfo^.unread_marker := 0; + jpeg_resync_to_restart := TRUE; + exit; + end; + 2: + { Scan to the next marker, and repeat the decision loop. } + begin + if not next_marker(cinfo) then + begin + jpeg_resync_to_restart := FALSE; + exit; + end; + marker := cinfo^.unread_marker; + end; + 3: + { Return without advancing past this marker. } + { Entropy decoder will be forced to process an empty segment. } + begin + jpeg_resync_to_restart := TRUE; + exit; + end; + end; { case } + Until false; { end loop } +end; { jpeg_resync_to_restart } + + +{ Reset marker processing state to begin a fresh datastream. } + +{METHODDEF} +procedure reset_marker_reader (cinfo : j_decompress_ptr); +var + marker : my_marker_ptr; +begin + marker := my_marker_ptr (cinfo^.marker); + with cinfo^ do + begin + comp_info := NIL; { until allocated by get_sof } + input_scan_number := 0; { no SOS seen yet } + unread_marker := 0; { no pending marker } + end; + marker^.pub.saw_SOI := FALSE; { set internal state too } + marker^.pub.saw_SOF := FALSE; + marker^.pub.discarded_bytes := 0; + marker^.cur_marker := NIL; +end; { reset_marker_reader } + + +{ Initialize the marker reader module. + This is called only once, when the decompression object is created. } + +{GLOBAL} +procedure jinit_marker_reader (cinfo : j_decompress_ptr); +var + marker : my_marker_ptr; + i : int; +begin + { Create subobject in permanent pool } + marker := my_marker_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_PERMANENT, + SIZEOF(my_marker_reader)) + ); + cinfo^.marker := jpeg_marker_reader_ptr(marker); + { Initialize method pointers } + marker^.pub.reset_marker_reader := reset_marker_reader; + marker^.pub.read_markers := read_markers; + marker^.pub.read_restart_marker := read_restart_marker; + { Initialize COM/APPn processing. + By default, we examine and then discard APP0 and APP14, + but simply discard COM and all other APPn. } + + marker^.process_COM := skip_variable; + marker^.length_limit_COM := 0; + for i := 0 to 16-1 do + begin + marker^.process_APPn[i] := skip_variable; + marker^.length_limit_APPn[i] := 0; + end; + marker^.process_APPn[0] := get_interesting_appn; + marker^.process_APPn[14] := get_interesting_appn; + { Reset marker processing state } + reset_marker_reader(cinfo); +end; { jinit_marker_reader } + + +{ Control saving of COM and APPn markers into marker_list. } + + +{$ifdef SAVE_MARKERS_SUPPORTED} + +{GLOBAL} +procedure jpeg_save_markers (cinfo : j_decompress_ptr; + marker_code : int; + length_limit : uint); +var + marker : my_marker_ptr; + maxlength : long; + processor : jpeg_marker_parser_method; +begin + marker := my_marker_ptr (cinfo^.marker); + + { Length limit mustn't be larger than what we can allocate + (should only be a concern in a 16-bit environment). } + + maxlength := cinfo^.mem^.max_alloc_chunk - SIZEOF(jpeg_marker_struct); + if (long(length_limit) > maxlength) then + length_limit := uint(maxlength); + + { Choose processor routine to use. + APP0/APP14 have special requirements. } + + if (length_limit <> 0) then + begin + processor := save_marker; + { If saving APP0/APP14, save at least enough for our internal use. } + if (marker_code = int(M_APP0)) and (length_limit < APP0_DATA_LEN) then + length_limit := APP0_DATA_LEN + else + if (marker_code = int(M_APP14)) and (length_limit < APP14_DATA_LEN) then + length_limit := APP14_DATA_LEN; + end + else + begin + processor := skip_variable; + { If discarding APP0/APP14, use our regular on-the-fly processor. } + if (marker_code = int(M_APP0)) or (marker_code = int(M_APP14)) then + processor := get_interesting_appn; + end; + + if (marker_code = int(M_COM)) then + begin + marker^.process_COM := processor; + marker^.length_limit_COM := length_limit; + end + else + if (marker_code >= int(M_APP0)) and (marker_code <= int(M_APP15)) then + begin + marker^.process_APPn[marker_code - int(M_APP0)] := processor; + marker^.length_limit_APPn[marker_code - int(M_APP0)] := length_limit; + end + else + ERREXIT1(j_common_ptr(cinfo), JERR_UNKNOWN_MARKER, marker_code); +end; + +{$endif} { SAVE_MARKERS_SUPPORTED } + +{ Install a special processing method for COM or APPn markers. } + +{GLOBAL} + +procedure jpeg_set_marker_processor (cinfo : j_decompress_ptr; + marker_code : int; + routine : jpeg_marker_parser_method); +var + marker : my_marker_ptr; +begin + marker := my_marker_ptr (cinfo^.marker); + if (marker_code = int(M_COM)) then + marker^.process_COM := routine + else + if (marker_code >= int(M_APP0)) and (marker_code <= int(M_APP15)) then + marker^.process_APPn[marker_code - int(M_APP0)] := routine + else + ERREXIT1(j_common_ptr(cinfo), JERR_UNKNOWN_MARKER, marker_code); +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdmaster.pas b/src/lib/vampimg/JpegLib/imjdmaster.pas new file mode 100644 index 0000000..4f233a0 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdmaster.pas @@ -0,0 +1,679 @@ +unit imjdmaster; + +{ This file contains master control logic for the JPEG decompressor. + These routines are concerned with selecting the modules to be executed + and with determining the number of passes and the work to be done in each + pass. } + +{ Original: jdmaster.c ; Copyright (C) 1991-1998, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjutils, + imjerror, + imjdeferr, + imjdcolor, imjdsample, imjdpostct, imjddctmgr, imjdphuff, + imjdhuff, imjdcoefct, imjdmainct, +{$ifdef QUANT_1PASS_SUPPORTED} + imjquant1, +{$endif} +{$ifdef QUANT_2PASS_SUPPORTED} + imjquant2, +{$endif} +{$ifdef UPSAMPLE_MERGING_SUPPORTED} + imjdmerge, +{$endif} + imjpeglib; + + +{ Compute output image dimensions and related values. + NOTE: this is exported for possible use by application. + Hence it mustn't do anything that can't be done twice. + Also note that it may be called before the master module is initialized! } + +{GLOBAL} +procedure jpeg_calc_output_dimensions (cinfo : j_decompress_ptr); +{ Do computations that are needed before master selection phase } + + +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + +{GLOBAL} +procedure jpeg_new_colormap (cinfo : j_decompress_ptr); + +{$endif} + +{ Initialize master decompression control and select active modules. + This is performed at the start of jpeg_start_decompress. } + +{GLOBAL} +procedure jinit_master_decompress (cinfo : j_decompress_ptr); + +implementation + +{ Private state } + +type + my_master_ptr = ^my_decomp_master; + my_decomp_master = record + pub : jpeg_decomp_master; { public fields } + + pass_number : int; { # of passes completed } + + using_merged_upsample : boolean; { TRUE if using merged upsample/cconvert } + + { Saved references to initialized quantizer modules, + in case we need to switch modes. } + + quantizer_1pass : jpeg_color_quantizer_ptr; + quantizer_2pass : jpeg_color_quantizer_ptr; + end; + +{ Determine whether merged upsample/color conversion should be used. + CRUCIAL: this must match the actual capabilities of jdmerge.c! } + +{LOCAL} +function use_merged_upsample (cinfo : j_decompress_ptr) : boolean; +var + compptr : jpeg_component_info_list_ptr; +begin + compptr := cinfo^.comp_info; + +{$ifdef UPSAMPLE_MERGING_SUPPORTED} + { Merging is the equivalent of plain box-filter upsampling } + if (cinfo^.do_fancy_upsampling) or (cinfo^.CCIR601_sampling) then + begin + use_merged_upsample := FALSE; + exit; + end; + { jdmerge.c only supports YCC=>RGB color conversion } + if (cinfo^.jpeg_color_space <> JCS_YCbCr) or (cinfo^.num_components <> 3) + or (cinfo^.out_color_space <> JCS_RGB) + or (cinfo^.out_color_components <> RGB_PIXELSIZE) then + begin + use_merged_upsample := FALSE; + exit; + end; + + { and it only handles 2h1v or 2h2v sampling ratios } + if (compptr^[0].h_samp_factor <> 2) or + (compptr^[1].h_samp_factor <> 1) or + (compptr^[2].h_samp_factor <> 1) or + (compptr^[0].v_samp_factor > 2) or + (compptr^[1].v_samp_factor <> 1) or + (compptr^[2].v_samp_factor <> 1) then + begin + use_merged_upsample := FALSE; + exit; + end; + { furthermore, it doesn't work if we've scaled the IDCTs differently } + if (compptr^[0].DCT_scaled_size <> cinfo^.min_DCT_scaled_size) or + (compptr^[1].DCT_scaled_size <> cinfo^.min_DCT_scaled_size) or + (compptr^[2].DCT_scaled_size <> cinfo^.min_DCT_scaled_size) then + begin + use_merged_upsample := FALSE; + exit; + end; + { ??? also need to test for upsample-time rescaling, when & if supported } + use_merged_upsample := TRUE; { by golly, it'll work... } +{$else} + use_merged_upsample := FALSE; +{$endif} +end; + + +{ Compute output image dimensions and related values. + NOTE: this is exported for possible use by application. + Hence it mustn't do anything that can't be done twice. + Also note that it may be called before the master module is initialized! } + +{GLOBAL} +procedure jpeg_calc_output_dimensions (cinfo : j_decompress_ptr); +{ Do computations that are needed before master selection phase } +{$ifdef IDCT_SCALING_SUPPORTED} +var + ci : int; + compptr : jpeg_component_info_ptr; +{$endif} +var + ssize : int; +begin + { Prevent application from calling me at wrong times } + if (cinfo^.global_state <> DSTATE_READY) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + +{$ifdef IDCT_SCALING_SUPPORTED} + + { Compute actual output image dimensions and DCT scaling choices. } + if (cinfo^.scale_num * 8 <= cinfo^.scale_denom) then + begin + { Provide 1/8 scaling } + cinfo^.output_width := JDIMENSION ( + jdiv_round_up( long(cinfo^.image_width), long(8)) ); + cinfo^.output_height := JDIMENSION ( + jdiv_round_up( long(cinfo^.image_height), long(8)) ); + cinfo^.min_DCT_scaled_size := 1; + end + else + if (cinfo^.scale_num * 4 <= cinfo^.scale_denom) then + begin + { Provide 1/4 scaling } + cinfo^.output_width := JDIMENSION ( + jdiv_round_up( long (cinfo^.image_width), long(4)) ); + cinfo^.output_height := JDIMENSION ( + jdiv_round_up( long (cinfo^.image_height), long(4)) ); + cinfo^.min_DCT_scaled_size := 2; + end + else + if (cinfo^.scale_num * 2 <= cinfo^.scale_denom) then + begin + { Provide 1/2 scaling } + cinfo^.output_width := JDIMENSION ( + jdiv_round_up( long(cinfo^.image_width), long(2)) ); + cinfo^.output_height := JDIMENSION ( + jdiv_round_up( long(cinfo^.image_height), long(2)) ); + cinfo^.min_DCT_scaled_size := 4; + end + else + begin + { Provide 1/1 scaling } + cinfo^.output_width := cinfo^.image_width; + cinfo^.output_height := cinfo^.image_height; + cinfo^.min_DCT_scaled_size := DCTSIZE; + end; + { In selecting the actual DCT scaling for each component, we try to + scale up the chroma components via IDCT scaling rather than upsampling. + This saves time if the upsampler gets to use 1:1 scaling. + Note this code assumes that the supported DCT scalings are powers of 2. } + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + ssize := cinfo^.min_DCT_scaled_size; + while (ssize < DCTSIZE) and + ((compptr^.h_samp_factor * ssize * 2 <= + cinfo^.max_h_samp_factor * cinfo^.min_DCT_scaled_size) and + (compptr^.v_samp_factor * ssize * 2 <= + cinfo^.max_v_samp_factor * cinfo^.min_DCT_scaled_size)) do + begin + ssize := ssize * 2; + end; + compptr^.DCT_scaled_size := ssize; + Inc(compptr); + end; + + { Recompute downsampled dimensions of components; + application needs to know these if using raw downsampled data. } + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Size in samples, after IDCT scaling } + compptr^.downsampled_width := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_width) * + long (compptr^.h_samp_factor * compptr^.DCT_scaled_size), + long (cinfo^.max_h_samp_factor * DCTSIZE)) ); + compptr^.downsampled_height := JDIMENSION ( + jdiv_round_up(long (cinfo^.image_height) * + long (compptr^.v_samp_factor * compptr^.DCT_scaled_size), + long (cinfo^.max_v_samp_factor * DCTSIZE)) ); + Inc(compptr); + end; + +{$else} { !IDCT_SCALING_SUPPORTED } + + { Hardwire it to "no scaling" } + cinfo^.output_width := cinfo^.image_width; + cinfo^.output_height := cinfo^.image_height; + { jdinput.c has already initialized DCT_scaled_size to DCTSIZE, + and has computed unscaled downsampled_width and downsampled_height. } + +{$endif} { IDCT_SCALING_SUPPORTED } + + { Report number of components in selected colorspace. } + { Probably this should be in the color conversion module... } + case (cinfo^.out_color_space) of + JCS_GRAYSCALE: + cinfo^.out_color_components := 1; +{$ifndef RGB_PIXELSIZE_IS_3} + JCS_RGB: + cinfo^.out_color_components := RGB_PIXELSIZE; +{$else} + JCS_RGB, +{$endif} { else share code with YCbCr } + JCS_YCbCr: + cinfo^.out_color_components := 3; + JCS_CMYK, + JCS_YCCK: + cinfo^.out_color_components := 4; + else { else must be same colorspace as in file } + cinfo^.out_color_components := cinfo^.num_components; + end; + if (cinfo^.quantize_colors) then + cinfo^.output_components := 1 + else + cinfo^.output_components := cinfo^.out_color_components; + + { See if upsampler will want to emit more than one row at a time } + if (use_merged_upsample(cinfo)) then + cinfo^.rec_outbuf_height := cinfo^.max_v_samp_factor + else + cinfo^.rec_outbuf_height := 1; +end; + + +{ Several decompression processes need to range-limit values to the range + 0..MAXJSAMPLE; the input value may fall somewhat outside this range + due to noise introduced by quantization, roundoff error, etc. These + processes are inner loops and need to be as fast as possible. On most + machines, particularly CPUs with pipelines or instruction prefetch, + a (subscript-check-less) C table lookup + x := sample_range_limit[x]; + is faster than explicit tests + if (x < 0) x := 0; + else if (x > MAXJSAMPLE) x := MAXJSAMPLE; + These processes all use a common table prepared by the routine below. + + For most steps we can mathematically guarantee that the initial value + of x is within MAXJSAMPLE+1 of the legal range, so a table running from + -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial + limiting step (just after the IDCT), a wildly out-of-range value is + possible if the input data is corrupt. To avoid any chance of indexing + off the end of memory and getting a bad-pointer trap, we perform the + post-IDCT limiting thus: + x := range_limit[x & MASK]; + where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit + samples. Under normal circumstances this is more than enough range and + a correct output will be generated; with bogus input data the mask will + cause wraparound, and we will safely generate a bogus-but-in-range output. + For the post-IDCT step, we want to convert the data from signed to unsigned + representation by adding CENTERJSAMPLE at the same time that we limit it. + So the post-IDCT limiting table ends up looking like this: + CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, + MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), + 0,1,...,CENTERJSAMPLE-1 + Negative inputs select values from the upper half of the table after + masking. + + We can save some space by overlapping the start of the post-IDCT table + with the simpler range limiting table. The post-IDCT table begins at + sample_range_limit + CENTERJSAMPLE. + + Note that the table is allocated in near data space on PCs; it's small + enough and used often enough to justify this. } + +{LOCAL} +procedure prepare_range_limit_table (cinfo : j_decompress_ptr); +{ Allocate and fill in the sample_range_limit table } +var + table : range_limit_table_ptr; + idct_table : JSAMPROW; + i : int; +begin + table := range_limit_table_ptr ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)) ); + + { First segment of "simple" table: limit[x] := 0 for x < 0 } + MEMZERO(table, (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); + + cinfo^.sample_range_limit := (table); + { allow negative subscripts of simple table } + { is noop, handled via type definition (Nomssi) } + { Main part of "simple" table: limit[x] := x } + for i := 0 to MAXJSAMPLE do + table^[i] := JSAMPLE (i); + idct_table := JSAMPROW(@ table^[CENTERJSAMPLE]); + { Point to where post-IDCT table starts } + { End of simple table, rest of first half of post-IDCT table } + for i := CENTERJSAMPLE to pred(2*(MAXJSAMPLE+1)) do + idct_table^[i] := MAXJSAMPLE; + { Second half of post-IDCT table } + MEMZERO(@(idct_table^[2 * (MAXJSAMPLE+1)]), + (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); + MEMCOPY(@(idct_table^[(4 * (MAXJSAMPLE+1) - CENTERJSAMPLE)]), + @cinfo^.sample_range_limit^[0], CENTERJSAMPLE * SIZEOF(JSAMPLE)); + +end; + + +{ Master selection of decompression modules. + This is done once at jpeg_start_decompress time. We determine + which modules will be used and give them appropriate initialization calls. + We also initialize the decompressor input side to begin consuming data. + + Since jpeg_read_header has finished, we know what is in the SOF + and (first) SOS markers. We also have all the application parameter + settings. } + +{LOCAL} +procedure master_selection (cinfo : j_decompress_ptr); +var + master : my_master_ptr; + use_c_buffer : boolean; + samplesperrow : long; + jd_samplesperrow : JDIMENSION; +var + nscans : int; +begin + master := my_master_ptr (cinfo^.master); + + { Initialize dimensions and other stuff } + jpeg_calc_output_dimensions(cinfo); + prepare_range_limit_table(cinfo); + + { Width of an output scanline must be representable as JDIMENSION. } + samplesperrow := long(cinfo^.output_width) * long (cinfo^.out_color_components); + jd_samplesperrow := JDIMENSION (samplesperrow); + if (long(jd_samplesperrow) <> samplesperrow) then + ERREXIT(j_common_ptr(cinfo), JERR_WIDTH_OVERFLOW); + + { Initialize my private state } + master^.pass_number := 0; + master^.using_merged_upsample := use_merged_upsample(cinfo); + + { Color quantizer selection } + master^.quantizer_1pass := NIL; + master^.quantizer_2pass := NIL; + { No mode changes if not using buffered-image mode. } + if (not cinfo^.quantize_colors) or (not cinfo^.buffered_image) then + begin + cinfo^.enable_1pass_quant := FALSE; + cinfo^.enable_external_quant := FALSE; + cinfo^.enable_2pass_quant := FALSE; + end; + if (cinfo^.quantize_colors) then + begin + if (cinfo^.raw_data_out) then + ERREXIT(j_common_ptr(cinfo), JERR_NOTIMPL); + { 2-pass quantizer only works in 3-component color space. } + if (cinfo^.out_color_components <> 3) then + begin + cinfo^.enable_1pass_quant := TRUE; + cinfo^.enable_external_quant := FALSE; + cinfo^.enable_2pass_quant := FALSE; + cinfo^.colormap := NIL; + end + else + if (cinfo^.colormap <> NIL) then + begin + cinfo^.enable_external_quant := TRUE; + end + else + if (cinfo^.two_pass_quantize) then + begin + cinfo^.enable_2pass_quant := TRUE; + end + else + begin + cinfo^.enable_1pass_quant := TRUE; + end; + + if (cinfo^.enable_1pass_quant) then + begin +{$ifdef QUANT_1PASS_SUPPORTED} + jinit_1pass_quantizer(cinfo); + master^.quantizer_1pass := cinfo^.cquantize; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end; + + { We use the 2-pass code to map to external colormaps. } + if (cinfo^.enable_2pass_quant) or (cinfo^.enable_external_quant) then + begin +{$ifdef QUANT_2PASS_SUPPORTED} + jinit_2pass_quantizer(cinfo); + master^.quantizer_2pass := cinfo^.cquantize; +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end; + { If both quantizers are initialized, the 2-pass one is left active; + this is necessary for starting with quantization to an external map. } + end; + + { Post-processing: in particular, color conversion first } + if (not cinfo^.raw_data_out) then + begin + if (master^.using_merged_upsample) then + begin +{$ifdef UPSAMPLE_MERGING_SUPPORTED} + jinit_merged_upsampler(cinfo); { does color conversion too } +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + begin + jinit_color_deconverter(cinfo); + jinit_upsampler(cinfo); + end; + jinit_d_post_controller(cinfo, cinfo^.enable_2pass_quant); + end; + { Inverse DCT } + jinit_inverse_dct(cinfo); + { Entropy decoding: either Huffman or arithmetic coding. } + if (cinfo^.arith_code) then + begin + ERREXIT(j_common_ptr(cinfo), JERR_ARITH_NOTIMPL); + end + else + begin + if (cinfo^.progressive_mode) then + begin +{$ifdef D_PROGRESSIVE_SUPPORTED} + jinit_phuff_decoder(cinfo); +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} + end + else + jinit_huff_decoder(cinfo); + end; + + { Initialize principal buffer controllers. } + use_c_buffer := cinfo^.inputctl^.has_multiple_scans or cinfo^.buffered_image; + jinit_d_coef_controller(cinfo, use_c_buffer); + + if (not cinfo^.raw_data_out) then + jinit_d_main_controller(cinfo, FALSE { never need full buffer here }); + + { We can now tell the memory manager to allocate virtual arrays. } + cinfo^.mem^.realize_virt_arrays (j_common_ptr(cinfo)); + + { Initialize input side of decompressor to consume first scan. } + cinfo^.inputctl^.start_input_pass (cinfo); + +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + { If jpeg_start_decompress will read the whole file, initialize + progress monitoring appropriately. The input step is counted + as one pass. } + + if (cinfo^.progress <> NIL) and (not cinfo^.buffered_image) and + (cinfo^.inputctl^.has_multiple_scans) then + begin + + { Estimate number of scans to set pass_limit. } + if (cinfo^.progressive_mode) then + begin + { Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. } + nscans := 2 + 3 * cinfo^.num_components; + end + else + begin + { For a nonprogressive multiscan file, estimate 1 scan per component. } + nscans := cinfo^.num_components; + end; + cinfo^.progress^.pass_counter := Long(0); + cinfo^.progress^.pass_limit := long (cinfo^.total_iMCU_rows) * nscans; + cinfo^.progress^.completed_passes := 0; + if cinfo^.enable_2pass_quant then + cinfo^.progress^.total_passes := 3 + else + cinfo^.progress^.total_passes := 2; + { Count the input pass as done } + Inc(master^.pass_number); + end; +{$endif} { D_MULTISCAN_FILES_SUPPORTED } +end; + + +{ Per-pass setup. + This is called at the beginning of each output pass. We determine which + modules will be active during this pass and give them appropriate + start_pass calls. We also set is_dummy_pass to indicate whether this + is a "real" output pass or a dummy pass for color quantization. + (In the latter case, jdapistd.c will crank the pass to completion.) } + +{METHODDEF} +procedure prepare_for_output_pass (cinfo : j_decompress_ptr); +var + master : my_master_ptr; +begin + master := my_master_ptr (cinfo^.master); + + if (master^.pub.is_dummy_pass) then + begin +{$ifdef QUANT_2PASS_SUPPORTED} + { Final pass of 2-pass quantization } + master^.pub.is_dummy_pass := FALSE; + cinfo^.cquantize^.start_pass (cinfo, FALSE); + cinfo^.post^.start_pass (cinfo, JBUF_CRANK_DEST); + cinfo^.main^.start_pass (cinfo, JBUF_CRANK_DEST); +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); +{$endif} { QUANT_2PASS_SUPPORTED } + end + else + begin + if (cinfo^.quantize_colors) and (cinfo^.colormap = NIL) then + begin + { Select new quantization method } + if (cinfo^.two_pass_quantize) and (cinfo^.enable_2pass_quant) then + begin + cinfo^.cquantize := master^.quantizer_2pass; + master^.pub.is_dummy_pass := TRUE; + end + else + if (cinfo^.enable_1pass_quant) then + begin + cinfo^.cquantize := master^.quantizer_1pass; + end + else + begin + ERREXIT(j_common_ptr(cinfo), JERR_MODE_CHANGE); + end; + end; + cinfo^.idct^.start_pass (cinfo); + cinfo^.coef^.start_output_pass (cinfo); + if (not cinfo^.raw_data_out) then + begin + if (not master^.using_merged_upsample) then + cinfo^.cconvert^.start_pass (cinfo); + cinfo^.upsample^.start_pass (cinfo); + if (cinfo^.quantize_colors) then + cinfo^.cquantize^.start_pass (cinfo, master^.pub.is_dummy_pass); + if master^.pub.is_dummy_pass then + cinfo^.post^.start_pass (cinfo, JBUF_SAVE_AND_PASS) + else + cinfo^.post^.start_pass (cinfo, JBUF_PASS_THRU); + cinfo^.main^.start_pass (cinfo, JBUF_PASS_THRU); + end; + end; + + { Set up progress monitor's pass info if present } + if (cinfo^.progress <> NIL) then + begin + cinfo^.progress^.completed_passes := master^.pass_number; + if master^.pub.is_dummy_pass then + cinfo^.progress^.total_passes := master^.pass_number + 2 + else + cinfo^.progress^.total_passes := master^.pass_number + 1; + { In buffered-image mode, we assume one more output pass if EOI not + yet reached, but no more passes if EOI has been reached. } + + if (cinfo^.buffered_image) and (not cinfo^.inputctl^.eoi_reached) then + begin + if cinfo^.enable_2pass_quant then + Inc(cinfo^.progress^.total_passes, 2) + else + Inc(cinfo^.progress^.total_passes, 1); + end; + end; +end; + + +{ Finish up at end of an output pass. } + +{METHODDEF} +procedure finish_output_pass (cinfo : j_decompress_ptr); +var + master : my_master_ptr; +begin + master := my_master_ptr (cinfo^.master); + + if (cinfo^.quantize_colors) then + cinfo^.cquantize^.finish_pass (cinfo); + Inc(master^.pass_number); +end; + + +{$ifdef D_MULTISCAN_FILES_SUPPORTED} + +{ Switch to a new external colormap between output passes. } + +{GLOBAL} +procedure jpeg_new_colormap (cinfo : j_decompress_ptr); +var + master : my_master_ptr; +begin + master := my_master_ptr (cinfo^.master); + + { Prevent application from calling me at wrong times } + if (cinfo^.global_state <> DSTATE_BUFIMAGE) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_STATE, cinfo^.global_state); + + if (cinfo^.quantize_colors) and (cinfo^.enable_external_quant) and + (cinfo^.colormap <> NIL) then + begin + { Select 2-pass quantizer for external colormap use } + cinfo^.cquantize := master^.quantizer_2pass; + { Notify quantizer of colormap change } + cinfo^.cquantize^.new_color_map (cinfo); + master^.pub.is_dummy_pass := FALSE; { just in case } + end + else + ERREXIT(j_common_ptr(cinfo), JERR_MODE_CHANGE); +end; + +{$endif} { D_MULTISCAN_FILES_SUPPORTED } + + +{ Initialize master decompression control and select active modules. + This is performed at the start of jpeg_start_decompress. } + +{GLOBAL} +procedure jinit_master_decompress (cinfo : j_decompress_ptr); +var + master : my_master_ptr; +begin + master := my_master_ptr ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_decomp_master)) ); + cinfo^.master := jpeg_decomp_master_ptr(master); + master^.pub.prepare_for_output_pass := prepare_for_output_pass; + master^.pub.finish_output_pass := finish_output_pass; + + master^.pub.is_dummy_pass := FALSE; + + master_selection(cinfo); +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdmerge.pas b/src/lib/vampimg/JpegLib/imjdmerge.pas new file mode 100644 index 0000000..a99d195 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdmerge.pas @@ -0,0 +1,514 @@ +unit imjdmerge; + +{ This file contains code for merged upsampling/color conversion. + + This file combines functions from jdsample.c and jdcolor.c; + read those files first to understand what's going on. + + When the chroma components are to be upsampled by simple replication + (ie, box filtering), we can save some work in color conversion by + calculating all the output pixels corresponding to a pair of chroma + samples at one time. In the conversion equations + R := Y + K1 * Cr + G := Y + K2 * Cb + K3 * Cr + B := Y + K4 * Cb + only the Y term varies among the group of pixels corresponding to a pair + of chroma samples, so the rest of the terms can be calculated just once. + At typical sampling ratios, this eliminates half or three-quarters of the + multiplications needed for color conversion. + + This file currently provides implementations for the following cases: + YCbCr => RGB color conversion only. + Sampling ratios of 2h1v or 2h2v. + No scaling needed at upsample time. + Corner-aligned (non-CCIR601) sampling alignment. + Other special cases could be added, but in most applications these are + the only common cases. (For uncommon cases we fall back on the more + general code in jdsample.c and jdcolor.c.) } + +{ Original: jdmerge.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjutils; + +{ Module initialization routine for merged upsampling/color conversion. + + NB: this is called under the conditions determined by use_merged_upsample() + in jdmaster.c. That routine MUST correspond to the actual capabilities + of this module; no safety checks are made here. } + +{GLOBAL} +procedure jinit_merged_upsampler (cinfo : j_decompress_ptr); + +implementation + + +{ Private subobject } + +type { the same definition as in JdColor } + int_Color_Table = array[0..MAXJSAMPLE+1-1] of int; + int_CConvertPtr = ^int_Color_Table; + INT32_Color_Table = array[0..MAXJSAMPLE+1-1] of INT32; + INT32_CConvertPtr = ^INT32_Color_Table; + +type + my_upsample_ptr = ^my_upsampler; + my_upsampler = record + pub : jpeg_upsampler; { public fields } + + { Pointer to routine to do actual upsampling/conversion of one row group } + upmethod : procedure (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + in_row_group_ctr : JDIMENSION; + output_buf : JSAMPARRAY); + + { Private state for YCC->RGB conversion } + Cr_r_tab : int_CConvertPtr; { => table for Cr to R conversion } + Cb_b_tab : int_CConvertPtr; { => table for Cb to B conversion } + Cr_g_tab : INT32_CConvertPtr; { => table for Cr to G conversion } + Cb_g_tab : INT32_CConvertPtr; { => table for Cb to G conversion } + + { For 2:1 vertical sampling, we produce two output rows at a time. + We need a "spare" row buffer to hold the second output row if the + application provides just a one-row buffer; we also use the spare + to discard the dummy last row if the image height is odd. } + + spare_row : JSAMPROW; + spare_full : boolean; { TRUE if spare buffer is occupied } + + out_row_width : JDIMENSION; { samples per output row } + rows_to_go : JDIMENSION; { counts rows remaining in image } + end; {my_upsampler;} + + +const + SCALEBITS = 16; { speediest right-shift on some machines } + ONE_HALF = (INT32(1) shl (SCALEBITS-1)); + + +{ Initialize tables for YCC->RGB colorspace conversion. + This is taken directly from jdcolor.c; see that file for more info. } + +{LOCAL} +procedure build_ycc_rgb_table (cinfo : j_decompress_ptr); +const + FIX_1_40200 = INT32( Round(1.40200 * (INT32(1) shl SCALEBITS)) ); + FIX_1_77200 = INT32( Round(1.77200 * (INT32(1) shl SCALEBITS)) ); + FIX_0_71414 = INT32( Round(0.71414 * (INT32(1) shl SCALEBITS)) ); + FIX_0_34414 = INT32( Round(0.34414 * (INT32(1) shl SCALEBITS)) ); +var + upsample : my_upsample_ptr; + i : int; + x : INT32; +var + shift_temp : INT32; +begin + upsample := my_upsample_ptr (cinfo^.upsample); + + upsample^.Cr_r_tab := int_CConvertPtr ( + cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)) ); + upsample^.Cb_b_tab := int_CConvertPtr ( + cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(int)) ); + upsample^.Cr_g_tab := INT32_CConvertPtr ( + cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)) ); + upsample^.Cb_g_tab := INT32_CConvertPtr ( + cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE, + (MAXJSAMPLE+1) * SIZEOF(INT32)) ); + + x := -CENTERJSAMPLE; + for i := 0 to pred(MAXJSAMPLE) do + begin + { i is the actual input pixel value, in the range 0..MAXJSAMPLE } + { The Cb or Cr value we are thinking of is x := i - CENTERJSAMPLE } + { Cr=>R value is nearest int to 1.40200 * x } + {upsample^.Cr_r_tab^[i] := int( + RIGHT_SHIFT(FIX_1_40200 * x + ONE_HALF, SCALEBITS) );} + shift_temp := FIX_1_40200 * x + ONE_HALF; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + upsample^.Cr_r_tab^[i] := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + upsample^.Cr_r_tab^[i] := int(shift_temp shr SCALEBITS); + + + { Cb=>B value is nearest int to 1.77200 * x } + {upsample^.Cb_b_tab^[i] := int( + RIGHT_SHIFT(FIX_1_77200 * x + ONE_HALF, SCALEBITS) );} + shift_temp := FIX_1_77200 * x + ONE_HALF; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + upsample^.Cb_b_tab^[i] := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + upsample^.Cb_b_tab^[i] := int(shift_temp shr SCALEBITS); + + { Cr=>G value is scaled-up -0.71414 * x } + upsample^.Cr_g_tab^[i] := (- FIX_0_71414) * x; + { Cb=>G value is scaled-up -0.34414 * x } + { We also add in ONE_HALF so that need not do it in inner loop } + upsample^.Cb_g_tab^[i] := (- FIX_0_34414) * x + ONE_HALF; + Inc(x); + end; +end; + + +{ Initialize for an upsampling pass. } + +{METHODDEF} +procedure start_pass_merged_upsample (cinfo : j_decompress_ptr); +var + upsample : my_upsample_ptr; +begin + upsample := my_upsample_ptr (cinfo^.upsample); + + { Mark the spare buffer empty } + upsample^.spare_full := FALSE; + { Initialize total-height counter for detecting bottom of image } + upsample^.rows_to_go := cinfo^.output_height; +end; + + +{ Control routine to do upsampling (and color conversion). + + The control routine just handles the row buffering considerations. } + +{METHODDEF} +procedure merged_2v_upsample (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +{ 2:1 vertical sampling case: may need a spare row. } +var + upsample : my_upsample_ptr; + work_ptrs : array[0..2-1] of JSAMPROW; + num_rows : JDIMENSION; { number of rows returned to caller } +begin + upsample := my_upsample_ptr (cinfo^.upsample); + + if (upsample^.spare_full) then + begin + { If we have a spare row saved from a previous cycle, just return it. } + jcopy_sample_rows(JSAMPARRAY(@upsample^.spare_row), + 0, + JSAMPARRAY(@ output_buf^[out_row_ctr]), + 0, 1, upsample^.out_row_width); + num_rows := 1; + upsample^.spare_full := FALSE; + end + else + begin + { Figure number of rows to return to caller. } + num_rows := 2; + { Not more than the distance to the end of the image. } + if (num_rows > upsample^.rows_to_go) then + num_rows := upsample^.rows_to_go; + { And not more than what the client can accept: } + Dec(out_rows_avail, {var} out_row_ctr); + if (num_rows > out_rows_avail) then + num_rows := out_rows_avail; + { Create output pointer array for upsampler. } + work_ptrs[0] := output_buf^[out_row_ctr]; + if (num_rows > 1) then + begin + work_ptrs[1] := output_buf^[out_row_ctr + 1]; + end + else + begin + work_ptrs[1] := upsample^.spare_row; + upsample^.spare_full := TRUE; + end; + { Now do the upsampling. } + upsample^.upmethod (cinfo, input_buf, {var}in_row_group_ctr, + JSAMPARRAY(@work_ptrs)); + end; + + { Adjust counts } + Inc(out_row_ctr, num_rows); + Dec(upsample^.rows_to_go, num_rows); + { When the buffer is emptied, declare this input row group consumed } + if (not upsample^.spare_full) then + Inc(in_row_group_ctr); +end; + + +{METHODDEF} +procedure merged_1v_upsample (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +{ 1:1 vertical sampling case: much easier, never need a spare row. } +var + upsample : my_upsample_ptr; +begin + upsample := my_upsample_ptr (cinfo^.upsample); + + { Just do the upsampling. } + upsample^.upmethod (cinfo, input_buf, in_row_group_ctr, + JSAMPARRAY(@ output_buf^[out_row_ctr])); + { Adjust counts } + Inc(out_row_ctr); + Inc(in_row_group_ctr); +end; + + +{ These are the routines invoked by the control routines to do + the actual upsampling/conversion. One row group is processed per call. + + Note: since we may be writing directly into application-supplied buffers, + we have to be honest about the output width; we can't assume the buffer + has been rounded up to an even width. } + + +{ Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. } + +{METHODDEF} +procedure h2v1_merged_upsample (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + in_row_group_ctr : JDIMENSION; + output_buf : JSAMPARRAY); +var + upsample : my_upsample_ptr; + {register} y, cred, cgreen, cblue : int; + cb, cr : int; + {register} outptr : JSAMPROW; + inptr0, inptr1, inptr2 : JSAMPLE_PTR; + col : JDIMENSION; + { copy these pointers into registers if possible } + {register} range_limit : range_limit_table_ptr; + Crrtab : int_CConvertPtr; + Cbbtab : int_CConvertPtr; + Crgtab : INT32_CConvertPtr; + Cbgtab : INT32_CConvertPtr; +var + shift_temp : INT32; +begin + upsample := my_upsample_ptr (cinfo^.upsample); + range_limit := cinfo^.sample_range_limit; + Crrtab := upsample^.Cr_r_tab; + Cbbtab := upsample^.Cb_b_tab; + Crgtab := upsample^.Cr_g_tab; + Cbgtab := upsample^.Cb_g_tab; + + inptr0 := JSAMPLE_PTR(input_buf^[0]^[in_row_group_ctr]); + inptr1 := JSAMPLE_PTR(input_buf^[1]^[in_row_group_ctr]); + inptr2 := JSAMPLE_PTR(input_buf^[2]^[in_row_group_ctr]); + outptr := output_buf^[0]; + { Loop for each pair of output pixels } + for col := pred(cinfo^.output_width shr 1) downto 0 do + begin + { Do the chroma part of the calculation } + cb := GETJSAMPLE(inptr1^); + Inc(inptr1); + cr := GETJSAMPLE(inptr2^); + Inc(inptr2); + cred := Crrtab^[cr]; + {cgreen := int( RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS) );} + shift_temp := Cbgtab^[cb] + Crgtab^[cr]; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + cgreen := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + cgreen := int(shift_temp shr SCALEBITS); + + cblue := Cbbtab^[cb]; + { Fetch 2 Y values and emit 2 pixels } + y := GETJSAMPLE(inptr0^); + Inc(inptr0); + outptr^[RGB_RED] := range_limit^[y + cred]; + outptr^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr^[RGB_BLUE] := range_limit^[y + cblue]; + Inc(JSAMPLE_PTR(outptr), RGB_PIXELSIZE); + y := GETJSAMPLE(inptr0^); + Inc(inptr0); + outptr^[RGB_RED] := range_limit^[y + cred]; + outptr^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr^[RGB_BLUE] := range_limit^[y + cblue]; + Inc(JSAMPLE_PTR(outptr), RGB_PIXELSIZE); + end; + { If image width is odd, do the last output column separately } + if Odd(cinfo^.output_width) then + begin + cb := GETJSAMPLE(inptr1^); + cr := GETJSAMPLE(inptr2^); + cred := Crrtab^[cr]; + {cgreen := int ( RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS) );} + shift_temp := Cbgtab^[cb] + Crgtab^[cr]; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + cgreen := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + cgreen := int(shift_temp shr SCALEBITS); + + cblue := Cbbtab^[cb]; + y := GETJSAMPLE(inptr0^); + outptr^[RGB_RED] := range_limit^[y + cred]; + outptr^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr^[RGB_BLUE] := range_limit^[y + cblue]; + end; +end; + + +{ Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. } + +{METHODDEF} +procedure h2v2_merged_upsample (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + in_row_group_ctr : JDIMENSION; + output_buf : JSAMPARRAY); +var + upsample : my_upsample_ptr; + {register} y, cred, cgreen, cblue : int; + cb, cr : int; + {register} outptr0, outptr1 : JSAMPROW; + inptr00, inptr01, inptr1, inptr2 : JSAMPLE_PTR; + col : JDIMENSION; + { copy these pointers into registers if possible } + {register} range_limit : range_limit_table_ptr; + Crrtab : int_CConvertPtr; + Cbbtab : int_CConvertPtr; + Crgtab : INT32_CConvertPtr; + Cbgtab : INT32_CConvertPtr; +var + shift_temp : INT32; +begin + upsample := my_upsample_ptr (cinfo^.upsample); + range_limit := cinfo^.sample_range_limit; + Crrtab := upsample^.Cr_r_tab; + Cbbtab := upsample^.Cb_b_tab; + Crgtab := upsample^.Cr_g_tab; + Cbgtab := upsample^.Cb_g_tab; + + inptr00 := JSAMPLE_PTR(input_buf^[0]^[in_row_group_ctr*2]); + inptr01 := JSAMPLE_PTR(input_buf^[0]^[in_row_group_ctr*2 + 1]); + inptr1 := JSAMPLE_PTR(input_buf^[1]^[in_row_group_ctr]); + inptr2 := JSAMPLE_PTR(input_buf^[2]^[in_row_group_ctr]); + outptr0 := output_buf^[0]; + outptr1 := output_buf^[1]; + { Loop for each group of output pixels } + for col := pred(cinfo^.output_width shr 1) downto 0 do + begin + { Do the chroma part of the calculation } + cb := GETJSAMPLE(inptr1^); + Inc(inptr1); + cr := GETJSAMPLE(inptr2^); + Inc(inptr2); + cred := Crrtab^[cr]; + {cgreen := int( RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS) );} + shift_temp := Cbgtab^[cb] + Crgtab^[cr]; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + cgreen := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + cgreen := int(shift_temp shr SCALEBITS); + + cblue := Cbbtab^[cb]; + { Fetch 4 Y values and emit 4 pixels } + y := GETJSAMPLE(inptr00^); + Inc(inptr00); + outptr0^[RGB_RED] := range_limit^[y + cred]; + outptr0^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr0^[RGB_BLUE] := range_limit^[y + cblue]; + Inc(JSAMPLE_PTR(outptr0), RGB_PIXELSIZE); + y := GETJSAMPLE(inptr00^); + Inc(inptr00); + outptr0^[RGB_RED] := range_limit^[y + cred]; + outptr0^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr0^[RGB_BLUE] := range_limit^[y + cblue]; + Inc(JSAMPLE_PTR(outptr0), RGB_PIXELSIZE); + y := GETJSAMPLE(inptr01^); + Inc(inptr01); + outptr1^[RGB_RED] := range_limit^[y + cred]; + outptr1^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr1^[RGB_BLUE] := range_limit^[y + cblue]; + Inc(JSAMPLE_PTR(outptr1), RGB_PIXELSIZE); + y := GETJSAMPLE(inptr01^); + Inc(inptr01); + outptr1^[RGB_RED] := range_limit^[y + cred]; + outptr1^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr1^[RGB_BLUE] := range_limit^[y + cblue]; + Inc(JSAMPLE_PTR(outptr1), RGB_PIXELSIZE); + end; + { If image width is odd, do the last output column separately } + if Odd(cinfo^.output_width) then + begin + cb := GETJSAMPLE(inptr1^); + cr := GETJSAMPLE(inptr2^); + cred := Crrtab^[cr]; + {cgreen := int (RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS));} + shift_temp := Cbgtab^[cb] + Crgtab^[cr]; + if shift_temp < 0 then { SHIFT arithmetic RIGHT } + cgreen := int((shift_temp shr SCALEBITS) + or ( (not INT32(0)) shl (32-SCALEBITS))) + else + cgreen := int(shift_temp shr SCALEBITS); + + cblue := Cbbtab^[cb]; + y := GETJSAMPLE(inptr00^); + outptr0^[RGB_RED] := range_limit^[y + cred]; + outptr0^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr0^[RGB_BLUE] := range_limit^[y + cblue]; + y := GETJSAMPLE(inptr01^); + outptr1^[RGB_RED] := range_limit^[y + cred]; + outptr1^[RGB_GREEN] := range_limit^[y + cgreen]; + outptr1^[RGB_BLUE] := range_limit^[y + cblue]; + end; +end; + + +{ Module initialization routine for merged upsampling/color conversion. + + NB: this is called under the conditions determined by use_merged_upsample() + in jdmaster.c. That routine MUST correspond to the actual capabilities + of this module; no safety checks are made here. } + + +{GLOBAL} +procedure jinit_merged_upsampler (cinfo : j_decompress_ptr); +var + upsample : my_upsample_ptr; +begin + upsample := my_upsample_ptr ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_upsampler)) ); + cinfo^.upsample := jpeg_upsampler_ptr (upsample); + upsample^.pub.start_pass := start_pass_merged_upsample; + upsample^.pub.need_context_rows := FALSE; + + upsample^.out_row_width := cinfo^.output_width * JDIMENSION(cinfo^.out_color_components); + + if (cinfo^.max_v_samp_factor = 2) then + begin + upsample^.pub.upsample := merged_2v_upsample; + upsample^.upmethod := h2v2_merged_upsample; + { Allocate a spare row buffer } + upsample^.spare_row := JSAMPROW( + cinfo^.mem^.alloc_large ( j_common_ptr(cinfo), JPOOL_IMAGE, + size_t (upsample^.out_row_width * SIZEOF(JSAMPLE))) ); + end + else + begin + upsample^.pub.upsample := merged_1v_upsample; + upsample^.upmethod := h2v1_merged_upsample; + { No spare row needed } + upsample^.spare_row := NIL; + end; + + build_ycc_rgb_table(cinfo); +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdphuff.pas b/src/lib/vampimg/JpegLib/imjdphuff.pas new file mode 100644 index 0000000..1ab53d2 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdphuff.pas @@ -0,0 +1,1061 @@ +unit imjdphuff; + +{ This file contains Huffman entropy decoding routines for progressive JPEG. + + Much of the complexity here has to do with supporting input suspension. + If the data source module demands suspension, we want to be able to back + up to the start of the current MCU. To do this, we copy state variables + into local working storage, and update them back to the permanent + storage only upon successful completion of an MCU. } + +{ Original: jdphuff.c ; Copyright (C) 1995-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdeferr, + imjerror, + imjutils, + imjdhuff; { Declarations shared with jdhuff.c } + + +{GLOBAL} +procedure jinit_phuff_decoder (cinfo : j_decompress_ptr); + +implementation + +{ Expanded entropy decoder object for progressive Huffman decoding. + + The savable_state subrecord contains fields that change within an MCU, + but must not be updated permanently until we complete the MCU. } + +type + savable_state = record + EOBRUN : uInt; { remaining EOBs in EOBRUN } + last_dc_val : array[00..MAX_COMPS_IN_SCAN-1] of int; + { last DC coef for each component } + end; + + +type + phuff_entropy_ptr = ^phuff_entropy_decoder; + phuff_entropy_decoder = record + pub : jpeg_entropy_decoder; { public fields } + + { These fields are loaded into local variables at start of each MCU. + In case of suspension, we exit WITHOUT updating them. } + + bitstate : bitread_perm_state; { Bit buffer at start of MCU } + saved : savable_state; { Other state at start of MCU } + + { These fields are NOT loaded into local working state. } + restarts_to_go : uInt; { MCUs left in this restart interval } + + { Pointers to derived tables (these workspaces have image lifespan) } + derived_tbls : array[0..NUM_HUFF_TBLS-1] of d_derived_tbl_ptr; + + ac_derived_tbl : d_derived_tbl_ptr; { active table during an AC scan } + end; + + + +{ Forward declarations } +{METHODDEF} +function decode_mcu_DC_first (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; + forward; +{METHODDEF} +function decode_mcu_AC_first (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; + forward; +{METHODDEF} +function decode_mcu_DC_refine (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; + forward; +{METHODDEF} +function decode_mcu_AC_refine (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; + forward; + +{ Initialize for a Huffman-compressed scan. } + +{METHODDEF} +procedure start_pass_phuff_decoder (cinfo : j_decompress_ptr); +var + entropy : phuff_entropy_ptr; + is_DC_band, bad : boolean; + ci, coefi, tbl : int; + coef_bit_ptr : coef_bits_ptr; + compptr : jpeg_component_info_ptr; +var + cindex : int; + expected : int; +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + + is_DC_band := (cinfo^.Ss = 0); + + { Validate scan parameters } + bad := FALSE; + if (is_DC_band) then + begin + if (cinfo^.Se <> 0) then + bad := TRUE; + end + else + begin + { need not check Ss/Se < 0 since they came from unsigned bytes } + if (cinfo^.Ss > cinfo^.Se) or (cinfo^.Se >= DCTSIZE2) then + bad := TRUE; + { AC scans may have only one component } + if (cinfo^.comps_in_scan <> 1) then + bad := TRUE; + end; + if (cinfo^.Ah <> 0) then + begin + { Successive approximation refinement scan: must have Al = Ah-1. } + if (cinfo^.Al <> cinfo^.Ah-1) then + bad := TRUE; + end; + if (cinfo^.Al > 13) then { need not check for < 0 } + bad := TRUE; + { Arguably the maximum Al value should be less than 13 for 8-bit precision, + but the spec doesn't say so, and we try to be liberal about what we + accept. Note: large Al values could result in out-of-range DC + coefficients during early scans, leading to bizarre displays due to + overflows in the IDCT math. But we won't crash. } + + if (bad) then + ERREXIT4(j_common_ptr(cinfo), JERR_BAD_PROGRESSION, + cinfo^.Ss, cinfo^.Se, cinfo^.Ah, cinfo^.Al); + { Update progression status, and verify that scan order is legal. + Note that inter-scan inconsistencies are treated as warnings + not fatal errors ... not clear if this is right way to behave. } + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + cindex := cinfo^.cur_comp_info[ci]^.component_index; + coef_bit_ptr := coef_bits_ptr(@(cinfo^.coef_bits^[cindex])); {^[0] ??? + Nomssi } + if (not is_DC_band) and (coef_bit_ptr^[0] < 0) then + { AC without prior DC scan } + WARNMS2(j_common_ptr(cinfo), JWRN_BOGUS_PROGRESSION, cindex, 0); + for coefi := cinfo^.Ss to cinfo^.Se do + begin + if (coef_bit_ptr^[coefi] < 0) then + expected := 0 + else + expected := coef_bit_ptr^[coefi]; + if (cinfo^.Ah <> expected) then + WARNMS2(j_common_ptr(cinfo), JWRN_BOGUS_PROGRESSION, cindex, coefi); + coef_bit_ptr^[coefi] := cinfo^.Al; + end; + end; + + { Select MCU decoding routine } + if (cinfo^.Ah = 0) then + begin + if (is_DC_band) then + entropy^.pub.decode_mcu := decode_mcu_DC_first + else + entropy^.pub.decode_mcu := decode_mcu_AC_first; + end + else + begin + if (is_DC_band) then + entropy^.pub.decode_mcu := decode_mcu_DC_refine + else + entropy^.pub.decode_mcu := decode_mcu_AC_refine; + end; + + for ci := 0 to pred(cinfo^.comps_in_scan) do + begin + compptr := cinfo^.cur_comp_info[ci]; + { Make sure requested tables are present, and compute derived tables. + We may build same derived table more than once, but it's not expensive. } + + if (is_DC_band) then + begin + if (cinfo^.Ah = 0) then + begin { DC refinement needs no table } + tbl := compptr^.dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + entropy^.derived_tbls[tbl]); + end; + end + else + begin + tbl := compptr^.ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + entropy^.derived_tbls[tbl]); + { remember the single active table } + entropy^.ac_derived_tbl := entropy^.derived_tbls[tbl]; + end; + { Initialize DC predictions to 0 } + entropy^.saved.last_dc_val[ci] := 0; + end; + + { Initialize bitread state variables } + entropy^.bitstate.bits_left := 0; + entropy^.bitstate.get_buffer := 0; { unnecessary, but keeps Purify quiet } + entropy^.pub.insufficient_data := FALSE; + + { Initialize private state variables } + entropy^.saved.EOBRUN := 0; + + { Initialize restart counter } + entropy^.restarts_to_go := cinfo^.restart_interval; +end; + + +{ Figure F.12: extend sign bit. + On some machines, a shift and add will be faster than a table lookup. } + +{$ifdef AVOID_TABLES} + +#define HUFF_EXTEND(x,s) + ((x) < (1shl((s)-1)) ? (x) + (((-1)shl(s)) + 1) : (x)) + +{$else} + +{ #define HUFF_EXTEND(x,s) + if (x) < extend_test[s] then + (x) + extend_offset[s] + else + (x)} + +const + extend_test : Array[0..16-1] of int = { entry n is 2**(n-1) } + ($0000, $0001, $0002, $0004, $0008, $0010, $0020, $0040, + $0080, $0100, $0200, $0400, $0800, $1000, $2000, $4000); + +const + extend_offset : array[0..16-1] of int = { entry n is (-1 shl n) + 1 } + ( 0, ((-1) shl 1) + 1, ((-1) shl 2) + 1, ((-1) shl 3) + 1, ((-1) shl 4) + 1, + ((-1) shl 5) + 1, ((-1) shl 6) + 1, ((-1) shl 7) + 1, ((-1) shl 8) + 1, + ((-1) shl 9) + 1, ((-1) shl 10) + 1, ((-1) shl 11) + 1, ((-1) shl 12) + 1, + ((-1) shl 13) + 1, ((-1) shl 14) + 1, ((-1) shl 15) + 1 ); + +{$endif} { AVOID_TABLES } + + +{ Check for a restart marker & resynchronize decoder. + return:=s FALSE if must suspend. } + +{LOCAL} +function process_restart (cinfo : j_decompress_ptr) : boolean; +var + entropy : phuff_entropy_ptr; + ci : int; +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + + { Throw away any unused bits remaining in bit buffer; } + { include any full bytes in next_marker's count of discarded bytes } + Inc(cinfo^.marker^.discarded_bytes, entropy^.bitstate.bits_left div 8); + entropy^.bitstate.bits_left := 0; + + { Advance past the RSTn marker } + if (not cinfo^.marker^.read_restart_marker (cinfo)) then + begin + process_restart := FALSE; + exit; + end; + + { Re-initialize DC predictions to 0 } + for ci := 0 to pred(cinfo^.comps_in_scan) do + entropy^.saved.last_dc_val[ci] := 0; + { Re-init EOB run count, too } + entropy^.saved.EOBRUN := 0; + + { Reset restart counter } + entropy^.restarts_to_go := cinfo^.restart_interval; + + { Reset out-of-data flag, unless read_restart_marker left us smack up + against a marker. In that case we will end up treating the next data + segment as empty, and we can avoid producing bogus output pixels by + leaving the flag set. } + if (cinfo^.unread_marker = 0) then + entropy^.pub.insufficient_data := FALSE; + + process_restart := TRUE; +end; + + +{ Huffman MCU decoding. + Each of these routines decodes and returns one MCU's worth of + Huffman-compressed coefficients. + The coefficients are reordered from zigzag order into natural array order, + but are not dequantized. + + The i'th block of the MCU is stored into the block pointed to by + MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER. + + We return FALSE if data source requested suspension. In that case no + changes have been made to permanent state. (Exception: some output + coefficients may already have been assigned. This is harmless for + spectral selection, since we'll just re-assign them on the next call. + Successive approximation AC refinement has to be more careful, however.) } + + +{ MCU decoding for DC initial scan (either spectral selection, + or first pass of successive approximation). } + +{METHODDEF} +function decode_mcu_DC_first (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; +label + label1; +var + entropy : phuff_entropy_ptr; + Al : int; + {register} s, r : int; + blkn, ci : int; + block : JBLOCK_PTR; + {BITREAD_STATE_VARS;} + get_buffer : bit_buf_type ; {register} + bits_left : int; {register} + br_state : bitread_working_state; + + state : savable_state; + tbl : d_derived_tbl_ptr; + compptr : jpeg_component_info_ptr; +var + nb, look : int; {register} +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + Al := cinfo^.Al; + + { Process restart marker if needed; may have to suspend } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + if (not process_restart(cinfo)) then + begin + decode_mcu_DC_first := FALSE; + exit; + end; + end; + + { If we've run out of data, just leave the MCU set to zeroes. + This way, we return uniform gray for the remainder of the segment. } + + if not entropy^.pub.insufficient_data then + begin + + { Load up working state } + {BITREAD_LOAD_STATE(cinfo,entropy^.bitstate);} + br_state.cinfo := cinfo; + br_state.next_input_byte := cinfo^.src^.next_input_byte; + br_state.bytes_in_buffer := cinfo^.src^.bytes_in_buffer; + get_buffer := entropy^.bitstate.get_buffer; + bits_left := entropy^.bitstate.bits_left; + + {ASSIGN_STATE(state, entropy^.saved);} + state := entropy^.saved; + + { Outer loop handles each block in the MCU } + + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + block := JBLOCK_PTR(MCU_data[blkn]); + ci := cinfo^.MCU_membership[blkn]; + compptr := cinfo^.cur_comp_info[ci]; + tbl := entropy^.derived_tbls[compptr^.dc_tbl_no]; + + { Decode a single block's worth of coefficients } + + { Section F.2.2.1: decode the DC coefficient difference } + {HUFF_DECODE(s, br_state, tbl, return FALSE, label1);} + if (bits_left < HUFF_LOOKAHEAD) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) then + begin + decode_mcu_DC_first := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + if (bits_left < HUFF_LOOKAHEAD) then + begin + nb := 1; + goto label1; + end; + end; + {look := PEEK_BITS(HUFF_LOOKAHEAD);} + look := int(get_buffer shr (bits_left - HUFF_LOOKAHEAD)) and + pred(1 shl HUFF_LOOKAHEAD); + + nb := tbl^.look_nbits[look]; + if (nb <> 0) then + begin + {DROP_BITS(nb);} + Dec(bits_left, nb); + + s := tbl^.look_sym[look]; + end + else + begin + nb := HUFF_LOOKAHEAD+1; + label1: + s := jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb); + if (s < 0) then + begin + decode_mcu_DC_first := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + if (s <> 0) then + begin + {CHECK_BIT_BUFFER(br_state, s, return FALSE);} + if (bits_left < s) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) then + begin + decode_mcu_DC_first := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {r := GET_BITS(s);} + Dec(bits_left, s); + r := (int(get_buffer shr bits_left)) and ( pred(1 shl s) ); + + {s := HUFF_EXTEND(r, s);} + if (r < extend_test[s]) then + s := r + extend_offset[s] + else + s := r; + end; + + { Convert DC difference to actual value, update last_dc_val } + Inc(s, state.last_dc_val[ci]); + state.last_dc_val[ci] := s; + { Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) } + block^[0] := JCOEF (s shl Al); + end; + + { Completed MCU, so update state } + {BITREAD_SAVE_STATE(cinfo,entropy^.bitstate);} + cinfo^.src^.next_input_byte := br_state.next_input_byte; + cinfo^.src^.bytes_in_buffer := br_state.bytes_in_buffer; + entropy^.bitstate.get_buffer := get_buffer; + entropy^.bitstate.bits_left := bits_left; + + {ASSIGN_STATE(entropy^.saved, state);} + entropy^.saved := state; + end; + + { Account for restart interval (no-op if not using restarts) } + Dec(entropy^.restarts_to_go); + + decode_mcu_DC_first := TRUE; +end; + + +{ MCU decoding for AC initial scan (either spectral selection, + or first pass of successive approximation). } + +{METHODDEF} +function decode_mcu_AC_first (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; +label + label2; +var + entropy : phuff_entropy_ptr; + Se : int; + Al : int; + {register} s, k, r : int; + EOBRUN : uInt; + block : JBLOCK_PTR; + {BITREAD_STATE_VARS;} + get_buffer : bit_buf_type ; {register} + bits_left : int; {register} + br_state : bitread_working_state; + + tbl : d_derived_tbl_ptr; +var + nb, look : int; {register} +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + Se := cinfo^.Se; + Al := cinfo^.Al; + + { Process restart marker if needed; may have to suspend } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + if (not process_restart(cinfo)) then + begin + decode_mcu_AC_first := FALSE; + exit; + end; + end; + + { If we've run out of data, just leave the MCU set to zeroes. + This way, we return uniform gray for the remainder of the segment. } + if not entropy^.pub.insufficient_data then + begin + + { Load up working state. + We can avoid loading/saving bitread state if in an EOB run. } + + EOBRUN := entropy^.saved.EOBRUN; { only part of saved state we care about } + + { There is always only one block per MCU } + + if (EOBRUN > 0) then { if it's a band of zeroes... } + Dec(EOBRUN) { ...process it now (we do nothing) } + else + begin + {BITREAD_LOAD_STATE(cinfo,entropy^.bitstate);} + br_state.cinfo := cinfo; + br_state.next_input_byte := cinfo^.src^.next_input_byte; + br_state.bytes_in_buffer := cinfo^.src^.bytes_in_buffer; + get_buffer := entropy^.bitstate.get_buffer; + bits_left := entropy^.bitstate.bits_left; + + block := JBLOCK_PTR(MCU_data[0]); + tbl := entropy^.ac_derived_tbl; + + k := cinfo^.Ss; + while (k <= Se) do + begin + {HUFF_DECODE(s, br_state, tbl, return FALSE, label2);} + if (bits_left < HUFF_LOOKAHEAD) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) then + begin + decode_mcu_AC_first := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + if (bits_left < HUFF_LOOKAHEAD) then + begin + nb := 1; + goto label2; + end; + end; + {look := PEEK_BITS(HUFF_LOOKAHEAD);} + look := int(get_buffer shr (bits_left - HUFF_LOOKAHEAD)) and + pred(1 shl HUFF_LOOKAHEAD); + + nb := tbl^.look_nbits[look]; + if (nb <> 0) then + begin + {DROP_BITS(nb);} + Dec(bits_left, nb); + + s := tbl^.look_sym[look]; + end + else + begin + nb := HUFF_LOOKAHEAD+1; + label2: + s := jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb); + if (s < 0) then + begin + decode_mcu_AC_first := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + r := s shr 4; + s := s and 15; + if (s <> 0) then + begin + Inc(k, r); + {CHECK_BIT_BUFFER(br_state, s, return FALSE);} + if (bits_left < s) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,s)) then + begin + decode_mcu_AC_first := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {r := GET_BITS(s);} + Dec(bits_left, s); + r := (int(get_buffer shr bits_left)) and ( pred(1 shl s) ); + + {s := HUFF_EXTEND(r, s);} + if (r < extend_test[s]) then + s := r + extend_offset[s] + else + s := r; + + { Scale and output coefficient in natural (dezigzagged) order } + block^[jpeg_natural_order[k]] := JCOEF (s shl Al); + end + else + begin + if (r = 15) then + begin { ZRL } + Inc(k, 15); { skip 15 zeroes in band } + end + else + begin { EOBr, run length is 2^r + appended bits } + EOBRUN := 1 shl r; + if (r <> 0) then + begin { EOBr, r > 0 } + {CHECK_BIT_BUFFER(br_state, r, return FALSE);} + if (bits_left < r) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,r)) then + begin + decode_mcu_AC_first := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {r := GET_BITS(r);} + Dec(bits_left, r); + r := (int(get_buffer shr bits_left)) and ( pred(1 shl r) ); + + Inc(EOBRUN, r); + end; + Dec(EOBRUN); { this band is processed at this moment } + break; { force end-of-band } + end; + end; + Inc(k); + end; + + {BITREAD_SAVE_STATE(cinfo,entropy^.bitstate);} + cinfo^.src^.next_input_byte := br_state.next_input_byte; + cinfo^.src^.bytes_in_buffer := br_state.bytes_in_buffer; + entropy^.bitstate.get_buffer := get_buffer; + entropy^.bitstate.bits_left := bits_left; + end; + + { Completed MCU, so update state } + entropy^.saved.EOBRUN := EOBRUN; { only part of saved state we care about } + end; + + { Account for restart interval (no-op if not using restarts) } + Dec(entropy^.restarts_to_go); + + decode_mcu_AC_first := TRUE; +end; + + +{ MCU decoding for DC successive approximation refinement scan. + Note: we assume such scans can be multi-component, although the spec + is not very clear on the point. } + +{METHODDEF} +function decode_mcu_DC_refine (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; + +var + entropy : phuff_entropy_ptr; + p1 : int; { 1 in the bit position being coded } + blkn : int; + block : JBLOCK_PTR; + {BITREAD_STATE_VARS;} + get_buffer : bit_buf_type ; {register} + bits_left : int; {register} + br_state : bitread_working_state; +begin + entropy := phuff_entropy_ptr (cinfo^.entropy); + p1 := 1 shl cinfo^.Al; + + { Process restart marker if needed; may have to suspend } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + if (not process_restart(cinfo)) then + begin + decode_mcu_DC_refine := FALSE; + exit; + end; + end; + + { Not worth the cycles to check insufficient_data here, + since we will not change the data anyway if we read zeroes. } + + { Load up working state } + {BITREAD_LOAD_STATE(cinfo,entropy^.bitstate);} + br_state.cinfo := cinfo; + br_state.next_input_byte := cinfo^.src^.next_input_byte; + br_state.bytes_in_buffer := cinfo^.src^.bytes_in_buffer; + get_buffer := entropy^.bitstate.get_buffer; + bits_left := entropy^.bitstate.bits_left; + + { Outer loop handles each block in the MCU } + + for blkn := 0 to pred(cinfo^.blocks_in_MCU) do + begin + block := JBLOCK_PTR(MCU_data[blkn]); + + { Encoded data is simply the next bit of the two's-complement DC value } + {CHECK_BIT_BUFFER(br_state, 1, return FALSE);} + if (bits_left < 1) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) then + begin + decode_mcu_DC_refine := FALSE; + exit; + end; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {if (GET_BITS(1)) then} + Dec(bits_left); + if (int(get_buffer shr bits_left)) and ( pred(1 shl 1) ) <> 0 then + block^[0] := block^[0] or p1; + { Note: since we use OR, repeating the assignment later is safe } + end; + + { Completed MCU, so update state } + {BITREAD_SAVE_STATE(cinfo,entropy^.bitstate);} + cinfo^.src^.next_input_byte := br_state.next_input_byte; + cinfo^.src^.bytes_in_buffer := br_state.bytes_in_buffer; + entropy^.bitstate.get_buffer := get_buffer; + entropy^.bitstate.bits_left := bits_left; + + { Account for restart interval (no-op if not using restarts) } + Dec(entropy^.restarts_to_go); + + decode_mcu_DC_refine := TRUE; +end; + + +{ MCU decoding for AC successive approximation refinement scan. } + +{METHODDEF} +function decode_mcu_AC_refine (cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; +label + undoit, label3; +var + entropy : phuff_entropy_ptr; + Se : int; + p1 : int; { 1 in the bit position being coded } + m1 : int; { -1 in the bit position being coded } + {register} s, k, r : int; + EOBRUN : uInt; + block : JBLOCK_PTR; + thiscoef : JCOEF_PTR; + {BITREAD_STATE_VARS;} + get_buffer : bit_buf_type ; {register} + bits_left : int; {register} + br_state : bitread_working_state; + + tbl : d_derived_tbl_ptr; + num_newnz : int; + newnz_pos : array[0..DCTSIZE2-1] of int; +var + pos : int; +var + nb, look : int; {register} +begin + num_newnz := 0; + block := nil; + + entropy := phuff_entropy_ptr (cinfo^.entropy); + Se := cinfo^.Se; + p1 := 1 shl cinfo^.Al; { 1 in the bit position being coded } + m1 := (-1) shl cinfo^.Al; { -1 in the bit position being coded } + + { Process restart marker if needed; may have to suspend } + if (cinfo^.restart_interval <> 0) then + begin + if (entropy^.restarts_to_go = 0) then + if (not process_restart(cinfo)) then + begin + decode_mcu_AC_refine := FALSE; + exit; + end; + end; + + { If we've run out of data, don't modify the MCU. } + if not entropy^.pub.insufficient_data then + begin + + { Load up working state } + {BITREAD_LOAD_STATE(cinfo,entropy^.bitstate);} + br_state.cinfo := cinfo; + br_state.next_input_byte := cinfo^.src^.next_input_byte; + br_state.bytes_in_buffer := cinfo^.src^.bytes_in_buffer; + get_buffer := entropy^.bitstate.get_buffer; + bits_left := entropy^.bitstate.bits_left; + + EOBRUN := entropy^.saved.EOBRUN; { only part of saved state we care about } + + { There is always only one block per MCU } + block := JBLOCK_PTR(MCU_data[0]); + tbl := entropy^.ac_derived_tbl; + + { If we are forced to suspend, we must undo the assignments to any newly + nonzero coefficients in the block, because otherwise we'd get confused + next time about which coefficients were already nonzero. + But we need not undo addition of bits to already-nonzero coefficients; + instead, we can test the current bit position to see if we already did it.} + + num_newnz := 0; + + { initialize coefficient loop counter to start of band } + k := cinfo^.Ss; + + if (EOBRUN = 0) then + begin + while (k <= Se) do + begin + {HUFF_DECODE(s, br_state, tbl, goto undoit, label3);} + if (bits_left < HUFF_LOOKAHEAD) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left, 0)) then + goto undoit; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + if (bits_left < HUFF_LOOKAHEAD) then + begin + nb := 1; + goto label3; + end; + end; + {look := PEEK_BITS(HUFF_LOOKAHEAD);} + look := int(get_buffer shr (bits_left - HUFF_LOOKAHEAD)) and + pred(1 shl HUFF_LOOKAHEAD); + + nb := tbl^.look_nbits[look]; + if (nb <> 0) then + begin + {DROP_BITS(nb);} + Dec(bits_left, nb); + + s := tbl^.look_sym[look]; + end + else + begin + nb := HUFF_LOOKAHEAD+1; + label3: + s := jpeg_huff_decode(br_state,get_buffer,bits_left,tbl,nb); + if (s < 0) then + goto undoit; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + r := s shr 4; + s := s and 15; + if (s <> 0) then + begin + if (s <> 1) then { size of new coef should always be 1 } + WARNMS(j_common_ptr(cinfo), JWRN_HUFF_BAD_CODE); + {CHECK_BIT_BUFFER(br_state, 1, goto undoit);} + if (bits_left < 1) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) then + goto undoit; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {if (GET_BITS(1)) then} + Dec(bits_left); + if (int(get_buffer shr bits_left)) and ( pred(1 shl 1) )<>0 then + s := p1 { newly nonzero coef is positive } + else + s := m1; { newly nonzero coef is negative } + end + else + begin + if (r <> 15) then + begin + EOBRUN := 1 shl r; { EOBr, run length is 2^r + appended bits } + if (r <> 0) then + begin + {CHECK_BIT_BUFFER(br_state, r, goto undoit);} + if (bits_left < r) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,r)) then + goto undoit; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {r := GET_BITS(r);} + Dec(bits_left, r); + r := (int(get_buffer shr bits_left)) and ( pred(1 shl r) ); + + Inc(EOBRUN, r); + end; + break; { rest of block is handled by EOB logic } + end; + { note s := 0 for processing ZRL } + end; + { Advance over already-nonzero coefs and r still-zero coefs, + appending correction bits to the nonzeroes. A correction bit is 1 + if the absolute value of the coefficient must be increased. } + + repeat + thiscoef :=@(block^[jpeg_natural_order[k]]); + if (thiscoef^ <> 0) then + begin + {CHECK_BIT_BUFFER(br_state, 1, goto undoit);} + if (bits_left < 1) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) then + goto undoit; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {if (GET_BITS(1)) then} + Dec(bits_left); + if (int(get_buffer shr bits_left)) and ( pred(1 shl 1) )<>0 then + begin + if ((thiscoef^ and p1) = 0) then + begin { do nothing if already set it } + if (thiscoef^ >= 0) then + Inc(thiscoef^, p1) + else + Inc(thiscoef^, m1); + end; + end; + end + else + begin + Dec(r); + if (r < 0) then + break; { reached target zero coefficient } + end; + Inc(k); + until (k > Se); + if (s <> 0) then + begin + pos := jpeg_natural_order[k]; + { Output newly nonzero coefficient } + block^[pos] := JCOEF (s); + { Remember its position in case we have to suspend } + newnz_pos[num_newnz] := pos; + Inc(num_newnz); + end; + Inc(k); + end; + end; + + if (EOBRUN > 0) then + begin + { Scan any remaining coefficient positions after the end-of-band + (the last newly nonzero coefficient, if any). Append a correction + bit to each already-nonzero coefficient. A correction bit is 1 + if the absolute value of the coefficient must be increased. } + + while (k <= Se) do + begin + thiscoef := @(block^[jpeg_natural_order[k]]); + if (thiscoef^ <> 0) then + begin + {CHECK_BIT_BUFFER(br_state, 1, goto undoit);} + if (bits_left < 1) then + begin + if (not jpeg_fill_bit_buffer(br_state,get_buffer,bits_left,1)) then + goto undoit; + get_buffer := br_state.get_buffer; + bits_left := br_state.bits_left; + end; + + {if (GET_BITS(1)) then} + Dec(bits_left); + if (int(get_buffer shr bits_left)) and ( pred(1 shl 1) )<>0 then + begin + if ((thiscoef^ and p1) = 0) then + begin { do nothing if already changed it } + if (thiscoef^ >= 0) then + Inc(thiscoef^, p1) + else + Inc(thiscoef^, m1); + end; + end; + end; + Inc(k); + end; + { Count one block completed in EOB run } + Dec(EOBRUN); + end; + + { Completed MCU, so update state } + {BITREAD_SAVE_STATE(cinfo,entropy^.bitstate);} + cinfo^.src^.next_input_byte := br_state.next_input_byte; + cinfo^.src^.bytes_in_buffer := br_state.bytes_in_buffer; + entropy^.bitstate.get_buffer := get_buffer; + entropy^.bitstate.bits_left := bits_left; + + entropy^.saved.EOBRUN := EOBRUN; { only part of saved state we care about } + end; + + { Account for restart interval (no-op if not using restarts) } + Dec(entropy^.restarts_to_go); + + decode_mcu_AC_refine := TRUE; + exit; + +undoit: + { Re-zero any output coefficients that we made newly nonzero } + while (num_newnz > 0) do + begin + Dec(num_newnz); + block^[newnz_pos[num_newnz]] := 0; + end; + + decode_mcu_AC_refine := FALSE; +end; + + +{ Module initialization routine for progressive Huffman entropy decoding. } + +{GLOBAL} +procedure jinit_phuff_decoder (cinfo : j_decompress_ptr); +var + entropy : phuff_entropy_ptr; + coef_bit_ptr : int_ptr; + ci, i : int; +begin + entropy := phuff_entropy_ptr( + cinfo^.mem^.alloc_small (j_common_ptr (cinfo), JPOOL_IMAGE, + SIZEOF(phuff_entropy_decoder)) ); + cinfo^.entropy := jpeg_entropy_decoder_ptr (entropy); + entropy^.pub.start_pass := start_pass_phuff_decoder; + + { Mark derived tables unallocated } + for i := 0 to pred(NUM_HUFF_TBLS) do + begin + entropy^.derived_tbls[i] := NIL; + end; + + { Create progression status table } + cinfo^.coef_bits := coef_bits_ptrrow ( + cinfo^.mem^.alloc_small ( j_common_ptr (cinfo), JPOOL_IMAGE, + cinfo^.num_components*DCTSIZE2*SIZEOF(int)) ); + coef_bit_ptr := @cinfo^.coef_bits^[0][0]; + for ci := 0 to pred(cinfo^.num_components) do + for i := 0 to pred(DCTSIZE2) do + begin + coef_bit_ptr^ := -1; + Inc(coef_bit_ptr); + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdpostct.pas b/src/lib/vampimg/JpegLib/imjdpostct.pas new file mode 100644 index 0000000..8769550 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdpostct.pas @@ -0,0 +1,341 @@ +unit imjdpostct; + +{ Original: jdpostct.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +{ This file contains the decompression postprocessing controller. + This controller manages the upsampling, color conversion, and color + quantization/reduction steps; specifically, it controls the buffering + between upsample/color conversion and color quantization/reduction. + + If no color quantization/reduction is required, then this module has no + work to do, and it just hands off to the upsample/color conversion code. + An integrated upsample/convert/quantize process would replace this module + entirely. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjutils, + imjpeglib; + +{ Initialize postprocessing controller. } + +{GLOBAL} +procedure jinit_d_post_controller (cinfo : j_decompress_ptr; + need_full_buffer : boolean); +implementation + + +{ Private buffer controller object } + +type + my_post_ptr = ^my_post_controller; + my_post_controller = record + pub : jpeg_d_post_controller; { public fields } + + { Color quantization source buffer: this holds output data from + the upsample/color conversion step to be passed to the quantizer. + For two-pass color quantization, we need a full-image buffer; + for one-pass operation, a strip buffer is sufficient. } + + whole_image : jvirt_sarray_ptr; { virtual array, or NIL if one-pass } + buffer : JSAMPARRAY; { strip buffer, or current strip of virtual } + strip_height : JDIMENSION; { buffer size in rows } + { for two-pass mode only: } + starting_row : JDIMENSION; { row # of first row in current strip } + next_row : JDIMENSION; { index of next row to fill/empty in strip } + end; + +{ Forward declarations } +{METHODDEF} +procedure post_process_1pass(cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); forward; +{$ifdef QUANT_2PASS_SUPPORTED} +{METHODDEF} +procedure post_process_prepass(cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); forward; +{METHODDEF} +procedure post_process_2pass(cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); forward; +{$endif} + + +{ Initialize for a processing pass. } + +{METHODDEF} +procedure start_pass_dpost (cinfo : j_decompress_ptr; + pass_mode : J_BUF_MODE); +var + post : my_post_ptr; +begin + post := my_post_ptr(cinfo^.post); + + case (pass_mode) of + JBUF_PASS_THRU: + if (cinfo^.quantize_colors) then + begin + { Single-pass processing with color quantization. } + post^.pub.post_process_data := post_process_1pass; + { We could be doing buffered-image output before starting a 2-pass + color quantization; in that case, jinit_d_post_controller did not + allocate a strip buffer. Use the virtual-array buffer as workspace. } + if (post^.buffer = NIL) then + begin + post^.buffer := cinfo^.mem^.access_virt_sarray + (j_common_ptr(cinfo), post^.whole_image, + JDIMENSION(0), post^.strip_height, TRUE); + end; + end + else + begin + { For single-pass processing without color quantization, + I have no work to do; just call the upsampler directly. } + + post^.pub.post_process_data := cinfo^.upsample^.upsample; + end; + +{$ifdef QUANT_2PASS_SUPPORTED} + JBUF_SAVE_AND_PASS: + begin + { First pass of 2-pass quantization } + if (post^.whole_image = NIL) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + post^.pub.post_process_data := post_process_prepass; + end; + JBUF_CRANK_DEST: + begin + { Second pass of 2-pass quantization } + if (post^.whole_image = NIL) then + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + post^.pub.post_process_data := post_process_2pass; + end; +{$endif} { QUANT_2PASS_SUPPORTED } + else + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); + end; + post^.next_row := 0; + post^.starting_row := 0; +end; + + +{ Process some data in the one-pass (strip buffer) case. + This is used for color precision reduction as well as one-pass quantization. } + +{METHODDEF} +procedure post_process_1pass (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +var + post : my_post_ptr; + num_rows, max_rows : JDIMENSION; +begin + post := my_post_ptr (cinfo^.post); + + { Fill the buffer, but not more than what we can dump out in one go. } + { Note we rely on the upsampler to detect bottom of image. } + max_rows := out_rows_avail - out_row_ctr; + if (max_rows > post^.strip_height) then + max_rows := post^.strip_height; + num_rows := 0; + cinfo^.upsample^.upsample (cinfo, + input_buf, + in_row_group_ctr, + in_row_groups_avail, + post^.buffer, + num_rows, { var } + max_rows); + { Quantize and emit data. } + + cinfo^.cquantize^.color_quantize (cinfo, + post^.buffer, + JSAMPARRAY(@ output_buf^[out_row_ctr]), + int(num_rows)); + + Inc(out_row_ctr, num_rows); +end; + + +{$ifdef QUANT_2PASS_SUPPORTED} + +{ Process some data in the first pass of 2-pass quantization. } + +{METHODDEF} +procedure post_process_prepass (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail:JDIMENSION); +var + post : my_post_ptr; + old_next_row, num_rows : JDIMENSION; +begin + post := my_post_ptr(cinfo^.post); + + { Reposition virtual buffer if at start of strip. } + if (post^.next_row = 0) then + begin + post^.buffer := cinfo^.mem^.access_virt_sarray + (j_common_ptr(cinfo), post^.whole_image, + post^.starting_row, post^.strip_height, TRUE); + end; + + { Upsample some data (up to a strip height's worth). } + old_next_row := post^.next_row; + cinfo^.upsample^.upsample (cinfo, + input_buf, in_row_group_ctr, in_row_groups_avail, + post^.buffer, post^.next_row, post^.strip_height); + + { Allow quantizer to scan new data. No data is emitted, } + { but we advance out_row_ctr so outer loop can tell when we're done. } + if (post^.next_row > old_next_row) then + begin + num_rows := post^.next_row - old_next_row; + + + cinfo^.cquantize^.color_quantize (cinfo, + JSAMPARRAY(@ post^.buffer^[old_next_row]), + JSAMPARRAY(NIL), + int(num_rows)); + Inc(out_row_ctr, num_rows); + end; + + { Advance if we filled the strip. } + if (post^.next_row >= post^.strip_height) then + begin + Inc(post^.starting_row, post^.strip_height); + post^.next_row := 0; + end; +end; + + +{ Process some data in the second pass of 2-pass quantization. } + +{METHODDEF} +procedure post_process_2pass (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +var + post : my_post_ptr; + num_rows, max_rows : JDIMENSION; +begin + post := my_post_ptr(cinfo^.post); + + { Reposition virtual buffer if at start of strip. } + if (post^.next_row = 0) then + begin + post^.buffer := cinfo^.mem^.access_virt_sarray + (j_common_ptr(cinfo), post^.whole_image, + post^.starting_row, post^.strip_height, FALSE); + end; + + { Determine number of rows to emit. } + num_rows := post^.strip_height - post^.next_row; { available in strip } + max_rows := out_rows_avail - out_row_ctr; { available in output area } + if (num_rows > max_rows) then + num_rows := max_rows; + { We have to check bottom of image here, can't depend on upsampler. } + max_rows := cinfo^.output_height - post^.starting_row; + if (num_rows > max_rows) then + num_rows := max_rows; + + { Quantize and emit data. } + cinfo^.cquantize^.color_quantize (cinfo, + JSAMPARRAY(@ post^.buffer^[post^.next_row]), + JSAMPARRAY(@ output_buf^[out_row_ctr]), + int(num_rows)); + Inc(out_row_ctr, num_rows); + + { Advance if we filled the strip. } + Inc(post^.next_row, num_rows); + if (post^.next_row >= post^.strip_height) then + begin + Inc(post^.starting_row, post^.strip_height); + post^.next_row := 0; + end; +end; + +{$endif} { QUANT_2PASS_SUPPORTED } + + +{ Initialize postprocessing controller. } + +{GLOBAL} +procedure jinit_d_post_controller (cinfo : j_decompress_ptr; + need_full_buffer : boolean); +var + post : my_post_ptr; +begin + post := my_post_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_post_controller)) ); + cinfo^.post := jpeg_d_post_controller_ptr (post); + post^.pub.start_pass := start_pass_dpost; + post^.whole_image := NIL; { flag for no virtual arrays } + post^.buffer := NIL; { flag for no strip buffer } + + { Create the quantization buffer, if needed } + if (cinfo^.quantize_colors) then + begin + { The buffer strip height is max_v_samp_factor, which is typically + an efficient number of rows for upsampling to return. + (In the presence of output rescaling, we might want to be smarter?) } + + post^.strip_height := JDIMENSION (cinfo^.max_v_samp_factor); + if (need_full_buffer) then + begin + { Two-pass color quantization: need full-image storage. } + { We round up the number of rows to a multiple of the strip height. } +{$ifdef QUANT_2PASS_SUPPORTED} + post^.whole_image := cinfo^.mem^.request_virt_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, FALSE, + LongInt(cinfo^.output_width) * cinfo^.out_color_components, + JDIMENSION (jround_up( long(cinfo^.output_height), + long(post^.strip_height)) ), + post^.strip_height); +{$else} + ERREXIT(j_common_ptr(cinfo), JERR_BAD_BUFFER_MODE); +{$endif} { QUANT_2PASS_SUPPORTED } + end + else + begin + { One-pass color quantization: just make a strip buffer. } + post^.buffer := cinfo^.mem^.alloc_sarray + (j_common_ptr (cinfo), JPOOL_IMAGE, + LongInt(cinfo^.output_width) * cinfo^.out_color_components, + post^.strip_height); + end; + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjdsample.pas b/src/lib/vampimg/JpegLib/imjdsample.pas new file mode 100644 index 0000000..ec95e34 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjdsample.pas @@ -0,0 +1,592 @@ +unit imjdsample; + +{ Original: jdsample.c; Copyright (C) 1991-1996, Thomas G. Lane. } + +{ This file contains upsampling routines. + + Upsampling input data is counted in "row groups". A row group + is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) + sample rows of each component. Upsampling will normally produce + max_v_samp_factor pixel rows from each row group (but this could vary + if the upsampler is applying a scale factor of its own). + + An excellent reference for image resampling is + Digital Image Warping, George Wolberg, 1990. + Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.} + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjutils, + imjpeglib, + imjdeferr, + imjerror; + + +{ Pointer to routine to upsample a single component } +type + upsample1_ptr = procedure (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); + +{ Module initialization routine for upsampling. } + +{GLOBAL} +procedure jinit_upsampler (cinfo : j_decompress_ptr); + +implementation + +{ Private subobject } + +type + my_upsample_ptr = ^my_upsampler; + my_upsampler = record + pub : jpeg_upsampler; { public fields } + + { Color conversion buffer. When using separate upsampling and color + conversion steps, this buffer holds one upsampled row group until it + has been color converted and output. + Note: we do not allocate any storage for component(s) which are full-size, + ie do not need rescaling. The corresponding entry of color_buf[] is + simply set to point to the input data array, thereby avoiding copying.} + + color_buf : array[0..MAX_COMPONENTS-1] of JSAMPARRAY; + + { Per-component upsampling method pointers } + methods : array[0..MAX_COMPONENTS-1] of upsample1_ptr; + + next_row_out : int; { counts rows emitted from color_buf } + rows_to_go : JDIMENSION; { counts rows remaining in image } + + { Height of an input row group for each component. } + rowgroup_height : array[0..MAX_COMPONENTS-1] of int; + + { These arrays save pixel expansion factors so that int_expand need not + recompute them each time. They are unused for other upsampling methods.} + h_expand : array[0..MAX_COMPONENTS-1] of UINT8 ; + v_expand : array[0..MAX_COMPONENTS-1] of UINT8 ; + end; + + +{ Initialize for an upsampling pass. } + +{METHODDEF} +procedure start_pass_upsample (cinfo : j_decompress_ptr); +var + upsample : my_upsample_ptr; +begin + upsample := my_upsample_ptr (cinfo^.upsample); + + { Mark the conversion buffer empty } + upsample^.next_row_out := cinfo^.max_v_samp_factor; + { Initialize total-height counter for detecting bottom of image } + upsample^.rows_to_go := cinfo^.output_height; +end; + + +{ Control routine to do upsampling (and color conversion). + + In this version we upsample each component independently. + We upsample one row group into the conversion buffer, then apply + color conversion a row at a time. } + +{METHODDEF} +procedure sep_upsample (cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); +var + upsample : my_upsample_ptr; + ci : int; + compptr : jpeg_component_info_ptr; + num_rows : JDIMENSION; +begin + upsample := my_upsample_ptr (cinfo^.upsample); + + { Fill the conversion buffer, if it's empty } + if (upsample^.next_row_out >= cinfo^.max_v_samp_factor) then + begin + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Invoke per-component upsample method. Notice we pass a POINTER + to color_buf[ci], so that fullsize_upsample can change it. } + + upsample^.methods[ci] (cinfo, compptr, + JSAMPARRAY(@ input_buf^[ci]^ + [LongInt(in_row_group_ctr) * upsample^.rowgroup_height[ci]]), + upsample^.color_buf[ci]); + + Inc(compptr); + end; + upsample^.next_row_out := 0; + end; + + { Color-convert and emit rows } + + { How many we have in the buffer: } + num_rows := JDIMENSION (cinfo^.max_v_samp_factor - upsample^.next_row_out); + { Not more than the distance to the end of the image. Need this test + in case the image height is not a multiple of max_v_samp_factor: } + + if (num_rows > upsample^.rows_to_go) then + num_rows := upsample^.rows_to_go; + { And not more than what the client can accept: } + Dec(out_rows_avail, out_row_ctr); + if (num_rows > out_rows_avail) then + num_rows := out_rows_avail; + + cinfo^.cconvert^.color_convert (cinfo, + JSAMPIMAGE(@(upsample^.color_buf)), + JDIMENSION (upsample^.next_row_out), + JSAMPARRAY(@(output_buf^[out_row_ctr])), + int (num_rows)); + + { Adjust counts } + Inc(out_row_ctr, num_rows); + Dec(upsample^.rows_to_go, num_rows); + Inc(upsample^.next_row_out, num_rows); + { When the buffer is emptied, declare this input row group consumed } + if (upsample^.next_row_out >= cinfo^.max_v_samp_factor) then + Inc(in_row_group_ctr); +end; + + +{ These are the routines invoked by sep_upsample to upsample pixel values + of a single component. One row group is processed per call. } + + +{ For full-size components, we just make color_buf[ci] point at the + input buffer, and thus avoid copying any data. Note that this is + safe only because sep_upsample doesn't declare the input row group + "consumed" until we are done color converting and emitting it. } + +{METHODDEF} +procedure fullsize_upsample (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); +begin + output_data_ptr := input_data; +end; + + +{ This is a no-op version used for "uninteresting" components. + These components will not be referenced by color conversion. } + +{METHODDEF} +procedure noop_upsample (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); +begin + output_data_ptr := NIL; { safety check } +end; + + +{ This version handles any integral sampling ratios. + This is not used for typical JPEG files, so it need not be fast. + Nor, for that matter, is it particularly accurate: the algorithm is + simple replication of the input pixel onto the corresponding output + pixels. The hi-falutin sampling literature refers to this as a + "box filter". A box filter tends to introduce visible artifacts, + so if you are actually going to use 3:1 or 4:1 sampling ratios + you would be well advised to improve this code. } + +{METHODDEF} +procedure int_upsample (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); +var + upsample : my_upsample_ptr; + output_data : JSAMPARRAY; + {register} inptr, outptr : JSAMPLE_PTR; + {register} invalue : JSAMPLE; + {register} h : int; + {outend} + h_expand, v_expand : int; + inrow, outrow : int; +var + outcount : int; { Nomssi: avoid pointer arithmetic } +begin + upsample := my_upsample_ptr (cinfo^.upsample); + output_data := output_data_ptr; + + h_expand := upsample^.h_expand[compptr^.component_index]; + v_expand := upsample^.v_expand[compptr^.component_index]; + + inrow := 0; + outrow := 0; + while (outrow < cinfo^.max_v_samp_factor) do + begin + { Generate one output row with proper horizontal expansion } + inptr := JSAMPLE_PTR(input_data^[inrow]); + outptr := JSAMPLE_PTR(output_data^[outrow]); + outcount := cinfo^.output_width; + while (outcount > 0) do { Nomssi } + begin + invalue := inptr^; { don't need GETJSAMPLE() here } + Inc(inptr); + for h := pred(h_expand) downto 0 do + begin + outptr^ := invalue; + inc(outptr); { <-- fix: this was left out in PasJpeg 1.0 } + Dec(outcount); { thanks to Jannie Gerber for the report } + end; + end; + + { Generate any additional output rows by duplicating the first one } + if (v_expand > 1) then + begin + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + v_expand-1, cinfo^.output_width); + end; + Inc(inrow); + Inc(outrow, v_expand); + end; +end; + + +{ Fast processing for the common case of 2:1 horizontal and 1:1 vertical. + It's still a box filter. } + +{METHODDEF} +procedure h2v1_upsample (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); +var + output_data : JSAMPARRAY; + {register} inptr, outptr : JSAMPLE_PTR; + {register} invalue : JSAMPLE; + {outend : JSAMPROW;} + outcount : int; + inrow : int; +begin + output_data := output_data_ptr; + + for inrow := 0 to pred(cinfo^.max_v_samp_factor) do + begin + inptr := JSAMPLE_PTR(input_data^[inrow]); + outptr := JSAMPLE_PTR(output_data^[inrow]); + {outend := outptr + cinfo^.output_width;} + outcount := cinfo^.output_width; + while (outcount > 0) do + begin + invalue := inptr^; { don't need GETJSAMPLE() here } + Inc(inptr); + outptr^ := invalue; + Inc(outptr); + outptr^ := invalue; + Inc(outptr); + Dec(outcount, 2); { Nomssi: to avoid pointer arithmetic } + end; + end; +end; + + +{ Fast processing for the common case of 2:1 horizontal and 2:1 vertical. + It's still a box filter. } + +{METHODDEF} +procedure h2v2_upsample (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); +var + output_data : JSAMPARRAY; + {register} inptr, outptr : JSAMPLE_PTR; + {register} invalue : JSAMPLE; + {outend : JSAMPROW;} + outcount : int; + inrow, outrow : int; +begin + output_data := output_data_ptr; + + inrow := 0; + outrow := 0; + while (outrow < cinfo^.max_v_samp_factor) do + begin + inptr := JSAMPLE_PTR(input_data^[inrow]); + outptr := JSAMPLE_PTR(output_data^[outrow]); + {outend := outptr + cinfo^.output_width;} + outcount := cinfo^.output_width; + while (outcount > 0) do + begin + invalue := inptr^; { don't need GETJSAMPLE() here } + Inc(inptr); + outptr^ := invalue; + Inc(outptr); + outptr^ := invalue; + Inc(outptr); + Dec(outcount, 2); + end; + jcopy_sample_rows(output_data, outrow, output_data, outrow+1, + 1, cinfo^.output_width); + Inc(inrow); + Inc(outrow, 2); + end; +end; + + +{ Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. + + The upsampling algorithm is linear interpolation between pixel centers, + also known as a "triangle filter". This is a good compromise between + speed and visual quality. The centers of the output pixels are 1/4 and 3/4 + of the way between input pixel centers. + + A note about the "bias" calculations: when rounding fractional values to + integer, we do not want to always round 0.5 up to the next integer. + If we did that, we'd introduce a noticeable bias towards larger values. + Instead, this code is arranged so that 0.5 will be rounded up or down at + alternate pixel locations (a simple ordered dither pattern). } + +{METHODDEF} +procedure h2v1_fancy_upsample (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); +var + output_data : JSAMPARRAY; + {register} pre_inptr, inptr, outptr : JSAMPLE_PTR; + {register} invalue : int; + {register} colctr : JDIMENSION; + inrow : int; +begin + output_data := output_data_ptr; + + for inrow := 0 to pred(cinfo^.max_v_samp_factor) do + begin + inptr := JSAMPLE_PTR(input_data^[inrow]); + outptr := JSAMPLE_PTR(output_data^[inrow]); + { Special case for first column } + pre_inptr := inptr; + invalue := GETJSAMPLE(inptr^); + Inc(inptr); + outptr^ := JSAMPLE (invalue); + Inc(outptr); + outptr^ := JSAMPLE ((invalue * 3 + GETJSAMPLE(inptr^) + 2) shr 2); + Inc(outptr); + + for colctr := pred(compptr^.downsampled_width - 2) downto 0 do + begin + { General case: 3/4 * nearer pixel + 1/4 * further pixel } + invalue := GETJSAMPLE(inptr^) * 3; + Inc(inptr); + outptr^ := JSAMPLE ((invalue + GETJSAMPLE(pre_inptr^) + 1) shr 2); + Inc(pre_inptr); + Inc(outptr); + outptr^ := JSAMPLE ((invalue + GETJSAMPLE(inptr^) + 2) shr 2); + Inc(outptr); + end; + + { Special case for last column } + invalue := GETJSAMPLE(inptr^); + outptr^ := JSAMPLE ((invalue * 3 + GETJSAMPLE(pre_inptr^) + 1) shr 2); + Inc(outptr); + outptr^ := JSAMPLE (invalue); + {Inc(outptr); - value never used } + end; +end; + + +{ Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. + Again a triangle filter; see comments for h2v1 case, above. + + It is OK for us to reference the adjacent input rows because we demanded + context from the main buffer controller (see initialization code). } + +{METHODDEF} +procedure h2v2_fancy_upsample (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + input_data : JSAMPARRAY; + var output_data_ptr : JSAMPARRAY); +var + output_data : JSAMPARRAY; + {register} inptr0, inptr1, outptr : JSAMPLE_PTR; +{$ifdef BITS_IN_JSAMPLE_IS_8} + {register} thiscolsum, lastcolsum, nextcolsum : int; +{$else} + {register} thiscolsum, lastcolsum, nextcolsum : INT32; +{$endif} + {register} colctr : JDIMENSION; + inrow, outrow, v : int; +var + prev_input_data : JSAMPARRAY; { Nomssi work around } +begin + output_data := output_data_ptr; + + outrow := 0; + inrow := 0; + while (outrow < cinfo^.max_v_samp_factor) do + begin + for v := 0 to pred(2) do + begin + { inptr0 points to nearest input row, inptr1 points to next nearest } + inptr0 := JSAMPLE_PTR(input_data^[inrow]); + if (v = 0) then { next nearest is row above } + begin + {inptr1 := JSAMPLE_PTR(input_data^[inrow-1]);} + prev_input_data := input_data; { work around } + Dec(JSAMPROW_PTR(prev_input_data)); { negative offsets } + inptr1 := JSAMPLE_PTR(prev_input_data^[inrow]); + end + else { next nearest is row below } + inptr1 := JSAMPLE_PTR(input_data^[inrow+1]); + outptr := JSAMPLE_PTR(output_data^[outrow]); + Inc(outrow); + + { Special case for first column } + thiscolsum := GETJSAMPLE(inptr0^) * 3 + GETJSAMPLE(inptr1^); + Inc(inptr0); + Inc(inptr1); + nextcolsum := GETJSAMPLE(inptr0^) * 3 + GETJSAMPLE(inptr1^); + Inc(inptr0); + Inc(inptr1); + + outptr^ := JSAMPLE ((thiscolsum * 4 + 8) shr 4); + Inc(outptr); + outptr^ := JSAMPLE ((thiscolsum * 3 + nextcolsum + 7) shr 4); + Inc(outptr); + lastcolsum := thiscolsum; thiscolsum := nextcolsum; + + for colctr := pred(compptr^.downsampled_width - 2) downto 0 do + begin + { General case: 3/4 * nearer pixel + 1/4 * further pixel in each } + { dimension, thus 9/16, 3/16, 3/16, 1/16 overall } + nextcolsum := GETJSAMPLE(inptr0^) * 3 + GETJSAMPLE(inptr1^); + Inc(inptr0); + Inc(inptr1); + outptr^ := JSAMPLE ((thiscolsum * 3 + lastcolsum + 8) shr 4); + Inc(outptr); + outptr^ := JSAMPLE ((thiscolsum * 3 + nextcolsum + 7) shr 4); + Inc(outptr); + lastcolsum := thiscolsum; + thiscolsum := nextcolsum; + end; + + { Special case for last column } + outptr^ := JSAMPLE ((thiscolsum * 3 + lastcolsum + 8) shr 4); + Inc(outptr); + outptr^ := JSAMPLE ((thiscolsum * 4 + 7) shr 4); + {Inc(outptr); - value never used } + end; + Inc(inrow); + end; +end; + + +{ Module initialization routine for upsampling. } + +{GLOBAL} +procedure jinit_upsampler (cinfo : j_decompress_ptr); +var + upsample : my_upsample_ptr; + ci : int; + compptr : jpeg_component_info_ptr; + need_buffer, do_fancy : boolean; + h_in_group, v_in_group, h_out_group, v_out_group : int; +begin + upsample := my_upsample_ptr ( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_upsampler)) ); + cinfo^.upsample := jpeg_upsampler_ptr (upsample); + upsample^.pub.start_pass := start_pass_upsample; + upsample^.pub.upsample := sep_upsample; + upsample^.pub.need_context_rows := FALSE; { until we find out differently } + + if (cinfo^.CCIR601_sampling) then { this isn't supported } + ERREXIT(j_common_ptr(cinfo), JERR_CCIR601_NOTIMPL); + + { jdmainct.c doesn't support context rows when min_DCT_scaled_size := 1, + so don't ask for it. } + + do_fancy := cinfo^.do_fancy_upsampling and (cinfo^.min_DCT_scaled_size > 1); + + { Verify we can handle the sampling factors, select per-component methods, + and create storage as needed. } + + compptr := jpeg_component_info_ptr(cinfo^.comp_info); + for ci := 0 to pred(cinfo^.num_components) do + begin + { Compute size of an "input group" after IDCT scaling. This many samples + are to be converted to max_h_samp_factor * max_v_samp_factor pixels. } + + h_in_group := (compptr^.h_samp_factor * compptr^.DCT_scaled_size) div + cinfo^.min_DCT_scaled_size; + v_in_group := (compptr^.v_samp_factor * compptr^.DCT_scaled_size) div + cinfo^.min_DCT_scaled_size; + h_out_group := cinfo^.max_h_samp_factor; + v_out_group := cinfo^.max_v_samp_factor; + upsample^.rowgroup_height[ci] := v_in_group; { save for use later } + need_buffer := TRUE; + if (not compptr^.component_needed) then + begin + { Don't bother to upsample an uninteresting component. } + upsample^.methods[ci] := noop_upsample; + need_buffer := FALSE; + end + else + if (h_in_group = h_out_group) and (v_in_group = v_out_group) then + begin + { Fullsize components can be processed without any work. } + upsample^.methods[ci] := fullsize_upsample; + need_buffer := FALSE; + end + else + if (h_in_group * 2 = h_out_group) and + (v_in_group = v_out_group) then + begin + { Special cases for 2h1v upsampling } + if (do_fancy) and (compptr^.downsampled_width > 2) then + upsample^.methods[ci] := h2v1_fancy_upsample + else + upsample^.methods[ci] := h2v1_upsample; + end + else + if (h_in_group * 2 = h_out_group) and + (v_in_group * 2 = v_out_group) then + begin + { Special cases for 2h2v upsampling } + if (do_fancy) and (compptr^.downsampled_width > 2) then + begin + upsample^.methods[ci] := h2v2_fancy_upsample; + upsample^.pub.need_context_rows := TRUE; + end + else + upsample^.methods[ci] := h2v2_upsample; + end + else + if ((h_out_group mod h_in_group) = 0) and + ((v_out_group mod v_in_group) = 0) then + begin + { Generic integral-factors upsampling method } + upsample^.methods[ci] := int_upsample; + upsample^.h_expand[ci] := UINT8 (h_out_group div h_in_group); + upsample^.v_expand[ci] := UINT8 (v_out_group div v_in_group); + end + else + ERREXIT(j_common_ptr(cinfo), JERR_FRACT_SAMPLE_NOTIMPL); + if (need_buffer) then + begin + upsample^.color_buf[ci] := cinfo^.mem^.alloc_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, + JDIMENSION (jround_up( long (cinfo^.output_width), + long (cinfo^.max_h_samp_factor))), + JDIMENSION (cinfo^.max_v_samp_factor)); + end; + Inc(compptr); + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjerror.pas b/src/lib/vampimg/JpegLib/imjerror.pas new file mode 100644 index 0000000..11f53fd --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjerror.pas @@ -0,0 +1,462 @@ +unit imjerror; + +{ This file contains simple error-reporting and trace-message routines. + These are suitable for Unix-like systems and others where writing to + stderr is the right thing to do. Many applications will want to replace + some or all of these routines. + + These routines are used by both the compression and decompression code. } + +{ Source: jerror.c; Copyright (C) 1991-1996, Thomas G. Lane. } +{ note: format_message still contains a hack } +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjdeferr, + imjpeglib; +{ + jversion; +} + +const + EXIT_FAILURE = 1; { define halt() codes if not provided } + +{GLOBAL} +function jpeg_std_error (var err : jpeg_error_mgr) : jpeg_error_mgr_ptr; + + + +procedure ERREXIT(cinfo : j_common_ptr; code : J_MESSAGE_CODE); + +procedure ERREXIT1(cinfo : j_common_ptr; code : J_MESSAGE_CODE; p1 : uInt); + +procedure ERREXIT2(cinfo : j_common_ptr; code : J_MESSAGE_CODE; p1 : int; p2 : int); + +procedure ERREXIT3(cinfo : j_common_ptr; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int); + +procedure ERREXIT4(cinfo : j_common_ptr; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int); + +procedure ERREXITS(cinfo : j_common_ptr;code : J_MESSAGE_CODE; + str : AnsiString); +{ Nonfatal errors (we can keep going, but the data is probably corrupt) } + +procedure WARNMS(cinfo : j_common_ptr; code : J_MESSAGE_CODE); + +procedure WARNMS1(cinfo : j_common_ptr;code : J_MESSAGE_CODE; p1 : int); + +procedure WARNMS2(cinfo : j_common_ptr; code : J_MESSAGE_CODE; + p1 : int; p2 : int); + +{ Informational/debugging messages } +procedure TRACEMS(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE); + +procedure TRACEMS1(cinfo : j_common_ptr; lvl : int; + code : J_MESSAGE_CODE; p1 : long); + +procedure TRACEMS2(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; + p2 : int); + +procedure TRACEMS3(cinfo : j_common_ptr; + lvl : int; + code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int); + +procedure TRACEMS4(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int); + +procedure TRACEMS5(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int; p5 : int); + +procedure TRACEMS8(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int; + p5 : int; p6 : int; p7 : int; p8 : int); + +procedure TRACEMSS(cinfo : j_common_ptr; lvl : int; + code : J_MESSAGE_CODE; str : AnsiString); + +implementation + + +{ How to format a message string, in format_message() ? } + +{$IFDEF OS2} + {$DEFINE NO_FORMAT} +{$ENDIF} +{$IFDEF FPC} + {$DEFINE NO_FORMAT} +{$ENDIF} + +uses +{$IFNDEF NO_FORMAT} + {$IFDEF VER70} + drivers, { Turbo Vision unit with FormatStr } + {$ELSE} + sysutils, { Delphi Unit with Format() } + {$ENDIF} +{$ENDIF} + imjcomapi; + +{ Error exit handler: must not return to caller. + + Applications may override this if they want to get control back after + an error. Typically one would longjmp somewhere instead of exiting. + The setjmp buffer can be made a private field within an expanded error + handler object. Note that the info needed to generate an error message + is stored in the error object, so you can generate the message now or + later, at your convenience. + You should make sure that the JPEG object is cleaned up (with jpeg_abort + or jpeg_destroy) at some point. } + + +{METHODDEF} +procedure error_exit (cinfo : j_common_ptr); +begin + { Always display the message } + cinfo^.err^.output_message(cinfo); + + { Let the memory manager delete any temp files before we die } + jpeg_destroy(cinfo); + + halt(EXIT_FAILURE); +end; + + +{ Actual output of an error or trace message. + Applications may override this method to send JPEG messages somewhere + other than stderr. } + +{ Macros to simplify using the error and trace message stuff } +{ The first parameter is either type of cinfo pointer } + +{ Fatal errors (print message and exit) } +procedure ERREXIT(cinfo : j_common_ptr; code : J_MESSAGE_CODE); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.error_exit(cinfo); +end; + +procedure ERREXIT1(cinfo : j_common_ptr; code : J_MESSAGE_CODE; p1 : uInt); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.error_exit (cinfo); +end; + +procedure ERREXIT2(cinfo : j_common_ptr; code : J_MESSAGE_CODE; + p1 : int; p2 : int); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.msg_parm.i[1] := p2; + cinfo^.err^.error_exit (cinfo); +end; + +procedure ERREXIT3(cinfo : j_common_ptr; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.msg_parm.i[1] := p2; + cinfo^.err^.msg_parm.i[2] := p3; + cinfo^.err^.error_exit (cinfo); +end; + +procedure ERREXIT4(cinfo : j_common_ptr; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.msg_parm.i[1] := p2; + cinfo^.err^.msg_parm.i[2] := p3; + cinfo^.err^.msg_parm.i[3] := p4; + cinfo^.err^.error_exit (cinfo); +end; + +procedure ERREXITS(cinfo : j_common_ptr;code : J_MESSAGE_CODE; + str : AnsiString); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.s := str; { string[JMSG_STR_PARM_MAX] } + cinfo^.err^.error_exit (cinfo); +end; + +{ Nonfatal errors (we can keep going, but the data is probably corrupt) } + +procedure WARNMS(cinfo : j_common_ptr; code : J_MESSAGE_CODE); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.emit_message(cinfo, -1); +end; + +procedure WARNMS1(cinfo : j_common_ptr;code : J_MESSAGE_CODE; p1 : int); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.emit_message (cinfo, -1); +end; + +procedure WARNMS2(cinfo : j_common_ptr; code : J_MESSAGE_CODE; + p1 : int; p2 : int); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.msg_parm.i[1] := p2; + cinfo^.err^.emit_message (cinfo, -1); +end; + +{ Informational/debugging messages } +procedure TRACEMS(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.emit_message(cinfo, lvl); +end; + +procedure TRACEMS1(cinfo : j_common_ptr; lvl : int; + code : J_MESSAGE_CODE; p1 : long); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.emit_message (cinfo, lvl); +end; + +procedure TRACEMS2(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; + p2 : int); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.i[0] := p1; + cinfo^.err^.msg_parm.i[1] := p2; + cinfo^.err^.emit_message (cinfo, lvl); +end; + +procedure TRACEMS3(cinfo : j_common_ptr; + lvl : int; + code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int); +var + _mp : int8array; +begin + _mp[0] := p1; _mp[1] := p2; _mp[2] := p3; + cinfo^.err^.msg_parm.i := _mp; + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.emit_message (cinfo, lvl); +end; + + +procedure TRACEMS4(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int); +var + _mp : int8array; +begin + _mp[0] := p1; _mp[1] := p2; _mp[2] := p3; _mp[3] := p4; + cinfo^.err^.msg_parm.i := _mp; + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.emit_message (cinfo, lvl); +end; + +procedure TRACEMS5(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int; p5 : int); +var + _mp : ^int8array; +begin + _mp := @cinfo^.err^.msg_parm.i; + _mp^[0] := p1; _mp^[1] := p2; _mp^[2] := p3; + _mp^[3] := p4; _mp^[5] := p5; + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.emit_message (cinfo, lvl); +end; + +procedure TRACEMS8(cinfo : j_common_ptr; lvl : int; code : J_MESSAGE_CODE; + p1 : int; p2 : int; p3 : int; p4 : int; + p5 : int; p6 : int; p7 : int; p8 : int); +var + _mp : int8array; +begin + _mp[0] := p1; _mp[1] := p2; _mp[2] := p3; _mp[3] := p4; + _mp[4] := p5; _mp[5] := p6; _mp[6] := p7; _mp[7] := p8; + cinfo^.err^.msg_parm.i := _mp; + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.emit_message (cinfo, lvl); +end; + +procedure TRACEMSS(cinfo : j_common_ptr; lvl : int; + code : J_MESSAGE_CODE; str : AnsiString); +begin + cinfo^.err^.msg_code := ord(code); + cinfo^.err^.msg_parm.s := str; { string JMSG_STR_PARM_MAX } + cinfo^.err^.emit_message (cinfo, lvl); +end; + +{METHODDEF} +procedure output_message (cinfo : j_common_ptr); +var + buffer : AnsiString; {[JMSG_LENGTH_MAX];} +begin + { Create the message } + cinfo^.err^.format_message (cinfo, buffer); + + { Send it to stderr, adding a newline } + WriteLn(output, buffer); +end; + + + +{ Decide whether to emit a trace or warning message. + msg_level is one of: + -1: recoverable corrupt-data warning, may want to abort. + 0: important advisory messages (always display to user). + 1: first level of tracing detail. + 2,3,...: successively more detailed tracing messages. + An application might override this method if it wanted to abort on warnings + or change the policy about which messages to display. } + + +{METHODDEF} +procedure emit_message (cinfo : j_common_ptr; msg_level : int); +var + err : jpeg_error_mgr_ptr; +begin + err := cinfo^.err; + if (msg_level < 0) then + begin + { It's a warning message. Since corrupt files may generate many warnings, + the policy implemented here is to show only the first warning, + unless trace_level >= 3. } + + if (err^.num_warnings = 0) or (err^.trace_level >= 3) then + err^.output_message(cinfo); + { Always count warnings in num_warnings. } + Inc( err^.num_warnings ); + end + else + begin + { It's a trace message. Show it if trace_level >= msg_level. } + if (err^.trace_level >= msg_level) then + err^.output_message (cinfo); + end; +end; + + +{ Format a message string for the most recent JPEG error or message. + The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + characters. Note that no '\n' character is added to the string. + Few applications should need to override this method. } + + +{METHODDEF} +procedure format_message (cinfo : j_common_ptr; var buffer : AnsiString); +var + err : jpeg_error_mgr_ptr; + msg_code : J_MESSAGE_CODE; + msgtext : AnsiString; + isstring : boolean; +begin + err := cinfo^.err; + msg_code := J_MESSAGE_CODE(err^.msg_code); + msgtext := ''; + + { Look up message string in proper table } + if (msg_code > JMSG_NOMESSAGE) + and (msg_code <= J_MESSAGE_CODE(err^.last_jpeg_message)) then + begin + msgtext := err^.jpeg_message_table^[msg_code]; + end + else + if (err^.addon_message_table <> NIL) and + (msg_code >= err^.first_addon_message) and + (msg_code <= err^.last_addon_message) then + begin + msgtext := err^.addon_message_table^[J_MESSAGE_CODE + (ord(msg_code) - ord(err^.first_addon_message))]; + end; + + { Defend against bogus message number } + if (msgtext = '') then + begin + err^.msg_parm.i[0] := int(msg_code); + msgtext := err^.jpeg_message_table^[JMSG_NOMESSAGE]; + end; + + { Check for string parameter, as indicated by %s in the message text } + isstring := Pos('%s', msgtext) > 0; + + { Format the message into the passed buffer } + if (isstring) then + buffer := Concat(msgtext, err^.msg_parm.s) + else + begin + {$IFDEF VER70} + FormatStr(buffer, msgtext, err^.msg_parm.i); + {$ELSE} + {$IFDEF NO_FORMAT} + buffer := msgtext; + {$ELSE} + buffer := Format(msgtext, [ + err^.msg_parm.i[0], err^.msg_parm.i[1], + err^.msg_parm.i[2], err^.msg_parm.i[3], + err^.msg_parm.i[4], err^.msg_parm.i[5], + err^.msg_parm.i[6], err^.msg_parm.i[7] ]); + {$ENDIF} + {$ENDIF} + end; +end; + + + +{ Reset error state variables at start of a new image. + This is called during compression startup to reset trace/error + processing to default state, without losing any application-specific + method pointers. An application might possibly want to override + this method if it has additional error processing state. } + + +{METHODDEF} +procedure reset_error_mgr (cinfo : j_common_ptr); +begin + cinfo^.err^.num_warnings := 0; + { trace_level is not reset since it is an application-supplied parameter } + cinfo^.err^.msg_code := 0; { may be useful as a flag for "no error" } +end; + + +{ Fill in the standard error-handling methods in a jpeg_error_mgr object. + Typical call is: + cinfo : jpeg_compress_struct; + err : jpeg_error_mgr; + + cinfo.err := jpeg_std_error(@err); + after which the application may override some of the methods. } + + +{GLOBAL} +function jpeg_std_error (var err : jpeg_error_mgr) : jpeg_error_mgr_ptr; +begin + err.error_exit := error_exit; + err.emit_message := emit_message; + err.output_message := output_message; + err.format_message := format_message; + err.reset_error_mgr := reset_error_mgr; + + err.trace_level := 0; { default := no tracing } + err.num_warnings := 0; { no warnings emitted yet } + err.msg_code := 0; { may be useful as a flag for "no error" } + + { Initialize message table pointers } + err.jpeg_message_table := @jpeg_std_message_table; + err.last_jpeg_message := pred(JMSG_LASTMSGCODE); + + err.addon_message_table := NIL; + err.first_addon_message := JMSG_NOMESSAGE; { for safety } + err.last_addon_message := JMSG_NOMESSAGE; + + jpeg_std_error := @err; +end; + + +end. diff --git a/src/lib/vampimg/JpegLib/imjfdctflt.pas b/src/lib/vampimg/JpegLib/imjfdctflt.pas new file mode 100644 index 0000000..1038284 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjfdctflt.pas @@ -0,0 +1,176 @@ +unit imjfdctflt; + +{$N+} +{ This file contains a floating-point implementation of the + forward DCT (Discrete Cosine Transform). + + This implementation should be more accurate than either of the integer + DCT implementations. However, it may not give the same results on all + machines because of differences in roundoff behavior. Speed will depend + on the hardware's floating point capacity. + + A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + on each column. Direct algorithms are also available, but they are + much more complex and seem not to be any faster when reduced to code. + + This implementation is based on Arai, Agui, and Nakajima's algorithm for + scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + Japanese, but the algorithm is described in the Pennebaker & Mitchell + JPEG textbook (see REFERENCES section in file README). The following code + is based directly on figure 4-8 in P&M. + While an 8-point DCT cannot be done in less than 11 multiplies, it is + possible to arrange the computation so that many of the multiplies are + simple scalings of the final outputs. These multiplies can then be + folded into the multiplications or divisions by the JPEG quantization + table entries. The AA&N method leaves only 5 multiplies and 29 adds + to be done in the DCT itself. + The primary disadvantage of this method is that with a fixed-point + implementation, accuracy is lost due to imprecise representation of the + scaled quantization values. However, that problem does not arise if + we use floating point arithmetic. } + +{ Original : jfdctflt.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + + +{ Perform the forward DCT on one block of samples.} + +{GLOBAL} +procedure jpeg_fdct_float (var data : array of FAST_FLOAT); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + + +{ Perform the forward DCT on one block of samples.} + +{GLOBAL} +procedure jpeg_fdct_float (var data : array of FAST_FLOAT); +type + PWorkspace = ^TWorkspace; + TWorkspace = array [0..DCTSIZE2-1] of FAST_FLOAT; +var + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 : FAST_FLOAT; + tmp10, tmp11, tmp12, tmp13 : FAST_FLOAT; + z1, z2, z3, z4, z5, z11, z13 : FAST_FLOAT; + dataptr : PWorkspace; + ctr : int; +begin + { Pass 1: process rows. } + + dataptr := PWorkspace(@data); + for ctr := DCTSIZE-1 downto 0 do + begin + tmp0 := dataptr^[0] + dataptr^[7]; + tmp7 := dataptr^[0] - dataptr^[7]; + tmp1 := dataptr^[1] + dataptr^[6]; + tmp6 := dataptr^[1] - dataptr^[6]; + tmp2 := dataptr^[2] + dataptr^[5]; + tmp5 := dataptr^[2] - dataptr^[5]; + tmp3 := dataptr^[3] + dataptr^[4]; + tmp4 := dataptr^[3] - dataptr^[4]; + + { Even part } + + tmp10 := tmp0 + tmp3; { phase 2 } + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + dataptr^[0] := tmp10 + tmp11; { phase 3 } + dataptr^[4] := tmp10 - tmp11; + + z1 := (tmp12 + tmp13) * ({FAST_FLOAT}(0.707106781)); { c4 } + dataptr^[2] := tmp13 + z1; { phase 5 } + dataptr^[6] := tmp13 - z1; + + { Odd part } + + tmp10 := tmp4 + tmp5; { phase 2 } + tmp11 := tmp5 + tmp6; + tmp12 := tmp6 + tmp7; + + { The rotator is modified from fig 4-8 to avoid extra negations. } + z5 := (tmp10 - tmp12) * ( {FAST_FLOAT}(0.382683433)); { c6 } + z2 := {FAST_FLOAT}(0.541196100) * tmp10 + z5; { c2-c6 } + z4 := {FAST_FLOAT}(1.306562965) * tmp12 + z5; { c2+c6 } + z3 := tmp11 * {FAST_FLOAT} (0.707106781); { c4 } + + z11 := tmp7 + z3; { phase 5 } + z13 := tmp7 - z3; + + dataptr^[5] := z13 + z2; { phase 6 } + dataptr^[3] := z13 - z2; + dataptr^[1] := z11 + z4; + dataptr^[7] := z11 - z4; + + Inc(FAST_FLOAT_PTR(dataptr), DCTSIZE); { advance pointer to next row } + end; + + { Pass 2: process columns. } + + dataptr := PWorkspace(@data); + for ctr := DCTSIZE-1 downto 0 do + begin + tmp0 := dataptr^[DCTSIZE*0] + dataptr^[DCTSIZE*7]; + tmp7 := dataptr^[DCTSIZE*0] - dataptr^[DCTSIZE*7]; + tmp1 := dataptr^[DCTSIZE*1] + dataptr^[DCTSIZE*6]; + tmp6 := dataptr^[DCTSIZE*1] - dataptr^[DCTSIZE*6]; + tmp2 := dataptr^[DCTSIZE*2] + dataptr^[DCTSIZE*5]; + tmp5 := dataptr^[DCTSIZE*2] - dataptr^[DCTSIZE*5]; + tmp3 := dataptr^[DCTSIZE*3] + dataptr^[DCTSIZE*4]; + tmp4 := dataptr^[DCTSIZE*3] - dataptr^[DCTSIZE*4]; + + { Even part } + + tmp10 := tmp0 + tmp3; { phase 2 } + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + dataptr^[DCTSIZE*0] := tmp10 + tmp11; { phase 3 } + dataptr^[DCTSIZE*4] := tmp10 - tmp11; + + z1 := (tmp12 + tmp13) * {FAST_FLOAT} (0.707106781); { c4 } + dataptr^[DCTSIZE*2] := tmp13 + z1; { phase 5 } + dataptr^[DCTSIZE*6] := tmp13 - z1; + + { Odd part } + + tmp10 := tmp4 + tmp5; { phase 2 } + tmp11 := tmp5 + tmp6; + tmp12 := tmp6 + tmp7; + + { The rotator is modified from fig 4-8 to avoid extra negations. } + z5 := (tmp10 - tmp12) * {FAST_FLOAT} (0.382683433); { c6 } + z2 := {FAST_FLOAT} (0.541196100) * tmp10 + z5; { c2-c6 } + z4 := {FAST_FLOAT} (1.306562965) * tmp12 + z5; { c2+c6 } + z3 := tmp11 * {FAST_FLOAT} (0.707106781); { c4 } + + z11 := tmp7 + z3; { phase 5 } + z13 := tmp7 - z3; + + dataptr^[DCTSIZE*5] := z13 + z2; { phase 6 } + dataptr^[DCTSIZE*3] := z13 - z2; + dataptr^[DCTSIZE*1] := z11 + z4; + dataptr^[DCTSIZE*7] := z11 - z4; + + Inc(FAST_FLOAT_PTR(dataptr)); { advance pointer to next column } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjfdctfst.pas b/src/lib/vampimg/JpegLib/imjfdctfst.pas new file mode 100644 index 0000000..40b2fd1 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjfdctfst.pas @@ -0,0 +1,237 @@ +unit imjfdctfst; + +{ This file contains a fast, not so accurate integer implementation of the + forward DCT (Discrete Cosine Transform). + + A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + on each column. Direct algorithms are also available, but they are + much more complex and seem not to be any faster when reduced to code. + + This implementation is based on Arai, Agui, and Nakajima's algorithm for + scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + Japanese, but the algorithm is described in the Pennebaker & Mitchell + JPEG textbook (see REFERENCES section in file README). The following code + is based directly on figure 4-8 in P&M. + While an 8-point DCT cannot be done in less than 11 multiplies, it is + possible to arrange the computation so that many of the multiplies are + simple scalings of the final outputs. These multiplies can then be + folded into the multiplications or divisions by the JPEG quantization + table entries. The AA&N method leaves only 5 multiplies and 29 adds + to be done in the DCT itself. + The primary disadvantage of this method is that with fixed-point math, + accuracy is lost due to imprecise representation of the scaled + quantization values. The smaller the quantization table entry, the less + precise the scaled value, so this implementation does worse with high- + quality-setting files than with low-quality ones. } + +{ Original: jfdctfst.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + + +{ Perform the forward DCT on one block of samples. } + +{GLOBAL} +procedure jpeg_fdct_ifast (var data : array of DCTELEM); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + + +{ Scaling decisions are generally the same as in the LL&M algorithm; + see jfdctint.c for more details. However, we choose to descale + (right shift) multiplication products as soon as they are formed, + rather than carrying additional fractional bits into subsequent additions. + This compromises accuracy slightly, but it lets us save a few shifts. + More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + everywhere except in the multiplications proper; this saves a good deal + of work on 16-bit-int machines. + + Again to save a few shifts, the intermediate results between pass 1 and + pass 2 are not upscaled, but are represented only to integral precision. + + A final compromise is to represent the multiplicative constants to only + 8 fractional bits, rather than 13. This saves some shifting work on some + machines, and may also reduce the cost of multiplication (since there + are fewer one-bits in the constants). } + +const + CONST_BITS = 8; +const + CONST_SCALE = (INT32(1) shl CONST_BITS); + + +const + FIX_0_382683433 = INT32(Round(CONST_SCALE * 0.382683433)); {98} + FIX_0_541196100 = INT32(Round(CONST_SCALE * 0.541196100)); {139} + FIX_0_707106781 = INT32(Round(CONST_SCALE * 0.707106781)); {181} + FIX_1_306562965 = INT32(Round(CONST_SCALE * 1.306562965)); {334} + +{ Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + +function DESCALE(x : INT32; n : int) : INT32; +var + shift_temp : INT32; +begin +{ We can gain a little more speed, with a further compromise in accuracy, + by omitting the addition in a descaling shift. This yields an incorrectly + rounded result half the time... } +{$ifndef USE_ACCURATE_ROUNDING} + shift_temp := x; +{$else} + shift_temp := x + (INT32(1) shl (n-1)); +{$endif} + +{$ifdef RIGHT_SHIFT_IS_UNSIGNED} + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else +{$endif} + Descale := (shift_temp shr n); +end; + +{ Multiply a DCTELEM variable by an INT32 constant, and immediately + descale to yield a DCTELEM result. } + + + function MULTIPLY(X : DCTELEM; Y: INT32): DCTELEM; + begin + Multiply := DeScale((X) * (Y), CONST_BITS); + end; + + +{ Perform the forward DCT on one block of samples. } + +{GLOBAL} +procedure jpeg_fdct_ifast (var data : array of DCTELEM); +type + PWorkspace = ^TWorkspace; + TWorkspace = array [0..DCTSIZE2-1] of DCTELEM; +var + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 : DCTELEM; + tmp10, tmp11, tmp12, tmp13 : DCTELEM; + z1, z2, z3, z4, z5, z11, z13 : DCTELEM; + dataptr : PWorkspace; + ctr : int; + {SHIFT_TEMPS} +begin + { Pass 1: process rows. } + + dataptr := PWorkspace(@data); + for ctr := DCTSIZE-1 downto 0 do + begin + tmp0 := dataptr^[0] + dataptr^[7]; + tmp7 := dataptr^[0] - dataptr^[7]; + tmp1 := dataptr^[1] + dataptr^[6]; + tmp6 := dataptr^[1] - dataptr^[6]; + tmp2 := dataptr^[2] + dataptr^[5]; + tmp5 := dataptr^[2] - dataptr^[5]; + tmp3 := dataptr^[3] + dataptr^[4]; + tmp4 := dataptr^[3] - dataptr^[4]; + + { Even part } + + tmp10 := tmp0 + tmp3; { phase 2 } + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + dataptr^[0] := tmp10 + tmp11; { phase 3 } + dataptr^[4] := tmp10 - tmp11; + + z1 := MULTIPLY(tmp12 + tmp13, FIX_0_707106781); { c4 } + dataptr^[2] := tmp13 + z1; { phase 5 } + dataptr^[6] := tmp13 - z1; + + { Odd part } + + tmp10 := tmp4 + tmp5; { phase 2 } + tmp11 := tmp5 + tmp6; + tmp12 := tmp6 + tmp7; + + { The rotator is modified from fig 4-8 to avoid extra negations. } + z5 := MULTIPLY(tmp10 - tmp12, FIX_0_382683433); { c6 } + z2 := MULTIPLY(tmp10, FIX_0_541196100) + z5; { c2-c6 } + z4 := MULTIPLY(tmp12, FIX_1_306562965) + z5; { c2+c6 } + z3 := MULTIPLY(tmp11, FIX_0_707106781); { c4 } + + z11 := tmp7 + z3; { phase 5 } + z13 := tmp7 - z3; + + dataptr^[5] := z13 + z2; { phase 6 } + dataptr^[3] := z13 - z2; + dataptr^[1] := z11 + z4; + dataptr^[7] := z11 - z4; + + Inc(DCTELEMPTR(dataptr), DCTSIZE); { advance pointer to next row } + end; + + { Pass 2: process columns. } + + dataptr := PWorkspace(@data); + for ctr := DCTSIZE-1 downto 0 do + begin + tmp0 := dataptr^[DCTSIZE*0] + dataptr^[DCTSIZE*7]; + tmp7 := dataptr^[DCTSIZE*0] - dataptr^[DCTSIZE*7]; + tmp1 := dataptr^[DCTSIZE*1] + dataptr^[DCTSIZE*6]; + tmp6 := dataptr^[DCTSIZE*1] - dataptr^[DCTSIZE*6]; + tmp2 := dataptr^[DCTSIZE*2] + dataptr^[DCTSIZE*5]; + tmp5 := dataptr^[DCTSIZE*2] - dataptr^[DCTSIZE*5]; + tmp3 := dataptr^[DCTSIZE*3] + dataptr^[DCTSIZE*4]; + tmp4 := dataptr^[DCTSIZE*3] - dataptr^[DCTSIZE*4]; + + { Even part } + + tmp10 := tmp0 + tmp3; { phase 2 } + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + dataptr^[DCTSIZE*0] := tmp10 + tmp11; { phase 3 } + dataptr^[DCTSIZE*4] := tmp10 - tmp11; + + z1 := MULTIPLY(tmp12 + tmp13, FIX_0_707106781); { c4 } + dataptr^[DCTSIZE*2] := tmp13 + z1; { phase 5 } + dataptr^[DCTSIZE*6] := tmp13 - z1; + + { Odd part } + + tmp10 := tmp4 + tmp5; { phase 2 } + tmp11 := tmp5 + tmp6; + tmp12 := tmp6 + tmp7; + + { The rotator is modified from fig 4-8 to avoid extra negations. } + z5 := MULTIPLY(tmp10 - tmp12, FIX_0_382683433); { c6 } + z2 := MULTIPLY(tmp10, FIX_0_541196100) + z5; { c2-c6 } + z4 := MULTIPLY(tmp12, FIX_1_306562965) + z5; { c2+c6 } + z3 := MULTIPLY(tmp11, FIX_0_707106781); { c4 } + + z11 := tmp7 + z3; { phase 5 } + z13 := tmp7 - z3; + + dataptr^[DCTSIZE*5] := z13 + z2; { phase 6 } + dataptr^[DCTSIZE*3] := z13 - z2; + dataptr^[DCTSIZE*1] := z11 + z4; + dataptr^[DCTSIZE*7] := z11 - z4; + + Inc(DCTELEMPTR(dataptr)); { advance pointer to next column } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjfdctint.pas b/src/lib/vampimg/JpegLib/imjfdctint.pas new file mode 100644 index 0000000..b676fff --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjfdctint.pas @@ -0,0 +1,297 @@ +unit imjfdctint; + + +{ This file contains a slow-but-accurate integer implementation of the + forward DCT (Discrete Cosine Transform). + + A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT + on each column. Direct algorithms are also available, but they are + much more complex and seem not to be any faster when reduced to code. + + This implementation is based on an algorithm described in + C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + The primary algorithm described there uses 11 multiplies and 29 adds. + We use their alternate method with 12 multiplies and 32 adds. + The advantage of this method is that no data path contains more than one + multiplication; this allows a very simple and accurate implementation in + scaled fixed-point arithmetic, with a minimal number of shifts. } + +{ Original : jfdctint.c ; Copyright (C) 1991-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjutils, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + + +{ Perform the forward DCT on one block of samples. } + +{GLOBAL} +procedure jpeg_fdct_islow (var data : array of DCTELEM); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + + +{ The poop on this scaling stuff is as follows: + + Each 1-D DCT step produces outputs which are a factor of sqrt(N) + larger than the true DCT outputs. The final outputs are therefore + a factor of N larger than desired; since N=8 this can be cured by + a simple right shift at the end of the algorithm. The advantage of + this arrangement is that we save two multiplications per 1-D DCT, + because the y0 and y4 outputs need not be divided by sqrt(N). + In the IJG code, this factor of 8 is removed by the quantization step + (in jcdctmgr.c), NOT in this module. + + We have to do addition and subtraction of the integer inputs, which + is no problem, and multiplication by fractional constants, which is + a problem to do in integer arithmetic. We multiply all the constants + by CONST_SCALE and convert them to integer constants (thus retaining + CONST_BITS bits of precision in the constants). After doing a + multiplication we have to divide the product by CONST_SCALE, with proper + rounding, to produce the correct output. This division can be done + cheaply as a right shift of CONST_BITS bits. We postpone shifting + as long as possible so that partial sums can be added together with + full fractional precision. + + The outputs of the first pass are scaled up by PASS1_BITS bits so that + they are represented to better-than-integral precision. These outputs + require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + with the recommended scaling. (For 12-bit sample data, the intermediate + array is INT32 anyway.) + + To avoid overflow of the 32-bit intermediate results in pass 2, we must + have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + shows that the values given below are the most effective. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + CONST_BITS = 13; + PASS1_BITS = 2; +{$else} +const + CONST_BITS = 13; + PASS1_BITS = 1; { lose a little precision to avoid overflow } +{$endif} + +const + CONST_SCALE = (INT32(1) shl CONST_BITS); + +const + FIX_0_298631336 = INT32(Round(CONST_SCALE * 0.298631336)); {2446} + FIX_0_390180644 = INT32(Round(CONST_SCALE * 0.390180644)); {3196} + FIX_0_541196100 = INT32(Round(CONST_SCALE * 0.541196100)); {4433} + FIX_0_765366865 = INT32(Round(CONST_SCALE * 0.765366865)); {6270} + FIX_0_899976223 = INT32(Round(CONST_SCALE * 0.899976223)); {7373} + FIX_1_175875602 = INT32(Round(CONST_SCALE * 1.175875602)); {9633} + FIX_1_501321110 = INT32(Round(CONST_SCALE * 1.501321110)); {12299} + FIX_1_847759065 = INT32(Round(CONST_SCALE * 1.847759065)); {15137} + FIX_1_961570560 = INT32(Round(CONST_SCALE * 1.961570560)); {16069} + FIX_2_053119869 = INT32(Round(CONST_SCALE * 2.053119869)); {16819} + FIX_2_562915447 = INT32(Round(CONST_SCALE * 2.562915447)); {20995} + FIX_3_072711026 = INT32(Round(CONST_SCALE * 3.072711026)); {25172} + + +{ Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + For 8-bit samples with the recommended scaling, all the variable + and constant values involved are no more than 16 bits wide, so a + 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + For 12-bit samples, a full 32-bit multiplication will be needed. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} + + {MULTIPLY16C16(var,const)} + function Multiply(X, Y: int): INT32; + begin + Multiply := int(X) * INT32(Y); + end; + +{$else} + function Multiply(X, Y: INT32): INT32; + begin + Multiply := X * Y; + end; +{$endif} + +{ Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + +function DESCALE(x : INT32; n : int) : INT32; +var + shift_temp : INT32; +begin +{$ifdef RIGHT_SHIFT_IS_UNSIGNED} + shift_temp := x + (INT32(1) shl (n-1)); + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else + Descale := (shift_temp shr n); +{$else} + Descale := (x + (INT32(1) shl (n-1)) shr n; +{$endif} +end; + + +{ Perform the forward DCT on one block of samples. } + +{GLOBAL} +procedure jpeg_fdct_islow (var data : array of DCTELEM); +type + PWorkspace = ^TWorkspace; + TWorkspace = array [0..DCTSIZE2-1] of DCTELEM; +var + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 : INT32; + tmp10, tmp11, tmp12, tmp13 : INT32; + z1, z2, z3, z4, z5 : INT32; + dataptr : PWorkspace; + ctr : int; + {SHIFT_TEMPS} +begin + + { Pass 1: process rows. } + { Note results are scaled up by sqrt(8) compared to a true DCT; } + { furthermore, we scale the results by 2**PASS1_BITS. } + + dataptr := PWorkspace(@data); + for ctr := DCTSIZE-1 downto 0 do + begin + tmp0 := dataptr^[0] + dataptr^[7]; + tmp7 := dataptr^[0] - dataptr^[7]; + tmp1 := dataptr^[1] + dataptr^[6]; + tmp6 := dataptr^[1] - dataptr^[6]; + tmp2 := dataptr^[2] + dataptr^[5]; + tmp5 := dataptr^[2] - dataptr^[5]; + tmp3 := dataptr^[3] + dataptr^[4]; + tmp4 := dataptr^[3] - dataptr^[4]; + + { Even part per LL&M figure 1 --- note that published figure is faulty; + rotator "sqrt(2)*c1" should be "sqrt(2)*c6". } + + tmp10 := tmp0 + tmp3; + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + dataptr^[0] := DCTELEM ((tmp10 + tmp11) shl PASS1_BITS); + dataptr^[4] := DCTELEM ((tmp10 - tmp11) shl PASS1_BITS); + + z1 := MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr^[2] := DCTELEM (DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS-PASS1_BITS)); + dataptr^[6] := DCTELEM (DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS-PASS1_BITS)); + + { Odd part per figure 8 --- note paper omits factor of sqrt(2). + cK represents cos(K*pi/16). + i0..i3 in the paper are tmp4..tmp7 here. } + + z1 := tmp4 + tmp7; + z2 := tmp5 + tmp6; + z3 := tmp4 + tmp6; + z4 := tmp5 + tmp7; + z5 := MULTIPLY(z3 + z4, FIX_1_175875602); { sqrt(2) * c3 } + + tmp4 := MULTIPLY(tmp4, FIX_0_298631336); { sqrt(2) * (-c1+c3+c5-c7) } + tmp5 := MULTIPLY(tmp5, FIX_2_053119869); { sqrt(2) * ( c1+c3-c5+c7) } + tmp6 := MULTIPLY(tmp6, FIX_3_072711026); { sqrt(2) * ( c1+c3+c5-c7) } + tmp7 := MULTIPLY(tmp7, FIX_1_501321110); { sqrt(2) * ( c1+c3-c5-c7) } + z1 := MULTIPLY(z1, - FIX_0_899976223); { sqrt(2) * (c7-c3) } + z2 := MULTIPLY(z2, - FIX_2_562915447); { sqrt(2) * (-c1-c3) } + z3 := MULTIPLY(z3, - FIX_1_961570560); { sqrt(2) * (-c3-c5) } + z4 := MULTIPLY(z4, - FIX_0_390180644); { sqrt(2) * (c5-c3) } + + Inc(z3, z5); + Inc(z4, z5); + + dataptr^[7] := DCTELEM(DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS)); + dataptr^[5] := DCTELEM(DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS)); + dataptr^[3] := DCTELEM(DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS)); + dataptr^[1] := DCTELEM(DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS)); + + Inc(DCTELEMPTR(dataptr), DCTSIZE); { advance pointer to next row } + end; + + { Pass 2: process columns. + We remove the PASS1_BITS scaling, but leave the results scaled up + by an overall factor of 8. } + + dataptr := PWorkspace(@data); + for ctr := DCTSIZE-1 downto 0 do + begin + tmp0 := dataptr^[DCTSIZE*0] + dataptr^[DCTSIZE*7]; + tmp7 := dataptr^[DCTSIZE*0] - dataptr^[DCTSIZE*7]; + tmp1 := dataptr^[DCTSIZE*1] + dataptr^[DCTSIZE*6]; + tmp6 := dataptr^[DCTSIZE*1] - dataptr^[DCTSIZE*6]; + tmp2 := dataptr^[DCTSIZE*2] + dataptr^[DCTSIZE*5]; + tmp5 := dataptr^[DCTSIZE*2] - dataptr^[DCTSIZE*5]; + tmp3 := dataptr^[DCTSIZE*3] + dataptr^[DCTSIZE*4]; + tmp4 := dataptr^[DCTSIZE*3] - dataptr^[DCTSIZE*4]; + + { Even part per LL&M figure 1 --- note that published figure is faulty; + rotator "sqrt(2)*c1" should be "sqrt(2)*c6". } + + tmp10 := tmp0 + tmp3; + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + dataptr^[DCTSIZE*0] := DCTELEM (DESCALE(tmp10 + tmp11, PASS1_BITS)); + dataptr^[DCTSIZE*4] := DCTELEM (DESCALE(tmp10 - tmp11, PASS1_BITS)); + + z1 := MULTIPLY(tmp12 + tmp13, FIX_0_541196100); + dataptr^[DCTSIZE*2] := DCTELEM (DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), + CONST_BITS+PASS1_BITS)); + dataptr^[DCTSIZE*6] := DCTELEM (DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), + CONST_BITS+PASS1_BITS)); + + { Odd part per figure 8 --- note paper omits factor of sqrt(2). + cK represents cos(K*pi/16). + i0..i3 in the paper are tmp4..tmp7 here. } + + z1 := tmp4 + tmp7; + z2 := tmp5 + tmp6; + z3 := tmp4 + tmp6; + z4 := tmp5 + tmp7; + z5 := MULTIPLY(z3 + z4, FIX_1_175875602); { sqrt(2) * c3 } + + tmp4 := MULTIPLY(tmp4, FIX_0_298631336); { sqrt(2) * (-c1+c3+c5-c7) } + tmp5 := MULTIPLY(tmp5, FIX_2_053119869); { sqrt(2) * ( c1+c3-c5+c7) } + tmp6 := MULTIPLY(tmp6, FIX_3_072711026); { sqrt(2) * ( c1+c3+c5-c7) } + tmp7 := MULTIPLY(tmp7, FIX_1_501321110); { sqrt(2) * ( c1+c3-c5-c7) } + z1 := MULTIPLY(z1, - FIX_0_899976223); { sqrt(2) * (c7-c3) } + z2 := MULTIPLY(z2, - FIX_2_562915447); { sqrt(2) * (-c1-c3) } + z3 := MULTIPLY(z3, - FIX_1_961570560); { sqrt(2) * (-c3-c5) } + z4 := MULTIPLY(z4, - FIX_0_390180644); { sqrt(2) * (c5-c3) } + + Inc(z3, z5); + Inc(z4, z5); + + dataptr^[DCTSIZE*7] := DCTELEM (DESCALE(tmp4 + z1 + z3, + CONST_BITS+PASS1_BITS)); + dataptr^[DCTSIZE*5] := DCTELEM (DESCALE(tmp5 + z2 + z4, + CONST_BITS+PASS1_BITS)); + dataptr^[DCTSIZE*3] := DCTELEM (DESCALE(tmp6 + z2 + z3, + CONST_BITS+PASS1_BITS)); + dataptr^[DCTSIZE*1] := DCTELEM (DESCALE(tmp7 + z1 + z4, + CONST_BITS+PASS1_BITS)); + + Inc(DCTELEMPTR(dataptr)); { advance pointer to next column } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjidctasm.pas b/src/lib/vampimg/JpegLib/imjidctasm.pas new file mode 100644 index 0000000..a699739 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjidctasm.pas @@ -0,0 +1,793 @@ +unit imjidctasm; + +{ This file contains a slow-but-accurate integer implementation of the + inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + must also perform dequantization of the input coefficients. + + A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + on each row (or vice versa, but it's more convenient to emit a row at + a time). Direct algorithms are also available, but they are much more + complex and seem not to be any faster when reduced to code. + + This implementation is based on an algorithm described in + C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + The primary algorithm described there uses 11 multiplies and 29 adds. + We use their alternate method with 12 multiplies and 32 adds. + The advantage of this method is that no data path contains more than one + multiplication; this allows a very simple and accurate implementation in + scaled fixed-point arithmetic, with a minimal number of shifts. } + +{ Original : jidctint.c ; Copyright (C) 1991-1996, Thomas G. Lane. } +{ ;------------------------------------------------------------------------- + ; JIDCTINT.ASM + ; 80386 protected mode assembly translation of JIDCTINT.C + ; **** Optimized to all hell by Jason M. Felice (jasonf@apk.net) **** + ; **** E-mail welcome **** + ; + ; ** This code does not make O/S calls -- use it for OS/2, Win95, WinNT, + ; ** DOS prot. mode., Linux, whatever... have fun. + ; + ; ** Note, this code is dependant on the structure member order in the .h + ; ** files for the following structures: + ; -- amazingly NOT j_decompress_struct... cool. + ; -- jpeg_component_info (dependant on position of dct_table element) + ; + ; Originally created with the /Fa option of MSVC 4.0 (why work when you + ; don't have to?) + ; + ; (this code, when compiled is 1K bytes smaller than the optimized MSVC + ; release build, not to mention 120-130 ms faster in my profile test with 1 + ; small color and and 1 medium black-and-white jpeg: stats using TASM 4.0 + ; and MSVC 4.0 to create a non-console app; jpeg_idct_islow accumulated + ; 5,760 hits on all trials) + ; + ; TASM -t -ml -os jidctint.asm, jidctint.obj + ;------------------------------------------------------------------------- + Converted to Delphi 2.0 BASM for PasJPEG + by Jacques NOMSSI NZALI + October 13th 1996 + * assumes Delphi "register" calling convention + first 3 parameter are in EAX,EDX,ECX + * register allocation revised +} + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_islow (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + +{ The poop on this scaling stuff is as follows: + + Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + larger than the true IDCT outputs. The final outputs are therefore + a factor of N larger than desired; since N=8 this can be cured by + a simple right shift at the end of the algorithm. The advantage of + this arrangement is that we save two multiplications per 1-D IDCT, + because the y0 and y4 inputs need not be divided by sqrt(N). + + We have to do addition and subtraction of the integer inputs, which + is no problem, and multiplication by fractional constants, which is + a problem to do in integer arithmetic. We multiply all the constants + by CONST_SCALE and convert them to integer constants (thus retaining + CONST_BITS bits of precision in the constants). After doing a + multiplication we have to divide the product by CONST_SCALE, with proper + rounding, to produce the correct output. This division can be done + cheaply as a right shift of CONST_BITS bits. We postpone shifting + as long as possible so that partial sums can be added together with + full fractional precision. + + The outputs of the first pass are scaled up by PASS1_BITS bits so that + they are represented to better-than-integral precision. These outputs + require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + with the recommended scaling. (To scale up 12-bit sample data further, an + intermediate INT32 array would be needed.) + + To avoid overflow of the 32-bit intermediate results in pass 2, we must + have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + shows that the values given below are the most effective. } + +const + CONST_BITS = 13; + +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + PASS1_BITS = 2; +{$else} +const + PASS1_BITS = 1; { lose a little precision to avoid overflow } +{$endif} + +const + CONST_SCALE = (INT32(1) shl CONST_BITS); + +const + FIX_0_298631336 = INT32(Round(CONST_SCALE * 0.298631336)); {2446} + FIX_0_390180644 = INT32(Round(CONST_SCALE * 0.390180644)); {3196} + FIX_0_541196100 = INT32(Round(CONST_SCALE * 0.541196100)); {4433} + FIX_0_765366865 = INT32(Round(CONST_SCALE * 0.765366865)); {6270} + FIX_0_899976223 = INT32(Round(CONST_SCALE * 0.899976223)); {7373} + FIX_1_175875602 = INT32(Round(CONST_SCALE * 1.175875602)); {9633} + FIX_1_501321110 = INT32(Round(CONST_SCALE * 1.501321110)); {12299} + FIX_1_847759065 = INT32(Round(CONST_SCALE * 1.847759065)); {15137} + FIX_1_961570560 = INT32(Round(CONST_SCALE * 1.961570560)); {16069} + FIX_2_053119869 = INT32(Round(CONST_SCALE * 2.053119869)); {16819} + FIX_2_562915447 = INT32(Round(CONST_SCALE * 2.562915447)); {20995} + FIX_3_072711026 = INT32(Round(CONST_SCALE * 3.072711026)); {25172} + + +{ for DESCALE } +const + ROUND_CONST = (INT32(1) shl (CONST_BITS-PASS1_BITS-1)); +const + ROUND_CONST_2 = (INT32(1) shl (CONST_BITS+PASS1_BITS+3-1)); + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_islow (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); +type + PWorkspace = ^TWorkspace; + TWorkspace = coef_bits_field; { buffers data between passes } +const + coefDCTSIZE = DCTSIZE*SizeOf(JCOEF); + wrkDCTSIZE = DCTSIZE*SizeOf(int); +var + tmp0, tmp1, tmp2, tmp3 : INT32; + tmp10, tmp11, tmp12, tmp13 : INT32; + z1, z2, z3, z4, z5 : INT32; +var + inptr : JCOEFPTR; + quantptr : ISLOW_MULT_TYPE_FIELD_PTR; + wsptr : PWorkspace; + outptr : JSAMPROW; +var + range_limit : JSAMPROW; + ctr : int; + workspace : TWorkspace; +var + dcval : int; +var + dcval_ : JSAMPLE; +asm + push edi + push esi + push ebx + + cld { The only direction we use, might as well set it now, as opposed } + { to inside 2 loops. } + +{ Each IDCT routine is responsible for range-limiting its results and + converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + be quite far out of range if the input data is corrupt, so a bulletproof + range-limiting step is required. We use a mask-and-table-lookup method + to do the combined operations quickly. See the comments with + prepare_range_limit_table (in jdmaster.c) for more info. } + + {range_limit := JSAMPROW(@(cinfo^.sample_range_limit^[CENTERJSAMPLE]));} + mov eax, [eax].jpeg_decompress_struct.sample_range_limit {eax=cinfo} + add eax, (MAXJSAMPLE+1 + CENTERJSAMPLE)*(Type JSAMPLE) + mov range_limit, eax + + { Pass 1: process columns from input, store into work array. } + { Note results are scaled up by sqrt(8) compared to a true IDCT; } + { furthermore, we scale the results by 2**PASS1_BITS. } + + {inptr := coef_block;} + mov esi, ecx { ecx=coef_block } + {quantptr := ISLOW_MULT_TYPE_FIELD_PTR (compptr^.dct_table);} + mov edi, [edx].jpeg_component_info.dct_table { edx=compptr } + + {wsptr := PWorkspace(@workspace);} + lea ecx, workspace + + {for ctr := pred(DCTSIZE) downto 0 do + begin} + mov ctr, DCTSIZE +@loop518: + { Due to quantization, we will usually find that many of the input + coefficients are zero, especially the AC terms. We can exploit this + by short-circuiting the IDCT calculation for any column in which all + the AC terms are zero. In that case each output is equal to the + DC coefficient (with scale factor as needed). + With typical images and quantization tables, half or more of the + column DCT calculations can be simplified this way. } + + {if ((inptr^[DCTSIZE*1]) or (inptr^[DCTSIZE*2]) or (inptr^[DCTSIZE*3]) or + (inptr^[DCTSIZE*4]) or (inptr^[DCTSIZE*5]) or (inptr^[DCTSIZE*6]) or + (inptr^[DCTSIZE*7]) = 0) then + begin} + mov eax, DWORD PTR [esi+coefDCTSIZE*1] + or eax, DWORD PTR [esi+coefDCTSIZE*2] + or eax, DWORD PTR [esi+coefDCTSIZE*3] + mov edx, DWORD PTR [esi+coefDCTSIZE*4] + or eax, edx + or eax, DWORD PTR [esi+coefDCTSIZE*5] + or eax, DWORD PTR [esi+coefDCTSIZE*6] + or eax, DWORD PTR [esi+coefDCTSIZE*7] + jne @loop520 + + { AC terms all zero } + {dcval := ISLOW_MULT_TYPE(inptr^[DCTSIZE*0]) * + (quantptr^[DCTSIZE*0]) shl PASS1_BITS;} + mov eax, DWORD PTR [esi+coefDCTSIZE*0] + imul eax, DWORD PTR [edi+wrkDCTSIZE*0] + shl eax, PASS1_BITS + + {wsptr^[DCTSIZE*0] := dcval; + wsptr^[DCTSIZE*1] := dcval; + wsptr^[DCTSIZE*2] := dcval; + wsptr^[DCTSIZE*3] := dcval; + wsptr^[DCTSIZE*4] := dcval; + wsptr^[DCTSIZE*5] := dcval; + wsptr^[DCTSIZE*6] := dcval; + wsptr^[DCTSIZE*7] := dcval;} + + mov DWORD PTR [ecx+ wrkDCTSIZE*0], eax + mov DWORD PTR [ecx+ wrkDCTSIZE*1], eax + mov DWORD PTR [ecx+ wrkDCTSIZE*2], eax + mov DWORD PTR [ecx+ wrkDCTSIZE*3], eax + mov DWORD PTR [ecx+ wrkDCTSIZE*4], eax + mov DWORD PTR [ecx+ wrkDCTSIZE*5], eax + mov DWORD PTR [ecx+ wrkDCTSIZE*6], eax + mov DWORD PTR [ecx+ wrkDCTSIZE*7], eax + + {Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + {Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + continue;} + dec ctr + je @loop519 + + add esi, Type JCOEF + add edi, Type ISLOW_MULT_TYPE + add ecx, Type int { int_ptr } + jmp @loop518 + +@loop520: + + {end;} + + { Even part: reverse the even part of the forward DCT. } + { The rotator is sqrt(2)*c(-6). } + + {z2 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*2]) * quantptr^[DCTSIZE*2]; + z3 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*6]) * quantptr^[DCTSIZE*6]; + + z1 := (z2 + z3) * INT32(FIX_0_541196100); + tmp2 := z1 + INT32(z3) * INT32(- FIX_1_847759065); + tmp3 := z1 + INT32(z2) * INT32(FIX_0_765366865);} + + mov edx, DWORD PTR [esi+coefDCTSIZE*2] + imul edx, DWORD PTR [edi+wrkDCTSIZE*2] {z2} + + mov eax, DWORD PTR [esi+coefDCTSIZE*6] + imul eax, DWORD PTR [edi+wrkDCTSIZE*6] {z3} + + lea ebx, [eax+edx] + imul ebx, FIX_0_541196100 {z1} + + imul eax, (-FIX_1_847759065) + add eax, ebx + mov tmp2, eax + + imul edx, FIX_0_765366865 + add edx, ebx + mov tmp3, edx + + {z2 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*0]) * quantptr^[DCTSIZE*0]; + z3 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*4]) * quantptr^[DCTSIZE*4];} + + mov edx, DWORD PTR [esi+coefDCTSIZE*4] + imul edx, DWORD PTR [edi+wrkDCTSIZE*4] { z3 = edx } + + mov eax, DWORD PTR [esi+coefDCTSIZE*0] + imul eax, DWORD PTR [edi+wrkDCTSIZE*0] { z2 = eax } + + {tmp0 := (z2 + z3) shl CONST_BITS; + tmp1 := (z2 - z3) shl CONST_BITS;} + lea ebx,[eax+edx] + sub eax, edx + shl ebx, CONST_BITS { tmp0 = ebx } + shl eax, CONST_BITS { tmp1 = eax } + + {tmp10 := tmp0 + tmp3; + tmp13 := tmp0 - tmp3;} + mov edx, tmp3 + sub ebx, edx + mov tmp13, ebx + add edx, edx + add ebx, edx + mov tmp10, ebx + + {tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2;} + mov ebx, tmp2 + sub eax, ebx + mov tmp12, eax + add ebx, ebx + add eax, ebx + mov tmp11, eax + + { Odd part per figure 8; the matrix is unitary and hence its + transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. } + + {tmp0 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*7]) * quantptr^[DCTSIZE*7];} + mov eax, DWORD PTR [esi+coefDCTSIZE*7] + imul eax, DWORD PTR [edi+wrkDCTSIZE*7] + mov edx, eax { edx = tmp0 } + {tmp0 := (tmp0) * INT32(FIX_0_298631336); { sqrt(2) * (-c1+c3+c5-c7) } + imul eax, FIX_0_298631336 + mov tmp0, eax + + {tmp3 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*1]) * quantptr^[DCTSIZE*1];} + mov eax, DWORD PTR [esi+coefDCTSIZE*1] + imul eax, DWORD PTR [edi+wrkDCTSIZE*1] + mov tmp3, eax + + {z1 := tmp0 + tmp3;} + {z1 := (z1) * INT32(- FIX_0_899976223); { sqrt(2) * (c7-c3) } + add eax, edx + imul eax, (-FIX_0_899976223) + mov z1, eax + + {tmp1 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*5]) * quantptr^[DCTSIZE*5];} + mov eax, DWORD PTR [esi+coefDCTSIZE*5] + imul eax, DWORD PTR [edi+wrkDCTSIZE*5] + mov ebx, eax { ebx = tmp1 } + {tmp1 := (tmp1) * INT32(FIX_2_053119869); { sqrt(2) * ( c1+c3-c5+c7) } + imul eax, FIX_2_053119869 + mov tmp1, eax + + {tmp2 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*3]) * quantptr^[DCTSIZE*3];} + mov eax, DWORD PTR [esi+coefDCTSIZE*3] + imul eax, DWORD PTR [edi+wrkDCTSIZE*3] + mov tmp2, eax + + {z3 := tmp0 + tmp2;} + add edx, eax { edx = z3 } + + {z2 := tmp1 + tmp2;} + {z2 := (z2) * INT32(- FIX_2_562915447); { sqrt(2) * (-c1-c3) } + add eax, ebx + imul eax, (-FIX_2_562915447) + mov z2, eax + + {z4 := tmp1 + tmp3;} + add ebx, tmp3 { ebx = z4 } + + {z5 := INT32(z3 + z4) * INT32(FIX_1_175875602); { sqrt(2) * c3 } + lea eax, [edx+ebx] + imul eax, FIX_1_175875602 { eax = z5 } + + {z4 := (z4) * INT32(- FIX_0_390180644); { sqrt(2) * (c5-c3) } + {Inc(z4, z5);} + imul ebx, (-FIX_0_390180644) + add ebx, eax + mov z4, ebx + + {z3 := (z3) * INT32(- FIX_1_961570560); { sqrt(2) * (-c3-c5) } + {Inc(z3, z5);} + imul edx, (-FIX_1_961570560) + add eax, edx { z3 = eax } + + {Inc(tmp0, z1 + z3);} + mov ebx, z1 + add ebx, eax + add tmp0, ebx + + {tmp2 := (tmp2) * INT32(FIX_3_072711026); { sqrt(2) * ( c1+c3+c5-c7) } + {Inc(tmp2, z2 + z3);} + mov ebx, tmp2 + imul ebx, FIX_3_072711026 + mov edx, z2 { z2 = edx } + add ebx, edx + add eax, ebx + mov tmp2, eax + + {Inc(tmp1, z2 + z4);} + mov eax, z4 { z4 = eax } + add edx, eax + add tmp1, edx + + {tmp3 := (tmp3) * INT32(FIX_1_501321110); { sqrt(2) * ( c1+c3-c5-c7) } + {Inc(tmp3, z1 + z4);} + mov edx, tmp3 + imul edx, FIX_1_501321110 + + add edx, eax + add edx, z1 { tmp3 = edx } + + { Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 } + + {wsptr^[DCTSIZE*0] := int (DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS));} + {wsptr^[DCTSIZE*7] := int (DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS));} + mov eax, tmp10 + add eax, ROUND_CONST + lea ebx, [eax+edx] + sar ebx, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*0], ebx + + sub eax, edx + sar eax, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*7], eax + + {wsptr^[DCTSIZE*1] := int (DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS));} + {wsptr^[DCTSIZE*6] := int (DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS));} + mov eax, tmp11 + add eax, ROUND_CONST + mov edx, tmp2 + lea ebx, [eax+edx] + sar ebx, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*1], ebx + + sub eax, edx + sar eax, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*6], eax + + {wsptr^[DCTSIZE*2] := int (DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS));} + {wsptr^[DCTSIZE*5] := int (DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS));} + mov eax, tmp12 + add eax, ROUND_CONST + mov edx, tmp1 + lea ebx, [eax+edx] + sar ebx, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*2], ebx + + sub eax, edx + sar eax, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*5], eax + + {wsptr^[DCTSIZE*3] := int (DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS));} + {wsptr^[DCTSIZE*4] := int (DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS));} + mov eax, tmp13 + add eax, ROUND_CONST + mov edx, tmp0 + lea ebx, [eax+edx] + sar ebx, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*3], ebx + + sub eax, edx + sar eax, CONST_BITS-PASS1_BITS + mov DWORD PTR [ecx+wrkDCTSIZE*4], eax + + {Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + {Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr));} + dec ctr + je @loop519 + + add esi, Type JCOEF + add edi, Type ISLOW_MULT_TYPE + add ecx, Type int { int_ptr } + {end;} + jmp @loop518 +@loop519: + { Save to memory what we've registerized for the preceding loop. } + + { Pass 2: process rows from work array, store into output array. } + { Note that we must descale the results by a factor of 8 == 2**3, } + { and also undo the PASS1_BITS scaling. } + + {wsptr := @workspace;} + lea esi, workspace + + {for ctr := 0 to pred(DCTSIZE) do + begin} + mov ctr, 0 +@loop523: + + {outptr := output_buf^[ctr];} + mov eax, ctr + mov ebx, output_buf + mov edi, DWORD PTR [ebx+eax*4] { 4 = SizeOf(pointer) } + + {Inc(JSAMPLE_PTR(outptr), output_col);} + add edi, LongWord(output_col) + + { Rows of zeroes can be exploited in the same way as we did with columns. + However, the column calculation has created many nonzero AC terms, so + the simplification applies less often (typically 5% to 10% of the time). + On machines with very fast multiplication, it's possible that the + test takes more time than it's worth. In that case this section + may be commented out. } + +{$ifndef NO_ZERO_ROW_TEST} + {if ((wsptr^[1]) or (wsptr^[2]) or (wsptr^[3]) or (wsptr^[4]) or + (wsptr^[5]) or (wsptr^[6]) or (wsptr^[7]) = 0) then + begin} + mov eax, DWORD PTR [esi+4*1] + or eax, DWORD PTR [esi+4*2] + or eax, DWORD PTR [esi+4*3] + jne @loop525 { Nomssi: early exit path may help } + or eax, DWORD PTR [esi+4*4] + or eax, DWORD PTR [esi+4*5] + or eax, DWORD PTR [esi+4*6] + or eax, DWORD PTR [esi+4*7] + jne @loop525 + + { AC terms all zero } + {JSAMPLE(dcval_) := range_limit^[int(DESCALE(INT32(wsptr^[0]), + PASS1_BITS+3)) and RANGE_MASK];} + mov eax, DWORD PTR [esi+4*0] + add eax, (INT32(1) shl (PASS1_BITS+3-1)) + sar eax, PASS1_BITS+3 + and eax, RANGE_MASK + mov ebx, range_limit + mov al, BYTE PTR [ebx+eax] + mov ah, al + + {outptr^[0] := dcval_; + outptr^[1] := dcval_; + outptr^[2] := dcval_; + outptr^[3] := dcval_; + outptr^[4] := dcval_; + outptr^[5] := dcval_; + outptr^[6] := dcval_; + outptr^[7] := dcval_;} + + stosw + stosw + stosw + stosw + + {Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + {continue;} + add esi, wrkDCTSIZE + inc ctr + cmp ctr, DCTSIZE + jl @loop523 + jmp @loop524 + {end;} +@loop525: +{$endif} + + + { Even part: reverse the even part of the forward DCT. } + { The rotator is sqrt(2)*c(-6). } + + {z2 := INT32 (wsptr^[2]);} + mov edx, DWORD PTR [esi+4*2] { z2 = edx } + + {z3 := INT32 (wsptr^[6]);} + mov ecx, DWORD PTR [esi+4*6] { z3 = ecx } + + {z1 := (z2 + z3) * INT32(FIX_0_541196100);} + lea eax, [edx+ecx] + imul eax, FIX_0_541196100 + mov ebx, eax { z1 = ebx } + + {tmp2 := z1 + (z3) * INT32(- FIX_1_847759065);} + imul ecx, (-FIX_1_847759065) + add ecx, ebx { tmp2 = ecx } + + {tmp3 := z1 + (z2) * INT32(FIX_0_765366865);} + imul edx, FIX_0_765366865 + add ebx, edx { tmp3 = ebx } + + {tmp0 := (INT32(wsptr^[0]) + INT32(wsptr^[4])) shl CONST_BITS;} + {tmp1 := (INT32(wsptr^[0]) - INT32(wsptr^[4])) shl CONST_BITS;} + mov edx, DWORD PTR [esi+4*4] + mov eax, DWORD PTR [esi+4*0] + sub eax, edx + add edx, edx + add edx, eax + shl edx, CONST_BITS { tmp0 = edx } + shl eax, CONST_BITS { tmp1 = eax } + + {tmp10 := tmp0 + tmp3;} + {tmp13 := tmp0 - tmp3;} + sub edx, ebx + mov tmp13, edx + add ebx, ebx + add edx, ebx + mov tmp10, edx + + {tmp11 := tmp1 + tmp2;} + {tmp12 := tmp1 - tmp2;} + lea ebx, [ecx+eax] + mov tmp11, ebx + sub eax, ecx + mov tmp12, eax + + { Odd part per figure 8; the matrix is unitary and hence its + transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. } + +{ The following lines no longer produce code, since wsptr has been + optimized to esi, it is more efficient to access these values + directly. + tmp0 := INT32(wsptr^[7]); + tmp1 := INT32(wsptr^[5]); + tmp2 := INT32(wsptr^[3]); + tmp3 := INT32(wsptr^[1]); } + + {z2 := tmp1 + tmp2;} + {z2 := (z2) * INT32(- FIX_2_562915447); { sqrt(2) * (-c1-c3) } + mov ebx, DWORD PTR [esi+4*3] { tmp2 } + mov ecx, DWORD PTR [esi+4*5] { tmp1 } + lea eax, [ebx+ecx] + imul eax, (-FIX_2_562915447) + mov z2, eax + + {z3 := tmp0 + tmp2;} + mov edx, DWORD PTR [esi+4*7] { tmp0 } + add ebx, edx { old z3 = ebx } + mov eax, ebx + {z3 := (z3) * INT32(- FIX_1_961570560); { sqrt(2) * (-c3-c5) } + imul eax, (-FIX_1_961570560) + mov z3, eax + + {z1 := tmp0 + tmp3;} + {z1 := (z1) * INT32(- FIX_0_899976223); { sqrt(2) * (c7-c3) } + mov eax, DWORD PTR [esi+4*1] { tmp3 } + add edx, eax + imul edx, (-FIX_0_899976223) { z1 = edx } + + {z4 := tmp1 + tmp3;} + add eax, ecx { +tmp1 } + add ebx, eax { z3 + z4 = ebx } + {z4 := (z4) * INT32(- FIX_0_390180644); { sqrt(2) * (c5-c3) } + imul eax, (-FIX_0_390180644) { z4 = eax } + + {z5 := (z3 + z4) * INT32(FIX_1_175875602); { sqrt(2) * c3 } + {Inc(z3, z5);} + imul ebx, FIX_1_175875602 + mov ecx, z3 + add ecx, ebx { ecx = z3 } + + {Inc(z4, z5);} + add ebx, eax { z4 = ebx } + + {tmp0 := (tmp0) * INT32(FIX_0_298631336); { sqrt(2) * (-c1+c3+c5-c7) } + {Inc(tmp0, z1 + z3);} + mov eax, DWORD PTR [esi+4*7] + imul eax, FIX_0_298631336 + add eax, edx + add eax, ecx + mov tmp0, eax + + {tmp1 := (tmp1) * INT32(FIX_2_053119869); { sqrt(2) * ( c1+c3-c5+c7) } + {Inc(tmp1, z2 + z4);} + mov eax, DWORD PTR [esi+4*5] + imul eax, FIX_2_053119869 + add eax, z2 + add eax, ebx + mov tmp1, eax + + {tmp2 := (tmp2) * INT32(FIX_3_072711026); { sqrt(2) * ( c1+c3+c5-c7) } + {Inc(tmp2, z2 + z3);} + mov eax, DWORD PTR [esi+4*3] + imul eax, FIX_3_072711026 + add eax, z2 + add ecx, eax { ecx = tmp2 } + + {tmp3 := (tmp3) * INT32(FIX_1_501321110); { sqrt(2) * ( c1+c3-c5-c7) } + {Inc(tmp3, z1 + z4);} + mov eax, DWORD PTR [esi+4*1] + imul eax, FIX_1_501321110 + add eax, edx + add ebx, eax { ebx = tmp3 } + + { Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 } + + {outptr^[0] := range_limit^[ int(DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK]; } + {outptr^[7] := range_limit^[ int(DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK];} + + mov edx, tmp10 + add edx, ROUND_CONST_2 + lea eax, [ebx+edx] + sub edx, ebx + + shr eax, CONST_BITS+PASS1_BITS+3 + and eax, RANGE_MASK + mov ebx, range_limit { once for all } + mov al, BYTE PTR [ebx+eax] + mov [edi+0], al + + shr edx, CONST_BITS+PASS1_BITS+3 + and edx, RANGE_MASK + mov al, BYTE PTR [ebx+edx] + mov [edi+7], al + + {outptr^[1] := range_limit^[ int(DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK];} + mov eax, tmp11 + add eax, ROUND_CONST_2 + lea edx, [eax+ecx] + shr edx, CONST_BITS+PASS1_BITS+3 + and edx, RANGE_MASK + mov dl, BYTE PTR [ebx+edx] + mov [edi+1], dl + + {outptr^[6] := range_limit^[ int(DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK];} + sub eax, ecx + shr eax, CONST_BITS+PASS1_BITS+3 + and eax, RANGE_MASK + mov al, BYTE PTR [ebx+eax] + mov [edi+6], al + + {outptr^[2] := range_limit^[ int(DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK];} + mov eax, tmp12 + add eax, ROUND_CONST_2 + mov ecx, tmp1 + lea edx, [eax+ecx] + shr edx, CONST_BITS+PASS1_BITS+3 + and edx, RANGE_MASK + mov dl, BYTE PTR [ebx+edx] + mov [edi+2], dl + + {outptr^[5] := range_limit^[ int(DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK];} + sub eax, ecx + shr eax, CONST_BITS+PASS1_BITS+3 + and eax, RANGE_MASK + mov al, BYTE PTR [ebx+eax] + mov [edi+5], al + + {outptr^[3] := range_limit^[ int(DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK];} + mov eax, tmp13 + add eax, ROUND_CONST_2 + mov ecx, tmp0 + lea edx, [eax+ecx] + shr edx, CONST_BITS+PASS1_BITS+3 + and edx, RANGE_MASK + mov dl, BYTE PTR [ebx+edx] + mov [edi+3], dl + + {outptr^[4] := range_limit^[ int(DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3)) and RANGE_MASK];} + sub eax, ecx + shr eax, CONST_BITS+PASS1_BITS+3 + and eax, RANGE_MASK + mov al, BYTE PTR [ebx+eax] + mov [edi+4], al + + {Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + add esi, wrkDCTSIZE + add edi, DCTSIZE + + {end;} + inc ctr + cmp ctr, DCTSIZE + jl @loop523 + +@loop524: +@loop496: + pop ebx + pop esi + pop edi +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjidctflt.pas b/src/lib/vampimg/JpegLib/imjidctflt.pas new file mode 100644 index 0000000..febd244 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjidctflt.pas @@ -0,0 +1,286 @@ +unit imjidctflt; + +{$N+} +{ This file contains a floating-point implementation of the + inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + must also perform dequantization of the input coefficients. + + This implementation should be more accurate than either of the integer + IDCT implementations. However, it may not give the same results on all + machines because of differences in roundoff behavior. Speed will depend + on the hardware's floating point capacity. + + A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + on each row (or vice versa, but it's more convenient to emit a row at + a time). Direct algorithms are also available, but they are much more + complex and seem not to be any faster when reduced to code. + + This implementation is based on Arai, Agui, and Nakajima's algorithm for + scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + Japanese, but the algorithm is described in the Pennebaker & Mitchell + JPEG textbook (see REFERENCES section in file README). The following code + is based directly on figure 4-8 in P&M. + While an 8-point DCT cannot be done in less than 11 multiplies, it is + possible to arrange the computation so that many of the multiplies are + simple scalings of the final outputs. These multiplies can then be + folded into the multiplications or divisions by the JPEG quantization + table entries. The AA&N method leaves only 5 multiplies and 29 adds + to be done in the DCT itself. + The primary disadvantage of this method is that with a fixed-point + implementation, accuracy is lost due to imprecise representation of the + scaled quantization values. However, that problem does not arise if + we use floating point arithmetic. } + +{ Original: jidctflt.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_float (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + + +{ Dequantize a coefficient by multiplying it by the multiplier-table + entry; produce a float result. } + +function DEQUANTIZE(coef : int; quantval : FAST_FLOAT) : FAST_FLOAT; +begin + Dequantize := ( (coef) * quantval); +end; + +{ Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + +function DESCALE(x : INT32; n : int) : INT32; +var + shift_temp : INT32; +begin +{$ifdef RIGHT_SHIFT_IS_UNSIGNED} + shift_temp := x + (INT32(1) shl (n-1)); + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else + Descale := (shift_temp shr n); +{$else} + Descale := (x + (INT32(1) shl (n-1)) shr n; +{$endif} +end; + + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_float (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); +type + PWorkspace = ^TWorkspace; + TWorkspace = array[0..DCTSIZE2-1] of FAST_FLOAT; +var + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 : FAST_FLOAT; + tmp10, tmp11, tmp12, tmp13 : FAST_FLOAT; + z5, z10, z11, z12, z13 : FAST_FLOAT; + inptr : JCOEFPTR; + quantptr : FLOAT_MULT_TYPE_FIELD_PTR; + wsptr : PWorkSpace; + outptr : JSAMPROW; + range_limit : JSAMPROW; + ctr : int; + workspace : TWorkspace; { buffers data between passes } + {SHIFT_TEMPS} +var + dcval : FAST_FLOAT; +begin +{ Each IDCT routine is responsible for range-limiting its results and + converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + be quite far out of range if the input data is corrupt, so a bulletproof + range-limiting step is required. We use a mask-and-table-lookup method + to do the combined operations quickly. See the comments with + prepare_range_limit_table (in jdmaster.c) for more info. } + + range_limit := JSAMPROW(@(cinfo^.sample_range_limit^[CENTERJSAMPLE])); + + { Pass 1: process columns from input, store into work array. } + + inptr := coef_block; + quantptr := FLOAT_MULT_TYPE_FIELD_PTR (compptr^.dct_table); + wsptr := @workspace; + for ctr := pred(DCTSIZE) downto 0 do + begin + { Due to quantization, we will usually find that many of the input + coefficients are zero, especially the AC terms. We can exploit this + by short-circuiting the IDCT calculation for any column in which all + the AC terms are zero. In that case each output is equal to the + DC coefficient (with scale factor as needed). + With typical images and quantization tables, half or more of the + column DCT calculations can be simplified this way. } + + if (inptr^[DCTSIZE*1]=0) and (inptr^[DCTSIZE*2]=0) and + (inptr^[DCTSIZE*3]=0) and (inptr^[DCTSIZE*4]=0) and + (inptr^[DCTSIZE*5]=0) and (inptr^[DCTSIZE*6]=0) and + (inptr^[DCTSIZE*7]=0) then + begin + { AC terms all zero } + FAST_FLOAT(dcval) := DEQUANTIZE(inptr^[DCTSIZE*0], quantptr^[DCTSIZE*0]); + + wsptr^[DCTSIZE*0] := dcval; + wsptr^[DCTSIZE*1] := dcval; + wsptr^[DCTSIZE*2] := dcval; + wsptr^[DCTSIZE*3] := dcval; + wsptr^[DCTSIZE*4] := dcval; + wsptr^[DCTSIZE*5] := dcval; + wsptr^[DCTSIZE*6] := dcval; + wsptr^[DCTSIZE*7] := dcval; + + Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + Inc(FLOAT_MULT_TYPE_PTR(quantptr)); + Inc(FAST_FLOAT_PTR(wsptr)); + continue; + end; + + { Even part } + + tmp0 := DEQUANTIZE(inptr^[DCTSIZE*0], quantptr^[DCTSIZE*0]); + tmp1 := DEQUANTIZE(inptr^[DCTSIZE*2], quantptr^[DCTSIZE*2]); + tmp2 := DEQUANTIZE(inptr^[DCTSIZE*4], quantptr^[DCTSIZE*4]); + tmp3 := DEQUANTIZE(inptr^[DCTSIZE*6], quantptr^[DCTSIZE*6]); + + tmp10 := tmp0 + tmp2; { phase 3 } + tmp11 := tmp0 - tmp2; + + tmp13 := tmp1 + tmp3; { phases 5-3 } + tmp12 := (tmp1 - tmp3) * ({FAST_FLOAT}(1.414213562)) - tmp13; { 2*c4 } + + tmp0 := tmp10 + tmp13; { phase 2 } + tmp3 := tmp10 - tmp13; + tmp1 := tmp11 + tmp12; + tmp2 := tmp11 - tmp12; + + { Odd part } + + tmp4 := DEQUANTIZE(inptr^[DCTSIZE*1], quantptr^[DCTSIZE*1]); + tmp5 := DEQUANTIZE(inptr^[DCTSIZE*3], quantptr^[DCTSIZE*3]); + tmp6 := DEQUANTIZE(inptr^[DCTSIZE*5], quantptr^[DCTSIZE*5]); + tmp7 := DEQUANTIZE(inptr^[DCTSIZE*7], quantptr^[DCTSIZE*7]); + + z13 := tmp6 + tmp5; { phase 6 } + z10 := tmp6 - tmp5; + z11 := tmp4 + tmp7; + z12 := tmp4 - tmp7; + + tmp7 := z11 + z13; { phase 5 } + tmp11 := (z11 - z13) * ({FAST_FLOAT}(1.414213562)); { 2*c4 } + + z5 := (z10 + z12) * ({FAST_FLOAT}(1.847759065)); { 2*c2 } + tmp10 := ({FAST_FLOAT}(1.082392200)) * z12 - z5; { 2*(c2-c6) } + tmp12 := ({FAST_FLOAT}(-2.613125930)) * z10 + z5; { -2*(c2+c6) } + + tmp6 := tmp12 - tmp7; { phase 2 } + tmp5 := tmp11 - tmp6; + tmp4 := tmp10 + tmp5; + + wsptr^[DCTSIZE*0] := tmp0 + tmp7; + wsptr^[DCTSIZE*7] := tmp0 - tmp7; + wsptr^[DCTSIZE*1] := tmp1 + tmp6; + wsptr^[DCTSIZE*6] := tmp1 - tmp6; + wsptr^[DCTSIZE*2] := tmp2 + tmp5; + wsptr^[DCTSIZE*5] := tmp2 - tmp5; + wsptr^[DCTSIZE*4] := tmp3 + tmp4; + wsptr^[DCTSIZE*3] := tmp3 - tmp4; + + Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + Inc(FLOAT_MULT_TYPE_PTR(quantptr)); + Inc(FAST_FLOAT_PTR(wsptr)); + end; + + { Pass 2: process rows from work array, store into output array. } + { Note that we must descale the results by a factor of 8 = 2**3. } + + wsptr := @workspace; + for ctr := 0 to pred(DCTSIZE) do + begin + outptr := JSAMPROW(@(output_buf^[ctr]^[output_col])); + { Rows of zeroes can be exploited in the same way as we did with columns. + However, the column calculation has created many nonzero AC terms, so + the simplification applies less often (typically 5% to 10% of the time). + And testing floats for zero is relatively expensive, so we don't bother. } + + { Even part } + + tmp10 := wsptr^[0] + wsptr^[4]; + tmp11 := wsptr^[0] - wsptr^[4]; + + tmp13 := wsptr^[2] + wsptr^[6]; + tmp12 := (wsptr^[2] - wsptr^[6]) * ({FAST_FLOAT}(1.414213562)) - tmp13; + + tmp0 := tmp10 + tmp13; + tmp3 := tmp10 - tmp13; + tmp1 := tmp11 + tmp12; + tmp2 := tmp11 - tmp12; + + { Odd part } + + z13 := wsptr^[5] + wsptr^[3]; + z10 := wsptr^[5] - wsptr^[3]; + z11 := wsptr^[1] + wsptr^[7]; + z12 := wsptr^[1] - wsptr^[7]; + + tmp7 := z11 + z13; + tmp11 := (z11 - z13) * ({FAST_FLOAT}(1.414213562)); + + z5 := (z10 + z12) * ({FAST_FLOAT}(1.847759065)); { 2*c2 } + tmp10 := ({FAST_FLOAT}(1.082392200)) * z12 - z5; { 2*(c2-c6) } + tmp12 := ({FAST_FLOAT}(-2.613125930)) * z10 + z5; { -2*(c2+c6) } + + tmp6 := tmp12 - tmp7; + tmp5 := tmp11 - tmp6; + tmp4 := tmp10 + tmp5; + + { Final output stage: scale down by a factor of 8 and range-limit } + + outptr^[0] := range_limit^[ int(DESCALE( INT32(Round((tmp0 + tmp7))), 3)) + and RANGE_MASK]; + outptr^[7] := range_limit^[ int(DESCALE( INT32(Round((tmp0 - tmp7))), 3)) + and RANGE_MASK]; + outptr^[1] := range_limit^[ int(DESCALE( INT32(Round((tmp1 + tmp6))), 3)) + and RANGE_MASK]; + outptr^[6] := range_limit^[ int(DESCALE( INT32(Round((tmp1 - tmp6))), 3)) + and RANGE_MASK]; + outptr^[2] := range_limit^[ int(DESCALE( INT32(Round((tmp2 + tmp5))), 3)) + and RANGE_MASK]; + outptr^[5] := range_limit^[ int(DESCALE( INT32(Round((tmp2 - tmp5))), 3)) + and RANGE_MASK]; + outptr^[4] := range_limit^[ int(DESCALE( INT32(Round((tmp3 + tmp4))), 3)) + and RANGE_MASK]; + outptr^[3] := range_limit^[ int(DESCALE( INT32(Round((tmp3 - tmp4))), 3)) + and RANGE_MASK]; + + Inc(FAST_FLOAT_PTR(wsptr), DCTSIZE); { advance pointer to next row } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjidctfst.pas b/src/lib/vampimg/JpegLib/imjidctfst.pas new file mode 100644 index 0000000..f66c731 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjidctfst.pas @@ -0,0 +1,410 @@ +unit imjidctfst; + +{ This file contains a fast, not so accurate integer implementation of the + inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + must also perform dequantization of the input coefficients. + + A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + on each row (or vice versa, but it's more convenient to emit a row at + a time). Direct algorithms are also available, but they are much more + complex and seem not to be any faster when reduced to code. + + This implementation is based on Arai, Agui, and Nakajima's algorithm for + scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + Japanese, but the algorithm is described in the Pennebaker & Mitchell + JPEG textbook (see REFERENCES section in file README). The following code + is based directly on figure 4-8 in P&M. + While an 8-point DCT cannot be done in less than 11 multiplies, it is + possible to arrange the computation so that many of the multiplies are + simple scalings of the final outputs. These multiplies can then be + folded into the multiplications or divisions by the JPEG quantization + table entries. The AA&N method leaves only 5 multiplies and 29 adds + to be done in the DCT itself. + The primary disadvantage of this method is that with fixed-point math, + accuracy is lost due to imprecise representation of the scaled + quantization values. The smaller the quantization table entry, the less + precise the scaled value, so this implementation does worse with high- + quality-setting files than with low-quality ones. } + +{ Original : jidctfst.c ; Copyright (C) 1994-1996, Thomas G. Lane. } + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_ifast (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + +{ Scaling decisions are generally the same as in the LL&M algorithm; + see jidctint.c for more details. However, we choose to descale + (right shift) multiplication products as soon as they are formed, + rather than carrying additional fractional bits into subsequent additions. + This compromises accuracy slightly, but it lets us save a few shifts. + More importantly, 16-bit arithmetic is then adequate (for 8-bit samples) + everywhere except in the multiplications proper; this saves a good deal + of work on 16-bit-int machines. + + The dequantized coefficients are not integers because the AA&N scaling + factors have been incorporated. We represent them scaled up by PASS1_BITS, + so that the first and second IDCT rounds have the same input scaling. + For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to + avoid a descaling shift; this compromises accuracy rather drastically + for small quantization table entries, but it saves a lot of shifts. + For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway, + so we use a much larger scaling factor to preserve accuracy. + + A final compromise is to represent the multiplicative constants to only + 8 fractional bits, rather than 13. This saves some shifting work on some + machines, and may also reduce the cost of multiplication (since there + are fewer one-bits in the constants). } + +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + CONST_BITS = 8; + PASS1_BITS = 2; +{$else} +const + CONST_BITS = 8; + PASS1_BITS = 1; { lose a little precision to avoid overflow } +{$endif} + + +const + FIX_1_082392200 = INT32(Round((INT32(1) shl CONST_BITS)*1.082392200)); {277} + FIX_1_414213562 = INT32(Round((INT32(1) shl CONST_BITS)*1.414213562)); {362} + FIX_1_847759065 = INT32(Round((INT32(1) shl CONST_BITS)*1.847759065)); {473} + FIX_2_613125930 = INT32(Round((INT32(1) shl CONST_BITS)*2.613125930)); {669} + + +{ Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + +function DESCALE(x : INT32; n : int) : INT32; +var + shift_temp : INT32; +begin +{$ifdef USE_ACCURATE_ROUNDING} + shift_temp := x + (INT32(1) shl (n-1)); +{$else} +{ We can gain a little more speed, with a further compromise in accuracy, + by omitting the addition in a descaling shift. This yields an incorrectly + rounded result half the time... } + shift_temp := x; +{$endif} + +{$ifdef RIGHT_SHIFT_IS_UNSIGNED} + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else +{$endif} + Descale := (shift_temp shr n); +end; + + +{ Multiply a DCTELEM variable by an INT32 constant, and immediately + descale to yield a DCTELEM result. } + + {(DCTELEM( DESCALE((var) * (const), CONST_BITS))} + function Multiply(Avar, Aconst: Integer): DCTELEM; + begin + Multiply := DCTELEM( Avar*INT32(Aconst) div (INT32(1) shl CONST_BITS)); + end; + + +{ Dequantize a coefficient by multiplying it by the multiplier-table + entry; produce a DCTELEM result. For 8-bit data a 16x16->16 + multiplication will do. For 12-bit data, the multiplier table is + declared INT32, so a 32-bit multiply will be used. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} + function DEQUANTIZE(coef,quantval : int) : int; + begin + Dequantize := ( IFAST_MULT_TYPE(coef) * quantval); + end; +{$else} + function DEQUANTIZE(coef,quantval : INT32) : int; + begin + Dequantize := DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS); + end; +{$endif} + + +{ Like DESCALE, but applies to a DCTELEM and produces an int. + We assume that int right shift is unsigned if INT32 right shift is. } + +function IDESCALE(x : DCTELEM; n : int) : int; +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + DCTELEMBITS = 16; { DCTELEM may be 16 or 32 bits } +{$else} +const + DCTELEMBITS = 32; { DCTELEM must be 32 bits } +{$endif} +var + ishift_temp : DCTELEM; +begin +{$ifndef USE_ACCURATE_ROUNDING} + ishift_temp := x + (INT32(1) shl (n-1)); +{$else} +{ We can gain a little more speed, with a further compromise in accuracy, + by omitting the addition in a descaling shift. This yields an incorrectly + rounded result half the time... } + ishift_temp := x; +{$endif} + +{$ifdef RIGHT_SHIFT_IS_UNSIGNED} + if ishift_temp < 0 then + IDescale := (ishift_temp shr n) + or ((not DCTELEM(0)) shl (DCTELEMBITS-n)) + else +{$endif} + IDescale := (ishift_temp shr n); +end; + + + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_ifast (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); +type + PWorkspace = ^TWorkspace; + TWorkspace = coef_bits_field; { buffers data between passes } +var + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7 : DCTELEM; + tmp10, tmp11, tmp12, tmp13 : DCTELEM; + z5, z10, z11, z12, z13 : DCTELEM; + inptr : JCOEFPTR; + quantptr : IFAST_MULT_TYPE_FIELD_PTR; + wsptr : PWorkspace; + outptr : JSAMPROW; + range_limit : JSAMPROW; + ctr : int; + workspace : TWorkspace; { buffers data between passes } + {SHIFT_TEMPS} { for DESCALE } + {ISHIFT_TEMPS} { for IDESCALE } +var + dcval : int; +var + dcval_ : JSAMPLE; +begin +{ Each IDCT routine is responsible for range-limiting its results and + converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + be quite far out of range if the input data is corrupt, so a bulletproof + range-limiting step is required. We use a mask-and-table-lookup method + to do the combined operations quickly. See the comments with + prepare_range_limit_table (in jdmaster.c) for more info. } + + range_limit := JSAMPROW(@(cinfo^.sample_range_limit^[CENTERJSAMPLE])); + { Pass 1: process columns from input, store into work array. } + + inptr := coef_block; + quantptr := IFAST_MULT_TYPE_FIELD_PTR(compptr^.dct_table); + wsptr := @workspace; + for ctr := pred(DCTSIZE) downto 0 do + begin + { Due to quantization, we will usually find that many of the input + coefficients are zero, especially the AC terms. We can exploit this + by short-circuiting the IDCT calculation for any column in which all + the AC terms are zero. In that case each output is equal to the + DC coefficient (with scale factor as needed). + With typical images and quantization tables, half or more of the + column DCT calculations can be simplified this way. } + + if (inptr^[DCTSIZE*1]=0) and (inptr^[DCTSIZE*2]=0) and (inptr^[DCTSIZE*3]=0) and + (inptr^[DCTSIZE*4]=0) and (inptr^[DCTSIZE*5]=0) and (inptr^[DCTSIZE*6]=0) and + (inptr^[DCTSIZE*7]=0) then + begin + { AC terms all zero } + dcval := int(DEQUANTIZE(inptr^[DCTSIZE*0], quantptr^[DCTSIZE*0])); + + wsptr^[DCTSIZE*0] := dcval; + wsptr^[DCTSIZE*1] := dcval; + wsptr^[DCTSIZE*2] := dcval; + wsptr^[DCTSIZE*3] := dcval; + wsptr^[DCTSIZE*4] := dcval; + wsptr^[DCTSIZE*5] := dcval; + wsptr^[DCTSIZE*6] := dcval; + wsptr^[DCTSIZE*7] := dcval; + + Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + Inc(IFAST_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + continue; + end; + + { Even part } + + tmp0 := DEQUANTIZE(inptr^[DCTSIZE*0], quantptr^[DCTSIZE*0]); + tmp1 := DEQUANTIZE(inptr^[DCTSIZE*2], quantptr^[DCTSIZE*2]); + tmp2 := DEQUANTIZE(inptr^[DCTSIZE*4], quantptr^[DCTSIZE*4]); + tmp3 := DEQUANTIZE(inptr^[DCTSIZE*6], quantptr^[DCTSIZE*6]); + + tmp10 := tmp0 + tmp2; { phase 3 } + tmp11 := tmp0 - tmp2; + + tmp13 := tmp1 + tmp3; { phases 5-3 } + tmp12 := MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; { 2*c4 } + + tmp0 := tmp10 + tmp13; { phase 2 } + tmp3 := tmp10 - tmp13; + tmp1 := tmp11 + tmp12; + tmp2 := tmp11 - tmp12; + + { Odd part } + + tmp4 := DEQUANTIZE(inptr^[DCTSIZE*1], quantptr^[DCTSIZE*1]); + tmp5 := DEQUANTIZE(inptr^[DCTSIZE*3], quantptr^[DCTSIZE*3]); + tmp6 := DEQUANTIZE(inptr^[DCTSIZE*5], quantptr^[DCTSIZE*5]); + tmp7 := DEQUANTIZE(inptr^[DCTSIZE*7], quantptr^[DCTSIZE*7]); + + z13 := tmp6 + tmp5; { phase 6 } + z10 := tmp6 - tmp5; + z11 := tmp4 + tmp7; + z12 := tmp4 - tmp7; + + tmp7 := z11 + z13; { phase 5 } + tmp11 := MULTIPLY(z11 - z13, FIX_1_414213562); { 2*c4 } + + z5 := MULTIPLY(z10 + z12, FIX_1_847759065); { 2*c2 } + tmp10 := MULTIPLY(z12, FIX_1_082392200) - z5; { 2*(c2-c6) } + tmp12 := MULTIPLY(z10, - FIX_2_613125930) + z5; { -2*(c2+c6) } + + tmp6 := tmp12 - tmp7; { phase 2 } + tmp5 := tmp11 - tmp6; + tmp4 := tmp10 + tmp5; + + wsptr^[DCTSIZE*0] := int (tmp0 + tmp7); + wsptr^[DCTSIZE*7] := int (tmp0 - tmp7); + wsptr^[DCTSIZE*1] := int (tmp1 + tmp6); + wsptr^[DCTSIZE*6] := int (tmp1 - tmp6); + wsptr^[DCTSIZE*2] := int (tmp2 + tmp5); + wsptr^[DCTSIZE*5] := int (tmp2 - tmp5); + wsptr^[DCTSIZE*4] := int (tmp3 + tmp4); + wsptr^[DCTSIZE*3] := int (tmp3 - tmp4); + + Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + Inc(IFAST_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + end; + + { Pass 2: process rows from work array, store into output array. } + { Note that we must descale the results by a factor of 8 == 2**3, } + { and also undo the PASS1_BITS scaling. } + + wsptr := @workspace; + for ctr := 0 to pred(DCTSIZE) do + begin + outptr := JSAMPROW(@output_buf^[ctr]^[output_col]); + { Rows of zeroes can be exploited in the same way as we did with columns. + However, the column calculation has created many nonzero AC terms, so + the simplification applies less often (typically 5% to 10% of the time). + On machines with very fast multiplication, it's possible that the + test takes more time than it's worth. In that case this section + may be commented out. } + +{$ifndef NO_ZERO_ROW_TEST} + if (wsptr^[1]=0) and (wsptr^[2]=0) and (wsptr^[3]=0) and (wsptr^[4]=0) and + (wsptr^[5]=0) and (wsptr^[6]=0) and (wsptr^[7]=0) then + begin + { AC terms all zero } + dcval_ := range_limit^[IDESCALE(wsptr^[0], PASS1_BITS+3) + and RANGE_MASK]; + + outptr^[0] := dcval_; + outptr^[1] := dcval_; + outptr^[2] := dcval_; + outptr^[3] := dcval_; + outptr^[4] := dcval_; + outptr^[5] := dcval_; + outptr^[6] := dcval_; + outptr^[7] := dcval_; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + continue; + end; +{$endif} + + { Even part } + + tmp10 := (DCTELEM(wsptr^[0]) + DCTELEM(wsptr^[4])); + tmp11 := (DCTELEM(wsptr^[0]) - DCTELEM(wsptr^[4])); + + tmp13 := (DCTELEM(wsptr^[2]) + DCTELEM(wsptr^[6])); + tmp12 := MULTIPLY(DCTELEM(wsptr^[2]) - DCTELEM(wsptr^[6]), FIX_1_414213562) + - tmp13; + + tmp0 := tmp10 + tmp13; + tmp3 := tmp10 - tmp13; + tmp1 := tmp11 + tmp12; + tmp2 := tmp11 - tmp12; + + { Odd part } + + z13 := DCTELEM(wsptr^[5]) + DCTELEM(wsptr^[3]); + z10 := DCTELEM(wsptr^[5]) - DCTELEM(wsptr^[3]); + z11 := DCTELEM(wsptr^[1]) + DCTELEM(wsptr^[7]); + z12 := DCTELEM(wsptr^[1]) - DCTELEM(wsptr^[7]); + + tmp7 := z11 + z13; { phase 5 } + tmp11 := MULTIPLY(z11 - z13, FIX_1_414213562); { 2*c4 } + + z5 := MULTIPLY(z10 + z12, FIX_1_847759065); { 2*c2 } + tmp10 := MULTIPLY(z12, FIX_1_082392200) - z5; { 2*(c2-c6) } + tmp12 := MULTIPLY(z10, - FIX_2_613125930) + z5; { -2*(c2+c6) } + + tmp6 := tmp12 - tmp7; { phase 2 } + tmp5 := tmp11 - tmp6; + tmp4 := tmp10 + tmp5; + + { Final output stage: scale down by a factor of 8 and range-limit } + + outptr^[0] := range_limit^[IDESCALE(tmp0 + tmp7, PASS1_BITS+3) + and RANGE_MASK]; + outptr^[7] := range_limit^[IDESCALE(tmp0 - tmp7, PASS1_BITS+3) + and RANGE_MASK]; + outptr^[1] := range_limit^[IDESCALE(tmp1 + tmp6, PASS1_BITS+3) + and RANGE_MASK]; + outptr^[6] := range_limit^[IDESCALE(tmp1 - tmp6, PASS1_BITS+3) + and RANGE_MASK]; + outptr^[2] := range_limit^[IDESCALE(tmp2 + tmp5, PASS1_BITS+3) + and RANGE_MASK]; + outptr^[5] := range_limit^[IDESCALE(tmp2 - tmp5, PASS1_BITS+3) + and RANGE_MASK]; + outptr^[4] := range_limit^[IDESCALE(tmp3 + tmp4, PASS1_BITS+3) + and RANGE_MASK]; + outptr^[3] := range_limit^[IDESCALE(tmp3 - tmp4, PASS1_BITS+3) + and RANGE_MASK]; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjidctint.pas b/src/lib/vampimg/JpegLib/imjidctint.pas new file mode 100644 index 0000000..e51628b --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjidctint.pas @@ -0,0 +1,440 @@ +unit imjidctint; +{$Q+} + +{ This file contains a slow-but-accurate integer implementation of the + inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + must also perform dequantization of the input coefficients. + + A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + on each row (or vice versa, but it's more convenient to emit a row at + a time). Direct algorithms are also available, but they are much more + complex and seem not to be any faster when reduced to code. + + This implementation is based on an algorithm described in + C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT + Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, + Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. + The primary algorithm described there uses 11 multiplies and 29 adds. + We use their alternate method with 12 multiplies and 32 adds. + The advantage of this method is that no data path contains more than one + multiplication; this allows a very simple and accurate implementation in + scaled fixed-point arithmetic, with a minimal number of shifts. } + +{ Original : jidctint.c ; Copyright (C) 1991-1998, Thomas G. Lane. } + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_islow (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + +{ The poop on this scaling stuff is as follows: + + Each 1-D IDCT step produces outputs which are a factor of sqrt(N) + larger than the true IDCT outputs. The final outputs are therefore + a factor of N larger than desired; since N=8 this can be cured by + a simple right shift at the end of the algorithm. The advantage of + this arrangement is that we save two multiplications per 1-D IDCT, + because the y0 and y4 inputs need not be divided by sqrt(N). + + We have to do addition and subtraction of the integer inputs, which + is no problem, and multiplication by fractional constants, which is + a problem to do in integer arithmetic. We multiply all the constants + by CONST_SCALE and convert them to integer constants (thus retaining + CONST_BITS bits of precision in the constants). After doing a + multiplication we have to divide the product by CONST_SCALE, with proper + rounding, to produce the correct output. This division can be done + cheaply as a right shift of CONST_BITS bits. We postpone shifting + as long as possible so that partial sums can be added together with + full fractional precision. + + The outputs of the first pass are scaled up by PASS1_BITS bits so that + they are represented to better-than-integral precision. These outputs + require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word + with the recommended scaling. (To scale up 12-bit sample data further, an + intermediate INT32 array would be needed.) + + To avoid overflow of the 32-bit intermediate results in pass 2, we must + have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis + shows that the values given below are the most effective. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + CONST_BITS = 13; + PASS1_BITS = 2; +{$else} +const + CONST_BITS = 13; + PASS1_BITS = 1; { lose a little precision to avoid overflow } +{$endif} + +const + CONST_SCALE = (INT32(1) shl CONST_BITS); + +const + FIX_0_298631336 = INT32(Round(CONST_SCALE * 0.298631336)); {2446} + FIX_0_390180644 = INT32(Round(CONST_SCALE * 0.390180644)); {3196} + FIX_0_541196100 = INT32(Round(CONST_SCALE * 0.541196100)); {4433} + FIX_0_765366865 = INT32(Round(CONST_SCALE * 0.765366865)); {6270} + FIX_0_899976223 = INT32(Round(CONST_SCALE * 0.899976223)); {7373} + FIX_1_175875602 = INT32(Round(CONST_SCALE * 1.175875602)); {9633} + FIX_1_501321110 = INT32(Round(CONST_SCALE * 1.501321110)); {12299} + FIX_1_847759065 = INT32(Round(CONST_SCALE * 1.847759065)); {15137} + FIX_1_961570560 = INT32(Round(CONST_SCALE * 1.961570560)); {16069} + FIX_2_053119869 = INT32(Round(CONST_SCALE * 2.053119869)); {16819} + FIX_2_562915447 = INT32(Round(CONST_SCALE * 2.562915447)); {20995} + FIX_3_072711026 = INT32(Round(CONST_SCALE * 3.072711026)); {25172} + + + +{ Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + For 8-bit samples with the recommended scaling, all the variable + and constant values involved are no more than 16 bits wide, so a + 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + For 12-bit samples, a full 32-bit multiplication will be needed. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} + + {$IFDEF BASM16} + {$IFNDEF WIN32} + {MULTIPLY16C16(var,const)} + function Multiply(X, Y: Integer): integer; assembler; + asm + mov ax, X + imul Y + mov al, ah + mov ah, dl + end; + {$ENDIF} + {$ENDIF} + + function Multiply(X, Y: INT32): INT32; + begin + Multiply := INT32(X) * INT32(Y); + end; + + +{$else} + {#define MULTIPLY(var,const) ((var) * (const))} + function Multiply(X, Y: INT32): INT32; + begin + Multiply := INT32(X) * INT32(Y); + end; +{$endif} + + +{ Dequantize a coefficient by multiplying it by the multiplier-table + entry; produce an int result. In this module, both inputs and result + are 16 bits or less, so either int or short multiply will work. } + +function DEQUANTIZE(coef,quantval : int) : int; +begin + Dequantize := ( ISLOW_MULT_TYPE(coef) * quantval); +end; + +{ Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + +function DESCALE(x : INT32; n : int) : INT32; +var + shift_temp : INT32; +begin +{$ifdef RIGHT_SHIFT_IS_UNSIGNED} + shift_temp := x + (INT32(1) shl (n-1)); + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else + Descale := (shift_temp shr n); +{$else} + Descale := (x + (INT32(1) shl (n-1)) shr n; +{$endif} +end; + +{ Perform dequantization and inverse DCT on one block of coefficients. } + +{GLOBAL} +procedure jpeg_idct_islow (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); +type + PWorkspace = ^TWorkspace; + TWorkspace = coef_bits_field; { buffers data between passes } +var + tmp0, tmp1, tmp2, tmp3 : INT32; + tmp10, tmp11, tmp12, tmp13 : INT32; + z1, z2, z3, z4, z5 : INT32; + inptr : JCOEFPTR; + quantptr : ISLOW_MULT_TYPE_FIELD_PTR; + wsptr : PWorkspace; + outptr : JSAMPROW; + range_limit : JSAMPROW; + ctr : int; + workspace : TWorkspace; + {SHIFT_TEMPS} +var + dcval : int; +var + dcval_ : JSAMPLE; +begin +{ Each IDCT routine is responsible for range-limiting its results and + converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + be quite far out of range if the input data is corrupt, so a bulletproof + range-limiting step is required. We use a mask-and-table-lookup method + to do the combined operations quickly. See the comments with + prepare_range_limit_table (in jdmaster.c) for more info. } + + range_limit := JSAMPROW(@(cinfo^.sample_range_limit^[CENTERJSAMPLE])); + + + { Pass 1: process columns from input, store into work array. } + { Note results are scaled up by sqrt(8) compared to a true IDCT; } + { furthermore, we scale the results by 2**PASS1_BITS. } + + inptr := coef_block; + quantptr := ISLOW_MULT_TYPE_FIELD_PTR (compptr^.dct_table); + wsptr := PWorkspace(@workspace); + for ctr := pred(DCTSIZE) downto 0 do + begin + { Due to quantization, we will usually find that many of the input + coefficients are zero, especially the AC terms. We can exploit this + by short-circuiting the IDCT calculation for any column in which all + the AC terms are zero. In that case each output is equal to the + DC coefficient (with scale factor as needed). + With typical images and quantization tables, half or more of the + column DCT calculations can be simplified this way. } + + if ((inptr^[DCTSIZE*1]=0) and (inptr^[DCTSIZE*2]=0) and + (inptr^[DCTSIZE*3]=0) and (inptr^[DCTSIZE*4]=0) and + (inptr^[DCTSIZE*5]=0) and (inptr^[DCTSIZE*6]=0) and + (inptr^[DCTSIZE*7]=0)) then + begin + { AC terms all zero } + dcval := DEQUANTIZE(inptr^[DCTSIZE*0], quantptr^[DCTSIZE*0]) shl PASS1_BITS; + + wsptr^[DCTSIZE*0] := dcval; + wsptr^[DCTSIZE*1] := dcval; + wsptr^[DCTSIZE*2] := dcval; + wsptr^[DCTSIZE*3] := dcval; + wsptr^[DCTSIZE*4] := dcval; + wsptr^[DCTSIZE*5] := dcval; + wsptr^[DCTSIZE*6] := dcval; + wsptr^[DCTSIZE*7] := dcval; + + Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + continue; + end; + + { Even part: reverse the even part of the forward DCT. } + { The rotator is sqrt(2)*c(-6). } + + z2 := DEQUANTIZE(inptr^[DCTSIZE*2], quantptr^[DCTSIZE*2]); + z3 := DEQUANTIZE(inptr^[DCTSIZE*6], quantptr^[DCTSIZE*6]); + + z1 := MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 := z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 := z1 + MULTIPLY(z2, FIX_0_765366865); + + z2 := DEQUANTIZE(inptr^[DCTSIZE*0], quantptr^[DCTSIZE*0]); + z3 := DEQUANTIZE(inptr^[DCTSIZE*4], quantptr^[DCTSIZE*4]); + + tmp0 := (z2 + z3) shl CONST_BITS; + tmp1 := (z2 - z3) shl CONST_BITS; + + tmp10 := tmp0 + tmp3; + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + { Odd part per figure 8; the matrix is unitary and hence its + transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. } + + tmp0 := DEQUANTIZE(inptr^[DCTSIZE*7], quantptr^[DCTSIZE*7]); + tmp1 := DEQUANTIZE(inptr^[DCTSIZE*5], quantptr^[DCTSIZE*5]); + tmp2 := DEQUANTIZE(inptr^[DCTSIZE*3], quantptr^[DCTSIZE*3]); + tmp3 := DEQUANTIZE(inptr^[DCTSIZE*1], quantptr^[DCTSIZE*1]); + + z1 := tmp0 + tmp3; + z2 := tmp1 + tmp2; + z3 := tmp0 + tmp2; + z4 := tmp1 + tmp3; + z5 := MULTIPLY(z3 + z4, FIX_1_175875602); { sqrt(2) * c3 } + + tmp0 := MULTIPLY(tmp0, FIX_0_298631336); { sqrt(2) * (-c1+c3+c5-c7) } + tmp1 := MULTIPLY(tmp1, FIX_2_053119869); { sqrt(2) * ( c1+c3-c5+c7) } + tmp2 := MULTIPLY(tmp2, FIX_3_072711026); { sqrt(2) * ( c1+c3+c5-c7) } + tmp3 := MULTIPLY(tmp3, FIX_1_501321110); { sqrt(2) * ( c1+c3-c5-c7) } + z1 := MULTIPLY(z1, - FIX_0_899976223); { sqrt(2) * (c7-c3) } + z2 := MULTIPLY(z2, - FIX_2_562915447); { sqrt(2) * (-c1-c3) } + z3 := MULTIPLY(z3, - FIX_1_961570560); { sqrt(2) * (-c3-c5) } + z4 := MULTIPLY(z4, - FIX_0_390180644); { sqrt(2) * (c5-c3) } + + Inc(z3, z5); + Inc(z4, z5); + + Inc(tmp0, z1 + z3); + Inc(tmp1, z2 + z4); + Inc(tmp2, z2 + z3); + Inc(tmp3, z1 + z4); + + { Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 } + + wsptr^[DCTSIZE*0] := int (DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS)); + wsptr^[DCTSIZE*7] := int (DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS)); + wsptr^[DCTSIZE*1] := int (DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS)); + wsptr^[DCTSIZE*6] := int (DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS)); + wsptr^[DCTSIZE*2] := int (DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS)); + wsptr^[DCTSIZE*5] := int (DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS)); + wsptr^[DCTSIZE*3] := int (DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS)); + wsptr^[DCTSIZE*4] := int (DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS)); + + Inc(JCOEF_PTR(inptr)); { advance pointers to next column } + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + end; + + { Pass 2: process rows from work array, store into output array. } + { Note that we must descale the results by a factor of 8 == 2**3, } + { and also undo the PASS1_BITS scaling. } + + wsptr := @workspace; + for ctr := 0 to pred(DCTSIZE) do + begin + outptr := output_buf^[ctr]; + Inc(JSAMPLE_PTR(outptr), output_col); + { Rows of zeroes can be exploited in the same way as we did with columns. + However, the column calculation has created many nonzero AC terms, so + the simplification applies less often (typically 5% to 10% of the time). + On machines with very fast multiplication, it's possible that the + test takes more time than it's worth. In that case this section + may be commented out. } + +{$ifndef NO_ZERO_ROW_TEST} + if ((wsptr^[1]=0) and (wsptr^[2]=0) and (wsptr^[3]=0) and (wsptr^[4]=0) + and (wsptr^[5]=0) and (wsptr^[6]=0) and (wsptr^[7]=0)) then + begin + { AC terms all zero } + JSAMPLE(dcval_) := range_limit^[int(DESCALE(INT32(wsptr^[0]), + PASS1_BITS+3)) and RANGE_MASK]; + + outptr^[0] := dcval_; + outptr^[1] := dcval_; + outptr^[2] := dcval_; + outptr^[3] := dcval_; + outptr^[4] := dcval_; + outptr^[5] := dcval_; + outptr^[6] := dcval_; + outptr^[7] := dcval_; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + continue; + end; +{$endif} + + { Even part: reverse the even part of the forward DCT. } + { The rotator is sqrt(2)*c(-6). } + + z2 := INT32 (wsptr^[2]); + z3 := INT32 (wsptr^[6]); + + z1 := MULTIPLY(z2 + z3, FIX_0_541196100); + tmp2 := z1 + MULTIPLY(z3, - FIX_1_847759065); + tmp3 := z1 + MULTIPLY(z2, FIX_0_765366865); + + tmp0 := (INT32(wsptr^[0]) + INT32(wsptr^[4])) shl CONST_BITS; + tmp1 := (INT32(wsptr^[0]) - INT32(wsptr^[4])) shl CONST_BITS; + + tmp10 := tmp0 + tmp3; + tmp13 := tmp0 - tmp3; + tmp11 := tmp1 + tmp2; + tmp12 := tmp1 - tmp2; + + { Odd part per figure 8; the matrix is unitary and hence its + transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. } + + tmp0 := INT32(wsptr^[7]); + tmp1 := INT32(wsptr^[5]); + tmp2 := INT32(wsptr^[3]); + tmp3 := INT32(wsptr^[1]); + + z1 := tmp0 + tmp3; + z2 := tmp1 + tmp2; + z3 := tmp0 + tmp2; + z4 := tmp1 + tmp3; + z5 := MULTIPLY(z3 + z4, FIX_1_175875602); { sqrt(2) * c3 } + + tmp0 := MULTIPLY(tmp0, FIX_0_298631336); { sqrt(2) * (-c1+c3+c5-c7) } + tmp1 := MULTIPLY(tmp1, FIX_2_053119869); { sqrt(2) * ( c1+c3-c5+c7) } + tmp2 := MULTIPLY(tmp2, FIX_3_072711026); { sqrt(2) * ( c1+c3+c5-c7) } + tmp3 := MULTIPLY(tmp3, FIX_1_501321110); { sqrt(2) * ( c1+c3-c5-c7) } + z1 := MULTIPLY(z1, - FIX_0_899976223); { sqrt(2) * (c7-c3) } + z2 := MULTIPLY(z2, - FIX_2_562915447); { sqrt(2) * (-c1-c3) } + z3 := MULTIPLY(z3, - FIX_1_961570560); { sqrt(2) * (-c3-c5) } + z4 := MULTIPLY(z4, - FIX_0_390180644); { sqrt(2) * (c5-c3) } + + Inc(z3, z5); + Inc(z4, z5); + + Inc(tmp0, z1 + z3); + Inc(tmp1, z2 + z4); + Inc(tmp2, z2 + z3); + Inc(tmp3, z1 + z4); + + { Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 } + + outptr^[0] := range_limit^[ int(DESCALE(tmp10 + tmp3, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + outptr^[7] := range_limit^[ int(DESCALE(tmp10 - tmp3, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + outptr^[1] := range_limit^[ int(DESCALE(tmp11 + tmp2, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + outptr^[6] := range_limit^[ int(DESCALE(tmp11 - tmp2, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + outptr^[2] := range_limit^[ int(DESCALE(tmp12 + tmp1, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + outptr^[5] := range_limit^[ int(DESCALE(tmp12 - tmp1, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + outptr^[3] := range_limit^[ int(DESCALE(tmp13 + tmp0, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + outptr^[4] := range_limit^[ int(DESCALE(tmp13 - tmp0, + CONST_BITS+PASS1_BITS+3)) + and RANGE_MASK]; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + end; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjidctred.pas b/src/lib/vampimg/JpegLib/imjidctred.pas new file mode 100644 index 0000000..27a0e43 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjidctred.pas @@ -0,0 +1,525 @@ +unit imjidctred; + + +{ This file contains inverse-DCT routines that produce reduced-size output: + either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. + + The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) + algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step + with an 8-to-4 step that produces the four averages of two adjacent outputs + (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). + These steps were derived by computing the corresponding values at the end + of the normal LL&M code, then simplifying as much as possible. + + 1x1 is trivial: just take the DC coefficient divided by 8. + + See jidctint.c for additional comments. } + + +{ Original : jidctred.c ; Copyright (C) 1994-1998, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib, + imjdct; { Private declarations for DCT subsystem } + +{ Perform dequantization and inverse DCT on one block of coefficients, + producing a reduced-size 1x1 output block. } + +{GLOBAL} +procedure jpeg_idct_1x1 (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); + +{ Perform dequantization and inverse DCT on one block of coefficients, + producing a reduced-size 2x2 output block. } + +{GLOBAL} +procedure jpeg_idct_2x2 (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); + +{ Perform dequantization and inverse DCT on one block of coefficients, + producing a reduced-size 4x4 output block. } + +{GLOBAL} +procedure jpeg_idct_4x4 (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); + +implementation + +{ This module is specialized to the case DCTSIZE = 8. } + +{$ifndef DCTSIZE_IS_8} + Sorry, this code only copes with 8x8 DCTs. { deliberate syntax err } +{$endif} + + +{ Scaling is the same as in jidctint.c. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} +const + CONST_BITS = 13; + PASS1_BITS = 2; +{$else} +const + CONST_BITS = 13; + PASS1_BITS = 1; { lose a little precision to avoid overflow } +{$endif} + +const + FIX_0_211164243 = INT32(Round((INT32(1) shl CONST_BITS) * 0.211164243)); {1730} + FIX_0_509795579 = INT32(Round((INT32(1) shl CONST_BITS) * 0.509795579)); {4176} + FIX_0_601344887 = INT32(Round((INT32(1) shl CONST_BITS) * 0.601344887)); {4926} + FIX_0_720959822 = INT32(Round((INT32(1) shl CONST_BITS) * 0.720959822)); {5906} + FIX_0_765366865 = INT32(Round((INT32(1) shl CONST_BITS) * 0.765366865)); {6270} + FIX_0_850430095 = INT32(Round((INT32(1) shl CONST_BITS) * 0.850430095)); {6967} + FIX_0_899976223 = INT32(Round((INT32(1) shl CONST_BITS) * 0.899976223)); {7373} + FIX_1_061594337 = INT32(Round((INT32(1) shl CONST_BITS) * 1.061594337)); {8697} + FIX_1_272758580 = INT32(Round((INT32(1) shl CONST_BITS) * 1.272758580)); {10426} + FIX_1_451774981 = INT32(Round((INT32(1) shl CONST_BITS) * 1.451774981)); {11893} + FIX_1_847759065 = INT32(Round((INT32(1) shl CONST_BITS) * 1.847759065)); {15137} + FIX_2_172734803 = INT32(Round((INT32(1) shl CONST_BITS) * 2.172734803)); {17799} + FIX_2_562915447 = INT32(Round((INT32(1) shl CONST_BITS) * 2.562915447)); {20995} + FIX_3_624509785 = INT32(Round((INT32(1) shl CONST_BITS) * 3.624509785)); {29692} + + +{ Multiply an INT32 variable by an INT32 constant to yield an INT32 result. + For 8-bit samples with the recommended scaling, all the variable + and constant values involved are no more than 16 bits wide, so a + 16x16->32 bit multiply can be used instead of a full 32x32 multiply. + For 12-bit samples, a full 32-bit multiplication will be needed. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} + + {function Multiply(X, Y: Integer): integer; assembler; + asm + mov ax, X + imul Y + mov al, ah + mov ah, dl + end;} + + {MULTIPLY16C16(var,const)} + function Multiply(X, Y: Integer): INT32; + begin + Multiply := X*INT32(Y); + end; + + +{$else} + function Multiply(X, Y: INT32): INT32; + begin + Multiply := X*Y; + end; +{$endif} + + +{ Dequantize a coefficient by multiplying it by the multiplier-table + entry; produce an int result. In this module, both inputs and result + are 16 bits or less, so either int or short multiply will work. } + +function DEQUANTIZE(coef,quantval : int) : int; +begin + Dequantize := ( ISLOW_MULT_TYPE(coef) * quantval); +end; + + +{ Descale and correctly round an INT32 value that's scaled by N bits. + We assume RIGHT_SHIFT rounds towards minus infinity, so adding + the fudge factor is correct for either sign of X. } + +function DESCALE(x : INT32; n : int) : INT32; +var + shift_temp : INT32; +begin +{$ifdef RIGHT_SHIFT_IS_UNSIGNED} + shift_temp := x + (INT32(1) shl (n-1)); + if shift_temp < 0 then + Descale := (shift_temp shr n) or ((not INT32(0)) shl (32-n)) + else + Descale := (shift_temp shr n); +{$else} + Descale := (x + (INT32(1) shl (n-1)) shr n; +{$endif} +end; + +{ Perform dequantization and inverse DCT on one block of coefficients, + producing a reduced-size 4x4 output block. } + +{GLOBAL} +procedure jpeg_idct_4x4 (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); +type + PWorkspace = ^TWorkspace; + TWorkspace = array[0..(DCTSIZE*4)-1] of int; { buffers data between passes } +var + tmp0, tmp2, tmp10, tmp12 : INT32; + z1, z2, z3, z4 : INT32; + inptr : JCOEFPTR; + quantptr : ISLOW_MULT_TYPE_FIELD_PTR; + wsptr : PWorkspace; + outptr : JSAMPROW; + range_limit : JSAMPROW; + ctr : int; + workspace : TWorkspace; { buffers data between passes } + {SHIFT_TEMPS} +var + dcval : int; +var + dcval_ : JSAMPLE; +begin +{ Each IDCT routine is responsible for range-limiting its results and + converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + be quite far out of range if the input data is corrupt, so a bulletproof + range-limiting step is required. We use a mask-and-table-lookup method + to do the combined operations quickly. See the comments with + prepare_range_limit_table (in jdmaster.c) for more info. } + + range_limit := JSAMPROW(@(cinfo^.sample_range_limit^[CENTERJSAMPLE])); + + { Pass 1: process columns from input, store into work array. } + + inptr := coef_block; + quantptr := ISLOW_MULT_TYPE_FIELD_PTR (compptr^.dct_table); + wsptr := @workspace; + for ctr := DCTSIZE downto 1 do + begin + { Don't bother to process column 4, because second pass won't use it } + if (ctr = DCTSIZE-4) then + begin + Inc(JCOEF_PTR(inptr)); + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + + continue; + end; + if (inptr^[DCTSIZE*1]=0) and (inptr^[DCTSIZE*2]=0) and (inptr^[DCTSIZE*3]=0) and + (inptr^[DCTSIZE*5]=0) and (inptr^[DCTSIZE*6]=0) and (inptr^[DCTSIZE*7]=0) then + begin + { AC terms all zero; we need not examine term 4 for 4x4 output } + dcval := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*0]) * + quantptr^[DCTSIZE*0]) shl PASS1_BITS; + + wsptr^[DCTSIZE*0] := dcval; + wsptr^[DCTSIZE*1] := dcval; + wsptr^[DCTSIZE*2] := dcval; + wsptr^[DCTSIZE*3] := dcval; + + Inc(JCOEF_PTR(inptr)); + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + + continue; + end; + + { Even part } + + tmp0 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*0]) * quantptr^[DCTSIZE*0]); + + tmp0 := tmp0 shl (CONST_BITS+1); + + z2 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*2]) * quantptr^[DCTSIZE*2]); + z3 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*6]) * quantptr^[DCTSIZE*6]); + + tmp2 := MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865); + + tmp10 := tmp0 + tmp2; + tmp12 := tmp0 - tmp2; + + { Odd part } + + z1 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*7]) * quantptr^[DCTSIZE*7]; + z2 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*5]) * quantptr^[DCTSIZE*5]; + z3 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*3]) * quantptr^[DCTSIZE*3]; + z4 := ISLOW_MULT_TYPE(inptr^[DCTSIZE*1]) * quantptr^[DCTSIZE*1]; + + tmp0 := MULTIPLY(z1, - FIX_0_211164243) { sqrt(2) * (c3-c1) } + + MULTIPLY(z2, FIX_1_451774981) { sqrt(2) * (c3+c7) } + + MULTIPLY(z3, - FIX_2_172734803) { sqrt(2) * (-c1-c5) } + + MULTIPLY(z4, FIX_1_061594337); { sqrt(2) * (c5+c7) } + + tmp2 := MULTIPLY(z1, - FIX_0_509795579) { sqrt(2) * (c7-c5) } + + MULTIPLY(z2, - FIX_0_601344887) { sqrt(2) * (c5-c1) } + + MULTIPLY(z3, FIX_0_899976223) { sqrt(2) * (c3-c7) } + + MULTIPLY(z4, FIX_2_562915447); { sqrt(2) * (c1+c3) } + + { Final output stage } + + wsptr^[DCTSIZE*0] := int(DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1)); + wsptr^[DCTSIZE*3] := int(DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1)); + wsptr^[DCTSIZE*1] := int(DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1)); + wsptr^[DCTSIZE*2] := int(DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1)); + + Inc(JCOEF_PTR(inptr)); + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + end; + + { Pass 2: process 4 rows from work array, store into output array. } + + wsptr := @workspace; + for ctr := 0 to pred(4) do + begin + outptr := JSAMPROW(@ output_buf^[ctr]^[output_col]); + { It's not clear whether a zero row test is worthwhile here ... } + +{$ifndef NO_ZERO_ROW_TEST} + if (wsptr^[1]=0) and (wsptr^[2]=0) and (wsptr^[3]=0) and + (wsptr^[5]=0) and (wsptr^[6]=0) and (wsptr^[7]=0) then + begin + { AC terms all zero } + dcval_ := range_limit^[int(DESCALE(INT32(wsptr^[0]), PASS1_BITS+3)) + and RANGE_MASK]; + + outptr^[0] := dcval_; + outptr^[1] := dcval_; + outptr^[2] := dcval_; + outptr^[3] := dcval_; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + continue; + end; +{$endif} + + { Even part } + + tmp0 := (INT32(wsptr^[0])) shl (CONST_BITS+1); + + tmp2 := MULTIPLY(INT32(wsptr^[2]), FIX_1_847759065) + + MULTIPLY(INT32(wsptr^[6]), - FIX_0_765366865); + + tmp10 := tmp0 + tmp2; + tmp12 := tmp0 - tmp2; + + { Odd part } + + z1 := INT32(wsptr^[7]); + z2 := INT32(wsptr^[5]); + z3 := INT32(wsptr^[3]); + z4 := INT32(wsptr^[1]); + + tmp0 := MULTIPLY(z1, - FIX_0_211164243) { sqrt(2) * (c3-c1) } + + MULTIPLY(z2, FIX_1_451774981) { sqrt(2) * (c3+c7) } + + MULTIPLY(z3, - FIX_2_172734803) { sqrt(2) * (-c1-c5) } + + MULTIPLY(z4, FIX_1_061594337); { sqrt(2) * (c5+c7) } + + tmp2 := MULTIPLY(z1, - FIX_0_509795579) { sqrt(2) * (c7-c5) } + + MULTIPLY(z2, - FIX_0_601344887) { sqrt(2) * (c5-c1) } + + MULTIPLY(z3, FIX_0_899976223) { sqrt(2) * (c3-c7) } + + MULTIPLY(z4, FIX_2_562915447); { sqrt(2) * (c1+c3) } + + { Final output stage } + + outptr^[0] := range_limit^[ int(DESCALE(tmp10 + tmp2, + CONST_BITS+PASS1_BITS+3+1)) + and RANGE_MASK]; + outptr^[3] := range_limit^[ int(DESCALE(tmp10 - tmp2, + CONST_BITS+PASS1_BITS+3+1)) + and RANGE_MASK]; + outptr^[1] := range_limit^[ int(DESCALE(tmp12 + tmp0, + CONST_BITS+PASS1_BITS+3+1)) + and RANGE_MASK]; + outptr^[2] := range_limit^[ int(DESCALE(tmp12 - tmp0, + CONST_BITS+PASS1_BITS+3+1)) + and RANGE_MASK]; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + end; +end; + + +{ Perform dequantization and inverse DCT on one block of coefficients, + producing a reduced-size 2x2 output block. } + +{GLOBAL} +procedure jpeg_idct_2x2 (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); +type + PWorkspace = ^TWorkspace; + TWorkspace = array[0..(DCTSIZE*2)-1] of int; { buffers data between passes } +var + tmp0, tmp10, z1 : INT32; + inptr : JCOEFPTR; + quantptr : ISLOW_MULT_TYPE_FIELD_PTR; + wsptr : PWorkspace; + outptr : JSAMPROW; + range_limit : JSAMPROW; + ctr : int; + workspace : TWorkspace; { buffers data between passes } + {SHIFT_TEMPS} +var + dcval : int; +var + dcval_ : JSAMPLE; +begin +{ Each IDCT routine is responsible for range-limiting its results and + converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + be quite far out of range if the input data is corrupt, so a bulletproof + range-limiting step is required. We use a mask-and-table-lookup method + to do the combined operations quickly. See the comments with + prepare_range_limit_table (in jdmaster.c) for more info. } + + range_limit := JSAMPROW(@(cinfo^.sample_range_limit^[CENTERJSAMPLE])); + { Pass 1: process columns from input, store into work array. } + + inptr := coef_block; + quantptr := ISLOW_MULT_TYPE_FIELD_PTR (compptr^.dct_table); + wsptr := @workspace; + for ctr := DCTSIZE downto 1 do + begin + { Don't bother to process columns 2,4,6 } + if (ctr = DCTSIZE-2) or (ctr = DCTSIZE-4) or (ctr = DCTSIZE-6) then + begin + Inc(JCOEF_PTR(inptr)); + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + + continue; + end; + if (inptr^[DCTSIZE*1]=0) and (inptr^[DCTSIZE*3]=0) and + (inptr^[DCTSIZE*5]=0) and (inptr^[DCTSIZE*7]=0) then + begin + { AC terms all zero; we need not examine terms 2,4,6 for 2x2 output } + dcval := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*0]) * + quantptr^[DCTSIZE*0]) shl PASS1_BITS; + + wsptr^[DCTSIZE*0] := dcval; + wsptr^[DCTSIZE*1] := dcval; + + Inc(JCOEF_PTR(inptr)); + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + + continue; + end; + + { Even part } + + z1 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*0]) * quantptr^[DCTSIZE*0]); + + tmp10 := z1 shl (CONST_BITS+2); + + { Odd part } + + z1 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*7]) * quantptr^[DCTSIZE*7]); + tmp0 := MULTIPLY(z1, - FIX_0_720959822); { sqrt(2) * (c7-c5+c3-c1) } + z1 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*5]) * quantptr^[DCTSIZE*5]); + Inc(tmp0, MULTIPLY(z1, FIX_0_850430095)); { sqrt(2) * (-c1+c3+c5+c7) } + z1 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*3]) * quantptr^[DCTSIZE*3]); + Inc(tmp0, MULTIPLY(z1, - FIX_1_272758580)); { sqrt(2) * (-c1+c3-c5-c7) } + z1 := (ISLOW_MULT_TYPE(inptr^[DCTSIZE*1]) * quantptr^[DCTSIZE*1]); + Inc(tmp0, MULTIPLY(z1, FIX_3_624509785)); { sqrt(2) * (c1+c3+c5+c7) } + + { Final output stage } + + wsptr^[DCTSIZE*0] := int (DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2)); + wsptr^[DCTSIZE*1] := int (DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2)); + + Inc(JCOEF_PTR(inptr)); + Inc(ISLOW_MULT_TYPE_PTR(quantptr)); + Inc(int_ptr(wsptr)); + end; + + { Pass 2: process 2 rows from work array, store into output array. } + + wsptr := @workspace; + for ctr := 0 to pred(2) do + begin + outptr := JSAMPROW(@ output_buf^[ctr]^[output_col]); + { It's not clear whether a zero row test is worthwhile here ... } + +{$ifndef NO_ZERO_ROW_TEST} + if (wsptr^[1]=0) and (wsptr^[3]=0) and (wsptr^[5]=0) and (wsptr^[7]= 0) then + begin + { AC terms all zero } + dcval_ := range_limit^[ int(DESCALE(INT32(wsptr^[0]), PASS1_BITS+3)) + and RANGE_MASK]; + + outptr^[0] := dcval_; + outptr^[1] := dcval_; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + continue; + end; +{$endif} + + { Even part } + + tmp10 := (INT32 (wsptr^[0])) shl (CONST_BITS+2); + + { Odd part } + + tmp0 := MULTIPLY( INT32(wsptr^[7]), - FIX_0_720959822) { sqrt(2) * (c7-c5+c3-c1) } + + MULTIPLY( INT32(wsptr^[5]), FIX_0_850430095) { sqrt(2) * (-c1+c3+c5+c7) } + + MULTIPLY( INT32(wsptr^[3]), - FIX_1_272758580) { sqrt(2) * (-c1+c3-c5-c7) } + + MULTIPLY( INT32(wsptr^[1]), FIX_3_624509785); { sqrt(2) * (c1+c3+c5+c7) } + + { Final output stage } + + outptr^[0] := range_limit^[ int(DESCALE(tmp10 + tmp0, + CONST_BITS+PASS1_BITS+3+2)) + and RANGE_MASK]; + outptr^[1] := range_limit^[ int(DESCALE(tmp10 - tmp0, + CONST_BITS+PASS1_BITS+3+2)) + and RANGE_MASK]; + + Inc(int_ptr(wsptr), DCTSIZE); { advance pointer to next row } + end; +end; + + +{ Perform dequantization and inverse DCT on one block of coefficients, + producing a reduced-size 1x1 output block. } + +{GLOBAL} +procedure jpeg_idct_1x1 (cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; + output_col : JDIMENSION); +var + dcval : int; + quantptr : ISLOW_MULT_TYPE_FIELD_PTR; + range_limit : JSAMPROW; + {SHIFT_TEMPS} +begin +{ Each IDCT routine is responsible for range-limiting its results and + converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could + be quite far out of range if the input data is corrupt, so a bulletproof + range-limiting step is required. We use a mask-and-table-lookup method + to do the combined operations quickly. See the comments with + prepare_range_limit_table (in jdmaster.c) for more info. } + + range_limit := JSAMPROW(@(cinfo^.sample_range_limit^[CENTERJSAMPLE])); + { Pass 1: process columns from input, store into work array. } + + { We hardly need an inverse DCT routine for this: just take the + average pixel value, which is one-eighth of the DC coefficient. } + + quantptr := ISLOW_MULT_TYPE_FIELD_PTR (compptr^.dct_table); + dcval := (ISLOW_MULT_TYPE(coef_block^[0]) * quantptr^[0]); + dcval := int (DESCALE( INT32(dcval), 3)); + + output_buf^[0]^[output_col] := range_limit^[dcval and RANGE_MASK]; +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjinclude.pas b/src/lib/vampimg/JpegLib/imjinclude.pas new file mode 100644 index 0000000..dcaa684 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjinclude.pas @@ -0,0 +1,126 @@ +unit imjinclude; + +{ This file exists to provide a single place to fix any problems with + including the wrong system include files. (Common problems are taken + care of by the standard jconfig symbols, but on really weird systems + you may have to edit this file.) + + NOTE: this file is NOT intended to be included by applications using the + JPEG library. Most applications need only include jpeglib.h. } + +{ Original: jinclude.h Copyright (C) 1991-1994, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +{ Include auto-config file to find out which system include files we need. } + +uses +{$ifdef Delphi_Stream} + classes, +{$endif} + imjmorecfg; + +{ Nomssi: + To write a dest/source manager that handle streams rather than files, + you can edit the FILEptr definition and the JFREAD() and JFWRITE() + functions in this unit, you don't need to change the default managers + JDATASRC and JDATADST. } + +{$ifdef Delphi_Stream} +type + FILEptr = ^TStream; +{$else} + {$ifdef Delphi_Jpeg} + type + FILEptr = TCustomMemoryStream; + {$else} + type + FILEptr = ^File; + {$endif} +{$endif} + +{ We need the NULL macro and size_t typedef. + On an ANSI-conforming system it is sufficient to include . + Otherwise, we get them from or ; we may have to + pull in as well. + Note that the core JPEG library does not require ; + only the default error handler and data source/destination modules do. + But we must pull it in because of the references to FILE in jpeglib.h. + You can remove those references if you want to compile without .} + + + +{ We need memory copying and zeroing functions, plus strncpy(). + ANSI and System V implementations declare these in . + BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + Some systems may declare memset and memcpy in . + + NOTE: we assume the size parameters to these functions are of type size_t. + Change the casts in these macros if not! } + +procedure MEMZERO(target : pointer; size : size_t); + +procedure MEMCOPY(dest, src : pointer; size : size_t); + +{function SIZEOF(object) : size_t;} + +function JFREAD(fp : FILEptr; buf : pointer; sizeofbuf : size_t) : size_t; + +function JFWRITE(fp : FILEptr; buf : pointer; sizeofbuf : size_t) : size_t; + +implementation + +procedure MEMZERO(target : pointer; size : size_t); +begin + FillChar(target^, size, 0); +end; + +procedure MEMCOPY(dest, src : pointer; size : size_t); +begin + Move(src^, dest^, size); +end; + +{ In ANSI C, and indeed any rational implementation, size_t is also the + type returned by sizeof(). However, it seems there are some irrational + implementations out there, in which sizeof() returns an int even though + size_t is defined as long or unsigned long. To ensure consistent results + we always use this SIZEOF() macro in place of using sizeof() directly. } + + +{#define + SIZEOF(object) (size_t(sizeof(object))} + + +{ The modules that use fread() and fwrite() always invoke them through + these macros. On some systems you may need to twiddle the argument casts. + CAUTION: argument order is different from underlying functions! } + + +function JFREAD(fp : FILEptr; buf : pointer; sizeofbuf : size_t) : size_t; +var + count : uint; +begin + {$ifdef Delphi_Stream} + count := fp^.Read(buf^, sizeofbuf); + {$else} + blockread(fp^, buf^, sizeofbuf, count); + {$endif} + JFREAD := size_t(count); +end; + +function JFWRITE(fp : FILEptr; buf : pointer; sizeofbuf : size_t) : size_t; +var + count : uint; +begin + {$ifdef Delphi_Stream} + count := fp^.Write(buf^, sizeofbuf); + {$else} + blockwrite(fp^, buf^, sizeofbuf, count); + {$endif} + JFWRITE := size_t(count); +end; + + +end. diff --git a/src/lib/vampimg/JpegLib/imjmemmgr.pas b/src/lib/vampimg/JpegLib/imjmemmgr.pas new file mode 100644 index 0000000..ca8239d --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjmemmgr.pas @@ -0,0 +1,1283 @@ +unit imjmemmgr; + +{ This file contains the JPEG system-independent memory management + routines. This code is usable across a wide variety of machines; most + of the system dependencies have been isolated in a separate file. + The major functions provided here are: + * pool-based allocation and freeing of memory; + * policy decisions about how to divide available memory among the + virtual arrays; + * control logic for swapping virtual arrays between main memory and + backing storage. + The separate system-dependent file provides the actual backing-storage + access code, and it contains the policy decision about how much total + main memory to use. + This file is system-dependent in the sense that some of its functions + are unnecessary in some systems. For example, if there is enough virtual + memory so that backing storage will never be used, much of the virtual + array control logic could be removed. (Of course, if you have that much + memory then you shouldn't care about a little bit of unused code...) } + +{ Original : jmemmgr.c ; Copyright (C) 1991-1997, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjdeferr, + imjerror, + imjpeglib, + imjutils, +{$IFDEF VER70} +{$ifndef NO_GETENV} + Dos, { DOS unit should declare getenv() } + { function GetEnv(name : string) : string; } +{$endif} + imjmemdos; { import the system-dependent declarations } +{$ELSE} + imjmemnobs; + {$DEFINE NO_GETENV} +{$ENDIF} + +{ Memory manager initialization. + When this is called, only the error manager pointer is valid in cinfo! } + +{GLOBAL} +procedure jinit_memory_mgr (cinfo : j_common_ptr); + +implementation + + +{ Some important notes: + The allocation routines provided here must never return NIL. + They should exit to error_exit if unsuccessful. + + It's not a good idea to try to merge the sarray and barray routines, + even though they are textually almost the same, because samples are + usually stored as bytes while coefficients are shorts or ints. Thus, + in machines where byte pointers have a different representation from + word pointers, the resulting machine code could not be the same. } + + +{ Many machines require storage alignment: longs must start on 4-byte + boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() + always returns pointers that are multiples of the worst-case alignment + requirement, and we had better do so too. + There isn't any really portable way to determine the worst-case alignment + requirement. This module assumes that the alignment requirement is + multiples of sizeof(ALIGN_TYPE). + By default, we define ALIGN_TYPE as double. This is necessary on some + workstations (where doubles really do need 8-byte alignment) and will work + fine on nearly everything. If your machine has lesser alignment needs, + you can save a few bytes by making ALIGN_TYPE smaller. + The only place I know of where this will NOT work is certain Macintosh + 680x0 compilers that define double as a 10-byte IEEE extended float. + Doing 10-byte alignment is counterproductive because longwords won't be + aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have + such a compiler. } + +{$ifndef ALIGN_TYPE} { so can override from jconfig.h } +type + ALIGN_TYPE = double; +{$endif} + + +{ We allocate objects from "pools", where each pool is gotten with a single + request to jpeg_get_small() or jpeg_get_large(). There is no per-object + overhead within a pool, except for alignment padding. Each pool has a + header with a link to the next pool of the same class. + Small and large pool headers are identical except that the latter's + link pointer must be FAR on 80x86 machines. + Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE + field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple + of the alignment requirement of ALIGN_TYPE. } + +type + small_pool_ptr = ^small_pool_hdr; + small_pool_hdr = record + case byte of + 0:(hdr : record + next : small_pool_ptr; { next in list of pools } + bytes_used : size_t; { how many bytes already used within pool } + bytes_left : size_t; { bytes still available in this pool } + end); + 1:(dummy : ALIGN_TYPE); { included in union to ensure alignment } + end; {small_pool_hdr;} + +type + large_pool_ptr = ^large_pool_hdr; {FAR} + large_pool_hdr = record + case byte of + 0:(hdr : record + next : large_pool_ptr; { next in list of pools } + bytes_used : size_t; { how many bytes already used within pool } + bytes_left : size_t; { bytes still available in this pool } + end); + 1:(dummy : ALIGN_TYPE); { included in union to ensure alignment } + end; {large_pool_hdr;} + + +{ Here is the full definition of a memory manager object. } + +type + my_mem_ptr = ^my_memory_mgr; + my_memory_mgr = record + pub : jpeg_memory_mgr; { public fields } + + { Each pool identifier (lifetime class) names a linked list of pools. } + small_list : array[0..JPOOL_NUMPOOLS-1] of small_pool_ptr ; + large_list : array[0..JPOOL_NUMPOOLS-1] of large_pool_ptr ; + + { Since we only have one lifetime class of virtual arrays, only one + linked list is necessary (for each datatype). Note that the virtual + array control blocks being linked together are actually stored somewhere + in the small-pool list. } + + virt_sarray_list : jvirt_sarray_ptr; + virt_barray_list : jvirt_barray_ptr; + + { This counts total space obtained from jpeg_get_small/large } + total_space_allocated : long; + + { alloc_sarray and alloc_barray set this value for use by virtual + array routines. } + + last_rowsperchunk : JDIMENSION; { from most recent alloc_sarray/barray } + end; {my_memory_mgr;} + + {$ifndef AM_MEMORY_MANAGER} { only jmemmgr.c defines these } + +{ The control blocks for virtual arrays. + Note that these blocks are allocated in the "small" pool area. + System-dependent info for the associated backing store (if any) is hidden + inside the backing_store_info struct. } +type + jvirt_sarray_control = record + mem_buffer : JSAMPARRAY; { => the in-memory buffer } + rows_in_array : JDIMENSION; { total virtual array height } + samplesperrow : JDIMENSION; { width of array (and of memory buffer) } + maxaccess : JDIMENSION; { max rows accessed by access_virt_sarray } + rows_in_mem : JDIMENSION; { height of memory buffer } + rowsperchunk : JDIMENSION; { allocation chunk size in mem_buffer } + cur_start_row : JDIMENSION; { first logical row # in the buffer } + first_undef_row : JDIMENSION; { row # of first uninitialized row } + pre_zero : boolean; { pre-zero mode requested? } + dirty : boolean; { do current buffer contents need written? } + b_s_open : boolean; { is backing-store data valid? } + next : jvirt_sarray_ptr; { link to next virtual sarray control block } + b_s_info : backing_store_info; { System-dependent control info } + end; + + jvirt_barray_control = record + mem_buffer : JBLOCKARRAY; { => the in-memory buffer } + rows_in_array : JDIMENSION; { total virtual array height } + blocksperrow : JDIMENSION; { width of array (and of memory buffer) } + maxaccess : JDIMENSION; { max rows accessed by access_virt_barray } + rows_in_mem : JDIMENSION; { height of memory buffer } + rowsperchunk : JDIMENSION; { allocation chunk size in mem_buffer } + cur_start_row : JDIMENSION; { first logical row # in the buffer } + first_undef_row : JDIMENSION; { row # of first uninitialized row } + pre_zero : boolean; { pre-zero mode requested? } + dirty : boolean; { do current buffer contents need written? } + b_s_open : boolean; { is backing-store data valid? } + next : jvirt_barray_ptr; { link to next virtual barray control block } + b_s_info : backing_store_info; { System-dependent control info } + end; + {$endif} { AM_MEMORY_MANAGER} + +{$ifdef MEM_STATS} { optional extra stuff for statistics } + +{LOCAL} +procedure print_mem_stats (cinfo : j_common_ptr; pool_id : int); +var + mem : my_mem_ptr; + shdr_ptr : small_pool_ptr; + lhdr_ptr : large_pool_ptr; +begin + mem := my_mem_ptr (cinfo^.mem); + + { Since this is only a debugging stub, we can cheat a little by using + fprintf directly rather than going through the trace message code. + This is helpful because message parm array can't handle longs. } + + WriteLn(output, 'Freeing pool ', pool_id,', total space := ', + mem^.total_space_allocated); + + lhdr_ptr := mem^.large_list[pool_id]; + while (lhdr_ptr <> NIL) do + begin + WriteLn(output, ' Large chunk used ', + long (lhdr_ptr^.hdr.bytes_used)); + lhdr_ptr := lhdr_ptr^.hdr.next; + end; + + shdr_ptr := mem^.small_list[pool_id]; + + while (shdr_ptr <> NIL) do + begin + WriteLn(output, ' Small chunk used ', + long (shdr_ptr^.hdr.bytes_used), ' free ', + long (shdr_ptr^.hdr.bytes_left) ); + shdr_ptr := shdr_ptr^.hdr.next; + end; +end; + +{$endif} { MEM_STATS } + + +{LOCAL} +procedure out_of_memory (cinfo : j_common_ptr; which : int); +{ Report an out-of-memory error and stop execution } +{ If we compiled MEM_STATS support, report alloc requests before dying } +begin +{$ifdef MEM_STATS} + cinfo^.err^.trace_level := 2; { force self_destruct to report stats } +{$endif} + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); +end; + + +{ Allocation of "small" objects. + + For these, we use pooled storage. When a new pool must be created, + we try to get enough space for the current request plus a "slop" factor, + where the slop will be the amount of leftover space in the new pool. + The speed vs. space tradeoff is largely determined by the slop values. + A different slop value is provided for each pool class (lifetime), + and we also distinguish the first pool of a class from later ones. + NOTE: the values given work fairly well on both 16- and 32-bit-int + machines, but may be too small if longs are 64 bits or more. } + +const + first_pool_slop : array[0..JPOOL_NUMPOOLS-1] of size_t = + (1600, { first PERMANENT pool } + 16000); { first IMAGE pool } + +const + extra_pool_slop : array[0..JPOOL_NUMPOOLS-1] of size_t = + (0, { additional PERMANENT pools } + 5000); { additional IMAGE pools } + +const + MIN_SLOP = 50; { greater than 0 to avoid futile looping } + + +{METHODDEF} +function alloc_small (cinfo : j_common_ptr; + pool_id : int; + sizeofobject : size_t) : pointer; +type + byteptr = ^byte; +{ Allocate a "small" object } +var + mem : my_mem_ptr; + hdr_ptr, prev_hdr_ptr : small_pool_ptr; + data_ptr : byteptr; + odd_bytes, min_request, slop : size_t; +begin + mem := my_mem_ptr (cinfo^.mem); + + { Check for unsatisfiable request (do now to ensure no overflow below) } + if (sizeofobject > size_t(MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) then + out_of_memory(cinfo, 1); { request exceeds malloc's ability } + + { Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) } + odd_bytes := sizeofobject mod SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) then + Inc(sizeofobject, SIZEOF(ALIGN_TYPE) - odd_bytes); + + { See if space is available in any existing pool } + if (pool_id < 0) or (pool_id >= JPOOL_NUMPOOLS) then + ERREXIT1(j_common_ptr(cinfo), JERR_BAD_POOL_ID, pool_id); { safety check } + prev_hdr_ptr := NIL; + hdr_ptr := mem^.small_list[pool_id]; + while (hdr_ptr <> NIL) do + begin + if (hdr_ptr^.hdr.bytes_left >= sizeofobject) then + break; { found pool with enough space } + prev_hdr_ptr := hdr_ptr; + hdr_ptr := hdr_ptr^.hdr.next; + end; + + { Time to make a new pool? } + if (hdr_ptr = NIL) then + begin + { min_request is what we need now, slop is what will be leftover } + min_request := sizeofobject + SIZEOF(small_pool_hdr); + if (prev_hdr_ptr = NIL) then { first pool in class? } + slop := first_pool_slop[pool_id] + else + slop := extra_pool_slop[pool_id]; + { Don't ask for more than MAX_ALLOC_CHUNK } + if (slop > size_t (MAX_ALLOC_CHUNK-min_request)) then + slop := size_t (MAX_ALLOC_CHUNK-min_request); + { Try to get space, if fail reduce slop and try again } + while TRUE do + begin + hdr_ptr := small_pool_ptr(jpeg_get_small(cinfo, min_request + slop)); + if (hdr_ptr <> NIL) then + break; + slop := slop div 2; + if (slop < MIN_SLOP) then { give up when it gets real small } + out_of_memory(cinfo, 2); { jpeg_get_small failed } + end; + Inc(mem^.total_space_allocated, min_request + slop); + { Success, initialize the new pool header and add to end of list } + hdr_ptr^.hdr.next := NIL; + hdr_ptr^.hdr.bytes_used := 0; + hdr_ptr^.hdr.bytes_left := sizeofobject + slop; + if (prev_hdr_ptr = NIL) then { first pool in class? } + mem^.small_list[pool_id] := hdr_ptr + else + prev_hdr_ptr^.hdr.next := hdr_ptr; + end; + + { OK, allocate the object from the current pool } + data_ptr := byteptr (hdr_ptr); + Inc(small_pool_ptr(data_ptr)); { point to first data byte in pool } + Inc(data_ptr, hdr_ptr^.hdr.bytes_used); { point to place for object } + Inc(hdr_ptr^.hdr.bytes_used, sizeofobject); + Dec(hdr_ptr^.hdr.bytes_left, sizeofobject); + + alloc_small := pointer(data_ptr); +end; + + +{ Allocation of "large" objects. + + The external semantics of these are the same as "small" objects, + except that FAR pointers are used on 80x86. However the pool + management heuristics are quite different. We assume that each + request is large enough that it may as well be passed directly to + jpeg_get_large; the pool management just links everything together + so that we can free it all on demand. + Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY + structures. The routines that create these structures (see below) + deliberately bunch rows together to ensure a large request size. } + +{METHODDEF} +function alloc_large (cinfo : j_common_ptr; + pool_id : int; + sizeofobject : size_t) : pointer; +{ Allocate a "large" object } +var + mem : my_mem_ptr; + hdr_ptr : large_pool_ptr; + odd_bytes : size_t; +var + dest_ptr : large_pool_ptr; +begin + mem := my_mem_ptr (cinfo^.mem); + + { Check for unsatisfiable request (do now to ensure no overflow below) } + if (sizeofobject > size_t (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) then + out_of_memory(cinfo, 3); { request exceeds malloc's ability } + + { Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) } + odd_bytes := sizeofobject mod SIZEOF(ALIGN_TYPE); + if (odd_bytes > 0) then + Inc(sizeofobject, SIZEOF(ALIGN_TYPE) - odd_bytes); + + { Always make a new pool } + if (pool_id < 0) or (pool_id >= JPOOL_NUMPOOLS) then + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); { safety check } + + hdr_ptr := large_pool_ptr (jpeg_get_large(cinfo, sizeofobject + + SIZEOF(large_pool_hdr))); + if (hdr_ptr = NIL) then + out_of_memory(cinfo, 4); { jpeg_get_large failed } + Inc(mem^.total_space_allocated, sizeofobject + SIZEOF(large_pool_hdr)); + + { Success, initialize the new pool header and add to list } + hdr_ptr^.hdr.next := mem^.large_list[pool_id]; + { We maintain space counts in each pool header for statistical purposes, + even though they are not needed for allocation. } + + hdr_ptr^.hdr.bytes_used := sizeofobject; + hdr_ptr^.hdr.bytes_left := 0; + mem^.large_list[pool_id] := hdr_ptr; + + {alloc_large := pointerFAR (hdr_ptr + 1); - point to first data byte in pool } + dest_ptr := hdr_ptr; + Inc(large_pool_ptr(dest_ptr)); + alloc_large := dest_ptr; +end; + + +{ Creation of 2-D sample arrays. + The pointers are in near heap, the samples themselves in FAR heap. + + To minimize allocation overhead and to allow I/O of large contiguous + blocks, we allocate the sample rows in groups of as many rows as possible + without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. + NB: the virtual array control routines, later in this file, know about + this chunking of rows. The rowsperchunk value is left in the mem manager + object so that it can be saved away if this sarray is the workspace for + a virtual array. } + +{METHODDEF} +function alloc_sarray (cinfo : j_common_ptr; + pool_id : int; + samplesperrow : JDIMENSION; + numrows : JDIMENSION) : JSAMPARRAY; +{ Allocate a 2-D sample array } +var + mem : my_mem_ptr; + the_result : JSAMPARRAY; + workspace : JSAMPROW; + rowsperchunk, currow, i : JDIMENSION; + ltemp : long; +begin + mem := my_mem_ptr(cinfo^.mem); + + { Calculate max # of rows allowed in one allocation chunk } + ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div + (long(samplesperrow) * SIZEOF(JSAMPLE)); + if (ltemp <= 0) then + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < long(numrows)) then + rowsperchunk := JDIMENSION (ltemp) + else + rowsperchunk := numrows; + mem^.last_rowsperchunk := rowsperchunk; + + { Get space for row pointers (small object) } + the_result := JSAMPARRAY (alloc_small(cinfo, pool_id, + size_t (numrows * SIZEOF(JSAMPROW)))); + + { Get the rows themselves (large objects) } + currow := 0; + while (currow < numrows) do + begin + {rowsperchunk := MIN(rowsperchunk, numrows - currow);} + if rowsperchunk > numrows - currow then + rowsperchunk := numrows - currow; + + workspace := JSAMPROW (alloc_large(cinfo, pool_id, + size_t (size_t(rowsperchunk) * size_t(samplesperrow) + * SIZEOF(JSAMPLE))) ); + for i := pred(rowsperchunk) downto 0 do + begin + the_result^[currow] := workspace; + Inc(currow); + Inc(JSAMPLE_PTR(workspace), samplesperrow); + end; + end; + + alloc_sarray := the_result; +end; + + +{ Creation of 2-D coefficient-block arrays. + This is essentially the same as the code for sample arrays, above. } + +{METHODDEF} +function alloc_barray (cinfo : j_common_ptr; + pool_id : int; + blocksperrow : JDIMENSION; + numrows : JDIMENSION) : JBLOCKARRAY; +{ Allocate a 2-D coefficient-block array } +var + mem : my_mem_ptr; + the_result : JBLOCKARRAY; + workspace : JBLOCKROW; + rowsperchunk, currow, i : JDIMENSION; + ltemp : long; +begin + mem := my_mem_ptr(cinfo^.mem); + + { Calculate max # of rows allowed in one allocation chunk } + ltemp := (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) div + (long(blocksperrow) * SIZEOF(JBLOCK)); + + if (ltemp <= 0) then + ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); + if (ltemp < long(numrows)) then + rowsperchunk := JDIMENSION (ltemp) + else + rowsperchunk := numrows; + mem^.last_rowsperchunk := rowsperchunk; + + { Get space for row pointers (small object) } + the_result := JBLOCKARRAY (alloc_small(cinfo, pool_id, + size_t (numrows * SIZEOF(JBLOCKROW))) ); + + { Get the rows themselves (large objects) } + currow := 0; + while (currow < numrows) do + begin + {rowsperchunk := MIN(rowsperchunk, numrows - currow);} + if rowsperchunk > numrows - currow then + rowsperchunk := numrows - currow; + + workspace := JBLOCKROW (alloc_large(cinfo, pool_id, + size_t (size_t(rowsperchunk) * size_t(blocksperrow) + * SIZEOF(JBLOCK))) ); + for i := rowsperchunk downto 1 do + begin + the_result^[currow] := workspace; + Inc(currow); + Inc(JBLOCK_PTR(workspace), blocksperrow); + end; + end; + + alloc_barray := the_result; +end; + + +{ About virtual array management: + + The above "normal" array routines are only used to allocate strip buffers + (as wide as the image, but just a few rows high). Full-image-sized buffers + are handled as "virtual" arrays. The array is still accessed a strip at a + time, but the memory manager must save the whole array for repeated + accesses. The intended implementation is that there is a strip buffer in + memory (as high as is possible given the desired memory limit), plus a + backing file that holds the rest of the array. + + The request_virt_array routines are told the total size of the image and + the maximum number of rows that will be accessed at once. The in-memory + buffer must be at least as large as the maxaccess value. + + The request routines create control blocks but not the in-memory buffers. + That is postponed until realize_virt_arrays is called. At that time the + total amount of space needed is known (approximately, anyway), so free + memory can be divided up fairly. + + The access_virt_array routines are responsible for making a specific strip + area accessible (after reading or writing the backing file, if necessary). + Note that the access routines are told whether the caller intends to modify + the accessed strip; during a read-only pass this saves having to rewrite + data to disk. The access routines are also responsible for pre-zeroing + any newly accessed rows, if pre-zeroing was requested. + + In current usage, the access requests are usually for nonoverlapping + strips; that is, successive access start_row numbers differ by exactly + num_rows := maxaccess. This means we can get good performance with simple + buffer dump/reload logic, by making the in-memory buffer be a multiple + of the access height; then there will never be accesses across bufferload + boundaries. The code will still work with overlapping access requests, + but it doesn't handle bufferload overlaps very efficiently. } + + +{METHODDEF} +function request_virt_sarray (cinfo : j_common_ptr; + pool_id : int; + pre_zero : boolean; + samplesperrow : JDIMENSION; + numrows : JDIMENSION; + maxaccess : JDIMENSION) : jvirt_sarray_ptr; +{ Request a virtual 2-D sample array } +var + mem : my_mem_ptr; + the_result : jvirt_sarray_ptr; +begin + mem := my_mem_ptr (cinfo^.mem); + + { Only IMAGE-lifetime virtual arrays are currently supported } + if (pool_id <> JPOOL_IMAGE) then + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); { safety check } + + { get control block } + the_result := jvirt_sarray_ptr (alloc_small(cinfo, pool_id, + SIZEOF(jvirt_sarray_control)) ); + + the_result^.mem_buffer := NIL; { marks array not yet realized } + the_result^.rows_in_array := numrows; + the_result^.samplesperrow := samplesperrow; + the_result^.maxaccess := maxaccess; + the_result^.pre_zero := pre_zero; + the_result^.b_s_open := FALSE; { no associated backing-store object } + the_result^.next := mem^.virt_sarray_list; { add to list of virtual arrays } + mem^.virt_sarray_list := the_result; + + request_virt_sarray := the_result; +end; + + +{METHODDEF} +function request_virt_barray (cinfo : j_common_ptr; + pool_id : int; + pre_zero : boolean; + blocksperrow : JDIMENSION; + numrows : JDIMENSION; + maxaccess : JDIMENSION) : jvirt_barray_ptr; +{ Request a virtual 2-D coefficient-block array } +var + mem : my_mem_ptr; + the_result : jvirt_barray_ptr; +begin + mem := my_mem_ptr(cinfo^.mem); + + { Only IMAGE-lifetime virtual arrays are currently supported } + if (pool_id <> JPOOL_IMAGE) then + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); { safety check } + + { get control block } + the_result := jvirt_barray_ptr(alloc_small(cinfo, pool_id, + SIZEOF(jvirt_barray_control)) ); + + the_result^.mem_buffer := NIL; { marks array not yet realized } + the_result^.rows_in_array := numrows; + the_result^.blocksperrow := blocksperrow; + the_result^.maxaccess := maxaccess; + the_result^.pre_zero := pre_zero; + the_result^.b_s_open := FALSE; { no associated backing-store object } + the_result^.next := mem^.virt_barray_list; { add to list of virtual arrays } + mem^.virt_barray_list := the_result; + + request_virt_barray := the_result; +end; + + +{METHODDEF} +procedure realize_virt_arrays (cinfo : j_common_ptr); +{ Allocate the in-memory buffers for any unrealized virtual arrays } +var + mem : my_mem_ptr; + space_per_minheight, maximum_space, avail_mem : long; + minheights, max_minheights : long; + sptr : jvirt_sarray_ptr; + bptr : jvirt_barray_ptr; +begin + mem := my_mem_ptr (cinfo^.mem); + { Compute the minimum space needed (maxaccess rows in each buffer) + and the maximum space needed (full image height in each buffer). + These may be of use to the system-dependent jpeg_mem_available routine. } + + space_per_minheight := 0; + maximum_space := 0; + sptr := mem^.virt_sarray_list; + while (sptr <> NIL) do + begin + if (sptr^.mem_buffer = NIL) then + begin { if not realized yet } + Inc(space_per_minheight, long(sptr^.maxaccess) * + long(sptr^.samplesperrow) * SIZEOF(JSAMPLE)); + Inc(maximum_space, long(sptr^.rows_in_array) * + long(sptr^.samplesperrow) * SIZEOF(JSAMPLE)); + end; + sptr := sptr^.next; + end; + bptr := mem^.virt_barray_list; + while (bptr <> NIL) do + begin + if (bptr^.mem_buffer = NIL) then + begin { if not realized yet } + Inc(space_per_minheight, long(bptr^.maxaccess) * + long(bptr^.blocksperrow) * SIZEOF(JBLOCK)); + Inc(maximum_space, long(bptr^.rows_in_array) * + long(bptr^.blocksperrow) * SIZEOF(JBLOCK)); + end; + bptr := bptr^.next; + end; + + if (space_per_minheight <= 0) then + exit; { no unrealized arrays, no work } + + { Determine amount of memory to actually use; this is system-dependent. } + avail_mem := jpeg_mem_available(cinfo, space_per_minheight, maximum_space, + mem^.total_space_allocated); + + { If the maximum space needed is available, make all the buffers full + height; otherwise parcel it out with the same number of minheights + in each buffer. } + + if (avail_mem >= maximum_space) then + max_minheights := long(1000000000) + else + begin + max_minheights := avail_mem div space_per_minheight; + { If there doesn't seem to be enough space, try to get the minimum + anyway. This allows a "stub" implementation of jpeg_mem_available(). } + if (max_minheights <= 0) then + max_minheights := 1; + end; + + { Allocate the in-memory buffers and initialize backing store as needed. } + + sptr := mem^.virt_sarray_list; + while (sptr <> NIL) do + begin + if (sptr^.mem_buffer = NIL) then + begin { if not realized yet } + minheights := (long(sptr^.rows_in_array) - long(1)) div LongInt(sptr^.maxaccess) + long(1); + if (minheights <= max_minheights) then + begin + { This buffer fits in memory } + sptr^.rows_in_mem := sptr^.rows_in_array; + end + else + begin + { It doesn't fit in memory, create backing store. } + sptr^.rows_in_mem := JDIMENSION(max_minheights) * sptr^.maxaccess; + jpeg_open_backing_store(cinfo, + @sptr^.b_s_info, + long(sptr^.rows_in_array) * + long(sptr^.samplesperrow) * + long(SIZEOF(JSAMPLE))); + sptr^.b_s_open := TRUE; + end; + sptr^.mem_buffer := alloc_sarray(cinfo, JPOOL_IMAGE, + sptr^.samplesperrow, sptr^.rows_in_mem); + sptr^.rowsperchunk := mem^.last_rowsperchunk; + sptr^.cur_start_row := 0; + sptr^.first_undef_row := 0; + sptr^.dirty := FALSE; + end; + sptr := sptr^.next; + end; + + bptr := mem^.virt_barray_list; + while (bptr <> NIL) do + begin + if (bptr^.mem_buffer = NIL) then + begin { if not realized yet } + minheights := (long(bptr^.rows_in_array) - long(1)) div LongInt(bptr^.maxaccess) + long(1); + if (minheights <= max_minheights) then + begin + { This buffer fits in memory } + bptr^.rows_in_mem := bptr^.rows_in_array; + end + else + begin + { It doesn't fit in memory, create backing store. } + bptr^.rows_in_mem := JDIMENSION (max_minheights) * bptr^.maxaccess; + jpeg_open_backing_store(cinfo, + @bptr^.b_s_info, + long(bptr^.rows_in_array) * + long(bptr^.blocksperrow) * + long(SIZEOF(JBLOCK))); + bptr^.b_s_open := TRUE; + end; + bptr^.mem_buffer := alloc_barray(cinfo, JPOOL_IMAGE, + bptr^.blocksperrow, bptr^.rows_in_mem); + bptr^.rowsperchunk := mem^.last_rowsperchunk; + bptr^.cur_start_row := 0; + bptr^.first_undef_row := 0; + bptr^.dirty := FALSE; + end; + bptr := bptr^.next; + end; +end; + + +{LOCAL} +procedure do_sarray_io (cinfo : j_common_ptr; + ptr : jvirt_sarray_ptr; + writing : boolean); +{ Do backing store read or write of a virtual sample array } +var + bytesperrow, file_offset, byte_count, rows, thisrow, i : long; +begin + + bytesperrow := long(ptr^.samplesperrow * SIZEOF(JSAMPLE)); + file_offset := LongInt(ptr^.cur_start_row) * bytesperrow; + { Loop to read or write each allocation chunk in mem_buffer } + i := 0; + while i < long(ptr^.rows_in_mem) do + begin + + { One chunk, but check for short chunk at end of buffer } + {rows := MIN(long(ptr^.rowsperchunk), long(ptr^.rows_in_mem - i));} + rows := long(ptr^.rowsperchunk); + if rows > long(ptr^.rows_in_mem) - i then + rows := long(ptr^.rows_in_mem) - i; + { Transfer no more than is currently defined } + thisrow := long (ptr^.cur_start_row) + i; + {rows := MIN(rows, long(ptr^.first_undef_row) - thisrow);} + if (rows > long(ptr^.first_undef_row) - thisrow) then + rows := long(ptr^.first_undef_row) - thisrow; + { Transfer no more than fits in file } + {rows := MIN(rows, long(ptr^.rows_in_array) - thisrow);} + if (rows > long(ptr^.rows_in_array) - thisrow) then + rows := long(ptr^.rows_in_array) - thisrow; + + if (rows <= 0) then { this chunk might be past end of file! } + break; + byte_count := rows * bytesperrow; + if (writing) then + ptr^.b_s_info.write_backing_store (cinfo, + @ptr^.b_s_info, + pointer {FAR} (ptr^.mem_buffer^[i]), + file_offset, byte_count) + else + ptr^.b_s_info.read_backing_store (cinfo, + @ptr^.b_s_info, + pointer {FAR} (ptr^.mem_buffer^[i]), + file_offset, byte_count); + Inc(file_offset, byte_count); + Inc(i, ptr^.rowsperchunk); + end; +end; + + +{LOCAL} +procedure do_barray_io (cinfo : j_common_ptr; + ptr : jvirt_barray_ptr; + writing : boolean); +{ Do backing store read or write of a virtual coefficient-block array } +var + bytesperrow, file_offset, byte_count, rows, thisrow, i : long; +begin + bytesperrow := long (ptr^.blocksperrow) * SIZEOF(JBLOCK); + file_offset := LongInt(ptr^.cur_start_row) * bytesperrow; + { Loop to read or write each allocation chunk in mem_buffer } + i := 0; + while (i < long(ptr^.rows_in_mem)) do + begin + { One chunk, but check for short chunk at end of buffer } + {rows := MIN(long(ptr^.rowsperchunk), long(ptr^.rows_in_mem - i));} + rows := long(ptr^.rowsperchunk); + if rows > long(ptr^.rows_in_mem) - i then + rows := long(ptr^.rows_in_mem) - i; + { Transfer no more than is currently defined } + thisrow := long (ptr^.cur_start_row) + i; + {rows := MIN(rows, long(ptr^.first_undef_row - thisrow));} + if rows > long(ptr^.first_undef_row) - thisrow then + rows := long(ptr^.first_undef_row) - thisrow; + { Transfer no more than fits in file } + {rows := MIN(rows, long (ptr^.rows_in_array - thisrow));} + if (rows > long (ptr^.rows_in_array) - thisrow) then + rows := long (ptr^.rows_in_array) - thisrow; + + if (rows <= 0) then { this chunk might be past end of file! } + break; + byte_count := rows * bytesperrow; + if (writing) then + ptr^.b_s_info.write_backing_store (cinfo, + @ptr^.b_s_info, + {FAR} pointer(ptr^.mem_buffer^[i]), + file_offset, byte_count) + else + ptr^.b_s_info.read_backing_store (cinfo, + @ptr^.b_s_info, + {FAR} pointer(ptr^.mem_buffer^[i]), + file_offset, byte_count); + Inc(file_offset, byte_count); + Inc(i, ptr^.rowsperchunk); + end; +end; + + +{METHODDEF} +function access_virt_sarray (cinfo : j_common_ptr; + ptr : jvirt_sarray_ptr; + start_row : JDIMENSION; + num_rows : JDIMENSION; + writable : boolean ) : JSAMPARRAY; +{ Access the part of a virtual sample array starting at start_row } +{ and extending for num_rows rows. writable is true if } +{ caller intends to modify the accessed area. } +var + end_row : JDIMENSION; + undef_row : JDIMENSION; +var + bytesperrow : size_t; +var + ltemp : long; +begin + end_row := start_row + num_rows; + { debugging check } + if (end_row > ptr^.rows_in_array) or (num_rows > ptr^.maxaccess) or + (ptr^.mem_buffer = NIL) then + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + { Make the desired part of the virtual array accessible } + if (start_row < ptr^.cur_start_row) or + (end_row > ptr^.cur_start_row+ptr^.rows_in_mem) then + begin + if (not ptr^.b_s_open) then + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + { Flush old buffer contents if necessary } + if (ptr^.dirty) then + begin + do_sarray_io(cinfo, ptr, TRUE); + ptr^.dirty := FALSE; + end; + { Decide what part of virtual array to access. + Algorithm: if target address > current window, assume forward scan, + load starting at target address. If target address < current window, + assume backward scan, load so that target area is top of window. + Note that when switching from forward write to forward read, will have + start_row := 0, so the limiting case applies and we load from 0 anyway. } + if (start_row > ptr^.cur_start_row) then + begin + ptr^.cur_start_row := start_row; + end + else + begin + { use long arithmetic here to avoid overflow & unsigned problems } + + + ltemp := long(end_row) - long(ptr^.rows_in_mem); + if (ltemp < 0) then + ltemp := 0; { don't fall off front end of file } + ptr^.cur_start_row := JDIMENSION(ltemp); + end; + { Read in the selected part of the array. + During the initial write pass, we will do no actual read + because the selected part is all undefined. } + + do_sarray_io(cinfo, ptr, FALSE); + end; + { Ensure the accessed part of the array is defined; prezero if needed. + To improve locality of access, we only prezero the part of the array + that the caller is about to access, not the entire in-memory array. } + if (ptr^.first_undef_row < end_row) then + begin + if (ptr^.first_undef_row < start_row) then + begin + if (writable) then { writer skipped over a section of array } + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row := start_row; { but reader is allowed to read ahead } + end + else + begin + undef_row := ptr^.first_undef_row; + end; + if (writable) then + ptr^.first_undef_row := end_row; + if (ptr^.pre_zero) then + begin + bytesperrow := size_t(ptr^.samplesperrow) * SIZEOF(JSAMPLE); + Dec(undef_row, ptr^.cur_start_row); { make indexes relative to buffer } + Dec(end_row, ptr^.cur_start_row); + while (undef_row < end_row) do + begin + jzero_far({FAR} pointer(ptr^.mem_buffer^[undef_row]), bytesperrow); + Inc(undef_row); + end; + end + else + begin + if (not writable) then { reader looking at undefined data } + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + end; + end; + { Flag the buffer dirty if caller will write in it } + if (writable) then + ptr^.dirty := TRUE; + { Return address of proper part of the buffer } + access_virt_sarray := JSAMPARRAY(@ ptr^.mem_buffer^[start_row - ptr^.cur_start_row]); +end; + + +{METHODDEF} +function access_virt_barray (cinfo : j_common_ptr; + ptr : jvirt_barray_ptr; + start_row : JDIMENSION; + num_rows : JDIMENSION; + writable : boolean) : JBLOCKARRAY; +{ Access the part of a virtual block array starting at start_row } +{ and extending for num_rows rows. writable is true if } +{ caller intends to modify the accessed area. } +var + end_row : JDIMENSION; + undef_row : JDIMENSION; + ltemp : long; +var + bytesperrow : size_t; +begin + end_row := start_row + num_rows; + + { debugging check } + if (end_row > ptr^.rows_in_array) or (num_rows > ptr^.maxaccess) or + (ptr^.mem_buffer = NIL) then + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + + { Make the desired part of the virtual array accessible } + if (start_row < ptr^.cur_start_row) or + (end_row > ptr^.cur_start_row+ptr^.rows_in_mem) then + begin + if (not ptr^.b_s_open) then + ERREXIT(cinfo, JERR_VIRTUAL_BUG); + { Flush old buffer contents if necessary } + if (ptr^.dirty) then + begin + do_barray_io(cinfo, ptr, TRUE); + ptr^.dirty := FALSE; + end; + { Decide what part of virtual array to access. + Algorithm: if target address > current window, assume forward scan, + load starting at target address. If target address < current window, + assume backward scan, load so that target area is top of window. + Note that when switching from forward write to forward read, will have + start_row := 0, so the limiting case applies and we load from 0 anyway. } + + if (start_row > ptr^.cur_start_row) then + begin + ptr^.cur_start_row := start_row; + end + else + begin + { use long arithmetic here to avoid overflow & unsigned problems } + + ltemp := long(end_row) - long(ptr^.rows_in_mem); + if (ltemp < 0) then + ltemp := 0; { don't fall off front end of file } + ptr^.cur_start_row := JDIMENSION (ltemp); + end; + { Read in the selected part of the array. + During the initial write pass, we will do no actual read + because the selected part is all undefined. } + + do_barray_io(cinfo, ptr, FALSE); + end; + { Ensure the accessed part of the array is defined; prezero if needed. + To improve locality of access, we only prezero the part of the array + that the caller is about to access, not the entire in-memory array. } + + if (ptr^.first_undef_row < end_row) then + begin + if (ptr^.first_undef_row < start_row) then + begin + if (writable) then { writer skipped over a section of array } + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + undef_row := start_row; { but reader is allowed to read ahead } + end + else + begin + undef_row := ptr^.first_undef_row; + end; + if (writable) then + ptr^.first_undef_row := end_row; + if (ptr^.pre_zero) then + begin + bytesperrow := size_t (ptr^.blocksperrow) * SIZEOF(JBLOCK); + Dec(undef_row, ptr^.cur_start_row); { make indexes relative to buffer } + Dec(end_row, ptr^.cur_start_row); + while (undef_row < end_row) do + begin + jzero_far({FAR}pointer(ptr^.mem_buffer^[undef_row]), bytesperrow); + Inc(undef_row); + end; + end + else + begin + if (not writable) then { reader looking at undefined data } + ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); + end; + end; + { Flag the buffer dirty if caller will write in it } + if (writable) then + ptr^.dirty := TRUE; + { Return address of proper part of the buffer } + access_virt_barray := JBLOCKARRAY(@ ptr^.mem_buffer^[start_row - ptr^.cur_start_row]); +end; + + +{ Release all objects belonging to a specified pool. } + +{METHODDEF} +procedure free_pool (cinfo : j_common_ptr; pool_id : int); +var + mem : my_mem_ptr; + shdr_ptr : small_pool_ptr; + lhdr_ptr : large_pool_ptr; + space_freed : size_t; +var + sptr : jvirt_sarray_ptr; + bptr : jvirt_barray_ptr; +var + next_lhdr_ptr : large_pool_ptr; + next_shdr_ptr : small_pool_ptr; +begin + mem := my_mem_ptr(cinfo^.mem); + + if (pool_id < 0) or (pool_id >= JPOOL_NUMPOOLS) then + ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); { safety check } + +{$ifdef MEM_STATS} + if (cinfo^.err^.trace_level > 1) then + print_mem_stats(cinfo, pool_id); { print pool's memory usage statistics } +{$endif} + + { If freeing IMAGE pool, close any virtual arrays first } + if (pool_id = JPOOL_IMAGE) then + begin + sptr := mem^.virt_sarray_list; + while (sptr <> NIL) do + begin + if (sptr^.b_s_open) then + begin { there may be no backing store } + sptr^.b_s_open := FALSE; { prevent recursive close if error } + sptr^.b_s_info.close_backing_store (cinfo, @sptr^.b_s_info); + end; + sptr := sptr^.next; + end; + mem^.virt_sarray_list := NIL; + bptr := mem^.virt_barray_list; + while (bptr <> NIL) do + begin + if (bptr^.b_s_open) then + begin { there may be no backing store } + bptr^.b_s_open := FALSE; { prevent recursive close if error } + bptr^.b_s_info.close_backing_store (cinfo, @bptr^.b_s_info); + end; + bptr := bptr^.next; + end; + mem^.virt_barray_list := NIL; + end; + + { Release large objects } + lhdr_ptr := mem^.large_list[pool_id]; + mem^.large_list[pool_id] := NIL; + + while (lhdr_ptr <> NIL) do + begin + next_lhdr_ptr := lhdr_ptr^.hdr.next; + space_freed := lhdr_ptr^.hdr.bytes_used + + lhdr_ptr^.hdr.bytes_left + + SIZEOF(large_pool_hdr); + jpeg_free_large(cinfo, {FAR} pointer(lhdr_ptr), space_freed); + Dec(mem^.total_space_allocated, space_freed); + lhdr_ptr := next_lhdr_ptr; + end; + + { Release small objects } + shdr_ptr := mem^.small_list[pool_id]; + mem^.small_list[pool_id] := NIL; + + while (shdr_ptr <> NIL) do + begin + next_shdr_ptr := shdr_ptr^.hdr.next; + space_freed := shdr_ptr^.hdr.bytes_used + + shdr_ptr^.hdr.bytes_left + + SIZEOF(small_pool_hdr); + jpeg_free_small(cinfo, pointer(shdr_ptr), space_freed); + Dec(mem^.total_space_allocated, space_freed); + shdr_ptr := next_shdr_ptr; + end; +end; + + +{ Close up shop entirely. + Note that this cannot be called unless cinfo^.mem is non-NIL. } + +{METHODDEF} +procedure self_destruct (cinfo : j_common_ptr); +var + pool : int; +begin + { Close all backing store, release all memory. + Releasing pools in reverse order might help avoid fragmentation + with some (brain-damaged) malloc libraries. } + + for pool := JPOOL_NUMPOOLS-1 downto JPOOL_PERMANENT do + begin + free_pool(cinfo, pool); + end; + + { Release the memory manager control block too. } + jpeg_free_small(cinfo, pointer(cinfo^.mem), SIZEOF(my_memory_mgr)); + cinfo^.mem := NIL; { ensures I will be called only once } + + jpeg_mem_term(cinfo); { system-dependent cleanup } +end; + + +{ Memory manager initialization. + When this is called, only the error manager pointer is valid in cinfo! } + +{GLOBAL} +procedure jinit_memory_mgr (cinfo : j_common_ptr); +var + mem : my_mem_ptr; + max_to_use : long; + pool : int; + test_mac : size_t; +{$ifndef NO_GETENV} +var + memenv : string; + code : integer; +{$endif} +begin + cinfo^.mem := NIL; { for safety if init fails } + + { Check for configuration errors. + SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably + doesn't reflect any real hardware alignment requirement. + The test is a little tricky: for X>0, X and X-1 have no one-bits + in common if and only if X is a power of 2, ie has only one one-bit. + Some compilers may give an "unreachable code" warning here; ignore it. } + if ((SIZEOF(ALIGN_TYPE) and (SIZEOF(ALIGN_TYPE)-1)) <> 0) then + ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE); + { MAX_ALLOC_CHUNK must be representable as type size_t, and must be + a multiple of SIZEOF(ALIGN_TYPE). + Again, an "unreachable code" warning may be ignored here. + But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK. } + + test_mac := size_t (MAX_ALLOC_CHUNK); + if (long (test_mac) <> MAX_ALLOC_CHUNK) or + ((MAX_ALLOC_CHUNK mod SIZEOF(ALIGN_TYPE)) <> 0) then + ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); + + max_to_use := jpeg_mem_init(cinfo); { system-dependent initialization } + + { Attempt to allocate memory manager's control block } + mem := my_mem_ptr (jpeg_get_small(cinfo, SIZEOF(my_memory_mgr))); + + if (mem = NIL) then + begin + jpeg_mem_term(cinfo); { system-dependent cleanup } + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); + end; + + { OK, fill in the method pointers } + mem^.pub.alloc_small := alloc_small; + mem^.pub.alloc_large := alloc_large; + mem^.pub.alloc_sarray := alloc_sarray; + mem^.pub.alloc_barray := alloc_barray; + mem^.pub.request_virt_sarray := request_virt_sarray; + mem^.pub.request_virt_barray := request_virt_barray; + mem^.pub.realize_virt_arrays := realize_virt_arrays; + mem^.pub.access_virt_sarray := access_virt_sarray; + mem^.pub.access_virt_barray := access_virt_barray; + mem^.pub.free_pool := free_pool; + mem^.pub.self_destruct := self_destruct; + + { Make MAX_ALLOC_CHUNK accessible to other modules } + mem^.pub.max_alloc_chunk := MAX_ALLOC_CHUNK; + + { Initialize working state } + mem^.pub.max_memory_to_use := max_to_use; + + for pool := JPOOL_NUMPOOLS-1 downto JPOOL_PERMANENT do + begin + mem^.small_list[pool] := NIL; + mem^.large_list[pool] := NIL; + end; + mem^.virt_sarray_list := NIL; + mem^.virt_barray_list := NIL; + + mem^.total_space_allocated := SIZEOF(my_memory_mgr); + + { Declare ourselves open for business } + cinfo^.mem := @mem^.pub; + + { Check for an environment variable JPEGMEM; if found, override the + default max_memory setting from jpeg_mem_init. Note that the + surrounding application may again override this value. + If your system doesn't support getenv(), define NO_GETENV to disable + this feature. } + +{$ifndef NO_GETENV} + memenv := getenv('JPEGMEM'); + if (memenv <> '') then + begin + Val(memenv, max_to_use, code); + if (Code = 0) then + begin + max_to_use := max_to_use * long(1000); + mem^.pub.max_memory_to_use := max_to_use * long(1000); + end; + end; +{$endif} + +end; + +end. diff --git a/src/lib/vampimg/JpegLib/imjmemnobs.pas b/src/lib/vampimg/JpegLib/imjmemnobs.pas new file mode 100644 index 0000000..750fd80 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjmemnobs.pas @@ -0,0 +1,259 @@ +unit imjmemnobs; +{ Delphi3 -- > jmemnobs from jmemwin } +{ This file provides an Win32-compatible implementation of the system- + dependent portion of the JPEG memory manager. } + +{ Check jmemnobs.c } +{ Copyright (C) 1996, Jacques Nomssi Nzali } + + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjdeferr, + imjerror, + imjpeglib; + +{ The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may + be requested in a single call to jpeg_get_large (and jpeg_get_small for that + matter, but that case should never come into play). This macro is needed + to model the 64Kb-segment-size limit of far addressing on 80x86 machines. + On those machines, we expect that jconfig.h will provide a proper value. + On machines with 32-bit flat address spaces, any large constant may be used. + + NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type + size_t and will be a multiple of sizeof(align_type). } + +const + MAX_ALLOC_CHUNK = long(1000000000); + +{GLOBAL} +procedure jpeg_open_backing_store (cinfo : j_common_ptr; + info : backing_store_ptr; + total_bytes_needed : long); + +{ These routines take care of any system-dependent initialization and + cleanup required. } + +{GLOBAL} +function jpeg_mem_init (cinfo : j_common_ptr) : long; + +{GLOBAL} +procedure jpeg_mem_term (cinfo : j_common_ptr); + +{ These two functions are used to allocate and release small chunks of + memory. (Typically the total amount requested through jpeg_get_small is + no more than 20K or so; this will be requested in chunks of a few K each.) + Behavior should be the same as for the standard library functions malloc + and free; in particular, jpeg_get_small must return NIL on failure. + On most systems, these ARE malloc and free. jpeg_free_small is passed the + size of the object being freed, just in case it's needed. + On an 80x86 machine using small-data memory model, these manage near heap. } + + +{ Near-memory allocation and freeing are controlled by the regular library + routines malloc() and free(). } + +{GLOBAL} +function jpeg_get_small (cinfo : j_common_ptr; + sizeofobject : size_t) : pointer; + +{GLOBAL} +{object is a reserved word in Borland Pascal } +procedure jpeg_free_small (cinfo : j_common_ptr; + an_object : pointer; + sizeofobject : size_t); + +{ These two functions are used to allocate and release large chunks of + memory (up to the total free space designated by jpeg_mem_available). + The interface is the same as above, except that on an 80x86 machine, + far pointers are used. On most other machines these are identical to + the jpeg_get/free_small routines; but we keep them separate anyway, + in case a different allocation strategy is desirable for large chunks. } + + +{ "Large" objects are allocated in far memory, if possible } + + +{GLOBAL} +function jpeg_get_large (cinfo : j_common_ptr; + sizeofobject : size_t) : voidp; {far} + +{GLOBAL} +procedure jpeg_free_large (cinfo : j_common_ptr; + {var?} an_object : voidp; {FAR} + sizeofobject : size_t); + +{ This routine computes the total memory space available for allocation. + It's impossible to do this in a portable way; our current solution is + to make the user tell us (with a default value set at compile time). + If you can actually get the available space, it's a good idea to subtract + a slop factor of 5% or so. } + +{GLOBAL} +function jpeg_mem_available (cinfo : j_common_ptr; + min_bytes_needed : long; + max_bytes_needed : long; + already_allocated : long) : long; + + +implementation + +{ This structure holds whatever state is needed to access a single + backing-store object. The read/write/close method pointers are called + by jmemmgr.c to manipulate the backing-store object; all other fields + are private to the system-dependent backing store routines. } + + + +{ These two functions are used to allocate and release small chunks of + memory. (Typically the total amount requested through jpeg_get_small is + no more than 20K or so; this will be requested in chunks of a few K each.) + Behavior should be the same as for the standard library functions malloc + and free; in particular, jpeg_get_small must return NIL on failure. + On most systems, these ARE malloc and free. jpeg_free_small is passed the + size of the object being freed, just in case it's needed. + On an 80x86 machine using small-data memory model, these manage near heap. } + + +{ Near-memory allocation and freeing are controlled by the regular library + routines malloc() and free(). } + +{GLOBAL} +function jpeg_get_small (cinfo : j_common_ptr; + sizeofobject : size_t) : pointer; +var + p : pointer; +begin + GetMem(p, sizeofobject); + jpeg_get_small := p; +end; + +{GLOBAL} +{object is a reserved word in Object Pascal } +procedure jpeg_free_small (cinfo : j_common_ptr; + an_object : pointer; + sizeofobject : size_t); +begin + FreeMem(an_object, sizeofobject); +end; + +{ These two functions are used to allocate and release large chunks of + memory (up to the total free space designated by jpeg_mem_available). + The interface is the same as above, except that on an 80x86 machine, + far pointers are used. On most other machines these are identical to + the jpeg_get/free_small routines; but we keep them separate anyway, + in case a different allocation strategy is desirable for large chunks. } + + + +{GLOBAL} +function jpeg_get_large (cinfo : j_common_ptr; + sizeofobject : size_t) : voidp; {far} +var + p : pointer; +begin + GetMem(p, sizeofobject); + jpeg_get_large := p; +end; + +{GLOBAL} +procedure jpeg_free_large (cinfo : j_common_ptr; + {var?} an_object : voidp; {FAR} + sizeofobject : size_t); +begin + Freemem(an_object, sizeofobject); +end; + +{ This routine computes the total space still available for allocation by + jpeg_get_large. If more space than this is needed, backing store will be + used. NOTE: any memory already allocated must not be counted. + + There is a minimum space requirement, corresponding to the minimum + feasible buffer sizes; jmemmgr.c will request that much space even if + jpeg_mem_available returns zero. The maximum space needed, enough to hold + all working storage in memory, is also passed in case it is useful. + Finally, the total space already allocated is passed. If no better + method is available, cinfo^.mem^.max_memory_to_use - already_allocated + is often a suitable calculation. + + It is OK for jpeg_mem_available to underestimate the space available + (that'll just lead to more backing-store access than is really necessary). + However, an overestimate will lead to failure. Hence it's wise to subtract + a slop factor from the true available space. 5% should be enough. + + On machines with lots of virtual memory, any large constant may be returned. + Conversely, zero may be returned to always use the minimum amount of memory.} + + + +{ This routine computes the total memory space available for allocation. + It's impossible to do this in a portable way; our current solution is + to make the user tell us (with a default value set at compile time). + If you can actually get the available space, it's a good idea to subtract + a slop factor of 5% or so. } + +const + DEFAULT_MAX_MEM = long(300000); { for total usage about 450K } + +{GLOBAL} +function jpeg_mem_available (cinfo : j_common_ptr; + min_bytes_needed : long; + max_bytes_needed : long; + already_allocated : long) : long; +begin + {jpeg_mem_available := cinfo^.mem^.max_memory_to_use - already_allocated;} + jpeg_mem_available := max_bytes_needed; +end; + + +{ Initial opening of a backing-store object. This must fill in the + read/write/close pointers in the object. The read/write routines + may take an error exit if the specified maximum file size is exceeded. + (If jpeg_mem_available always returns a large value, this routine can + just take an error exit.) } + + + +{ Initial opening of a backing-store object. } + +{GLOBAL} +procedure jpeg_open_backing_store (cinfo : j_common_ptr; + info : backing_store_ptr; + total_bytes_needed : long); +begin + ERREXIT(cinfo, JERR_NO_BACKING_STORE); +end; + +{ These routines take care of any system-dependent initialization and + cleanup required. jpeg_mem_init will be called before anything is + allocated (and, therefore, nothing in cinfo is of use except the error + manager pointer). It should return a suitable default value for + max_memory_to_use; this may subsequently be overridden by the surrounding + application. (Note that max_memory_to_use is only important if + jpeg_mem_available chooses to consult it ... no one else will.) + jpeg_mem_term may assume that all requested memory has been freed and that + all opened backing-store objects have been closed. } + + +{ These routines take care of any system-dependent initialization and + cleanup required. } + + +{GLOBAL} +function jpeg_mem_init (cinfo : j_common_ptr) : long; +begin + jpeg_mem_init := DEFAULT_MAX_MEM; { default for max_memory_to_use } +end; + +{GLOBAL} +procedure jpeg_mem_term (cinfo : j_common_ptr); +begin + +end; + + +end. diff --git a/src/lib/vampimg/JpegLib/imjmorecfg.pas b/src/lib/vampimg/JpegLib/imjmorecfg.pas new file mode 100644 index 0000000..fddf3f5 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjmorecfg.pas @@ -0,0 +1,219 @@ +unit imjmorecfg; + +{ This file contains additional configuration options that customize the + JPEG software for special applications or support machine-dependent + optimizations. Most users will not need to touch this file. } + +{ Source: jmorecfg.h; Copyright (C) 1991-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +type + int = Integer; + uInt = Cardinal; + short = SmallInt; + ushort = Word; + long = LongInt; + +type + voidp = pointer; + +type + int_ptr = ^int; + size_t = int; + +{ Define BITS_IN_JSAMPLE as either + 8 for 8-bit sample values (the usual setting) + 12 for 12-bit sample values + Only 8 and 12 are legal data precisions for lossy JPEG according to the + JPEG standard, and the IJG code does not support anything else! + We do not support run-time selection of data precision, sorry. } + + +{$ifdef BITS_IN_JSAMPLE_IS_8} { use 8 or 12 } +const + BITS_IN_JSAMPLE = 8; +{$else} +const + BITS_IN_JSAMPLE = 12; +{$endif} + + +{ Maximum number of components (color channels) allowed in JPEG image. + To meet the letter of the JPEG spec, set this to 255. However, darn + few applications need more than 4 channels (maybe 5 for CMYK + alpha + mask). We recommend 10 as a reasonable compromise; use 4 if you are + really short on memory. (Each allowed component costs a hundred or so + bytes of storage, whether actually used in an image or not.) } + + +const + MAX_COMPONENTS = 10; { maximum number of image components } + + +{ Basic data types. + You may need to change these if you have a machine with unusual data + type sizes; for example, "char" not 8 bits, "short" not 16 bits, + or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, + but it had better be at least 16. } + + +{ Representation of a single sample (pixel element value). + We frequently allocate large arrays of these, so it's important to keep + them small. But if you have memory to burn and access to char or short + arrays is very slow on your hardware, you might want to change these. } + + +{$ifdef BITS_IN_JSAMPLE_IS_8} +{ JSAMPLE should be the smallest type that will hold the values 0..255. + You can use a signed char by having GETJSAMPLE mask it with $FF. } + +{ CHAR_IS_UNSIGNED } +type + JSAMPLE = byte; { Pascal unsigned char } + GETJSAMPLE = int; + +const + MAXJSAMPLE = 255; + CENTERJSAMPLE = 128; + +{$endif} + +{$ifndef BITS_IN_JSAMPLE_IS_8} +{ JSAMPLE should be the smallest type that will hold the values 0..4095. + On nearly all machines "short" will do nicely. } + +type + JSAMPLE = short; + GETJSAMPLE = int; + +const + MAXJSAMPLE = 4095; + CENTERJSAMPLE = 2048; + +{$endif} { BITS_IN_JSAMPLE = 12 } + + +{ Representation of a DCT frequency coefficient. + This should be a signed value of at least 16 bits; "short" is usually OK. + Again, we allocate large arrays of these, but you can change to int + if you have memory to burn and "short" is really slow. } +type + JCOEF = int; + JCOEF_PTR = ^JCOEF; + + +{ Compressed datastreams are represented as arrays of JOCTET. + These must be EXACTLY 8 bits wide, at least once they are written to + external storage. Note that when using the stdio data source/destination + managers, this is also the data type passed to fread/fwrite. } + + +type + JOCTET = Byte; + jTOctet = 0..(MaxInt div SizeOf(JOCTET))-1; + JOCTET_FIELD = array[jTOctet] of JOCTET; + JOCTET_FIELD_PTR = ^JOCTET_FIELD; + JOCTETPTR = ^JOCTET; + + GETJOCTET = JOCTET; { A work around } + + +{ These typedefs are used for various table entries and so forth. + They must be at least as wide as specified; but making them too big + won't cost a huge amount of memory, so we don't provide special + extraction code like we did for JSAMPLE. (In other words, these + typedefs live at a different point on the speed/space tradeoff curve.) } + + +{ UINT8 must hold at least the values 0..255. } + +type + UINT8 = Byte; + +{ UINT16 must hold at least the values 0..65535. } + + UINT16 = Word; + +{ INT16 must hold at least the values -32768..32767. } + + INT16 = SmallInt; + +{ INT32 must hold at least signed 32-bit values. } + + INT32 = LongInt; +type + INT32PTR = ^INT32; + +{ Datatype used for image dimensions. The JPEG standard only supports + images up to 64K*64K due to 16-bit fields in SOF markers. Therefore + "unsigned int" is sufficient on all machines. However, if you need to + handle larger images and you don't mind deviating from the spec, you + can change this datatype. } + +type + JDIMENSION = uInt; + +const + JPEG_MAX_DIMENSION = 65500; { a tad under 64K to prevent overflows } + + +{ Ordering of RGB data in scanlines passed to or from the application. + If your application wants to deal with data in the order B,G,R, just + change these macros. You can also deal with formats such as R,G,B,X + (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing + the offsets will also change the order in which colormap data is organized. + RESTRICTIONS: + 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. + 2. These macros only affect RGB<=>YCbCr color conversion, so they are not + useful if you are using JPEG color spaces other than YCbCr or grayscale. + 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE + is not 3 (they don't understand about dummy color components!). So you + can't use color quantization if you change that value. } + +{$ifdef RGB_RED_IS_0} +const + RGB_RED = 0; { Offset of Red in an RGB scanline element } + RGB_GREEN = 1; { Offset of Green } + RGB_BLUE = 2; { Offset of Blue } +{$else} +const + RGB_RED = 2; { Offset of Red in an RGB scanline element } + RGB_GREEN = 1; { Offset of Green } + RGB_BLUE = 0; { Offset of Blue } +{$endif} + +{$ifdef RGB_PIXELSIZE_IS_3} +const + RGB_PIXELSIZE = 3; { JSAMPLEs per RGB scanline element } +{$else} +const + RGB_PIXELSIZE = ??; { Nomssi: deliberate syntax error. Set this value } +{$endif} + +{ Definitions for speed-related optimizations. } + +{ On some machines (notably 68000 series) "int" is 32 bits, but multiplying + two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER + as short on such a machine. MULTIPLIER must be at least 16 bits wide. } +type + MULTIPLIER = int; { type for fastest integer multiply } + + +{ FAST_FLOAT should be either float or double, whichever is done faster + by your compiler. (Note that this type is only used in the floating point + DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) + Typically, float is faster in ANSI C compilers, while double is faster in + pre-ANSI compilers (because they insist on converting to double anyway). + The code below therefore chooses float if we have ANSI-style prototypes. } + +type + FAST_FLOAT = double; {float} + + +implementation + + +end. diff --git a/src/lib/vampimg/JpegLib/imjpeglib.pas b/src/lib/vampimg/JpegLib/imjpeglib.pas new file mode 100644 index 0000000..dc35daa --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjpeglib.pas @@ -0,0 +1,1300 @@ +unit imjpeglib; + +{ This file defines the application interface for the JPEG library. + Most applications using the library need only include this file, + and perhaps jerror.h if they want to know the exact error codes. } + +{ Source:jpeglib.h+jpegint.h; Copyright (C) 1991-1998, Thomas G. Lane. } + + +interface + +{$I imjconfig.inc} + +{ First we include the configuration files that record how this + installation of the JPEG library is set up. jconfig.h can be + generated automatically for many systems. jmorecfg.h contains + manual configuration options that most people need not worry about. } + +uses + imjdeferr, + imjmorecfg; { seldom changed options } + +{ Version ID for the JPEG library. + Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". } + + +Const + JPEG_LIB_VERSION = 62; { Version 6b } + + +{ These marker codes are exported since applications and data source modules + are likely to want to use them. } + +const + JPEG_RST0 = $D0; { RST0 marker code } + JPEG_EOI = $D9; { EOI marker code } + JPEG_APP0 = $E0; { APP0 marker code } + JPEG_COM = $FE; { COM marker code } + + +{ Various constants determining the sizes of things. + All of these are specified by the JPEG standard, so don't change them + if you want to be compatible. } + +const + DCTSIZE = 8; { The basic DCT block is 8x8 samples } + DCTSIZE2 = 64; { DCTSIZE squared; # of elements in a block } + NUM_QUANT_TBLS = 4; { Quantization tables are numbered 0..3 } + NUM_HUFF_TBLS = 4; { Huffman tables are numbered 0..3 } + NUM_ARITH_TBLS = 16; { Arith-coding tables are numbered 0..15 } + MAX_COMPS_IN_SCAN = 4; { JPEG limit on # of components in one scan } + MAX_SAMP_FACTOR = 4; { JPEG limit on sampling factors } +{ Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + to handle it. We even let you do this from the jconfig.h file. However, + we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + sometimes emits noncompliant files doesn't mean you should too. } + C_MAX_BLOCKS_IN_MCU = 10; { compressor's limit on blocks per MCU } + D_MAX_BLOCKS_IN_MCU = 10; { decompressor's limit on blocks per MCU } + + +{ Data structures for images (arrays of samples and of DCT coefficients). + On 80x86 machines, the image arrays are too big for near pointers, + but the pointer arrays can fit in near memory. } + +type +{ for typecasting } + JSAMPLE_PTR = ^JSAMPLE; + JSAMPROW_PTR = ^JSAMPROW; + JBLOCKROW_PTR = ^JBLOCKROW; + + jTSample = 0..(MaxInt div SIZEOF(JSAMPLE))-1; + JSAMPLE_ARRAY = Array[jTSample] of JSAMPLE; {far} + JSAMPROW = ^JSAMPLE_ARRAY; { ptr to one image row of pixel samples. } + + jTRow = 0..(MaxInt div SIZEOF(JSAMPROW))-1; + JSAMPROW_ARRAY = Array[jTRow] of JSAMPROW; + JSAMPARRAY = ^JSAMPROW_ARRAY; { ptr to some rows (a 2-D sample array) } + + jTArray = 0..(MaxInt div SIZEOF(JSAMPARRAY))-1; + JSAMP_ARRAY = Array[jTArray] of JSAMPARRAY; + JSAMPIMAGE = ^JSAMP_ARRAY; { a 3-D sample array: top index is color } + + JBLOCK = Array[0..DCTSIZE2-1] of JCOEF; { one block of coefficients } + JBLOCK_PTR = ^JBLOCK; + + jTBlockRow = 0..(MaxInt div SIZEOF(JBLOCK))-1; + JBLOCK_ROWS = Array[jTBlockRow] of JBLOCK; + JBLOCKROW = ^JBLOCK_ROWS; {far} { pointer to one row of coefficient blocks } + + + jTBlockArray = 0..(MaxInt div SIZEOF(JBLOCKROW))-1; + JBLOCK_ARRAY = Array[jTBlockArray] of JBLOCKROW; + JBLOCKARRAY = ^JBLOCK_ARRAY; { a 2-D array of coefficient blocks } + + jTBlockImage = 0..(MaxInt div SIZEOF(JBLOCKARRAY))-1; + JBLOCK_IMAGE = Array[jTBlockImage] of JBLOCKARRAY; + JBLOCKIMAGE = ^JBLOCK_IMAGE; { a 3-D array of coefficient blocks } + + jTCoef = 0..(MaxInt div SIZEOF(JCOEF))-1; + JCOEF_ROW = Array[jTCoef] of JCOEF; + JCOEFPTR = ^JCOEF_ROW; {far} { useful in a couple of places } + + +type + jTByte = 0..(MaxInt div SIZEOF(byte))-1; + JByteArray = Array[jTByte] of byte; + JBytePtr = ^JByteArray; +type + byteptr = ^byte; + +{ Types for JPEG compression parameters and working tables. } + + +{ DCT coefficient quantization tables. } + +type + JQUANT_TBL_PTR = ^JQUANT_TBL; + JQUANT_TBL = record + { This array gives the coefficient quantizers in natural array order + (not the zigzag order in which they are stored in a JPEG DQT marker). + CAUTION: IJG versions prior to v6a kept this array in zigzag order. } + quantval : Array[0..DCTSIZE2-1] of UINT16; + { quantization step for each coefficient } + { This field is used only during compression. It's initialized FALSE when + the table is created, and set TRUE when it's been output to the file. + You could suppress output of a table by setting this to TRUE. + (See jpeg_suppress_tables for an example.) } + sent_table : boolean; { TRUE when table has been output } + end; + JQUANT_TBL_FIELD = Array[0..(MaxInt div SizeOf(JQUANT_TBL))-1] of JQUANT_TBL; + +{ Huffman coding tables. } + +type + JHUFF_TBL_PTR = ^JHUFF_TBL; + JHUFF_TBL = record + { These two fields directly represent the contents of a JPEG DHT marker } + bits : Array[0..17-1] of UINT8; { bits[k] = # of symbols with codes of } + { length k bits; bits[0] is unused } + huffval : Array[0..256-1] of UINT8; + { The symbols, in order of incr code length } + { This field is used only during compression. It's initialized FALSE when + the table is created, and set TRUE when it's been output to the file. + You could suppress output of a table by setting this to TRUE. + (See jpeg_suppress_tables for an example.) } + sent_table : boolean; { TRUE when table has been output } + end; + JHUFF_TBL_FIELD = Array[0..(MaxInt div SizeOf(JHUFF_TBL))-1] of JHUFF_TBL; + +{ Declarations for both compression & decompression } + +type + J_BUF_MODE = ( { Operating modes for buffer controllers } + JBUF_PASS_THRU, { Plain stripwise operation } + { Remaining modes require a full-image buffer to have been created } + JBUF_SAVE_SOURCE, { Run source subobject only, save output } + JBUF_CRANK_DEST, { Run dest subobject only, using saved data } + JBUF_SAVE_AND_PASS { Run both subobjects, save output } + ); + +{ Values of global_state field (jdapi.c has some dependencies on ordering!) } +const + CSTATE_START = 100; { after create_compress } + CSTATE_SCANNING = 101; { start_compress done, write_scanlines OK } + CSTATE_RAW_OK = 102; { start_compress done, write_raw_data OK } + CSTATE_WRCOEFS = 103; { jpeg_write_coefficients done } + DSTATE_START = 200; { after create_decompress } + DSTATE_INHEADER = 201; { reading header markers, no SOS yet } + DSTATE_READY = 202; { found SOS, ready for start_decompress } + DSTATE_PRELOAD = 203; { reading multiscan file in start_decompress} + DSTATE_PRESCAN = 204; { performing dummy pass for 2-pass quant } + DSTATE_SCANNING = 205; { start_decompress done, read_scanlines OK } + DSTATE_RAW_OK = 206; { start_decompress done, read_raw_data OK } + DSTATE_BUFIMAGE = 207; { expecting jpeg_start_output } + DSTATE_BUFPOST = 208; { looking for SOS/EOI in jpeg_finish_output } + DSTATE_RDCOEFS = 209; { reading file in jpeg_read_coefficients } + DSTATE_STOPPING = 210; { looking for EOI in jpeg_finish_decompress } + + + +{ Basic info about one component (color channel). } + +type + jpeg_component_info_ptr = ^jpeg_component_info; + jpeg_component_info = record + { These values are fixed over the whole image. } + { For compression, they must be supplied by parameter setup; } + { for decompression, they are read from the SOF marker. } + component_id : int; { identifier for this component (0..255) } + component_index : int; { its index in SOF or cinfo^.comp_info[] } + h_samp_factor : int; { horizontal sampling factor (1..4) } + v_samp_factor : int; { vertical sampling factor (1..4) } + quant_tbl_no : int; { quantization table selector (0..3) } + { These values may vary between scans. } + { For compression, they must be supplied by parameter setup; } + { for decompression, they are read from the SOS marker. } + { The decompressor output side may not use these variables. } + dc_tbl_no : int; { DC entropy table selector (0..3) } + ac_tbl_no : int; { AC entropy table selector (0..3) } + + { Remaining fields should be treated as private by applications. } + + { These values are computed during compression or decompression startup: } + { Component's size in DCT blocks. + Any dummy blocks added to complete an MCU are not counted; therefore + these values do not depend on whether a scan is interleaved or not. } + width_in_blocks : JDIMENSION; + height_in_blocks : JDIMENSION; + { Size of a DCT block in samples. Always DCTSIZE for compression. + For decompression this is the size of the output from one DCT block, + reflecting any scaling we choose to apply during the IDCT step. + Values of 1,2,4,8 are likely to be supported. Note that different + components may receive different IDCT scalings. } + + DCT_scaled_size : int; + { The downsampled dimensions are the component's actual, unpadded number + of samples at the main buffer (preprocessing/compression interface), thus + downsampled_width = ceil(image_width * Hi/Hmax) + and similarly for height. For decompression, IDCT scaling is included, so + downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE)} + + downsampled_width : JDIMENSION; { actual width in samples } + downsampled_height : JDIMENSION; { actual height in samples } + { This flag is used only for decompression. In cases where some of the + components will be ignored (eg grayscale output from YCbCr image), + we can skip most computations for the unused components. } + + component_needed : boolean; { do we need the value of this component? } + + { These values are computed before starting a scan of the component. } + { The decompressor output side may not use these variables. } + MCU_width : int; { number of blocks per MCU, horizontally } + MCU_height : int; { number of blocks per MCU, vertically } + MCU_blocks : int; { MCU_width * MCU_height } + MCU_sample_width : int; { MCU width in samples, MCU_width*DCT_scaled_size } + last_col_width : int; { # of non-dummy blocks across in last MCU } + last_row_height : int; { # of non-dummy blocks down in last MCU } + + { Saved quantization table for component; NIL if none yet saved. + See jdinput.c comments about the need for this information. + This field is currently used only for decompression. } + + quant_table : JQUANT_TBL_PTR; + + { Private per-component storage for DCT or IDCT subsystem. } + dct_table : pointer; + end; { record jpeg_component_info } + + jTCinfo = 0..(MaxInt div SizeOf(jpeg_component_info))-1; + jpeg_component_info_array = array[jTCinfo] of jpeg_component_info; + jpeg_component_info_list_ptr = ^jpeg_component_info_array; + + +{ The script for encoding a multiple-scan file is an array of these: } + +type + jpeg_scan_info_ptr = ^jpeg_scan_info; + jpeg_scan_info = record + comps_in_scan : int; { number of components encoded in this scan } + component_index : Array[0..MAX_COMPS_IN_SCAN-1] of int; + { their SOF/comp_info[] indexes } + Ss, Se : int; { progressive JPEG spectral selection parms } + Ah, Al : int; { progressive JPEG successive approx. parms } + end; + +{ The decompressor can save APPn and COM markers in a list of these: } + +type + jpeg_saved_marker_ptr = ^jpeg_marker_struct; + jpeg_marker_struct = record + next : jpeg_saved_marker_ptr; { next in list, or NULL } + marker : UINT8; { marker code: JPEG_COM, or JPEG_APP0+n } + original_length : uint; { # bytes of data in the file } + data_length : uint; { # bytes of data saved at data[] } + data : JOCTET_FIELD_PTR; { the data contained in the marker } + { the marker length word is not counted in data_length or original_length } + end; + +{ Known color spaces. } + +type + J_COLOR_SPACE = ( + JCS_UNKNOWN, { error/unspecified } + JCS_GRAYSCALE, { monochrome } + JCS_RGB, { red/green/blue } + JCS_YCbCr, { Y/Cb/Cr (also known as YUV) } + JCS_CMYK, { C/M/Y/K } + JCS_YCCK { Y/Cb/Cr/K } + ); + +{ DCT/IDCT algorithm options. } + +type + J_DCT_METHOD = ( + JDCT_ISLOW, { slow but accurate integer algorithm } + JDCT_IFAST, { faster, less accurate integer method } + JDCT_FLOAT { floating-point: accurate, fast on fast HW } + ); + +const + JDCT_DEFAULT = JDCT_ISLOW; + JDCT_FASTEST = JDCT_IFAST; + +{ Dithering options for decompression. } + +type + J_DITHER_MODE = ( + JDITHER_NONE, { no dithering } + JDITHER_ORDERED, { simple ordered dither } + JDITHER_FS { Floyd-Steinberg error diffusion dither } + ); + + +const + JPOOL_PERMANENT = 0; { lasts until master record is destroyed } + JPOOL_IMAGE = 1; { lasts until done with image/datastream } + JPOOL_NUMPOOLS = 2; + + +{ "Object" declarations for JPEG modules that may be supplied or called + directly by the surrounding application. + As with all objects in the JPEG library, these structs only define the + publicly visible methods and state variables of a module. Additional + private fields may exist after the public ones. } + + +{ Error handler object } + +const + JMSG_LENGTH_MAX = 200; { recommended size of format_message buffer } + JMSG_STR_PARM_MAX = 80; + +const + TEMP_NAME_LENGTH = 64; { max length of a temporary file's name } +type + TEMP_STRING = string[TEMP_NAME_LENGTH]; + +{$ifdef USE_MSDOS_MEMMGR} { DOS-specific junk } +type + XMSH = ushort; { type of extended-memory handles } + EMSH = ushort; { type of expanded-memory handles } + + handle_union = record + case byte of + 0:(file_handle : short); { DOS file handle if it's a temp file } + 1:(xms_handle : XMSH); { handle if it's a chunk of XMS } + 2:(ems_handle : EMSH); { handle if it's a chunk of EMS } + end; +{$endif} { USE_MSDOS_MEMMGR } + +type + jpeg_error_mgr_ptr = ^jpeg_error_mgr; + jpeg_memory_mgr_ptr = ^jpeg_memory_mgr; + jpeg_progress_mgr_ptr = ^jpeg_progress_mgr; + + +{$ifdef common} +{ Common fields between JPEG compression and decompression master structs. } + err : jpeg_error_mgr_ptr; { Error handler module } + mem : jpeg_memory_mgr_ptr; { Memory manager module } + progress : jpeg_progress_mgr_ptr; { Progress monitor, or NIL if none } + client_data : voidp; { Available for use by application } + is_decompressor : boolean; { so common code can tell which is which } + global_state : int; { for checking call sequence validity } +{$endif} + + j_common_ptr = ^jpeg_common_struct; + j_compress_ptr = ^jpeg_compress_struct; + j_decompress_ptr = ^jpeg_decompress_struct; + + {$ifdef AM_MEMORY_MANAGER} { only jmemmgr.c defines these } + +{ This structure holds whatever state is needed to access a single + backing-store object. The read/write/close method pointers are called + by jmemmgr.c to manipulate the backing-store object; all other fields + are private to the system-dependent backing store routines. } + + + backing_store_ptr = ^backing_store_info; + backing_store_info = record + { Methods for reading/writing/closing this backing-store object } + read_backing_store : procedure (cinfo : j_common_ptr; + info : backing_store_ptr; + buffer_address : pointer; {far} + file_offset : long; + byte_count : long); + write_backing_store : procedure (cinfo : j_common_ptr; + info : backing_store_ptr; + buffer_address : pointer; {far} + file_offset : long; + byte_count : long); + + close_backing_store : procedure (cinfo : j_common_ptr; + info : backing_store_ptr); + + { Private fields for system-dependent backing-store management } + {$ifdef USE_MSDOS_MEMMGR} + { For the MS-DOS manager (jmemdos.c), we need: } + handle : handle_union; { reference to backing-store storage object } + temp_name : TEMP_STRING; { name if it's a file } + {$else} + { For a typical implementation with temp files, we need: } + temp_file : file; { stdio reference to temp file } + temp_name : TEMP_STRING; { name of temp file } + {$endif} + end; + + +{ The control blocks for virtual arrays. + Note that these blocks are allocated in the "small" pool area. + System-dependent info for the associated backing store (if any) is hidden + inside the backing_store_info struct. } + + jvirt_sarray_ptr = ^jvirt_sarray_control; + jvirt_sarray_control = record + mem_buffer : JSAMPARRAY; { => the in-memory buffer } + rows_in_array : JDIMENSION; { total virtual array height } + samplesperrow : JDIMENSION; { width of array (and of memory buffer) } + maxaccess : JDIMENSION; { max rows accessed by access_virt_sarray } + rows_in_mem : JDIMENSION; { height of memory buffer } + rowsperchunk : JDIMENSION; { allocation chunk size in mem_buffer } + cur_start_row : JDIMENSION; { first logical row # in the buffer } + first_undef_row : JDIMENSION; { row # of first uninitialized row } + pre_zero : boolean; { pre-zero mode requested? } + dirty : boolean; { do current buffer contents need written? } + b_s_open : boolean; { is backing-store data valid? } + next : jvirt_sarray_ptr; { link to next virtual sarray control block } + b_s_info : backing_store_info; { System-dependent control info } + end; + + jvirt_barray_ptr = ^jvirt_barray_control; + jvirt_barray_control = record + mem_buffer : JBLOCKARRAY; { => the in-memory buffer } + rows_in_array : JDIMENSION; { total virtual array height } + blocksperrow : JDIMENSION; { width of array (and of memory buffer) } + maxaccess : JDIMENSION; { max rows accessed by access_virt_barray } + rows_in_mem : JDIMENSION; { height of memory buffer } + rowsperchunk : JDIMENSION; { allocation chunk size in mem_buffer } + cur_start_row : JDIMENSION; { first logical row # in the buffer } + first_undef_row : JDIMENSION; { row # of first uninitialized row } + pre_zero : boolean; { pre-zero mode requested? } + dirty : boolean; { do current buffer contents need written? } + b_s_open : boolean; { is backing-store data valid? } + next : jvirt_barray_ptr; { link to next virtual barray control block } + b_s_info : backing_store_info; { System-dependent control info } + end; + + {$endif} { AM_MEMORY_MANAGER } + +{ Declarations for compression modules } + +{ Master control module } + jpeg_comp_master_ptr = ^jpeg_comp_master; + jpeg_comp_master = record + prepare_for_pass : procedure(cinfo : j_compress_ptr); + pass_startup : procedure(cinfo : j_compress_ptr); + finish_pass : procedure(cinfo : j_compress_ptr); + + { State variables made visible to other modules } + call_pass_startup : Boolean; { True if pass_startup must be called } + is_last_pass : Boolean; { True during last pass } + end; + +{ Main buffer control (downsampled-data buffer) } + jpeg_c_main_controller_ptr = ^jpeg_c_main_controller; + jpeg_c_main_controller = record + start_pass : procedure(cinfo : j_compress_ptr; pass_mode : J_BUF_MODE); + process_data : procedure(cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr : JDIMENSION; + in_rows_avail : JDIMENSION); + end; + +{ Compression preprocessing (downsampling input buffer control) } + jpeg_c_prep_controller_ptr = ^jpeg_c_prep_controller; + jpeg_c_prep_controller = record + start_pass : procedure(cinfo : j_compress_ptr; pass_mode : J_BUF_MODE); + pre_process_data : procedure(cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + var in_row_ctr : JDIMENSION; + in_rows_avail : JDIMENSION; + output_buf : JSAMPIMAGE; + var out_row_group_ctr : JDIMENSION; + out_row_groups_avail : JDIMENSION); + end; + +{ Coefficient buffer control } + jpeg_c_coef_controller_ptr = ^jpeg_c_coef_controller; + jpeg_c_coef_controller = record + start_pass : procedure(cinfo : j_compress_ptr; pass_mode : J_BUF_MODE); + compress_data : function(cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE) : boolean; + end; + +{ Colorspace conversion } + jpeg_color_converter_ptr = ^jpeg_color_converter; + jpeg_color_converter = record + start_pass : procedure(cinfo : j_compress_ptr); + color_convert : procedure(cinfo : j_compress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPIMAGE; + output_row : JDIMENSION; + num_rows : int); + end; + +{ Downsampling } + jpeg_downsampler_ptr = ^jpeg_downsampler; + jpeg_downsampler = record + start_pass : procedure(cinfo : j_compress_ptr); + downsample : procedure(cinfo : j_compress_ptr; + input_buf : JSAMPIMAGE; + in_row_index : JDIMENSION; + output_buf : JSAMPIMAGE; + out_row_group_index: JDIMENSION); + need_context_rows : Boolean; { TRUE if need rows above & below } + end; + +{ Forward DCT (also controls coefficient quantization) } + jpeg_forward_dct_ptr = ^jpeg_forward_dct; + jpeg_forward_dct = record + start_pass : procedure(cinfo : j_compress_ptr); + { perhaps this should be an array??? } + forward_DCT : procedure(cinfo : j_compress_ptr; + compptr : jpeg_component_info_ptr; + sample_data : JSAMPARRAY; + coef_blocks : JBLOCKROW; + start_row : JDIMENSION; + start_col : JDIMENSION; + num_blocks : JDIMENSION); + end; + +{ Entropy encoding } + + jpeg_entropy_encoder_ptr = ^jpeg_entropy_encoder; + jpeg_entropy_encoder = record + start_pass : procedure(cinfo : j_compress_ptr; gather_statistics : boolean); + encode_mcu : function(cinfo : j_compress_ptr; + const MCU_data: array of JBLOCKROW) : boolean; + finish_pass : procedure(cinfo : j_compress_ptr); + end; + +{ Marker writing } + jpeg_marker_writer_ptr = ^jpeg_marker_writer; + jpeg_marker_writer = record + write_file_header : procedure(cinfo : j_compress_ptr); + write_frame_header : procedure(cinfo : j_compress_ptr); + write_scan_header : procedure(cinfo : j_compress_ptr); + write_file_trailer : procedure(cinfo : j_compress_ptr); + write_tables_only : procedure(cinfo : j_compress_ptr); + { These routines are exported to allow insertion of extra markers } + { Probably only COM and APPn markers should be written this way } + write_marker_header : procedure (cinfo : j_compress_ptr; + marker : int; + datalen : uint); + write_marker_byte : procedure (cinfo : j_compress_ptr; val : int); + end; + +{ Declarations for decompression modules } + +{ Master control module } + jpeg_decomp_master_ptr = ^jpeg_decomp_master; + jpeg_decomp_master = record + prepare_for_output_pass : procedure( cinfo : j_decompress_ptr); + finish_output_pass : procedure(cinfo : j_decompress_ptr); + + { State variables made visible to other modules } + is_dummy_pass : Boolean; { True during 1st pass for 2-pass quant } + end; + +{ Input control module } + jpeg_input_controller_ptr = ^jpeg_input_controller; + jpeg_input_controller = record + consume_input : function (cinfo : j_decompress_ptr) : int; + reset_input_controller : procedure(cinfo : j_decompress_ptr); + start_input_pass : procedure(cinfo : j_decompress_ptr); + finish_input_pass : procedure(cinfo : j_decompress_ptr); + + { State variables made visible to other modules } + has_multiple_scans : Boolean; { True if file has multiple scans } + eoi_reached : Boolean; { True when EOI has been consumed } + end; + +{ Main buffer control (downsampled-data buffer) } + + jpeg_d_main_controller_ptr = ^jpeg_d_main_controller; + jpeg_d_main_controller = record + start_pass : procedure(cinfo : j_decompress_ptr; pass_mode : J_BUF_MODE); + process_data : procedure(cinfo : j_decompress_ptr; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); + end; + +{ Coefficient buffer control } + jvirt_barray_tbl = array[0..MAX_COMPONENTS-1] of jvirt_barray_ptr; + jvirt_barray_tbl_ptr = ^jvirt_barray_tbl; + jpeg_d_coef_controller_ptr = ^jpeg_d_coef_controller; + jpeg_d_coef_controller = record + start_input_pass : procedure(cinfo : j_decompress_ptr); + consume_data : function (cinfo : j_decompress_ptr) : int; + start_output_pass : procedure(cinfo : j_decompress_ptr); + decompress_data : function (cinfo : j_decompress_ptr; + output_buf : JSAMPIMAGE) : int; + { Pointer to array of coefficient virtual arrays, or NIL if none } + coef_arrays : jvirt_barray_tbl_ptr; + end; + +{ Decompression postprocessing (color quantization buffer control) } + jpeg_d_post_controller_ptr = ^jpeg_d_post_controller; + jpeg_d_post_controller = record + start_pass : procedure(cinfo : j_decompress_ptr; + pass_mode : J_BUF_MODE); + post_process_data : procedure(cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); + end; + + +{ Routine signature for application-supplied marker processing methods. + Need not pass marker code since it is stored in cinfo^.unread_marker. } + + jpeg_marker_parser_method = function(cinfo : j_decompress_ptr) : boolean; + +{ Marker reading & parsing } + jpeg_marker_reader_ptr = ^jpeg_marker_reader; + jpeg_marker_reader = record + reset_marker_reader : procedure(cinfo : j_decompress_ptr); + { Read markers until SOS or EOI. + Returns same codes as are defined for jpeg_consume_input: + JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI. } + + read_markers : function (cinfo : j_decompress_ptr) : int; + { Read a restart marker --- exported for use by entropy decoder only } + read_restart_marker : jpeg_marker_parser_method; + + { State of marker reader --- nominally internal, but applications + supplying COM or APPn handlers might like to know the state. } + + saw_SOI : boolean; { found SOI? } + saw_SOF : boolean; { found SOF? } + next_restart_num : int; { next restart number expected (0-7) } + discarded_bytes : uint; { # of bytes skipped looking for a marker } + end; + +{ Entropy decoding } + jpeg_entropy_decoder_ptr = ^jpeg_entropy_decoder; + jpeg_entropy_decoder = record + start_pass : procedure(cinfo : j_decompress_ptr); + decode_mcu : function(cinfo : j_decompress_ptr; + var MCU_data : array of JBLOCKROW) : boolean; + { This is here to share code between baseline and progressive decoders; } + { other modules probably should not use it } + insufficient_data : BOOLEAN; { set TRUE after emitting warning } + end; + +{ Inverse DCT (also performs dequantization) } + inverse_DCT_method_ptr = procedure(cinfo : j_decompress_ptr; + compptr : jpeg_component_info_ptr; + coef_block : JCOEFPTR; + output_buf : JSAMPARRAY; output_col : JDIMENSION); + + jpeg_inverse_dct_ptr = ^jpeg_inverse_dct; + jpeg_inverse_dct = record + start_pass : procedure(cinfo : j_decompress_ptr); + { It is useful to allow each component to have a separate IDCT method. } + inverse_DCT : Array[0..MAX_COMPONENTS-1] of inverse_DCT_method_ptr; + end; + +{ Upsampling (note that upsampler must also call color converter) } + jpeg_upsampler_ptr = ^jpeg_upsampler; + jpeg_upsampler = record + start_pass : procedure(cinfo : j_decompress_ptr); + upsample : procedure(cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + var in_row_group_ctr : JDIMENSION; { array of } + in_row_groups_avail : JDIMENSION; + output_buf : JSAMPARRAY; + var out_row_ctr : JDIMENSION; + out_rows_avail : JDIMENSION); + + need_context_rows : boolean; { TRUE if need rows above & below } + end; + +{ Colorspace conversion } + jpeg_color_deconverter_ptr = ^jpeg_color_deconverter; + jpeg_color_deconverter = record + start_pass : procedure(cinfo: j_decompress_ptr); + color_convert : procedure(cinfo : j_decompress_ptr; + input_buf : JSAMPIMAGE; + input_row : JDIMENSION; + output_buf : JSAMPARRAY; + num_rows : int); + end; + +{ Color quantization or color precision reduction } + jpeg_color_quantizer_ptr = ^jpeg_color_quantizer; + jpeg_color_quantizer = record + start_pass : procedure(cinfo : j_decompress_ptr; is_pre_scan : boolean); + color_quantize : procedure(cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); + + finish_pass : procedure(cinfo : j_decompress_ptr); + new_color_map : procedure(cinfo : j_decompress_ptr); + end; + + {int8array = Array[0..8-1] of int;} + int8array = Array[0..8-1] of longint; { for TP FormatStr } + + jpeg_error_mgr = record + { Error exit handler: does not return to caller } + error_exit : procedure (cinfo : j_common_ptr); + { Conditionally emit a trace or warning message } + emit_message : procedure (cinfo : j_common_ptr; msg_level : int); + { Routine that actually outputs a trace or error message } + output_message : procedure (cinfo : j_common_ptr); + { Format a message string for the most recent JPEG error or message } + format_message : procedure (cinfo : j_common_ptr; var buffer : AnsiString); + + { Reset error state variables at start of a new image } + reset_error_mgr : procedure (cinfo : j_common_ptr); + + { The message ID code and any parameters are saved here. + A message can have one string parameter or up to 8 int parameters. } + + msg_code : int; + + msg_parm : record + case byte of + 0:(i : int8array); + 1:(s : string[JMSG_STR_PARM_MAX]); + end; + + { Standard state variables for error facility } + + trace_level : int; { max msg_level that will be displayed } + + { For recoverable corrupt-data errors, we emit a warning message, + but keep going unless emit_message chooses to abort. emit_message + should count warnings in num_warnings. The surrounding application + can check for bad data by seeing if num_warnings is nonzero at the + end of processing. } + + num_warnings : long; { number of corrupt-data warnings } + + { These fields point to the table(s) of error message strings. + An application can change the table pointer to switch to a different + message list (typically, to change the language in which errors are + reported). Some applications may wish to add additional error codes + that will be handled by the JPEG library error mechanism; the second + table pointer is used for this purpose. + + First table includes all errors generated by JPEG library itself. + Error code 0 is reserved for a "no such error string" message. } + + {const char * const * jpeg_message_table; } + jpeg_message_table : ^msg_table; { Library errors } + + last_jpeg_message : J_MESSAGE_CODE; + { Table contains strings 0..last_jpeg_message } + { Second table can be added by application (see cjpeg/djpeg for example). + It contains strings numbered first_addon_message..last_addon_message. } + + {const char * const * addon_message_table; } + addon_message_table : ^msg_table; { Non-library errors } + + first_addon_message : J_MESSAGE_CODE; { code for first string in addon table } + last_addon_message : J_MESSAGE_CODE; { code for last string in addon table } + end; + + +{ Progress monitor object } + + jpeg_progress_mgr = record + progress_monitor : procedure(cinfo : j_common_ptr); + + pass_counter : long; { work units completed in this pass } + pass_limit : long; { total number of work units in this pass } + completed_passes : int; { passes completed so far } + total_passes : int; { total number of passes expected } + end; + + +{ Data destination object for compression } + jpeg_destination_mgr_ptr = ^jpeg_destination_mgr; + jpeg_destination_mgr = record + next_output_byte : JOCTETptr; { => next byte to write in buffer } + free_in_buffer : size_t; { # of byte spaces remaining in buffer } + + init_destination : procedure (cinfo : j_compress_ptr); + empty_output_buffer : function (cinfo : j_compress_ptr) : boolean; + term_destination : procedure (cinfo : j_compress_ptr); + end; + + +{ Data source object for decompression } + + jpeg_source_mgr_ptr = ^jpeg_source_mgr; + jpeg_source_mgr = record + {const JOCTET * next_input_byte;} + next_input_byte : JOCTETptr; { => next byte to read from buffer } + bytes_in_buffer : size_t; { # of bytes remaining in buffer } + + init_source : procedure (cinfo : j_decompress_ptr); + fill_input_buffer : function (cinfo : j_decompress_ptr) : boolean; + skip_input_data : procedure (cinfo : j_decompress_ptr; num_bytes : long); + resync_to_restart : function (cinfo : j_decompress_ptr; + desired : int) : boolean; + term_source : procedure (cinfo : j_decompress_ptr); + end; + + +{ Memory manager object. + Allocates "small" objects (a few K total), "large" objects (tens of K), + and "really big" objects (virtual arrays with backing store if needed). + The memory manager does not allow individual objects to be freed; rather, + each created object is assigned to a pool, and whole pools can be freed + at once. This is faster and more convenient than remembering exactly what + to free, especially where malloc()/free() are not too speedy. + NB: alloc routines never return NIL. They exit to error_exit if not + successful. } + + + jpeg_memory_mgr = record + { Method pointers } + alloc_small : function (cinfo : j_common_ptr; pool_id : int; + sizeofobject : size_t) : pointer; + alloc_large : function (cinfo : j_common_ptr; pool_id : int; + sizeofobject : size_t) : pointer; {far} + alloc_sarray : function (cinfo : j_common_ptr; pool_id : int; + samplesperrow : JDIMENSION; + numrows : JDIMENSION) : JSAMPARRAY; + + alloc_barray : function (cinfo : j_common_ptr; pool_id : int; + blocksperrow : JDIMENSION; + numrows : JDIMENSION) : JBLOCKARRAY; + + request_virt_sarray : function(cinfo : j_common_ptr; + pool_id : int; + pre_zero : boolean; + samplesperrow : JDIMENSION; + numrows : JDIMENSION; + maxaccess : JDIMENSION) : jvirt_sarray_ptr; + + request_virt_barray : function(cinfo : j_common_ptr; + pool_id : int; + pre_zero : boolean; + blocksperrow : JDIMENSION; + numrows : JDIMENSION; + maxaccess : JDIMENSION) : jvirt_barray_ptr; + + realize_virt_arrays : procedure (cinfo : j_common_ptr); + + access_virt_sarray : function (cinfo : j_common_ptr; + ptr : jvirt_sarray_ptr; + start_row : JDIMENSION; + num_rows : JDIMENSION; + writable : boolean) : JSAMPARRAY; + + access_virt_barray : function (cinfo : j_common_ptr; + ptr : jvirt_barray_ptr; + start_row : JDIMENSION; + num_rows : JDIMENSION; + writable : boolean) : JBLOCKARRAY; + + free_pool : procedure (cinfo : j_common_ptr; pool_id : int); + self_destruct : procedure (cinfo : j_common_ptr); + + { Limit on memory allocation for this JPEG object. (Note that this is + merely advisory, not a guaranteed maximum; it only affects the space + used for virtual-array buffers.) May be changed by outer application + after creating the JPEG object. } + max_memory_to_use : long; + + { Maximum allocation request accepted by alloc_large. } + max_alloc_chunk : long; + end; + +{ Routines that are to be used by both halves of the library are declared + to receive a pointer to this structure. There are no actual instances of + jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.} + jpeg_common_struct = record + { Fields common to both master struct types } + err : jpeg_error_mgr_ptr; { Error handler module } + mem : jpeg_memory_mgr_ptr; { Memory manager module } + progress : jpeg_progress_mgr_ptr; { Progress monitor, or NIL if none } + client_data : voidp; { Available for use by application } + is_decompressor : boolean; { so common code can tell which is which } + global_state : int; { for checking call sequence validity } + + { Additional fields follow in an actual jpeg_compress_struct or + jpeg_decompress_struct. All three structs must agree on these + initial fields! (This would be a lot cleaner in C++.) } + end; + + +{ Master record for a compression instance } + + jpeg_compress_struct = record + { Fields shared with jpeg_decompress_struct } + err : jpeg_error_mgr_ptr; { Error handler module } + mem : jpeg_memory_mgr_ptr; { Memory manager module } + progress : jpeg_progress_mgr_ptr; { Progress monitor, or NIL if none } + client_data : voidp; { Available for use by application } + is_decompressor : boolean; { so common code can tell which is which } + global_state : int; { for checking call sequence validity } + + { Destination for compressed data } + dest : jpeg_destination_mgr_ptr; + + { Description of source image --- these fields must be filled in by + outer application before starting compression. in_color_space must + be correct before you can even call jpeg_set_defaults(). } + + + image_width : JDIMENSION; { input image width } + image_height : JDIMENSION; { input image height } + input_components : int; { # of color components in input image } + in_color_space : J_COLOR_SPACE; { colorspace of input image } + + input_gamma : double; { image gamma of input image } + + { Compression parameters --- these fields must be set before calling + jpeg_start_compress(). We recommend calling jpeg_set_defaults() to + initialize everything to reasonable defaults, then changing anything + the application specifically wants to change. That way you won't get + burnt when new parameters are added. Also note that there are several + helper routines to simplify changing parameters. } + + data_precision : int; { bits of precision in image data } + + num_components : int; { # of color components in JPEG image } + jpeg_color_space : J_COLOR_SPACE; { colorspace of JPEG image } + + comp_info : jpeg_component_info_list_ptr; + { comp_info^[i] describes component that appears i'th in SOF } + + quant_tbl_ptrs: Array[0..NUM_QUANT_TBLS-1] of JQUANT_TBL_PTR; + { ptrs to coefficient quantization tables, or NIL if not defined } + + dc_huff_tbl_ptrs : Array[0..NUM_HUFF_TBLS-1] of JHUFF_TBL_PTR; + ac_huff_tbl_ptrs : Array[0..NUM_HUFF_TBLS-1] of JHUFF_TBL_PTR; + { ptrs to Huffman coding tables, or NIL if not defined } + + arith_dc_L : Array[0..NUM_ARITH_TBLS-1] of UINT8; { L values for DC arith-coding tables } + arith_dc_U : Array[0..NUM_ARITH_TBLS-1] of UINT8; { U values for DC arith-coding tables } + arith_ac_K : Array[0..NUM_ARITH_TBLS-1] of UINT8; { Kx values for AC arith-coding tables } + + num_scans : int; { # of entries in scan_info array } + scan_info : jpeg_scan_info_ptr; { script for multi-scan file, or NIL } + { The default value of scan_info is NIL, which causes a single-scan + sequential JPEG file to be emitted. To create a multi-scan file, + set num_scans and scan_info to point to an array of scan definitions. } + + raw_data_in : boolean; { TRUE=caller supplies downsampled data } + arith_code : boolean; { TRUE=arithmetic coding, FALSE=Huffman } + optimize_coding : boolean; { TRUE=optimize entropy encoding parms } + CCIR601_sampling : boolean; { TRUE=first samples are cosited } + smoothing_factor : int; { 1..100, or 0 for no input smoothing } + dct_method : J_DCT_METHOD; { DCT algorithm selector } + + { The restart interval can be specified in absolute MCUs by setting + restart_interval, or in MCU rows by setting restart_in_rows + (in which case the correct restart_interval will be figured + for each scan). } + + restart_interval : uint; { MCUs per restart, or 0 for no restart } + restart_in_rows : int; { if > 0, MCU rows per restart interval } + + { Parameters controlling emission of special markers. } + + write_JFIF_header : boolean; { should a JFIF marker be written? } + JFIF_major_version : UINT8; { What to write for the JFIF version number } + JFIF_minor_version : UINT8; + { These three values are not used by the JPEG code, merely copied } + { into the JFIF APP0 marker. density_unit can be 0 for unknown, } + { 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect } + { ratio is defined by X_density/Y_density even when density_unit=0. } + density_unit : UINT8; { JFIF code for pixel size units } + X_density : UINT16; { Horizontal pixel density } + Y_density : UINT16; { Vertical pixel density } + write_Adobe_marker : boolean; { should an Adobe marker be written? } + + { State variable: index of next scanline to be written to + jpeg_write_scanlines(). Application may use this to control its + processing loop, e.g., "while (next_scanline < image_height)". } + + next_scanline : JDIMENSION; { 0 .. image_height-1 } + + { Remaining fields are known throughout compressor, but generally + should not be touched by a surrounding application. } + + { These fields are computed during compression startup } + progressive_mode : boolean; { TRUE if scan script uses progressive mode } + max_h_samp_factor : int; { largest h_samp_factor } + max_v_samp_factor : int; { largest v_samp_factor } + + total_iMCU_rows : JDIMENSION; { # of iMCU rows to be input to coef ctlr } + { The coefficient controller receives data in units of MCU rows as defined + for fully interleaved scans (whether the JPEG file is interleaved or not). + There are v_samp_factor * DCTSIZE sample rows of each component in an + "iMCU" (interleaved MCU) row. } + + { These fields are valid during any one scan. + They describe the components and MCUs actually appearing in the scan. } + + comps_in_scan : int; { # of JPEG components in this scan } + cur_comp_info : Array[0..MAX_COMPS_IN_SCAN-1] of jpeg_component_info_ptr; + { cur_comp_info[i]^ describes component that appears i'th in SOS } + + MCUs_per_row : JDIMENSION; { # of MCUs across the image } + MCU_rows_in_scan : JDIMENSION;{ # of MCU rows in the image } + + blocks_in_MCU : int; { # of DCT blocks per MCU } + MCU_membership : Array[0..C_MAX_BLOCKS_IN_MCU-1] of int; + { MCU_membership[i] is index in cur_comp_info of component owning } + { i'th block in an MCU } + + Ss, Se, Ah, Al : int; { progressive JPEG parameters for scan } + + { Links to compression subobjects (methods and private variables of modules) } + master : jpeg_comp_master_ptr; + main : jpeg_c_main_controller_ptr; + prep : jpeg_c_prep_controller_ptr; + coef : jpeg_c_coef_controller_ptr; + marker : jpeg_marker_writer_ptr; + cconvert : jpeg_color_converter_ptr; + downsample : jpeg_downsampler_ptr; + fdct : jpeg_forward_dct_ptr; + entropy : jpeg_entropy_encoder_ptr; + script_space : jpeg_scan_info_ptr; { workspace for jpeg_simple_progression } + script_space_size : int; + end; + + +{ Master record for a decompression instance } + + coef_bits_field = Array[0..DCTSIZE2-1] of int; + coef_bits_ptr = ^coef_bits_field; + coef_bits_ptrfield = Array[0..MAX_COMPS_IN_SCAN-1] of coef_bits_field; + coef_bits_ptrrow = ^coef_bits_ptrfield; + + range_limit_table = array[-(MAXJSAMPLE+1)..4*(MAXJSAMPLE+1) + + CENTERJSAMPLE -1] of JSAMPLE; + range_limit_table_ptr = ^range_limit_table; + + jpeg_decompress_struct = record + { Fields shared with jpeg_compress_struct } + err : jpeg_error_mgr_ptr; { Error handler module } + mem : jpeg_memory_mgr_ptr; { Memory manager module } + progress : jpeg_progress_mgr_ptr; { Progress monitor, or NIL if none } + client_data : voidp; { Available for use by application } + is_decompressor : boolean; { so common code can tell which is which } + global_state : int; { for checking call sequence validity } + + { Source of compressed data } + src : jpeg_source_mgr_ptr; + + { Basic description of image --- filled in by jpeg_read_header(). } + { Application may inspect these values to decide how to process image. } + + image_width : JDIMENSION; { nominal image width (from SOF marker) } + image_height : JDIMENSION; { nominal image height } + num_components : int; { # of color components in JPEG image } + jpeg_color_space : J_COLOR_SPACE; { colorspace of JPEG image } + + { Decompression processing parameters --- these fields must be set before + calling jpeg_start_decompress(). Note that jpeg_read_header() + initializes them to default values. } + + out_color_space : J_COLOR_SPACE; { colorspace for output } + + scale_num, scale_denom : uint ; { fraction by which to scale image } + + output_gamma : double; { image gamma wanted in output } + + buffered_image : boolean; { TRUE=multiple output passes } + raw_data_out : boolean; { TRUE=downsampled data wanted } + + dct_method : J_DCT_METHOD; { IDCT algorithm selector } + do_fancy_upsampling : boolean; { TRUE=apply fancy upsampling } + do_block_smoothing : boolean; { TRUE=apply interblock smoothing } + + quantize_colors : boolean; { TRUE=colormapped output wanted } + { the following are ignored if not quantize_colors: } + dither_mode : J_DITHER_MODE; { type of color dithering to use } + two_pass_quantize : boolean; { TRUE=use two-pass color quantization } + desired_number_of_colors : int; { max # colors to use in created colormap } + { these are significant only in buffered-image mode: } + enable_1pass_quant : boolean; { enable future use of 1-pass quantizer } + enable_external_quant : boolean; { enable future use of external colormap } + enable_2pass_quant : boolean; { enable future use of 2-pass quantizer } + + { Description of actual output image that will be returned to application. + These fields are computed by jpeg_start_decompress(). + You can also use jpeg_calc_output_dimensions() to determine these values + in advance of calling jpeg_start_decompress(). } + + output_width : JDIMENSION; { scaled image width } + output_height: JDIMENSION; { scaled image height } + out_color_components : int; { # of color components in out_color_space } + output_components : int; { # of color components returned } + { output_components is 1 (a colormap index) when quantizing colors; + otherwise it equals out_color_components. } + + rec_outbuf_height : int; { min recommended height of scanline buffer } + { If the buffer passed to jpeg_read_scanlines() is less than this many + rows high, space and time will be wasted due to unnecessary data + copying. Usually rec_outbuf_height will be 1 or 2, at most 4. } + + { When quantizing colors, the output colormap is described by these + fields. The application can supply a colormap by setting colormap + non-NIL before calling jpeg_start_decompress; otherwise a colormap + is created during jpeg_start_decompress or jpeg_start_output. The map + has out_color_components rows and actual_number_of_colors columns. } + + actual_number_of_colors : int; { number of entries in use } + colormap : JSAMPARRAY; { The color map as a 2-D pixel array } + + { State variables: these variables indicate the progress of decompression. + The application may examine these but must not modify them. } + + { Row index of next scanline to be read from jpeg_read_scanlines(). + Application may use this to control its processing loop, e.g., + "while (output_scanline < output_height)". } + + output_scanline : JDIMENSION; { 0 .. output_height-1 } + + { Current input scan number and number of iMCU rows completed in scan. + These indicate the progress of the decompressor input side. } + + input_scan_number : int; { Number of SOS markers seen so far } + input_iMCU_row : JDIMENSION; { Number of iMCU rows completed } + + { The "output scan number" is the notional scan being displayed by the + output side. The decompressor will not allow output scan/row number + to get ahead of input scan/row, but it can fall arbitrarily far behind.} + + output_scan_number : int; { Nominal scan number being displayed } + output_iMCU_row : int; { Number of iMCU rows read } + + { Current progression status. coef_bits[c][i] indicates the precision + with which component c's DCT coefficient i (in zigzag order) is known. + It is -1 when no data has yet been received, otherwise it is the point + transform (shift) value for the most recent scan of the coefficient + (thus, 0 at completion of the progression). + This pointer is NIL when reading a non-progressive file. } + + coef_bits : coef_bits_ptrrow; + { -1 or current Al value for each coef } + + { Internal JPEG parameters --- the application usually need not look at + these fields. Note that the decompressor output side may not use + any parameters that can change between scans. } + + { Quantization and Huffman tables are carried forward across input + datastreams when processing abbreviated JPEG datastreams. } + + quant_tbl_ptrs : Array[0..NUM_QUANT_TBLS-1] of JQUANT_TBL_PTR; + { ptrs to coefficient quantization tables, or NIL if not defined } + + dc_huff_tbl_ptrs : Array[0..NUM_HUFF_TBLS-1] of JHUFF_TBL_PTR; + ac_huff_tbl_ptrs : Array[0..NUM_HUFF_TBLS-1] of JHUFF_TBL_PTR; + { ptrs to Huffman coding tables, or NIL if not defined } + + { These parameters are never carried across datastreams, since they + are given in SOF/SOS markers or defined to be reset by SOI. } + + data_precision : int; { bits of precision in image data } + + comp_info : jpeg_component_info_list_ptr; + { comp_info^[i] describes component that appears i'th in SOF } + + progressive_mode : boolean; { TRUE if SOFn specifies progressive mode } + arith_code : boolean; { TRUE=arithmetic coding, FALSE=Huffman } + + arith_dc_L : Array[0..NUM_ARITH_TBLS-1] of UINT8; { L values for DC arith-coding tables } + arith_dc_U : Array[0..NUM_ARITH_TBLS-1] of UINT8; { U values for DC arith-coding tables } + arith_ac_K : Array[0..NUM_ARITH_TBLS-1] of UINT8; { Kx values for AC arith-coding tables } + + restart_interval : uint; { MCUs per restart interval, or 0 for no restart } + + { These fields record data obtained from optional markers recognized by + the JPEG library. } + + saw_JFIF_marker : boolean; { TRUE iff a JFIF APP0 marker was found } + { Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: } + JFIF_major_version : UINT8; { JFIF version number } + JFIF_minor_version : UINT8; + density_unit : UINT8; { JFIF code for pixel size units } + X_density : UINT16; { Horizontal pixel density } + Y_density : UINT16; { Vertical pixel density } + saw_Adobe_marker : boolean; { TRUE iff an Adobe APP14 marker was found } + Adobe_transform : UINT8; { Color transform code from Adobe marker } + + CCIR601_sampling : boolean; { TRUE=first samples are cosited } + + { Aside from the specific data retained from APPn markers known to the + library, the uninterpreted contents of any or all APPn and COM markers + can be saved in a list for examination by the application. } + + marker_list : jpeg_saved_marker_ptr; { Head of list of saved markers } + + { Remaining fields are known throughout decompressor, but generally + should not be touched by a surrounding application. } + + + { These fields are computed during decompression startup } + + max_h_samp_factor : int; { largest h_samp_factor } + max_v_samp_factor : int; { largest v_samp_factor } + + min_DCT_scaled_size : int; { smallest DCT_scaled_size of any component } + + total_iMCU_rows : JDIMENSION; { # of iMCU rows in image } + { The coefficient controller's input and output progress is measured in + units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows + in fully interleaved JPEG scans, but are used whether the scan is + interleaved or not. We define an iMCU row as v_samp_factor DCT block + rows of each component. Therefore, the IDCT output contains + v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row.} + + sample_range_limit : range_limit_table_ptr; { table for fast range-limiting } + + + { These fields are valid during any one scan. + They describe the components and MCUs actually appearing in the scan. + Note that the decompressor output side must not use these fields. } + + comps_in_scan : int; { # of JPEG components in this scan } + cur_comp_info : Array[0..MAX_COMPS_IN_SCAN-1] of jpeg_component_info_ptr; + { cur_comp_info[i]^ describes component that appears i'th in SOS } + + MCUs_per_row : JDIMENSION; { # of MCUs across the image } + MCU_rows_in_scan : JDIMENSION; { # of MCU rows in the image } + + blocks_in_MCU : JDIMENSION; { # of DCT blocks per MCU } + MCU_membership : Array[0..D_MAX_BLOCKS_IN_MCU-1] of int; + { MCU_membership[i] is index in cur_comp_info of component owning } + { i'th block in an MCU } + + Ss, Se, Ah, Al : int; { progressive JPEG parameters for scan } + + { This field is shared between entropy decoder and marker parser. + It is either zero or the code of a JPEG marker that has been + read from the data source, but has not yet been processed. } + + unread_marker : int; + + { Links to decompression subobjects + (methods, private variables of modules) } + + master : jpeg_decomp_master_ptr; + main : jpeg_d_main_controller_ptr; + coef : jpeg_d_coef_controller_ptr; + post : jpeg_d_post_controller_ptr; + inputctl : jpeg_input_controller_ptr; + marker : jpeg_marker_reader_ptr; + entropy : jpeg_entropy_decoder_ptr; + idct : jpeg_inverse_dct_ptr; + upsample : jpeg_upsampler_ptr; + cconvert : jpeg_color_deconverter_ptr; + cquantize : jpeg_color_quantizer_ptr; + end; + +{ Decompression startup: read start of JPEG datastream to see what's there + function jpeg_read_header (cinfo : j_decompress_ptr; + require_image : boolean) : int; + Return value is one of: } +const + JPEG_SUSPENDED = 0; { Suspended due to lack of input data } + JPEG_HEADER_OK = 1; { Found valid image datastream } + JPEG_HEADER_TABLES_ONLY = 2; { Found valid table-specs-only datastream } +{ If you pass require_image = TRUE (normal case), you need not check for + a TABLES_ONLY return code; an abbreviated file will cause an error exit. + JPEG_SUSPENDED is only possible if you use a data source module that can + give a suspension return (the stdio source module doesn't). } + + +{ function jpeg_consume_input (cinfo : j_decompress_ptr) : int; + Return value is one of: } + + JPEG_REACHED_SOS = 1; { Reached start of new scan } + JPEG_REACHED_EOI = 2; { Reached end of image } + JPEG_ROW_COMPLETED = 3; { Completed one iMCU row } + JPEG_SCAN_COMPLETED = 4; { Completed last iMCU row of a scan } + + + + +implementation + +end. diff --git a/src/lib/vampimg/JpegLib/imjquant1.pas b/src/lib/vampimg/JpegLib/imjquant1.pas new file mode 100644 index 0000000..c5df360 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjquant1.pas @@ -0,0 +1,1009 @@ +unit imjquant1; + +{ This file contains 1-pass color quantization (color mapping) routines. + These routines provide mapping to a fixed color map using equally spaced + color values. Optional Floyd-Steinberg or ordered dithering is available. } + +{ Original: jquant1.c; Copyright (C) 1991-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjpeglib; + +{GLOBAL} +procedure jinit_1pass_quantizer (cinfo : j_decompress_ptr); + +implementation + +uses + imjmorecfg, + imjdeferr, + imjerror, + imjutils; + +{ The main purpose of 1-pass quantization is to provide a fast, if not very + high quality, colormapped output capability. A 2-pass quantizer usually + gives better visual quality; however, for quantized grayscale output this + quantizer is perfectly adequate. Dithering is highly recommended with this + quantizer, though you can turn it off if you really want to. + + In 1-pass quantization the colormap must be chosen in advance of seeing the + image. We use a map consisting of all combinations of Ncolors[i] color + values for the i'th component. The Ncolors[] values are chosen so that + their product, the total number of colors, is no more than that requested. + (In most cases, the product will be somewhat less.) + + Since the colormap is orthogonal, the representative value for each color + component can be determined without considering the other components; + then these indexes can be combined into a colormap index by a standard + N-dimensional-array-subscript calculation. Most of the arithmetic involved + can be precalculated and stored in the lookup table colorindex[]. + colorindex[i][j] maps pixel value j in component i to the nearest + representative value (grid plane) for that component; this index is + multiplied by the array stride for component i, so that the + index of the colormap entry closest to a given pixel value is just + sum( colorindex[component-number][pixel-component-value] ) + Aside from being fast, this scheme allows for variable spacing between + representative values with no additional lookup cost. + + If gamma correction has been applied in color conversion, it might be wise + to adjust the color grid spacing so that the representative colors are + equidistant in linear space. At this writing, gamma correction is not + implemented by jdcolor, so nothing is done here. } + + +{ Declarations for ordered dithering. + + We use a standard 16x16 ordered dither array. The basic concept of ordered + dithering is described in many references, for instance Dale Schumacher's + chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991). + In place of Schumacher's comparisons against a "threshold" value, we add a + "dither" value to the input pixel and then round the result to the nearest + output value. The dither value is equivalent to (0.5 - threshold) times + the distance between output values. For ordered dithering, we assume that + the output colors are equally spaced; if not, results will probably be + worse, since the dither may be too much or too little at a given point. + + The normal calculation would be to form pixel value + dither, range-limit + this to 0..MAXJSAMPLE, and then index into the colorindex table as usual. + We can skip the separate range-limiting step by extending the colorindex + table in both directions. } + + +const + ODITHER_SIZE = 16; { dimension of dither matrix } +{ NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break } + ODITHER_CELLS = (ODITHER_SIZE*ODITHER_SIZE); { # cells in matrix } + ODITHER_MASK = (ODITHER_SIZE-1); { mask for wrapping around counters } + +type + ODITHER_vector = Array[0..ODITHER_SIZE-1] of int; + ODITHER_MATRIX = Array[0..ODITHER_SIZE-1] of ODITHER_vector; + {ODITHER_MATRIX_PTR = ^array[0..ODITHER_SIZE-1] of int;} + ODITHER_MATRIX_PTR = ^ODITHER_MATRIX; + +const + base_dither_matrix : Array[0..ODITHER_SIZE-1,0..ODITHER_SIZE-1] of UINT8 + = ( + { Bayer's order-4 dither array. Generated by the code given in + Stephen Hawley's article "Ordered Dithering" in Graphics Gems I. + The values in this array must range from 0 to ODITHER_CELLS-1. } + + ( 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 ), + ( 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 ), + ( 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 ), + ( 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 ), + ( 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 ), + ( 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 ), + ( 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 ), + ( 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 ), + ( 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 ), + ( 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 ), + ( 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 ), + ( 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 ), + ( 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 ), + ( 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 ), + ( 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 ), + ( 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 ) + ); + + +{ Declarations for Floyd-Steinberg dithering. + + Errors are accumulated into the array fserrors[], at a resolution of + 1/16th of a pixel count. The error at a given pixel is propagated + to its not-yet-processed neighbors using the standard F-S fractions, + ... (here) 7/16 + 3/16 5/16 1/16 + We work left-to-right on even rows, right-to-left on odd rows. + + We can get away with a single array (holding one row's worth of errors) + by using it to store the current row's errors at pixel columns not yet + processed, but the next row's errors at columns already processed. We + need only a few extra variables to hold the errors immediately around the + current column. (If we are lucky, those variables are in registers, but + even if not, they're probably cheaper to access than array elements are.) + + The fserrors[] array is indexed [component#][position]. + We provide (#columns + 2) entries per component; the extra entry at each + end saves us from special-casing the first and last pixels. + + Note: on a wide image, we might not have enough room in a PC's near data + segment to hold the error array; so it is allocated with alloc_large. } + +{$ifdef BITS_IN_JSAMPLE_IS_8} +type + FSERROR = INT16; { 16 bits should be enough } + LOCFSERROR = int; { use 'int' for calculation temps } +{$else} +type + FSERROR = INT32; { may need more than 16 bits } + LOCFSERROR = INT32; { be sure calculation temps are big enough } +{$endif} + +type + jFSError = 0..(MaxInt div SIZEOF(FSERROR))-1; + FS_ERROR_FIELD = array[jFSError] of FSERROR; + FS_ERROR_FIELD_PTR = ^FS_ERROR_FIELD;{far} + { pointer to error array (in FAR storage!) } + FSERRORPTR = ^FSERROR; + + +{ Private subobject } + +const + MAX_Q_COMPS = 4; { max components I can handle } + +type + my_cquantize_ptr = ^my_cquantizer; + my_cquantizer = record + pub : jpeg_color_quantizer; { public fields } + + { Initially allocated colormap is saved here } + sv_colormap : JSAMPARRAY; { The color map as a 2-D pixel array } + sv_actual : int; { number of entries in use } + + colorindex : JSAMPARRAY; { Precomputed mapping for speed } + { colorindex[i][j] = index of color closest to pixel value j in component i, + premultiplied as described above. Since colormap indexes must fit into + JSAMPLEs, the entries of this array will too. } + + is_padded : boolean; { is the colorindex padded for odither? } + + Ncolors : array[0..MAX_Q_COMPS-1] of int; + { # of values alloced to each component } + + { Variables for ordered dithering } + row_index : int; { cur row's vertical index in dither matrix } + odither : array[0..MAX_Q_COMPS-1] of ODITHER_MATRIX_PTR; + { one dither array per component } + { Variables for Floyd-Steinberg dithering } + fserrors : array[0..MAX_Q_COMPS-1] of FS_ERROR_FIELD_PTR; + { accumulated errors } + on_odd_row : boolean; { flag to remember which row we are on } + end; + + +{ Policy-making subroutines for create_colormap and create_colorindex. + These routines determine the colormap to be used. The rest of the module + only assumes that the colormap is orthogonal. + + * select_ncolors decides how to divvy up the available colors + among the components. + * output_value defines the set of representative values for a component. + * largest_input_value defines the mapping from input values to + representative values for a component. + Note that the latter two routines may impose different policies for + different components, though this is not currently done. } + + + +{LOCAL} +function select_ncolors (cinfo : j_decompress_ptr; + var Ncolors : array of int) : int; +{ Determine allocation of desired colors to components, } +{ and fill in Ncolors[] array to indicate choice. } +{ Return value is total number of colors (product of Ncolors[] values). } +var + nc : int; + max_colors : int; + total_colors, iroot, i, j : int; + changed : boolean; + temp : long; +const + RGB_order:array[0..2] of int = (RGB_GREEN, RGB_RED, RGB_BLUE); +begin + nc := cinfo^.out_color_components; { number of color components } + max_colors := cinfo^.desired_number_of_colors; + + { We can allocate at least the nc'th root of max_colors per component. } + { Compute floor(nc'th root of max_colors). } + iroot := 1; + repeat + Inc(iroot); + temp := iroot; { set temp = iroot ** nc } + for i := 1 to pred(nc) do + temp := temp * iroot; + until (temp > long(max_colors)); { repeat till iroot exceeds root } + Dec(iroot); { now iroot = floor(root) } + + { Must have at least 2 color values per component } + if (iroot < 2) then + ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_FEW_COLORS, int(temp)); + + { Initialize to iroot color values for each component } + total_colors := 1; + for i := 0 to pred(nc) do + begin + Ncolors[i] := iroot; + total_colors := total_colors * iroot; + end; + + { We may be able to increment the count for one or more components without + exceeding max_colors, though we know not all can be incremented. + Sometimes, the first component can be incremented more than once! + (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.) + In RGB colorspace, try to increment G first, then R, then B. } + + repeat + changed := FALSE; + for i := 0 to pred(nc) do + begin + if cinfo^.out_color_space = JCS_RGB then + j := RGB_order[i] + else + j := i; + { calculate new total_colors if Ncolors[j] is incremented } + temp := total_colors div Ncolors[j]; + temp := temp * (Ncolors[j]+1); { done in long arith to avoid oflo } + if (temp > long(max_colors)) then + break; { won't fit, done with this pass } + Inc(Ncolors[j]); { OK, apply the increment } + total_colors := int(temp); + changed := TRUE; + end; + until not changed; + + select_ncolors := total_colors; +end; + + +{LOCAL} +function output_value (cinfo : j_decompress_ptr; + ci : int; j : int; maxj : int) : int; +{ Return j'th output value, where j will range from 0 to maxj } +{ The output values must fall in 0..MAXJSAMPLE in increasing order } +begin + { We always provide values 0 and MAXJSAMPLE for each component; + any additional values are equally spaced between these limits. + (Forcing the upper and lower values to the limits ensures that + dithering can't produce a color outside the selected gamut.) } + + output_value := int (( INT32(j) * MAXJSAMPLE + maxj div 2) div maxj); +end; + + +{LOCAL} +function largest_input_value (cinfo : j_decompress_ptr; + ci : int; j : int; maxj : int) : int; +{ Return largest input value that should map to j'th output value } +{ Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE } +begin + { Breakpoints are halfway between values returned by output_value } + largest_input_value := int (( INT32(2*j + 1) * MAXJSAMPLE + + maxj) div (2*maxj)); +end; + + +{ Create the colormap. } + +{LOCAL} +procedure create_colormap (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; + colormap : JSAMPARRAY; { Created colormap } + + total_colors : int; { Number of distinct output colors } + i,j,k, nci, blksize, blkdist, ptr, val : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + + { Select number of colors for each component } + total_colors := select_ncolors(cinfo, cquantize^.Ncolors); + + { Report selected color counts } + {$IFDEF DEBUG} + if (cinfo^.out_color_components = 3) then + TRACEMS4(j_common_ptr(cinfo), 1, JTRC_QUANT_3_NCOLORS, + total_colors, cquantize^.Ncolors[0], + cquantize^.Ncolors[1], cquantize^.Ncolors[2]) + else + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_QUANT_NCOLORS, total_colors); + {$ENDIF} + + { Allocate and fill in the colormap. } + { The colors are ordered in the map in standard row-major order, } + { i.e. rightmost (highest-indexed) color changes most rapidly. } + + colormap := cinfo^.mem^.alloc_sarray( + j_common_ptr(cinfo), JPOOL_IMAGE, + JDIMENSION(total_colors), JDIMENSION(cinfo^.out_color_components)); + + { blksize is number of adjacent repeated entries for a component } + { blkdist is distance between groups of identical entries for a component } + blkdist := total_colors; + + for i := 0 to pred(cinfo^.out_color_components) do + begin + { fill in colormap entries for i'th color component } + nci := cquantize^.Ncolors[i]; { # of distinct values for this color } + blksize := blkdist div nci; + for j := 0 to pred(nci) do + begin + { Compute j'th output value (out of nci) for component } + val := output_value(cinfo, i, j, nci-1); + { Fill in all colormap entries that have this value of this component } + ptr := j * blksize; + while (ptr < total_colors) do + begin + { fill in blksize entries beginning at ptr } + for k := 0 to pred(blksize) do + colormap^[i]^[ptr+k] := JSAMPLE(val); + + Inc(ptr, blkdist); + end; + end; + blkdist := blksize; { blksize of this color is blkdist of next } + end; + + { Save the colormap in private storage, + where it will survive color quantization mode changes. } + + cquantize^.sv_colormap := colormap; + cquantize^.sv_actual := total_colors; +end; + +{ Create the color index table. } + +{LOCAL} +procedure create_colorindex (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; + indexptr, + help_indexptr : JSAMPROW; { for negative offsets } + i,j,k, nci, blksize, val, pad : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + { For ordered dither, we pad the color index tables by MAXJSAMPLE in + each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE). + This is not necessary in the other dithering modes. However, we + flag whether it was done in case user changes dithering mode. } + + if (cinfo^.dither_mode = JDITHER_ORDERED) then + begin + pad := MAXJSAMPLE*2; + cquantize^.is_padded := TRUE; + end + else + begin + pad := 0; + cquantize^.is_padded := FALSE; + end; + + cquantize^.colorindex := cinfo^.mem^.alloc_sarray + (j_common_ptr(cinfo), JPOOL_IMAGE, + JDIMENSION(MAXJSAMPLE+1 + pad), + JDIMENSION(cinfo^.out_color_components)); + + { blksize is number of adjacent repeated entries for a component } + blksize := cquantize^.sv_actual; + + for i := 0 to pred(cinfo^.out_color_components) do + begin + { fill in colorindex entries for i'th color component } + nci := cquantize^.Ncolors[i]; { # of distinct values for this color } + blksize := blksize div nci; + + { adjust colorindex pointers to provide padding at negative indexes. } + if (pad <> 0) then + Inc(JSAMPLE_PTR(cquantize^.colorindex^[i]), MAXJSAMPLE); + + { in loop, val = index of current output value, } + { and k = largest j that maps to current val } + indexptr := cquantize^.colorindex^[i]; + val := 0; + k := largest_input_value(cinfo, i, 0, nci-1); + for j := 0 to MAXJSAMPLE do + begin + while (j > k) do { advance val if past boundary } + begin + Inc(val); + k := largest_input_value(cinfo, i, val, nci-1); + end; + { premultiply so that no multiplication needed in main processing } + indexptr^[j] := JSAMPLE (val * blksize); + end; + { Pad at both ends if necessary } + if (pad <> 0) then + begin + help_indexptr := indexptr; + { adjust the help pointer to avoid negative offsets } + Dec(JSAMPLE_PTR(help_indexptr), MAXJSAMPLE); + + for j := 1 to MAXJSAMPLE do + begin + {indexptr^[-j] := indexptr^[0];} + help_indexptr^[MAXJSAMPLE-j] := indexptr^[0]; + indexptr^[MAXJSAMPLE+j] := indexptr^[MAXJSAMPLE]; + end; + end; + end; +end; + + +{ Create an ordered-dither array for a component having ncolors + distinct output values. } + +{LOCAL} +function make_odither_array (cinfo : j_decompress_ptr; + ncolors : int) : ODITHER_MATRIX_PTR; +var + odither : ODITHER_MATRIX_PTR; + j, k : int; + num, den : INT32; +begin + odither := ODITHER_MATRIX_PTR ( + cinfo^.mem^.alloc_small(j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(ODITHER_MATRIX))); + { The inter-value distance for this color is MAXJSAMPLE/(ncolors-1). + Hence the dither value for the matrix cell with fill order f + (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1). + On 16-bit-int machine, be careful to avoid overflow. } + + den := 2 * ODITHER_CELLS * ( INT32(ncolors - 1)); + for j := 0 to pred(ODITHER_SIZE) do + begin + for k := 0 to pred(ODITHER_SIZE) do + begin + num := ( INT32(ODITHER_CELLS-1 - 2*( int(base_dither_matrix[j][k])))) + * MAXJSAMPLE; + { Ensure round towards zero despite C's lack of consistency + about rounding negative values in integer division... } + + if num<0 then + odither^[j][k] := int (-((-num) div den)) + else + odither^[j][k] := int (num div den); + end; + end; + make_odither_array := odither; +end; + + +{ Create the ordered-dither tables. + Components having the same number of representative colors may + share a dither table. } + +{LOCAL} +procedure create_odither_tables (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; + odither : ODITHER_MATRIX_PTR; + i, j, nci : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + + for i := 0 to pred(cinfo^.out_color_components) do + begin + nci := cquantize^.Ncolors[i]; { # of distinct values for this color } + odither := NIL; { search for matching prior component } + for j := 0 to pred(i) do + begin + if (nci = cquantize^.Ncolors[j]) then + begin + odither := cquantize^.odither[j]; + break; + end; + end; + if (odither = NIL) then { need a new table? } + odither := make_odither_array(cinfo, nci); + cquantize^.odither[i] := odither; + end; +end; + + +{ Map some rows of pixels to the output colormapped representation. } + +{METHODDEF} +procedure color_quantize (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +{ General case, no dithering } +var + cquantize : my_cquantize_ptr; + colorindex : JSAMPARRAY; + pixcode, ci : int; {register} + ptrin, ptrout : JSAMPLE_PTR; {register} + row : int; + col : JDIMENSION; + width : JDIMENSION; + nc : int; {register} +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + colorindex := cquantize^.colorindex; + width := cinfo^.output_width; + nc := cinfo^.out_color_components; + + for row := 0 to pred(num_rows) do + begin + ptrin := JSAMPLE_PTR(input_buf^[row]); + ptrout := JSAMPLE_PTR(output_buf^[row]); + for col := pred(width) downto 0 do + begin + pixcode := 0; + for ci := 0 to pred(nc) do + begin + Inc(pixcode, GETJSAMPLE(colorindex^[ci]^[GETJSAMPLE(ptrin^)]) ); + Inc(ptrin); + end; + ptrout^ := JSAMPLE (pixcode); + Inc(ptrout); + end; + end; +end; + + +{METHODDEF} +procedure color_quantize3 (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +{ Fast path for out_color_components=3, no dithering } +var + cquantize : my_cquantize_ptr; + pixcode : int; {register} + ptrin, ptrout : JSAMPLE_PTR; {register} + colorindex0 : JSAMPROW; + colorindex1 : JSAMPROW; + colorindex2 : JSAMPROW; + row : int; + col : JDIMENSION; + width : JDIMENSION; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + colorindex0 := (cquantize^.colorindex)^[0]; + colorindex1 := (cquantize^.colorindex)^[1]; + colorindex2 := (cquantize^.colorindex)^[2]; + width := cinfo^.output_width; + + for row := 0 to pred(num_rows) do + begin + ptrin := JSAMPLE_PTR(input_buf^[row]); + ptrout := JSAMPLE_PTR(output_buf^[row]); + for col := pred(width) downto 0 do + begin + pixcode := GETJSAMPLE((colorindex0)^[GETJSAMPLE(ptrin^)]); + Inc(ptrin); + Inc( pixcode, GETJSAMPLE((colorindex1)^[GETJSAMPLE(ptrin^)]) ); + Inc(ptrin); + Inc( pixcode, GETJSAMPLE((colorindex2)^[GETJSAMPLE(ptrin^)]) ); + Inc(ptrin); + ptrout^ := JSAMPLE (pixcode); + Inc(ptrout); + end; + end; +end; + + +{METHODDEF} +procedure quantize_ord_dither (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +{ General case, with ordered dithering } +var + cquantize : my_cquantize_ptr; + input_ptr, {register} + output_ptr : JSAMPLE_PTR; {register} + colorindex_ci : JSAMPROW; + dither : ^ODITHER_vector; { points to active row of dither matrix } + row_index, col_index : int; { current indexes into dither matrix } + nc : int; + ci : int; + row : int; + col : JDIMENSION; + width : JDIMENSION; +var + pad_offset : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + nc := cinfo^.out_color_components; + width := cinfo^.output_width; + + { Nomssi: work around negative offset } + if my_cquantize_ptr (cinfo^.cquantize)^.is_padded then + pad_offset := MAXJSAMPLE + else + pad_offset := 0; + + for row := 0 to pred(num_rows) do + begin + { Initialize output values to 0 so can process components separately } + jzero_far( {far} pointer(output_buf^[row]), + size_t(width * SIZEOF(JSAMPLE))); + row_index := cquantize^.row_index; + for ci := 0 to pred(nc) do + begin + input_ptr := JSAMPLE_PTR(@ input_buf^[row]^[ci]); + output_ptr := JSAMPLE_PTR(output_buf^[row]); + colorindex_ci := cquantize^.colorindex^[ci]; + { Nomssi } + Dec(JSAMPLE_PTR(colorindex_ci), pad_offset); + + dither := @(cquantize^.odither[ci]^[row_index]); + col_index := 0; + + for col := pred(width) downto 0 do + begin + { Form pixel value + dither, range-limit to 0..MAXJSAMPLE, + select output value, accumulate into output code for this pixel. + Range-limiting need not be done explicitly, as we have extended + the colorindex table to produce the right answers for out-of-range + inputs. The maximum dither is +- MAXJSAMPLE; this sets the + required amount of padding. } + + Inc(output_ptr^, + colorindex_ci^[GETJSAMPLE(input_ptr^)+ pad_offset + + dither^[col_index]]); + Inc(output_ptr); + Inc(input_ptr, nc); + col_index := (col_index + 1) and ODITHER_MASK; + end; + end; + { Advance row index for next row } + row_index := (row_index + 1) and ODITHER_MASK; + cquantize^.row_index := row_index; + end; +end; + +{METHODDEF} +procedure quantize3_ord_dither (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +{ Fast path for out_color_components=3, with ordered dithering } +var + cquantize : my_cquantize_ptr; + pixcode : int; {register} + input_ptr : JSAMPLE_PTR; {register} + output_ptr : JSAMPLE_PTR; {register} + colorindex0 : JSAMPROW; + colorindex1 : JSAMPROW; + colorindex2 : JSAMPROW; + dither0 : ^ODITHER_vector; { points to active row of dither matrix } + dither1 : ^ODITHER_vector; + dither2 : ^ODITHER_vector; + row_index, col_index : int; { current indexes into dither matrix } + row : int; + col : JDIMENSION; + width : JDIMENSION; +var + pad_offset : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + colorindex0 := (cquantize^.colorindex)^[0]; + colorindex1 := (cquantize^.colorindex)^[1]; + colorindex2 := (cquantize^.colorindex)^[2]; + width := cinfo^.output_width; + + { Nomssi: work around negative offset } + if my_cquantize_ptr (cinfo^.cquantize)^.is_padded then + pad_offset := MAXJSAMPLE + else + pad_offset := 0; + + Dec(JSAMPLE_PTR(colorindex0), pad_offset); + Dec(JSAMPLE_PTR(colorindex1), pad_offset); + Dec(JSAMPLE_PTR(colorindex2), pad_offset); + + for row := 0 to pred(num_rows) do + begin + row_index := cquantize^.row_index; + input_ptr := JSAMPLE_PTR(input_buf^[row]); + output_ptr := JSAMPLE_PTR(output_buf^[row]); + dither0 := @(cquantize^.odither[0]^[row_index]); + dither1 := @(cquantize^.odither[1]^[row_index]); + dither2 := @(cquantize^.odither[2]^[row_index]); + col_index := 0; + + + for col := pred(width) downto 0 do + begin + pixcode := GETJSAMPLE(colorindex0^[GETJSAMPLE(input_ptr^) + pad_offset + + dither0^[col_index]]); + Inc(input_ptr); + Inc(pixcode, GETJSAMPLE(colorindex1^[GETJSAMPLE(input_ptr^) + pad_offset + + dither1^[col_index]])); + Inc(input_ptr); + Inc(pixcode, GETJSAMPLE(colorindex2^[GETJSAMPLE(input_ptr^) + pad_offset + + dither2^[col_index]])); + Inc(input_ptr); + output_ptr^ := JSAMPLE (pixcode); + Inc(output_ptr); + col_index := (col_index + 1) and ODITHER_MASK; + end; + row_index := (row_index + 1) and ODITHER_MASK; + cquantize^.row_index := row_index; + end; +end; + + +{METHODDEF} +procedure quantize_fs_dither (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +{ General case, with Floyd-Steinberg dithering } +var + cquantize : my_cquantize_ptr; + cur : LOCFSERROR; {register} { current error or pixel value } + belowerr : LOCFSERROR; { error for pixel below cur } + bpreverr : LOCFSERROR; { error for below/prev col } + bnexterr : LOCFSERROR; { error for below/next col } + delta : LOCFSERROR; + prev_errorptr, + errorptr : FSERRORPTR; {register} { => fserrors[] at column before current } + input_ptr, {register} + output_ptr : JSAMPLE_PTR; {register} + colorindex_ci : JSAMPROW; + colormap_ci : JSAMPROW; + pixcode : int; + nc : int; + dir : int; { 1 for left-to-right, -1 for right-to-left } + dirnc : int; { dir * nc } + ci : int; + row : int; + col : JDIMENSION; + width : JDIMENSION; + range_limit : range_limit_table_ptr; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + nc := cinfo^.out_color_components; + width := cinfo^.output_width; + range_limit := cinfo^.sample_range_limit; + + for row := 0 to pred(num_rows) do + begin + { Initialize output values to 0 so can process components separately } + jzero_far( (output_buf)^[row], + size_t(width * SIZEOF(JSAMPLE))); + for ci := 0 to pred(nc) do + begin + input_ptr := JSAMPLE_PTR(@ input_buf^[row]^[ci]); + output_ptr := JSAMPLE_PTR(output_buf^[row]); + errorptr := FSERRORPTR(cquantize^.fserrors[ci]); { => entry before first column } + if (cquantize^.on_odd_row) then + begin + { work right to left in this row } + Inc(input_ptr, (width-1) * JDIMENSION(nc)); { so point to rightmost pixel } + Inc(output_ptr, width-1); + dir := -1; + dirnc := -nc; + Inc(errorptr, (width+1)); { => entry after last column } + end + else + begin + { work left to right in this row } + dir := 1; + dirnc := nc; + {errorptr := cquantize^.fserrors[ci];} + end; + + colorindex_ci := cquantize^.colorindex^[ci]; + + colormap_ci := (cquantize^.sv_colormap)^[ci]; + { Preset error values: no error propagated to first pixel from left } + cur := 0; + { and no error propagated to row below yet } + belowerr := 0; + bpreverr := 0; + + for col := pred(width) downto 0 do + begin + prev_errorptr := errorptr; + Inc(errorptr, dir); { advance errorptr to current column } + + { cur holds the error propagated from the previous pixel on the + current line. Add the error propagated from the previous line + to form the complete error correction term for this pixel, and + round the error term (which is expressed * 16) to an integer. + RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + for either sign of the error value. + Note: errorptr points to *previous* column's array entry. } + + cur := (cur + errorptr^ + 8) div 16; + + { Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + The maximum error is +- MAXJSAMPLE; this sets the required size + of the range_limit array. } + + Inc( cur, GETJSAMPLE(input_ptr^)); + cur := GETJSAMPLE(range_limit^[cur]); + { Select output value, accumulate into output code for this pixel } + pixcode := GETJSAMPLE(colorindex_ci^[cur]); + Inc(output_ptr^, JSAMPLE (pixcode)); + { Compute actual representation error at this pixel } + { Note: we can do this even though we don't have the final } + { pixel code, because the colormap is orthogonal. } + Dec(cur, GETJSAMPLE(colormap_ci^[pixcode])); + { Compute error fractions to be propagated to adjacent pixels. + Add these into the running sums, and simultaneously shift the + next-line error sums left by 1 column. } + + bnexterr := cur; + delta := cur * 2; + Inc(cur, delta); { form error * 3 } + prev_errorptr^ := FSERROR (bpreverr + cur); + Inc(cur, delta); { form error * 5 } + bpreverr := belowerr + cur; + belowerr := bnexterr; + Inc(cur, delta); { form error * 7 } + { At this point cur contains the 7/16 error value to be propagated + to the next pixel on the current line, and all the errors for the + next line have been shifted over. We are therefore ready to move on. } + + Inc(input_ptr, dirnc); { advance input ptr to next column } + Inc(output_ptr, dir); { advance output ptr to next column } + + end; + { Post-loop cleanup: we must unload the final error value into the + final fserrors[] entry. Note we need not unload belowerr because + it is for the dummy column before or after the actual array. } + + errorptr^ := FSERROR (bpreverr); { unload prev err into array } + { Nomssi : ?? } + end; + cquantize^.on_odd_row := not cquantize^.on_odd_row; + end; +end; + + +{ Allocate workspace for Floyd-Steinberg errors. } + +{LOCAL} +procedure alloc_fs_workspace (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; + arraysize : size_t; + i : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + arraysize := size_t ((cinfo^.output_width + 2) * SIZEOF(FSERROR)); + for i := 0 to pred(cinfo^.out_color_components) do + begin + cquantize^.fserrors[i] := FS_ERROR_FIELD_PTR( + cinfo^.mem^.alloc_large(j_common_ptr(cinfo), JPOOL_IMAGE, arraysize)); + end; +end; + + +{ Initialize for one-pass color quantization. } + +{METHODDEF} +procedure start_pass_1_quant (cinfo : j_decompress_ptr; + is_pre_scan : boolean); +var + cquantize : my_cquantize_ptr; + arraysize : size_t; + i : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + { Install my colormap. } + cinfo^.colormap := cquantize^.sv_colormap; + cinfo^.actual_number_of_colors := cquantize^.sv_actual; + + { Initialize for desired dithering mode. } + case (cinfo^.dither_mode) of + JDITHER_NONE: + if (cinfo^.out_color_components = 3) then + cquantize^.pub.color_quantize := color_quantize3 + else + cquantize^.pub.color_quantize := color_quantize; + JDITHER_ORDERED: + begin + if (cinfo^.out_color_components = 3) then + cquantize^.pub.color_quantize := quantize3_ord_dither + else + cquantize^.pub.color_quantize := quantize_ord_dither; + cquantize^.row_index := 0; { initialize state for ordered dither } + { If user changed to ordered dither from another mode, + we must recreate the color index table with padding. + This will cost extra space, but probably isn't very likely. } + + if (not cquantize^.is_padded) then + create_colorindex(cinfo); + { Create ordered-dither tables if we didn't already. } + if (cquantize^.odither[0] = NIL) then + create_odither_tables(cinfo); + end; + JDITHER_FS: + begin + cquantize^.pub.color_quantize := quantize_fs_dither; + cquantize^.on_odd_row := FALSE; { initialize state for F-S dither } + { Allocate Floyd-Steinberg workspace if didn't already. } + if (cquantize^.fserrors[0] = NIL) then + alloc_fs_workspace(cinfo); + { Initialize the propagated errors to zero. } + arraysize := size_t ((cinfo^.output_width + 2) * SIZEOF(FSERROR)); + for i := 0 to pred(cinfo^.out_color_components) do + jzero_far({far} pointer( cquantize^.fserrors[i] ), arraysize); + end; + else + ERREXIT(j_common_ptr(cinfo), JERR_NOT_COMPILED); + end; +end; + + +{ Finish up at the end of the pass. } + +{METHODDEF} +procedure finish_pass_1_quant (cinfo : j_decompress_ptr); +begin + { no work in 1-pass case } +end; + + +{ Switch to a new external colormap between output passes. + Shouldn't get to this module! } + +{METHODDEF} +procedure new_color_map_1_quant (cinfo : j_decompress_ptr); +begin + ERREXIT(j_common_ptr(cinfo), JERR_MODE_CHANGE); +end; + + +{ Module initialization routine for 1-pass color quantization. } + +{GLOBAL} +procedure jinit_1pass_quantizer (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; +begin + cquantize := my_cquantize_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_cquantizer))); + cinfo^.cquantize := jpeg_color_quantizer_ptr(cquantize); + cquantize^.pub.start_pass := start_pass_1_quant; + cquantize^.pub.finish_pass := finish_pass_1_quant; + cquantize^.pub.new_color_map := new_color_map_1_quant; + cquantize^.fserrors[0] := NIL; { Flag FS workspace not allocated } + cquantize^.odither[0] := NIL; { Also flag odither arrays not allocated } + + { Make sure my internal arrays won't overflow } + if (cinfo^.out_color_components > MAX_Q_COMPS) then + ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_COMPONENTS, MAX_Q_COMPS); + { Make sure colormap indexes can be represented by JSAMPLEs } + if (cinfo^.desired_number_of_colors > (MAXJSAMPLE+1)) then + ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); + + { Create the colormap and color index table. } + create_colormap(cinfo); + create_colorindex(cinfo); + + { Allocate Floyd-Steinberg workspace now if requested. + We do this now since it is FAR storage and may affect the memory + manager's space calculations. If the user changes to FS dither + mode in a later pass, we will allocate the space then, and will + possibly overrun the max_memory_to_use setting. } + + if (cinfo^.dither_mode = JDITHER_FS) then + alloc_fs_workspace(cinfo); +end; + + +end. diff --git a/src/lib/vampimg/JpegLib/imjquant2.pas b/src/lib/vampimg/JpegLib/imjquant2.pas new file mode 100644 index 0000000..5d4e4dc --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjquant2.pas @@ -0,0 +1,1551 @@ +unit imjquant2; + + +{ This file contains 2-pass color quantization (color mapping) routines. + These routines provide selection of a custom color map for an image, + followed by mapping of the image to that color map, with optional + Floyd-Steinberg dithering. + It is also possible to use just the second pass to map to an arbitrary + externally-given color map. + + Note: ordered dithering is not supported, since there isn't any fast + way to compute intercolor distances; it's unclear that ordered dither's + fundamental assumptions even hold with an irregularly spaced color map. } + +{ Original: jquant2.c; Copyright (C) 1991-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjdeferr, + imjerror, + imjutils, + imjpeglib; + +{ Module initialization routine for 2-pass color quantization. } + + +{GLOBAL} +procedure jinit_2pass_quantizer (cinfo : j_decompress_ptr); + +implementation + +{ This module implements the well-known Heckbert paradigm for color + quantization. Most of the ideas used here can be traced back to + Heckbert's seminal paper + Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", + Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. + + In the first pass over the image, we accumulate a histogram showing the + usage count of each possible color. To keep the histogram to a reasonable + size, we reduce the precision of the input; typical practice is to retain + 5 or 6 bits per color, so that 8 or 4 different input values are counted + in the same histogram cell. + + Next, the color-selection step begins with a box representing the whole + color space, and repeatedly splits the "largest" remaining box until we + have as many boxes as desired colors. Then the mean color in each + remaining box becomes one of the possible output colors. + + The second pass over the image maps each input pixel to the closest output + color (optionally after applying a Floyd-Steinberg dithering correction). + This mapping is logically trivial, but making it go fast enough requires + considerable care. + + Heckbert-style quantizers vary a good deal in their policies for choosing + the "largest" box and deciding where to cut it. The particular policies + used here have proved out well in experimental comparisons, but better ones + may yet be found. + + In earlier versions of the IJG code, this module quantized in YCbCr color + space, processing the raw upsampled data without a color conversion step. + This allowed the color conversion math to be done only once per colormap + entry, not once per pixel. However, that optimization precluded other + useful optimizations (such as merging color conversion with upsampling) + and it also interfered with desired capabilities such as quantizing to an + externally-supplied colormap. We have therefore abandoned that approach. + The present code works in the post-conversion color space, typically RGB. + + To improve the visual quality of the results, we actually work in scaled + RGB space, giving G distances more weight than R, and R in turn more than + B. To do everything in integer math, we must use integer scale factors. + The 2/3/1 scale factors used here correspond loosely to the relative + weights of the colors in the NTSC grayscale equation. + If you want to use this code to quantize a non-RGB color space, you'll + probably need to change these scale factors. } + +const + R_SCALE = 2; { scale R distances by this much } + G_SCALE = 3; { scale G distances by this much } + B_SCALE = 1; { and B by this much } + +{ Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined + in jmorecfg.h. As the code stands, it will do the right thing for R,G,B + and B,G,R orders. If you define some other weird order in jmorecfg.h, + you'll get compile errors until you extend this logic. In that case + you'll probably want to tweak the histogram sizes too. } + +{$ifdef RGB_RED_IS_0} +const + C0_SCALE = R_SCALE; + C1_SCALE = G_SCALE; + C2_SCALE = B_SCALE; +{$else} +const + C0_SCALE = B_SCALE; + C1_SCALE = G_SCALE; + C2_SCALE = R_SCALE; +{$endif} + + +{ First we have the histogram data structure and routines for creating it. + + The number of bits of precision can be adjusted by changing these symbols. + We recommend keeping 6 bits for G and 5 each for R and B. + If you have plenty of memory and cycles, 6 bits all around gives marginally + better results; if you are short of memory, 5 bits all around will save + some space but degrade the results. + To maintain a fully accurate histogram, we'd need to allocate a "long" + (preferably unsigned long) for each cell. In practice this is overkill; + we can get by with 16 bits per cell. Few of the cell counts will overflow, + and clamping those that do overflow to the maximum value will give close- + enough results. This reduces the recommended histogram size from 256Kb + to 128Kb, which is a useful savings on PC-class machines. + (In the second pass the histogram space is re-used for pixel mapping data; + in that capacity, each cell must be able to store zero to the number of + desired colors. 16 bits/cell is plenty for that too.) + Since the JPEG code is intended to run in small memory model on 80x86 + machines, we can't just allocate the histogram in one chunk. Instead + of a true 3-D array, we use a row of pointers to 2-D arrays. Each + pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and + each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that + on 80x86 machines, the pointer row is in near memory but the actual + arrays are in far memory (same arrangement as we use for image arrays). } + + +const + MAXNUMCOLORS = (MAXJSAMPLE+1); { maximum size of colormap } + +{ These will do the right thing for either R,G,B or B,G,R color order, + but you may not like the results for other color orders. } + +const + HIST_C0_BITS = 5; { bits of precision in R/B histogram } + HIST_C1_BITS = 6; { bits of precision in G histogram } + HIST_C2_BITS = 5; { bits of precision in B/R histogram } + +{ Number of elements along histogram axes. } +const + HIST_C0_ELEMS = (1 shl HIST_C0_BITS); + HIST_C1_ELEMS = (1 shl HIST_C1_BITS); + HIST_C2_ELEMS = (1 shl HIST_C2_BITS); + +{ These are the amounts to shift an input value to get a histogram index. } +const + C0_SHIFT = (BITS_IN_JSAMPLE-HIST_C0_BITS); + C1_SHIFT = (BITS_IN_JSAMPLE-HIST_C1_BITS); + C2_SHIFT = (BITS_IN_JSAMPLE-HIST_C2_BITS); + + +type { Nomssi } + RGBptr = ^RGBtype; + RGBtype = packed record + r,g,b : JSAMPLE; + end; +type + histcell = UINT16; { histogram cell; prefer an unsigned type } + +type + histptr = ^histcell {FAR}; { for pointers to histogram cells } + +type + hist1d = array[0..HIST_C2_ELEMS-1] of histcell; { typedefs for the array } + {hist1d_ptr = ^hist1d;} + hist1d_field = array[0..HIST_C1_ELEMS-1] of hist1d; + { type for the 2nd-level pointers } + hist2d = ^hist1d_field; + hist2d_field = array[0..HIST_C0_ELEMS-1] of hist2d; + hist3d = ^hist2d_field; { type for top-level pointer } + + +{ Declarations for Floyd-Steinberg dithering. + + Errors are accumulated into the array fserrors[], at a resolution of + 1/16th of a pixel count. The error at a given pixel is propagated + to its not-yet-processed neighbors using the standard F-S fractions, + ... (here) 7/16 + 3/16 5/16 1/16 + We work left-to-right on even rows, right-to-left on odd rows. + + We can get away with a single array (holding one row's worth of errors) + by using it to store the current row's errors at pixel columns not yet + processed, but the next row's errors at columns already processed. We + need only a few extra variables to hold the errors immediately around the + current column. (If we are lucky, those variables are in registers, but + even if not, they're probably cheaper to access than array elements are.) + + The fserrors[] array has (#columns + 2) entries; the extra entry at + each end saves us from special-casing the first and last pixels. + Each entry is three values long, one value for each color component. + + Note: on a wide image, we might not have enough room in a PC's near data + segment to hold the error array; so it is allocated with alloc_large. } + + +{$ifdef BITS_IN_JSAMPLE_IS_8} +type + FSERROR = INT16; { 16 bits should be enough } + LOCFSERROR = int; { use 'int' for calculation temps } +{$else} +type + FSERROR = INT32; { may need more than 16 bits } + LOCFSERROR = INT32; { be sure calculation temps are big enough } +{$endif} +type { Nomssi } + RGB_FSERROR_PTR = ^RGB_FSERROR; + RGB_FSERROR = packed record + r,g,b : FSERROR; + end; + LOCRGB_FSERROR = packed record + r,g,b : LOCFSERROR; + end; + +type + FSERROR_PTR = ^FSERROR; + jFSError = 0..(MaxInt div SIZEOF(RGB_FSERROR))-1; + FS_ERROR_FIELD = array[jFSError] of RGB_FSERROR; + FS_ERROR_FIELD_PTR = ^FS_ERROR_FIELD;{far} + { pointer to error array (in FAR storage!) } + +type + error_limit_array = array[-MAXJSAMPLE..MAXJSAMPLE] of int; + { table for clamping the applied error } + error_limit_ptr = ^error_limit_array; + +{ Private subobject } +type + my_cquantize_ptr = ^my_cquantizer; + my_cquantizer = record + pub : jpeg_color_quantizer; { public fields } + + { Space for the eventually created colormap is stashed here } + sv_colormap : JSAMPARRAY; { colormap allocated at init time } + desired : int; { desired # of colors = size of colormap } + + { Variables for accumulating image statistics } + histogram : hist3d; { pointer to the histogram } + + needs_zeroed : boolean; { TRUE if next pass must zero histogram } + + { Variables for Floyd-Steinberg dithering } + fserrors : FS_ERROR_FIELD_PTR; { accumulated errors } + on_odd_row : boolean; { flag to remember which row we are on } + error_limiter : error_limit_ptr; { table for clamping the applied error } + end; + + + +{ Prescan some rows of pixels. + In this module the prescan simply updates the histogram, which has been + initialized to zeroes by start_pass. + An output_buf parameter is required by the method signature, but no data + is actually output (in fact the buffer controller is probably passing a + NIL pointer). } + +{METHODDEF} +procedure prescan_quantize (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +var + cquantize : my_cquantize_ptr; + {register} ptr : RGBptr; + {register} histp : histptr; + {register} histogram : hist3d; + row : int; + col : JDIMENSION; + width : JDIMENSION; +begin + cquantize := my_cquantize_ptr(cinfo^.cquantize); + histogram := cquantize^.histogram; + width := cinfo^.output_width; + + for row := 0 to pred(num_rows) do + begin + ptr := RGBptr(input_buf^[row]); + for col := pred(width) downto 0 do + begin + { get pixel value and index into the histogram } + histp := @(histogram^[GETJSAMPLE(ptr^.r) shr C0_SHIFT]^ + [GETJSAMPLE(ptr^.g) shr C1_SHIFT] + [GETJSAMPLE(ptr^.b) shr C2_SHIFT]); + { increment, check for overflow and undo increment if so. } + Inc(histp^); + if (histp^ <= 0) then + Dec(histp^); + Inc(ptr); + end; + end; +end; + +{ Next we have the really interesting routines: selection of a colormap + given the completed histogram. + These routines work with a list of "boxes", each representing a rectangular + subset of the input color space (to histogram precision). } + +type + box = record + { The bounds of the box (inclusive); expressed as histogram indexes } + c0min, c0max : int; + c1min, c1max : int; + c2min, c2max : int; + { The volume (actually 2-norm) of the box } + volume : INT32; + { The number of nonzero histogram cells within this box } + colorcount : long; + end; + +type + jBoxList = 0..(MaxInt div SizeOf(box))-1; + box_field = array[jBoxlist] of box; + boxlistptr = ^box_field; + boxptr = ^box; + +{LOCAL} +function find_biggest_color_pop (boxlist : boxlistptr; numboxes : int) : boxptr; +{ Find the splittable box with the largest color population } +{ Returns NIL if no splittable boxes remain } +var + boxp : boxptr ; {register} + i : int; {register} + maxc : long; {register} + which : boxptr; +begin + which := NIL; + boxp := @(boxlist^[0]); + maxc := 0; + for i := 0 to pred(numboxes) do + begin + if (boxp^.colorcount > maxc) and (boxp^.volume > 0) then + begin + which := boxp; + maxc := boxp^.colorcount; + end; + Inc(boxp); + end; + find_biggest_color_pop := which; +end; + + +{LOCAL} +function find_biggest_volume (boxlist : boxlistptr; numboxes : int) : boxptr; +{ Find the splittable box with the largest (scaled) volume } +{ Returns NULL if no splittable boxes remain } +var + {register} boxp : boxptr; + {register} i : int; + {register} maxv : INT32; + which : boxptr; +begin + maxv := 0; + which := NIL; + boxp := @(boxlist^[0]); + for i := 0 to pred(numboxes) do + begin + if (boxp^.volume > maxv) then + begin + which := boxp; + maxv := boxp^.volume; + end; + Inc(boxp); + end; + find_biggest_volume := which; +end; + + +{LOCAL} +procedure update_box (cinfo : j_decompress_ptr; var boxp : box); +label + have_c0min, have_c0max, + have_c1min, have_c1max, + have_c2min, have_c2max; +{ Shrink the min/max bounds of a box to enclose only nonzero elements, } +{ and recompute its volume and population } +var + cquantize : my_cquantize_ptr; + histogram : hist3d; + histp : histptr; + c0,c1,c2 : int; + c0min,c0max,c1min,c1max,c2min,c2max : int; + dist0,dist1,dist2 : INT32; + ccount : long; +begin + cquantize := my_cquantize_ptr(cinfo^.cquantize); + histogram := cquantize^.histogram; + + c0min := boxp.c0min; c0max := boxp.c0max; + c1min := boxp.c1min; c1max := boxp.c1max; + c2min := boxp.c2min; c2max := boxp.c2max; + + if (c0max > c0min) then + for c0 := c0min to c0max do + for c1 := c1min to c1max do + begin + histp := @(histogram^[c0]^[c1][c2min]); + for c2 := c2min to c2max do + begin + if (histp^ <> 0) then + begin + c0min := c0; + boxp.c0min := c0min; + goto have_c0min; + end; + Inc(histp); + end; + end; + have_c0min: + if (c0max > c0min) then + for c0 := c0max downto c0min do + for c1 := c1min to c1max do + begin + histp := @(histogram^[c0]^[c1][c2min]); + for c2 := c2min to c2max do + begin + if ( histp^ <> 0) then + begin + c0max := c0; + boxp.c0max := c0; + goto have_c0max; + end; + Inc(histp); + end; + end; + have_c0max: + if (c1max > c1min) then + for c1 := c1min to c1max do + for c0 := c0min to c0max do + begin + histp := @(histogram^[c0]^[c1][c2min]); + for c2 := c2min to c2max do + begin + if (histp^ <> 0) then + begin + c1min := c1; + boxp.c1min := c1; + goto have_c1min; + end; + Inc(histp); + end; + end; + have_c1min: + if (c1max > c1min) then + for c1 := c1max downto c1min do + for c0 := c0min to c0max do + begin + histp := @(histogram^[c0]^[c1][c2min]); + for c2 := c2min to c2max do + begin + if (histp^ <> 0) then + begin + c1max := c1; + boxp.c1max := c1; + goto have_c1max; + end; + Inc(histp); + end; + end; + have_c1max: + if (c2max > c2min) then + for c2 := c2min to c2max do + for c0 := c0min to c0max do + begin + histp := @(histogram^[c0]^[c1min][c2]); + for c1 := c1min to c1max do + begin + if (histp^ <> 0) then + begin + c2min := c2; + boxp.c2min := c2min; + goto have_c2min; + end; + Inc(histp, HIST_C2_ELEMS); + end; + end; + have_c2min: + if (c2max > c2min) then + for c2 := c2max downto c2min do + for c0 := c0min to c0max do + begin + histp := @(histogram^[c0]^[c1min][c2]); + for c1 := c1min to c1max do + begin + if (histp^ <> 0) then + begin + c2max := c2; + boxp.c2max := c2max; + goto have_c2max; + end; + Inc(histp, HIST_C2_ELEMS); + end; + end; + have_c2max: + + { Update box volume. + We use 2-norm rather than real volume here; this biases the method + against making long narrow boxes, and it has the side benefit that + a box is splittable iff norm > 0. + Since the differences are expressed in histogram-cell units, + we have to shift back to JSAMPLE units to get consistent distances; + after which, we scale according to the selected distance scale factors.} + + dist0 := ((c0max - c0min) shl C0_SHIFT) * C0_SCALE; + dist1 := ((c1max - c1min) shl C1_SHIFT) * C1_SCALE; + dist2 := ((c2max - c2min) shl C2_SHIFT) * C2_SCALE; + boxp.volume := dist0*dist0 + dist1*dist1 + dist2*dist2; + + { Now scan remaining volume of box and compute population } + ccount := 0; + for c0 := c0min to c0max do + for c1 := c1min to c1max do + begin + histp := @(histogram^[c0]^[c1][c2min]); + for c2 := c2min to c2max do + begin + if (histp^ <> 0) then + Inc(ccount); + Inc(histp); + end; + end; + boxp.colorcount := ccount; +end; + + +{LOCAL} +function median_cut (cinfo : j_decompress_ptr; boxlist : boxlistptr; + numboxes : int; desired_colors : int) : int; +{ Repeatedly select and split the largest box until we have enough boxes } +var + n,lb : int; + c0,c1,c2,cmax : int; + {register} b1,b2 : boxptr; +begin + while (numboxes < desired_colors) do + begin + { Select box to split. + Current algorithm: by population for first half, then by volume. } + + if (numboxes*2 <= desired_colors) then + b1 := find_biggest_color_pop(boxlist, numboxes) + else + b1 := find_biggest_volume(boxlist, numboxes); + + if (b1 = NIL) then { no splittable boxes left! } + break; + b2 := @(boxlist^[numboxes]); { where new box will go } + { Copy the color bounds to the new box. } + b2^.c0max := b1^.c0max; b2^.c1max := b1^.c1max; b2^.c2max := b1^.c2max; + b2^.c0min := b1^.c0min; b2^.c1min := b1^.c1min; b2^.c2min := b1^.c2min; + { Choose which axis to split the box on. + Current algorithm: longest scaled axis. + See notes in update_box about scaling distances. } + + c0 := ((b1^.c0max - b1^.c0min) shl C0_SHIFT) * C0_SCALE; + c1 := ((b1^.c1max - b1^.c1min) shl C1_SHIFT) * C1_SCALE; + c2 := ((b1^.c2max - b1^.c2min) shl C2_SHIFT) * C2_SCALE; + { We want to break any ties in favor of green, then red, blue last. + This code does the right thing for R,G,B or B,G,R color orders only. } + +{$ifdef RGB_RED_IS_0} + cmax := c1; n := 1; + if (c0 > cmax) then + begin + cmax := c0; + n := 0; + end; + if (c2 > cmax) then + n := 2; +{$else} + cmax := c1; + n := 1; + if (c2 > cmax) then + begin + cmax := c2; + n := 2; + end; + if (c0 > cmax) then + n := 0; +{$endif} + { Choose split point along selected axis, and update box bounds. + Current algorithm: split at halfway point. + (Since the box has been shrunk to minimum volume, + any split will produce two nonempty subboxes.) + Note that lb value is max for lower box, so must be < old max. } + + case n of + 0:begin + lb := (b1^.c0max + b1^.c0min) div 2; + b1^.c0max := lb; + b2^.c0min := lb+1; + end; + 1:begin + lb := (b1^.c1max + b1^.c1min) div 2; + b1^.c1max := lb; + b2^.c1min := lb+1; + end; + 2:begin + lb := (b1^.c2max + b1^.c2min) div 2; + b1^.c2max := lb; + b2^.c2min := lb+1; + end; + end; + { Update stats for boxes } + update_box(cinfo, b1^); + update_box(cinfo, b2^); + Inc(numboxes); + end; + median_cut := numboxes; +end; + + +{LOCAL} +procedure compute_color (cinfo : j_decompress_ptr; + const boxp : box; icolor : int); +{ Compute representative color for a box, put it in colormap[icolor] } +var + { Current algorithm: mean weighted by pixels (not colors) } + { Note it is important to get the rounding correct! } + cquantize : my_cquantize_ptr; + histogram : hist3d; + histp : histptr; + c0,c1,c2 : int; + c0min,c0max,c1min,c1max,c2min,c2max : int; + count : long; + total : long; + c0total : long; + c1total : long; + c2total : long; +begin + cquantize := my_cquantize_ptr(cinfo^.cquantize); + histogram := cquantize^.histogram; + total := 0; + c0total := 0; + c1total := 0; + c2total := 0; + + c0min := boxp.c0min; c0max := boxp.c0max; + c1min := boxp.c1min; c1max := boxp.c1max; + c2min := boxp.c2min; c2max := boxp.c2max; + + for c0 := c0min to c0max do + for c1 := c1min to c1max do + begin + histp := @(histogram^[c0]^[c1][c2min]); + for c2 := c2min to c2max do + begin + count := histp^; + Inc(histp); + if (count <> 0) then + begin + Inc(total, count); + Inc(c0total, ((c0 shl C0_SHIFT) + ((1 shl C0_SHIFT) shr 1)) * count); + Inc(c1total, ((c1 shl C1_SHIFT) + ((1 shl C1_SHIFT) shr 1)) * count); + Inc(c2total, ((c2 shl C2_SHIFT) + ((1 shl C2_SHIFT) shr 1)) * count); + end; + end; + end; + + cinfo^.colormap^[0]^[icolor] := JSAMPLE ((c0total + (total shr 1)) div total); + cinfo^.colormap^[1]^[icolor] := JSAMPLE ((c1total + (total shr 1)) div total); + cinfo^.colormap^[2]^[icolor] := JSAMPLE ((c2total + (total shr 1)) div total); +end; + + +{LOCAL} +procedure select_colors (cinfo : j_decompress_ptr; desired_colors : int); +{ Master routine for color selection } +var + boxlist : boxlistptr; + numboxes : int; + i : int; +begin + { Allocate workspace for box list } + boxlist := boxlistptr(cinfo^.mem^.alloc_small( + j_common_ptr(cinfo), JPOOL_IMAGE, desired_colors * SIZEOF(box))); + { Initialize one box containing whole space } + numboxes := 1; + boxlist^[0].c0min := 0; + boxlist^[0].c0max := MAXJSAMPLE shr C0_SHIFT; + boxlist^[0].c1min := 0; + boxlist^[0].c1max := MAXJSAMPLE shr C1_SHIFT; + boxlist^[0].c2min := 0; + boxlist^[0].c2max := MAXJSAMPLE shr C2_SHIFT; + { Shrink it to actually-used volume and set its statistics } + update_box(cinfo, boxlist^[0]); + { Perform median-cut to produce final box list } + numboxes := median_cut(cinfo, boxlist, numboxes, desired_colors); + { Compute the representative color for each box, fill colormap } + for i := 0 to pred(numboxes) do + compute_color(cinfo, boxlist^[i], i); + cinfo^.actual_number_of_colors := numboxes; + {$IFDEF DEBUG} + TRACEMS1(j_common_ptr(cinfo), 1, JTRC_QUANT_SELECTED, numboxes); + {$ENDIF} +end; + + +{ These routines are concerned with the time-critical task of mapping input + colors to the nearest color in the selected colormap. + + We re-use the histogram space as an "inverse color map", essentially a + cache for the results of nearest-color searches. All colors within a + histogram cell will be mapped to the same colormap entry, namely the one + closest to the cell's center. This may not be quite the closest entry to + the actual input color, but it's almost as good. A zero in the cache + indicates we haven't found the nearest color for that cell yet; the array + is cleared to zeroes before starting the mapping pass. When we find the + nearest color for a cell, its colormap index plus one is recorded in the + cache for future use. The pass2 scanning routines call fill_inverse_cmap + when they need to use an unfilled entry in the cache. + + Our method of efficiently finding nearest colors is based on the "locally + sorted search" idea described by Heckbert and on the incremental distance + calculation described by Spencer W. Thomas in chapter III.1 of Graphics + Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that + the distances from a given colormap entry to each cell of the histogram can + be computed quickly using an incremental method: the differences between + distances to adjacent cells themselves differ by a constant. This allows a + fairly fast implementation of the "brute force" approach of computing the + distance from every colormap entry to every histogram cell. Unfortunately, + it needs a work array to hold the best-distance-so-far for each histogram + cell (because the inner loop has to be over cells, not colormap entries). + The work array elements have to be INT32s, so the work array would need + 256Kb at our recommended precision. This is not feasible in DOS machines. + + To get around these problems, we apply Thomas' method to compute the + nearest colors for only the cells within a small subbox of the histogram. + The work array need be only as big as the subbox, so the memory usage + problem is solved. Furthermore, we need not fill subboxes that are never + referenced in pass2; many images use only part of the color gamut, so a + fair amount of work is saved. An additional advantage of this + approach is that we can apply Heckbert's locality criterion to quickly + eliminate colormap entries that are far away from the subbox; typically + three-fourths of the colormap entries are rejected by Heckbert's criterion, + and we need not compute their distances to individual cells in the subbox. + The speed of this approach is heavily influenced by the subbox size: too + small means too much overhead, too big loses because Heckbert's criterion + can't eliminate as many colormap entries. Empirically the best subbox + size seems to be about 1/512th of the histogram (1/8th in each direction). + + Thomas' article also describes a refined method which is asymptotically + faster than the brute-force method, but it is also far more complex and + cannot efficiently be applied to small subboxes. It is therefore not + useful for programs intended to be portable to DOS machines. On machines + with plenty of memory, filling the whole histogram in one shot with Thomas' + refined method might be faster than the present code --- but then again, + it might not be any faster, and it's certainly more complicated. } + + + +{ log2(histogram cells in update box) for each axis; this can be adjusted } +const + BOX_C0_LOG = (HIST_C0_BITS-3); + BOX_C1_LOG = (HIST_C1_BITS-3); + BOX_C2_LOG = (HIST_C2_BITS-3); + + BOX_C0_ELEMS = (1 shl BOX_C0_LOG); { # of hist cells in update box } + BOX_C1_ELEMS = (1 shl BOX_C1_LOG); + BOX_C2_ELEMS = (1 shl BOX_C2_LOG); + + BOX_C0_SHIFT = (C0_SHIFT + BOX_C0_LOG); + BOX_C1_SHIFT = (C1_SHIFT + BOX_C1_LOG); + BOX_C2_SHIFT = (C2_SHIFT + BOX_C2_LOG); + + +{ The next three routines implement inverse colormap filling. They could + all be folded into one big routine, but splitting them up this way saves + some stack space (the mindist[] and bestdist[] arrays need not coexist) + and may allow some compilers to produce better code by registerizing more + inner-loop variables. } + +{LOCAL} +function find_nearby_colors (cinfo : j_decompress_ptr; + minc0 : int; minc1 : int; minc2 : int; + var colorlist : array of JSAMPLE) : int; +{ Locate the colormap entries close enough to an update box to be candidates + for the nearest entry to some cell(s) in the update box. The update box + is specified by the center coordinates of its first cell. The number of + candidate colormap entries is returned, and their colormap indexes are + placed in colorlist[]. + This routine uses Heckbert's "locally sorted search" criterion to select + the colors that need further consideration. } + +var + numcolors : int; + maxc0, maxc1, maxc2 : int; + centerc0, centerc1, centerc2 : int; + i, x, ncolors : int; + minmaxdist, min_dist, max_dist, tdist : INT32; + mindist : array[0..MAXNUMCOLORS-1] of INT32; + { min distance to colormap entry i } +begin + numcolors := cinfo^.actual_number_of_colors; + + { Compute true coordinates of update box's upper corner and center. + Actually we compute the coordinates of the center of the upper-corner + histogram cell, which are the upper bounds of the volume we care about. + Note that since ">>" rounds down, the "center" values may be closer to + min than to max; hence comparisons to them must be "<=", not "<". } + + maxc0 := minc0 + ((1 shl BOX_C0_SHIFT) - (1 shl C0_SHIFT)); + centerc0 := (minc0 + maxc0) shr 1; + maxc1 := minc1 + ((1 shl BOX_C1_SHIFT) - (1 shl C1_SHIFT)); + centerc1 := (minc1 + maxc1) shr 1; + maxc2 := minc2 + ((1 shl BOX_C2_SHIFT) - (1 shl C2_SHIFT)); + centerc2 := (minc2 + maxc2) shr 1; + + { For each color in colormap, find: + 1. its minimum squared-distance to any point in the update box + (zero if color is within update box); + 2. its maximum squared-distance to any point in the update box. + Both of these can be found by considering only the corners of the box. + We save the minimum distance for each color in mindist[]; + only the smallest maximum distance is of interest. } + + minmaxdist := long($7FFFFFFF); + + for i := 0 to pred(numcolors) do + begin + { We compute the squared-c0-distance term, then add in the other two. } + x := GETJSAMPLE(cinfo^.colormap^[0]^[i]); + if (x < minc0) then + begin + tdist := (x - minc0) * C0_SCALE; + min_dist := tdist*tdist; + tdist := (x - maxc0) * C0_SCALE; + max_dist := tdist*tdist; + end + else + if (x > maxc0) then + begin + tdist := (x - maxc0) * C0_SCALE; + min_dist := tdist*tdist; + tdist := (x - minc0) * C0_SCALE; + max_dist := tdist*tdist; + end + else + begin + { within cell range so no contribution to min_dist } + min_dist := 0; + if (x <= centerc0) then + begin + tdist := (x - maxc0) * C0_SCALE; + max_dist := tdist*tdist; + end + else + begin + tdist := (x - minc0) * C0_SCALE; + max_dist := tdist*tdist; + end; + end; + + x := GETJSAMPLE(cinfo^.colormap^[1]^[i]); + if (x < minc1) then + begin + tdist := (x - minc1) * C1_SCALE; + Inc(min_dist, tdist*tdist); + tdist := (x - maxc1) * C1_SCALE; + Inc(max_dist, tdist*tdist); + end + else + if (x > maxc1) then + begin + tdist := (x - maxc1) * C1_SCALE; + Inc(min_dist, tdist*tdist); + tdist := (x - minc1) * C1_SCALE; + Inc(max_dist, tdist*tdist); + end + else + begin + { within cell range so no contribution to min_dist } + if (x <= centerc1) then + begin + tdist := (x - maxc1) * C1_SCALE; + Inc(max_dist, tdist*tdist); + end + else + begin + tdist := (x - minc1) * C1_SCALE; + Inc(max_dist, tdist*tdist); + end + end; + + x := GETJSAMPLE(cinfo^.colormap^[2]^[i]); + if (x < minc2) then + begin + tdist := (x - minc2) * C2_SCALE; + Inc(min_dist, tdist*tdist); + tdist := (x - maxc2) * C2_SCALE; + Inc(max_dist, tdist*tdist); + end + else + if (x > maxc2) then + begin + tdist := (x - maxc2) * C2_SCALE; + Inc(min_dist, tdist*tdist); + tdist := (x - minc2) * C2_SCALE; + Inc(max_dist, tdist*tdist); + end + else + begin + { within cell range so no contribution to min_dist } + if (x <= centerc2) then + begin + tdist := (x - maxc2) * C2_SCALE; + Inc(max_dist, tdist*tdist); + end + else + begin + tdist := (x - minc2) * C2_SCALE; + Inc(max_dist, tdist*tdist); + end; + end; + + mindist[i] := min_dist; { save away the results } + if (max_dist < minmaxdist) then + minmaxdist := max_dist; + end; + + { Now we know that no cell in the update box is more than minmaxdist + away from some colormap entry. Therefore, only colors that are + within minmaxdist of some part of the box need be considered. } + + ncolors := 0; + for i := 0 to pred(numcolors) do + begin + if (mindist[i] <= minmaxdist) then + begin + colorlist[ncolors] := JSAMPLE(i); + Inc(ncolors); + end; + end; + find_nearby_colors := ncolors; +end; + + +{LOCAL} +procedure find_best_colors (cinfo : j_decompress_ptr; + minc0 : int; minc1 : int; minc2 : int; + numcolors : int; + var colorlist : array of JSAMPLE; + var bestcolor : array of JSAMPLE); +{ Find the closest colormap entry for each cell in the update box, + given the list of candidate colors prepared by find_nearby_colors. + Return the indexes of the closest entries in the bestcolor[] array. + This routine uses Thomas' incremental distance calculation method to + find the distance from a colormap entry to successive cells in the box. } +const + { Nominal steps between cell centers ("x" in Thomas article) } + STEP_C0 = ((1 shl C0_SHIFT) * C0_SCALE); + STEP_C1 = ((1 shl C1_SHIFT) * C1_SCALE); + STEP_C2 = ((1 shl C2_SHIFT) * C2_SCALE); +var + ic0, ic1, ic2 : int; + i, icolor : int; + {register} bptr : INT32PTR; { pointer into bestdist[] array } + cptr : JSAMPLE_PTR; { pointer into bestcolor[] array } + dist0, dist1 : INT32; { initial distance values } + {register} dist2 : INT32; { current distance in inner loop } + xx0, xx1 : INT32; { distance increments } + {register} xx2 : INT32; + inc0, inc1, inc2 : INT32; { initial values for increments } + { This array holds the distance to the nearest-so-far color for each cell } + bestdist : array[0..BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS-1] of INT32; +begin + { Initialize best-distance for each cell of the update box } + for i := BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1 downto 0 do + bestdist[i] := $7FFFFFFF; + + { For each color selected by find_nearby_colors, + compute its distance to the center of each cell in the box. + If that's less than best-so-far, update best distance and color number. } + + + + for i := 0 to pred(numcolors) do + begin + icolor := GETJSAMPLE(colorlist[i]); + { Compute (square of) distance from minc0/c1/c2 to this color } + inc0 := (minc0 - GETJSAMPLE(cinfo^.colormap^[0]^[icolor])) * C0_SCALE; + dist0 := inc0*inc0; + inc1 := (minc1 - GETJSAMPLE(cinfo^.colormap^[1]^[icolor])) * C1_SCALE; + Inc(dist0, inc1*inc1); + inc2 := (minc2 - GETJSAMPLE(cinfo^.colormap^[2]^[icolor])) * C2_SCALE; + Inc(dist0, inc2*inc2); + { Form the initial difference increments } + inc0 := inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 := inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 := inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + { Now loop over all cells in box, updating distance per Thomas method } + bptr := @bestdist[0]; + cptr := @bestcolor[0]; + xx0 := inc0; + for ic0 := BOX_C0_ELEMS-1 downto 0 do + begin + dist1 := dist0; + xx1 := inc1; + for ic1 := BOX_C1_ELEMS-1 downto 0 do + begin + dist2 := dist1; + xx2 := inc2; + for ic2 := BOX_C2_ELEMS-1 downto 0 do + begin + if (dist2 < bptr^) then + begin + bptr^ := dist2; + cptr^ := JSAMPLE (icolor); + end; + Inc(dist2, xx2); + Inc(xx2, 2 * STEP_C2 * STEP_C2); + Inc(bptr); + Inc(cptr); + end; + Inc(dist1, xx1); + Inc(xx1, 2 * STEP_C1 * STEP_C1); + end; + Inc(dist0, xx0); + Inc(xx0, 2 * STEP_C0 * STEP_C0); + end; + end; +end; + + +{LOCAL} +procedure fill_inverse_cmap (cinfo : j_decompress_ptr; + c0 : int; c1 : int; c2 : int); +{ Fill the inverse-colormap entries in the update box that contains } +{ histogram cell c0/c1/c2. (Only that one cell MUST be filled, but } +{ we can fill as many others as we wish.) } +var + cquantize : my_cquantize_ptr; + histogram : hist3d; + minc0, minc1, minc2 : int; { lower left corner of update box } + ic0, ic1, ic2 : int; + {register} cptr : JSAMPLE_PTR; { pointer into bestcolor[] array } + {register} cachep : histptr; { pointer into main cache array } + { This array lists the candidate colormap indexes. } + colorlist : array[0..MAXNUMCOLORS-1] of JSAMPLE; + numcolors : int; { number of candidate colors } + { This array holds the actually closest colormap index for each cell. } + bestcolor : array[0..BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS-1] of JSAMPLE; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + histogram := cquantize^.histogram; + + { Convert cell coordinates to update box ID } + c0 := c0 shr BOX_C0_LOG; + c1 := c1 shr BOX_C1_LOG; + c2 := c2 shr BOX_C2_LOG; + + { Compute true coordinates of update box's origin corner. + Actually we compute the coordinates of the center of the corner + histogram cell, which are the lower bounds of the volume we care about.} + + minc0 := (c0 shl BOX_C0_SHIFT) + ((1 shl C0_SHIFT) shr 1); + minc1 := (c1 shl BOX_C1_SHIFT) + ((1 shl C1_SHIFT) shr 1); + minc2 := (c2 shl BOX_C2_SHIFT) + ((1 shl C2_SHIFT) shr 1); + + { Determine which colormap entries are close enough to be candidates + for the nearest entry to some cell in the update box. } + + numcolors := find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); + + { Determine the actually nearest colors. } + find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, + bestcolor); + + { Save the best color numbers (plus 1) in the main cache array } + c0 := c0 shl BOX_C0_LOG; { convert ID back to base cell indexes } + c1 := c1 shl BOX_C1_LOG; + c2 := c2 shl BOX_C2_LOG; + cptr := @(bestcolor[0]); + for ic0 := 0 to pred(BOX_C0_ELEMS) do + for ic1 := 0 to pred(BOX_C1_ELEMS) do + begin + cachep := @(histogram^[c0+ic0]^[c1+ic1][c2]); + for ic2 := 0 to pred(BOX_C2_ELEMS) do + begin + cachep^ := histcell (GETJSAMPLE(cptr^) + 1); + Inc(cachep); + Inc(cptr); + end; + end; +end; + + +{ Map some rows of pixels to the output colormapped representation. } + +{METHODDEF} +procedure pass2_no_dither (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +{ This version performs no dithering } +var + cquantize : my_cquantize_ptr; + histogram : hist3d; + {register} inptr : RGBptr; + outptr : JSAMPLE_PTR; + {register} cachep : histptr; + {register} c0, c1, c2 : int; + row : int; + col : JDIMENSION; + width : JDIMENSION; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + histogram := cquantize^.histogram; + width := cinfo^.output_width; + + for row := 0 to pred(num_rows) do + begin + inptr := RGBptr(input_buf^[row]); + outptr := JSAMPLE_PTR(output_buf^[row]); + for col := pred(width) downto 0 do + begin + { get pixel value and index into the cache } + c0 := GETJSAMPLE(inptr^.r) shr C0_SHIFT; + c1 := GETJSAMPLE(inptr^.g) shr C1_SHIFT; + c2 := GETJSAMPLE(inptr^.b) shr C2_SHIFT; + Inc(inptr); + cachep := @(histogram^[c0]^[c1][c2]); + { If we have not seen this color before, find nearest colormap entry } + { and update the cache } + if (cachep^ = 0) then + fill_inverse_cmap(cinfo, c0,c1,c2); + { Now emit the colormap index for this cell } + outptr^ := JSAMPLE (cachep^ - 1); + Inc(outptr); + end; + end; +end; + + +{METHODDEF} +procedure pass2_fs_dither (cinfo : j_decompress_ptr; + input_buf : JSAMPARRAY; + output_buf : JSAMPARRAY; + num_rows : int); +{ This version performs Floyd-Steinberg dithering } +var + cquantize : my_cquantize_ptr; + histogram : hist3d; + {register} cur : LOCRGB_FSERROR; { current error or pixel value } + belowerr : LOCRGB_FSERROR; { error for pixel below cur } + bpreverr : LOCRGB_FSERROR; { error for below/prev col } + prev_errorptr, + {register} errorptr : RGB_FSERROR_PTR; { => fserrors[] at column before current } + inptr : RGBptr; { => current input pixel } + outptr : JSAMPLE_PTR; { => current output pixel } + cachep : histptr; + dir : int; { +1 or -1 depending on direction } + row : int; + col : JDIMENSION; + width : JDIMENSION; + range_limit : range_limit_table_ptr; + error_limit : error_limit_ptr; + colormap0 : JSAMPROW; + colormap1 : JSAMPROW; + colormap2 : JSAMPROW; + {register} pixcode : int; + {register} bnexterr, delta : LOCFSERROR; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + histogram := cquantize^.histogram; + width := cinfo^.output_width; + range_limit := cinfo^.sample_range_limit; + error_limit := cquantize^.error_limiter; + colormap0 := cinfo^.colormap^[0]; + colormap1 := cinfo^.colormap^[1]; + colormap2 := cinfo^.colormap^[2]; + + for row := 0 to pred(num_rows) do + begin + inptr := RGBptr(input_buf^[row]); + outptr := JSAMPLE_PTR(output_buf^[row]); + errorptr := RGB_FSERROR_PTR(cquantize^.fserrors); { => entry before first real column } + if (cquantize^.on_odd_row) then + begin + { work right to left in this row } + Inc(inptr, (width-1)); { so point to rightmost pixel } + Inc(outptr, width-1); + dir := -1; + Inc(errorptr, (width+1)); { => entry after last column } + cquantize^.on_odd_row := FALSE; { flip for next time } + end + else + begin + { work left to right in this row } + dir := 1; + cquantize^.on_odd_row := TRUE; { flip for next time } + end; + + { Preset error values: no error propagated to first pixel from left } + cur.r := 0; + cur.g := 0; + cur.b := 0; + { and no error propagated to row below yet } + belowerr.r := 0; + belowerr.g := 0; + belowerr.b := 0; + bpreverr.r := 0; + bpreverr.g := 0; + bpreverr.b := 0; + + for col := pred(width) downto 0 do + begin + prev_errorptr := errorptr; + Inc(errorptr, dir); { advance errorptr to current column } + + { curN holds the error propagated from the previous pixel on the + current line. Add the error propagated from the previous line + to form the complete error correction term for this pixel, and + round the error term (which is expressed * 16) to an integer. + RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct + for either sign of the error value. + Note: prev_errorptr points to *previous* column's array entry. } + + { Nomssi Note: Borland Pascal SHR is unsigned } + cur.r := (cur.r + errorptr^.r + 8) div 16; + cur.g := (cur.g + errorptr^.g + 8) div 16; + cur.b := (cur.b + errorptr^.b + 8) div 16; + { Limit the error using transfer function set by init_error_limit. + See comments with init_error_limit for rationale. } + + cur.r := error_limit^[cur.r]; + cur.g := error_limit^[cur.g]; + cur.b := error_limit^[cur.b]; + { Form pixel value + error, and range-limit to 0..MAXJSAMPLE. + The maximum error is +- MAXJSAMPLE (or less with error limiting); + this sets the required size of the range_limit array. } + + Inc(cur.r, GETJSAMPLE(inptr^.r)); + Inc(cur.g, GETJSAMPLE(inptr^.g)); + Inc(cur.b, GETJSAMPLE(inptr^.b)); + + cur.r := GETJSAMPLE(range_limit^[cur.r]); + cur.g := GETJSAMPLE(range_limit^[cur.g]); + cur.b := GETJSAMPLE(range_limit^[cur.b]); + { Index into the cache with adjusted pixel value } + cachep := @(histogram^[cur.r shr C0_SHIFT]^ + [cur.g shr C1_SHIFT][cur.b shr C2_SHIFT]); + { If we have not seen this color before, find nearest colormap } + { entry and update the cache } + if (cachep^ = 0) then + fill_inverse_cmap(cinfo, cur.r shr C0_SHIFT, + cur.g shr C1_SHIFT, + cur.b shr C2_SHIFT); + { Now emit the colormap index for this cell } + + pixcode := cachep^ - 1; + outptr^ := JSAMPLE (pixcode); + + { Compute representation error for this pixel } + Dec(cur.r, GETJSAMPLE(colormap0^[pixcode])); + Dec(cur.g, GETJSAMPLE(colormap1^[pixcode])); + Dec(cur.b, GETJSAMPLE(colormap2^[pixcode])); + + { Compute error fractions to be propagated to adjacent pixels. + Add these into the running sums, and simultaneously shift the + next-line error sums left by 1 column. } + + bnexterr := cur.r; { Process component 0 } + delta := cur.r * 2; + Inc(cur.r, delta); { form error * 3 } + prev_errorptr^.r := FSERROR (bpreverr.r + cur.r); + Inc(cur.r, delta); { form error * 5 } + bpreverr.r := belowerr.r + cur.r; + belowerr.r := bnexterr; + Inc(cur.r, delta); { form error * 7 } + bnexterr := cur.g; { Process component 1 } + delta := cur.g * 2; + Inc(cur.g, delta); { form error * 3 } + prev_errorptr^.g := FSERROR (bpreverr.g + cur.g); + Inc(cur.g, delta); { form error * 5 } + bpreverr.g := belowerr.g + cur.g; + belowerr.g := bnexterr; + Inc(cur.g, delta); { form error * 7 } + bnexterr := cur.b; { Process component 2 } + delta := cur.b * 2; + Inc(cur.b, delta); { form error * 3 } + prev_errorptr^.b := FSERROR (bpreverr.b + cur.b); + Inc(cur.b, delta); { form error * 5 } + bpreverr.b := belowerr.b + cur.b; + belowerr.b := bnexterr; + Inc(cur.b, delta); { form error * 7 } + + { At this point curN contains the 7/16 error value to be propagated + to the next pixel on the current line, and all the errors for the + next line have been shifted over. We are therefore ready to move on.} + + Inc(inptr, dir); { Advance pixel pointers to next column } + Inc(outptr, dir); + end; + { Post-loop cleanup: we must unload the final error values into the + final fserrors[] entry. Note we need not unload belowerrN because + it is for the dummy column before or after the actual array. } + + errorptr^.r := FSERROR (bpreverr.r); { unload prev errs into array } + errorptr^.g := FSERROR (bpreverr.g); + errorptr^.b := FSERROR (bpreverr.b); + end; +end; + + +{ Initialize the error-limiting transfer function (lookup table). + The raw F-S error computation can potentially compute error values of up to + +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be + much less, otherwise obviously wrong pixels will be created. (Typical + effects include weird fringes at color-area boundaries, isolated bright + pixels in a dark area, etc.) The standard advice for avoiding this problem + is to ensure that the "corners" of the color cube are allocated as output + colors; then repeated errors in the same direction cannot cause cascading + error buildup. However, that only prevents the error from getting + completely out of hand; Aaron Giles reports that error limiting improves + the results even with corner colors allocated. + A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty + well, but the smoother transfer function used below is even better. Thanks + to Aaron Giles for this idea. } + +{LOCAL} +procedure init_error_limit (cinfo : j_decompress_ptr); +const + STEPSIZE = ((MAXJSAMPLE+1) div 16); +{ Allocate and fill in the error_limiter table } +var + cquantize : my_cquantize_ptr; + table : error_limit_ptr; + inp, out : int; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + table := error_limit_ptr (cinfo^.mem^.alloc_small + (j_common_ptr (cinfo), JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int))); + { not needed: Inc(table, MAXJSAMPLE); + so can index -MAXJSAMPLE .. +MAXJSAMPLE } + cquantize^.error_limiter := table; + { Map errors 1:1 up to +- MAXJSAMPLE/16 } + out := 0; + for inp := 0 to pred(STEPSIZE) do + begin + table^[inp] := out; + table^[-inp] := -out; + Inc(out); + end; + { Map errors 1:2 up to +- 3*MAXJSAMPLE/16 } + inp := STEPSIZE; { Nomssi: avoid problems with Delphi2 optimizer } + while (inp < STEPSIZE*3) do + begin + table^[inp] := out; + table^[-inp] := -out; + Inc(inp); + if Odd(inp) then + Inc(out); + end; + { Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) } + inp := STEPSIZE*3; { Nomssi: avoid problems with Delphi 2 optimizer } + while inp <= MAXJSAMPLE do + begin + table^[inp] := out; + table^[-inp] := -out; + Inc(inp); + end; +end; + +{ Finish up at the end of each pass. } + +{METHODDEF} +procedure finish_pass1 (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + + { Select the representative colors and fill in cinfo^.colormap } + cinfo^.colormap := cquantize^.sv_colormap; + select_colors(cinfo, cquantize^.desired); + { Force next pass to zero the color index table } + cquantize^.needs_zeroed := TRUE; +end; + + +{METHODDEF} +procedure finish_pass2 (cinfo : j_decompress_ptr); +begin + { no work } +end; + + +{ Initialize for each processing pass. } + +{METHODDEF} +procedure start_pass_2_quant (cinfo : j_decompress_ptr; + is_pre_scan : boolean); +var + cquantize : my_cquantize_ptr; + histogram : hist3d; + i : int; +var + arraysize : size_t; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + histogram := cquantize^.histogram; + { Only F-S dithering or no dithering is supported. } + { If user asks for ordered dither, give him F-S. } + if (cinfo^.dither_mode <> JDITHER_NONE) then + cinfo^.dither_mode := JDITHER_FS; + + if (is_pre_scan) then + begin + { Set up method pointers } + cquantize^.pub.color_quantize := prescan_quantize; + cquantize^.pub.finish_pass := finish_pass1; + cquantize^.needs_zeroed := TRUE; { Always zero histogram } + end + else + begin + { Set up method pointers } + if (cinfo^.dither_mode = JDITHER_FS) then + cquantize^.pub.color_quantize := pass2_fs_dither + else + cquantize^.pub.color_quantize := pass2_no_dither; + cquantize^.pub.finish_pass := finish_pass2; + + { Make sure color count is acceptable } + i := cinfo^.actual_number_of_colors; + if (i < 1) then + ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_FEW_COLORS, 1); + if (i > MAXNUMCOLORS) then + ERREXIT1(j_common_ptr(cinfo), JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + + if (cinfo^.dither_mode = JDITHER_FS) then + begin + arraysize := size_t ((cinfo^.output_width + 2) * + (3 * SIZEOF(FSERROR))); + { Allocate Floyd-Steinberg workspace if we didn't already. } + if (cquantize^.fserrors = NIL) then + cquantize^.fserrors := FS_ERROR_FIELD_PTR (cinfo^.mem^.alloc_large + (j_common_ptr(cinfo), JPOOL_IMAGE, arraysize)); + { Initialize the propagated errors to zero. } + jzero_far(cquantize^.fserrors, arraysize); + { Make the error-limit table if we didn't already. } + if (cquantize^.error_limiter = NIL) then + init_error_limit(cinfo); + cquantize^.on_odd_row := FALSE; + end; + + end; + { Zero the histogram or inverse color map, if necessary } + if (cquantize^.needs_zeroed) then + begin + for i := 0 to pred(HIST_C0_ELEMS) do + begin + jzero_far( histogram^[i], + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell)); + end; + cquantize^.needs_zeroed := FALSE; + end; +end; + + +{ Switch to a new external colormap between output passes. } + +{METHODDEF} +procedure new_color_map_2_quant (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; +begin + cquantize := my_cquantize_ptr (cinfo^.cquantize); + + { Reset the inverse color map } + cquantize^.needs_zeroed := TRUE; +end; + + +{ Module initialization routine for 2-pass color quantization. } + + +{GLOBAL} +procedure jinit_2pass_quantizer (cinfo : j_decompress_ptr); +var + cquantize : my_cquantize_ptr; + i : int; +var + desired : int; +begin + cquantize := my_cquantize_ptr( + cinfo^.mem^.alloc_small (j_common_ptr(cinfo), JPOOL_IMAGE, + SIZEOF(my_cquantizer))); + cinfo^.cquantize := jpeg_color_quantizer_ptr(cquantize); + cquantize^.pub.start_pass := start_pass_2_quant; + cquantize^.pub.new_color_map := new_color_map_2_quant; + cquantize^.fserrors := NIL; { flag optional arrays not allocated } + cquantize^.error_limiter := NIL; + + { Make sure jdmaster didn't give me a case I can't handle } + if (cinfo^.out_color_components <> 3) then + ERREXIT(j_common_ptr(cinfo), JERR_NOTIMPL); + + { Allocate the histogram/inverse colormap storage } + cquantize^.histogram := hist3d (cinfo^.mem^.alloc_small + (j_common_ptr (cinfo), JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d))); + for i := 0 to pred(HIST_C0_ELEMS) do + begin + cquantize^.histogram^[i] := hist2d (cinfo^.mem^.alloc_large + (j_common_ptr (cinfo), JPOOL_IMAGE, + HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell))); + end; + cquantize^.needs_zeroed := TRUE; { histogram is garbage now } + + { Allocate storage for the completed colormap, if required. + We do this now since it is FAR storage and may affect + the memory manager's space calculations. } + + if (cinfo^.enable_2pass_quant) then + begin + { Make sure color count is acceptable } + desired := cinfo^.desired_number_of_colors; + { Lower bound on # of colors ... somewhat arbitrary as long as > 0 } + if (desired < 8) then + ERREXIT1(j_common_ptr (cinfo), JERR_QUANT_FEW_COLORS, 8); + { Make sure colormap indexes can be represented by JSAMPLEs } + if (desired > MAXNUMCOLORS) then + ERREXIT1(j_common_ptr (cinfo), JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); + cquantize^.sv_colormap := cinfo^.mem^.alloc_sarray + (j_common_ptr (cinfo),JPOOL_IMAGE, JDIMENSION(desired), JDIMENSION(3)); + cquantize^.desired := desired; + end + else + cquantize^.sv_colormap := NIL; + + { Only F-S dithering or no dithering is supported. } + { If user asks for ordered dither, give him F-S. } + if (cinfo^.dither_mode <> JDITHER_NONE) then + cinfo^.dither_mode := JDITHER_FS; + + { Allocate Floyd-Steinberg workspace if necessary. + This isn't really needed until pass 2, but again it is FAR storage. + Although we will cope with a later change in dither_mode, + we do not promise to honor max_memory_to_use if dither_mode changes. } + + if (cinfo^.dither_mode = JDITHER_FS) then + begin + cquantize^.fserrors := FS_ERROR_FIELD_PTR (cinfo^.mem^.alloc_large + (j_common_ptr(cinfo), JPOOL_IMAGE, + size_t ((cinfo^.output_width + 2) * (3 * SIZEOF(FSERROR))) ) ); + { Might as well create the error-limiting table too. } + init_error_limit(cinfo); + end; +end; +{ QUANT_2PASS_SUPPORTED } +end. diff --git a/src/lib/vampimg/JpegLib/imjutils.pas b/src/lib/vampimg/JpegLib/imjutils.pas new file mode 100644 index 0000000..fc0eac7 --- /dev/null +++ b/src/lib/vampimg/JpegLib/imjutils.pas @@ -0,0 +1,232 @@ +unit imjutils; + +{ This file contains tables and miscellaneous utility routines needed + for both compression and decompression. + Note we prefix all global names with "j" to minimize conflicts with + a surrounding application. } + +{ Source: jutils.c; Copyright (C) 1991-1996, Thomas G. Lane. } + +interface + +{$I imjconfig.inc} + +uses + imjmorecfg, + imjinclude, + imjpeglib; + + +{ jpeg_zigzag_order[i] is the zigzag-order position of the i'th element + of a DCT block read in natural order (left to right, top to bottom). } + + +{$ifdef FALSE} { This table is not actually needed in v6a } + +const + jpeg_zigzag_order : array[0..DCTSIZE2] of int = + (0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63); + +{$endif} + + +{ jpeg_natural_order[i] is the natural-order position of the i'th element + of zigzag order. + + When reading corrupted data, the Huffman decoders could attempt + to reference an entry beyond the end of this array (if the decoded + zero run length reaches past the end of the block). To prevent + wild stores without adding an inner-loop test, we put some extra + "63"s after the real entries. This will cause the extra coefficient + to be stored in location 63 of the block, not somewhere random. + The worst case would be a run-length of 15, which means we need 16 + fake entries. } + + +const + jpeg_natural_order : array[0..DCTSIZE2+16-1] of int = + (0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + 63, 63, 63, 63, 63, 63, 63, 63, { extra entries for safety in decoder } + 63, 63, 63, 63, 63, 63, 63, 63); + + + +{ Arithmetic utilities } + +{GLOBAL} +function jdiv_round_up (a : long; b : long) : long; + +{GLOBAL} +function jround_up (a : long; b : long) : long; + +{GLOBAL} +procedure jcopy_sample_rows (input_array : JSAMPARRAY; + source_row : int; + output_array : JSAMPARRAY; dest_row : int; + num_rows : int; num_cols : JDIMENSION); + +{GLOBAL} +procedure jcopy_block_row (input_row : JBLOCKROW; + output_row : JBLOCKROW; + num_blocks : JDIMENSION); + +{GLOBAL} +procedure jzero_far (target : pointer;{far} bytestozero : size_t); + +procedure FMEMZERO(target : pointer; size : size_t); + +procedure FMEMCOPY(dest,src : pointer; size : size_t); + +implementation + +{GLOBAL} +function jdiv_round_up (a : long; b : long) : long; +{ Compute a/b rounded up to next integer, ie, ceil(a/b) } +{ Assumes a >= 0, b > 0 } +begin + jdiv_round_up := (a + b - long(1)) div b; +end; + + +{GLOBAL} +function jround_up (a : long; b : long) : long; +{ Compute a rounded up to next multiple of b, ie, ceil(a/b)*b } +{ Assumes a >= 0, b > 0 } +begin + Inc(a, b - long(1)); + jround_up := a - (a mod b); +end; + +{ On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays + and coefficient-block arrays. This won't work on 80x86 because the arrays + are FAR and we're assuming a small-pointer memory model. However, some + DOS compilers provide far-pointer versions of memcpy() and memset() even + in the small-model libraries. These will be used if USE_FMEM is defined. + Otherwise, the routines below do it the hard way. (The performance cost + is not all that great, because these routines aren't very heavily used.) } + + +{$ifndef NEED_FAR_POINTERS} { normal case, same as regular macros } +procedure FMEMZERO(target : pointer; size : size_t); +begin + FillChar(target^, size, 0); +end; + +procedure FMEMCOPY(dest,src : pointer; size : size_t); +begin + Move(src^, dest^, size); +end; + + +{$else} { 80x86 case, define if we can } + {$ifdef USE_FMEM} + FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) + FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) + {$endif} +{$endif} + + +{GLOBAL} +procedure jcopy_sample_rows (input_array : JSAMPARRAY; source_row : int; + output_array : JSAMPARRAY; dest_row : int; + num_rows : int; num_cols : JDIMENSION); +{ Copy some rows of samples from one place to another. + num_rows rows are copied from input_array[source_row++] + to output_array[dest_row++]; these areas may overlap for duplication. + The source and destination arrays must be at least as wide as num_cols. } +var + inptr, outptr : JSAMPLE_PTR; {register} +{$ifdef FMEMCOPY} + count : size_t; {register} +{$else} + count : JDIMENSION; {register} +{$endif} + row : int; {register} +begin +{$ifdef FMEMCOPY} + count := size_t(num_cols * SIZEOF(JSAMPLE)); +{$endif} + Inc(JSAMPROW_PTR(input_array), source_row); + Inc(JSAMPROW_PTR(output_array), dest_row); + + for row := pred(num_rows) downto 0 do + begin + inptr := JSAMPLE_PTR(input_array^[0]); + Inc(JSAMPROW_PTR(input_array)); + outptr := JSAMPLE_PTR(output_array^[0]); + Inc(JSAMPROW_PTR(output_array)); +{$ifdef FMEMCOPY} + FMEMCOPY(outptr, inptr, count); +{$else} + for count := pred(num_cols) downto 0 do + begin + outptr^ := inptr^; { needn't bother with GETJSAMPLE() here } + Inc(inptr); + Inc(outptr); + end; +{$endif} + end; +end; + + +{GLOBAL} +procedure jcopy_block_row (input_row : JBLOCKROW; + output_row : JBLOCKROW; + num_blocks : JDIMENSION); +{ Copy a row of coefficient blocks from one place to another. } +{$ifdef FMEMCOPY} +begin + FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); +{$else} +var + inptr, outptr : JCOEFPTR; {register} + count : long; {register} +begin + inptr := JCOEFPTR (input_row); + outptr := JCOEFPTR (output_row); + for count := long(num_blocks) * DCTSIZE2 -1 downto 0 do + begin + outptr^ := inptr^; + Inc(outptr); + Inc(inptr); + end; +{$endif} +end; + + +{GLOBAL} +procedure jzero_far (target : pointer;{far} bytestozero : size_t); +{ Zero out a chunk of FAR memory. } +{ This might be sample-array data, block-array data, or alloc_large data. } +{$ifdef FMEMZERO} +begin + FMEMZERO(target, bytestozero); +{$else} +var + ptr : byteptr; + count : size_t; {register} +begin + ptr := target; + for count := bytestozero-1 downto 0 do + begin + ptr^ := 0; + Inc(ptr); + end; +{$endif} +end; + +end. diff --git a/src/lib/vampimg/JpegLib/readme.txt b/src/lib/vampimg/JpegLib/readme.txt new file mode 100644 index 0000000..6df345b --- /dev/null +++ b/src/lib/vampimg/JpegLib/readme.txt @@ -0,0 +1,381 @@ +_____________________________________________________________________________ + +PASJPEG 1.1 May 29th, 1999 + +Based on the Independent JPEG Group's JPEG software release 6b + +Copyright (C) 1996,1998,1999 by NOMSSI NZALI Jacques H. C. +[kn&n DES] See "Legal issues" for conditions of distribution and use. +_____________________________________________________________________________ + + +Information in this file +======================== + + o Introduction + o Notes + o File list + o Translation + o Legal issues + o Archive Locations + +Introduction +============ + +PASJPEG is a port of the sixth public release of the IJG C source (release +6b of 27-Mar-98) [3], that implements JPEG baseline, extended-sequential, and +progressive compression processes to Turbo Pascal 7.0 for DOS (TP). The code +has been tested under Delphi 3.0, it can be ported to other Pascal +environments, since many compilers try to be compatible to TP. + +JPEG (pronounced "jay-peg") is a standardized familly of algorithms for +compression of continous tone still images. Most JPEG processes are lossy, +the output image is not exactly identical to the input image. However, on +typical photographic images, very good compression levels can be obtained +with no visible change, and remarkably high compression levels are possible +if you can tolerate a low-quality image [1],[2]. The Independent JPEG Group +(IJG) has created a free, portable C library for JPEG compression and +decompression of JPEG images. + +The IJG documentation (system architecture, using the IJG JPEG library, +usage and file list) is a must read. The files DEMO.PAS, TEST.PAS, CJPEG.PAS, +DJPEG.PAS and EXAMPLE.PAS demonstrate the usage of the JPEG decompression +and compression library. The RDJPGCOM application shows how to parse a JFIF +file. + +Notes: +====== + +* Please report any errors/problems you may find in code and in the + documentation (e.g. this README.TXT file). + +* The sample applications (CJPEG, DJPEG) doesn't support all the options + of the original C code. WRJPGCOM is not ported. + +* Environment variable JPEGMEM syntax changed; + +* You can modify the jpeg.pas unit from the Delphi 3 distribution to + use PasJPEG. + +Change log +========== + +1. bugs fixed: + * in procedure read_gif_map(), unit RDCOLMAP.PAS (used by DJPEG sample + application). Davie Lee Reed + * -dct int and -dct fast now bytewise equal to the IJG output. + * -dct float produced large files + +2. Support for scripts + +3. BASM version of JIDCTINT.PAS for Delphi 2 and 3. + +4. images with integral sampling ratios were not decoded correctly. + Create a jpeg file with cjpeg and the option "-sample 4x1" and try to decode + it with any software that uses PasJpeg. Thanks to Jannie Gerber for reporting + this with a fix: In JDSAMPLE.PAS, procedure int_upsample(), + + for h := pred(h_expand) downto 0 do + begin + outptr^ := invalue; + +=> inc(outptr); { this is the culprit that was left out!!! } + Dec(outcount); + end; + +File list +========= + +Here is a road map to the files in the PasJPEG distribution. The +distribution includes the JPEG library proper, plus two application +programs ("cjpeg" and "djpeg") which use the library to convert JPEG +files to and from some other popular image formats. A third application +"jpegtran" uses the library to do lossless conversion between different +variants of JPEG. There is also the stand-alone applications "rdjpgcom". + +Documentation(see README for a guide to the documentation files): + +readme.txt Introduction, Documentation + +Additional files + +demo.pas Demo program, uses example.pas +example.pas Sample code for calling JPEG library. +test.pas Sample application code for demo.pas + +Configuration/installation files and programs (see install.doc for more info): + +jconfig.inc Configuration declarations. + +*.ijg script files + +Pascal source code files: + +jinclude.pas Central include file used by all IJG .c files to reference + system include files. +jpeglib.pas JPEG library's internal data structures, exported data + and function declarations. +jmorecfg.pas Additional configuration declarations; need not be changed + for a standard installation. +jdeferr.pas defines the error and message text. +jerror.pas Declares JPEG library's error and trace message codes. +jinclude.pas the place to specify system depedent input/output code. +jdct.pas Private declarations for forward & reverse DCT subsystems. + +These files contain most of the functions intended to be called directly by +an application program: + +jcapimin.pas Application program interface: core routines for compression. +jcapistd.pas Application program interface: standard compression. +jdapimin.pas Application program interface: core routines for decompression. +jdapistd.pas Application program interface: standard decompression. +jcomapi.pas Application program interface routines common to compression + and decompression. +jcparam.pas Compression parameter setting helper routines. +jctrans.pas API and library routines for transcoding compression. +jdtrans.pas API and library routines for transcoding decompression. + +Compression side of the library: + +jcinit.pas Initialization: determines which other modules to use. +jcmaster.pas Master control: setup and inter-pass sequencing logic. +jcmainct.pas Main buffer controller (preprocessor => JPEG compressor). +jcprepct.pas Preprocessor buffer controller. +jccoefct.pas Buffer controller for DCT coefficient buffer. +jccolor.pas Color space conversion. +jcsample.pas Downsampling. +jcdctmgr.pas DCT manager (DCT implementation selection & control). +jfdctint.pas Forward DCT using slow-but-accurate integer method. +jfdctfst.pas Forward DCT using faster, less accurate integer method. +jfdctflt.pas Forward DCT using floating-point arithmetic. +jchuff.pas Huffman entropy coding for sequential JPEG. +jcphuff.pas Huffman entropy coding for progressive JPEG. +jcmarker.pas JPEG marker writing. +jdatadst.pas Data destination manager for stdio output. + +Decompression side of the library: + +jdmaster.pas Master control: determines which other modules to use. +jdinput.pas Input controller: controls input processing modules. +jdmainct.pas Main buffer controller (JPEG decompressor => postprocessor). +jdcoefct.pas Buffer controller for DCT coefficient buffer. +jdpostct.pas Postprocessor buffer controller. +jdmarker.pas JPEG marker reading. +jdhuff.pas Huffman entropy decoding for sequential JPEG. +jdphuff.pas Huffman entropy decoding for progressive JPEG. +jddctmgr.pas IDCT manager (IDCT implementation selection & control). +jidctint.pas Inverse DCT using slow-but-accurate integer method. +jidctasm.pas BASM specific version of jidctint.pas for 32bit Delphi. +jidctfst.pas Inverse DCT using faster, less accurate integer method. +jidctflt.pas Inverse DCT using floating-point arithmetic. +jidctred.pas Inverse DCTs with reduced-size outputs. +jidct2d.pas How to for a direct 2D Inverse DCT - not used +jdsample.pas Upsampling. +jdcolor.pas Color space conversion. +jdmerge.pas Merged upsampling/color conversion (faster, lower quality). +jquant1.pas One-pass color quantization using a fixed-spacing colormap. +jquant2.pas Two-pass color quantization using a custom-generated colormap. + Also handles one-pass quantization to an externally given map. +jdatasrc.pas Data source manager for stdio input. + +Support files for both compression and decompression: + +jerror.pas Standard error handling routines (application replaceable). +jmemmgr.pas System-independent (more or less) memory management code. +jutils.pas Miscellaneous utility routines. + +jmemmgr.pas relies on a system-dependent memory management module. The +PASJPEG distribution includes the following implementations of the system- +dependent module: + +jmemnobs.pas "No backing store": assumes adequate virtual memory exists. +jmemdos.pas Custom implementation for MS-DOS (16-bit environment only): + can use extended and expanded memory as well as temporary + files. +jmemsys.pas A skeleton with all the declaration you need to create a + working system-dependent JPEG memory manager on unusual + systems. + +Exactly one of the system-dependent units should be used in jmemmgr.pas. + +jmemdosa.pas BASM 80x86 assembly code support for jmemdos.pas; used only + in MS-DOS-specific configurations of the JPEG library. + + +Applications using the library should use jmorecfg, jerror, jpeglib, and +include jconfig.inc. + +CJPEG/DJPEG/JPEGTRAN + +Pascal source code files: + +cderror.pas Additional error and trace message codes for cjpeg/djpeg. + Not used, Those errors have been added to jdeferr. +cjpeg.pas Main program for cjpeg. +djpeg.pas Main program for djpeg. +jpegtran.pas Main program for jpegtran. +cdjpeg.pas Utility routines used by all three programs. +rdcolmap.pas Code to read a colormap file for djpeg's "-map" switch. +rdswitch.pas Code to process some of cjpeg's more complex switches. + Also used by jpegtran. +transupp.pas Support code for jpegtran: lossless image manipulations. + +fcache.pas +rdswitch.pas Code to process some of cjpeg's more complex switches. + Also used by jpegtran. + +Image file writer modules for djpeg: + +wrbmp.pas BMP file output. +wrppm.pas PPM/PGM file output. +wrtarga.pas Targa file output. + +Image file reader modules for cjpeg: + +rdbmp.pas BMP file input. +rdppm.pas PPM/PGM file input. +rdtarga.pas Targa file input. - NOT READY YET + +This program does not depend on the JPEG library + +rdjpgcom.pas Stand-alone rdjpgcom application. + + +Translation +=========== + +TP is unit-centric, exported type definitions and routines are declared +in the "interface" part of the unit, "make" files are not needed. +Macros are not supported, they were either copied as needed or translated +to Pascal routines (procedure). The procedures will be replaced by code in +later releases. +Conditional defines that indicate whether to include various optional +functions are defined in the file JCONFIG.INC. This file is included first +in all source files. + +The base type definitions are in the unit JMORECFG.PAS. The error handling +macros have been converted to procedures in JERROR.PAS. The error codes are +in JDEFERR.PAS. jpegint.h and jpeglib.h were merged into one large unit +JPEGLIB.PAS containing type definitions with global scope. + +The translation of the header file is the most sophisticated work, a good +understanding of the syntax is required. Once the header files are done, +the translation turns into a lot of editing work. Each C source file was +converted to a unit by editing the syntax (separate variable definition +and usage, define labels, group variable definitions, expanding macros, etc). + +The IJG source labels routines GLOBAL, METHODDEF and LOCAL. All globals +routines are in the interface section of the units. The "far" directive is +used for methods (METHODDEF). + +Some C -> Pascal examples. + +* "{" -> "begin" "->" -> "^." " = " -> " := " "<<" -> " shl " + "}" -> "end;" "!=" -> "<>" " == " -> " = " ">>" -> " shr " + "/*" -> "{" routine -> function "0x" -> "$" + "*/" -> "}" (void) procedure "NULL" -> "NIL" + +* structs are records, Unions are variable records, pointers are always far, + the operators && and || (and/or) have not the same priority in both + languages, so parenthesis are important. The Pascal "case" doesn't have the + falltrough option of the C "switch" statement, my work around is to split + one "switch" statement into many case statements. +* The pointer type in C is not readily interchangeable. It is used to address + an array (Pascal pointer to an array) or in pointer arithmetic a pointer to + a single element. I've used the Inc() statement with type casting to + translate pointer arithmetic most of the time. + + C example: + typedef JSAMPLE* JSAMPROW; /* ptr to one image row of pixel samples. */ + + Pascal + type + JSAMPLE_PTR = ^JSAMPLE; { ptr to a single pixel sample. } + jTSample = 0..(MaxInt div SIZEOF(JSAMPLE))-1; + JSAMPLE_ARRAY = Array[jTSample] of JSAMPLE; {far} + JSAMPROW = ^JSAMPLE_ARRAY; { ptr to one image row of pixel samples. } + + The following code + + JSAMPROW buffer0, buffer1; /* ptr to a JSAMPLE buffer. */ + + ... + + buffer1 = buffer0 + i; + + can be translated to + + var + buffer0, buffer1 : JSAMPROW; + + ... + + buffer1 := buffer0; + Inc(JSAMPLE_PTR(buffer1), i); + + or + + buffer1 := JSAMPROW(@ buffer0^[i]); + + Declaring the variables as JSAMPLE_PTR may reduce type casting in some + places. I use help pointers to handle negative array offsets. + +While translating the type of function parameter from C to Pascal, one can +often use "var", "const", or "array of" parameters instead of pointers. + +While translating for(;;)-loops with more than one induction variable to +Pascal "for to/downto do"-loops, the extra induction variables have to be +manually updated at the end of the loop and before "continue"-statements. + + +Legal issues +============ + +Copyright (C) 1996,1998 by Jacques Nomssi Nzali + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +Archive Locations: +================== + +[1] Thomas G. Lane, JPEG FAQ + + in comp.graphics.misc and related newsgroups + +[2] Wallace, Gregory K.: The JPEG Still Picture Compression Standard + + ftp.uu.net, graphics/jpeg/wallace.ps.Z + +[3] The Independent JPEG Group C library for JPEG encoding and decoding, + rev 6b. + + ftp://ftp.uu.net/graphics/jpeg/ + + or SimTel in msdos/graphics/ + +[4] JPEG implementation, written by the PVRG group at Stanford, + ftp havefun.stanford.edu:/pub/jpeg/JPEGv1.2.tar.Z. + +[5] PASJPEG.ZIP at NView ftp site + + ftp://druckfix.physik.tu-chemnitz.de/pub/nv/ + http://www.tu-chemnitz.de/~nomssi/pub/pasjpeg.zip + +[6] The PasJPEG home page with links + + http://www.tu-chemnitz.de/~nomssi/pasjpeg.html +_____________________________________________________________________________ diff --git a/src/lib/vampimg/ZLib/dzlib.pas b/src/lib/vampimg/ZLib/dzlib.pas new file mode 100644 index 0000000..05e278d --- /dev/null +++ b/src/lib/vampimg/ZLib/dzlib.pas @@ -0,0 +1,523 @@ +{*******************************************************} +{ } +{ Delphi Supplemental Components } +{ ZLIB Data Compression Interface Unit } +{ } +{ Copyright (c) 1997 Borland International } +{ Copyright (c) 1998 Jacques Nomssi Nzali } +{ } +{*******************************************************} + +{ + Modified for + Vampyre Imaging Library + by Marek Mauder + http://imaginglib.sourceforge.net + + You can choose which pascal zlib implementation will be + used. IMPASZLIB and FPCPASZLIB are translations of zlib + to pascal so they don't need any *.obj files. + The others are interfaces to *.obj files (Windows) or + *.so libraries (Linux). + Default implementation is IMPASZLIB because it can be compiled + by all supported compilers and works on all supported platforms. + I usually use implementation with the fastest decompression + when building release Win32 binaries. + FPCPASZLIB is useful for Lazarus applications. FPC's zlib is linked + to exe by default so there is no need to link additional (and almost identical) + IMPASZLIB. + + There is a small speed comparison table of some of the + supported implementations (TGA image 28 311 570 bytes, compression level = 6, + Delphi 9, Win32, Athlon XP 1900). + + ZLib version Decompression Compression Comp. Size + IMPASZLIB | 1.1.2 | 824 ms | 4 280 ms | 18 760 133 B + ZLIBEX | 1.2.2 | 710 ms | 1 590 ms* | 19 056 621 B + DELPHIZLIB | 1.0.4 | 976 ms | 9 190 ms | 18 365 562 B + ZLIBPAS | 1.2.3 | 680 ms | 3 790 ms | 18 365 387 B + * obj files are compiled with compression level hardcoded to 1 (fastest) +} + +unit dzlib; + +{$I ImagingOptions.inc} + +interface + +{$DEFINE IMPASZLIB} +{ $DEFINE ZLIBPAS} +{ $DEFINE FPCPASZLIB} +{ $DEFINE ZLIBEX} +{ $DEFINE DELPHIZLIB} + +{ Automatically use FPC's PasZLib when compiling with FPC.} + +{$IFDEF FPC} + {$UNDEF IMPASZLIB} + {$DEFINE FPCPASZLIB} +{$ENDIF} + +uses +{$IF Defined(IMPASZLIB)} + { Use paszlib modified by me for Delphi and FPC } + imzdeflate, imzinflate, impaszlib, +{$ELSEIF Defined(FPCPASZLIB)} + { Use FPC's paszlib } + zbase, paszlib, +{$ELSEIF Defined(ZLIBPAS)} + { Pascal interface to ZLib shipped with ZLib C source } + zlibpas, +{$ELSEIF Defined(ZLIBEX)} + { Use ZlibEx unit } + ZLibEx, +{$ELSEIF Defined(DELPHIZLIB)} + { Use ZLib unit shipped with Delphi } + ZLib, +{$IFEND} + ImagingTypes, SysUtils, Classes; + +{$IF Defined(IMPASZLIB) or Defined(FPCPASZLIB) or Defined(ZLIBPAS)} +type + TZStreamRec = z_stream; +{$IFEND} + +const + Z_NO_FLUSH = 0; + Z_PARTIAL_FLUSH = 1; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; + + Z_OK = 0; + Z_STREAM_END = 1; + Z_NEED_DICT = 2; + Z_ERRNO = -1; + Z_STREAM_ERROR = -2; + Z_DATA_ERROR = -3; + Z_MEM_ERROR = -4; + Z_BUF_ERROR = -5; + Z_VERSION_ERROR = -6; + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = -1; + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_RLE = 3; + Z_DEFAULT_STRATEGY = 0; + + Z_BINARY = 0; + Z_ASCII = 1; + Z_UNKNOWN = 2; + + Z_DEFLATED = 8; + +type + { Abstract ancestor class } + TCustomZlibStream = class(TStream) + private + FStrm: TStream; + FStrmPos: Integer; + FOnProgress: TNotifyEvent; + FZRec: TZStreamRec; + FBuffer: array [Word] of Byte; + protected + procedure Progress(Sender: TObject); dynamic; + property OnProgress: TNotifyEvent read FOnProgress write FOnProgress; + constructor Create(Strm: TStream); + end; + +{ TCompressionStream compresses data on the fly as data is written to it, and + stores the compressed data to another stream. + + TCompressionStream is write-only and strictly sequential. Reading from the + stream will raise an exception. Using Seek to move the stream pointer + will raise an exception. + + Output data is cached internally, written to the output stream only when + the internal output buffer is full. All pending output data is flushed + when the stream is destroyed. + + The Position property returns the number of uncompressed bytes of + data that have been written to the stream so far. + + CompressionRate returns the on-the-fly percentage by which the original + data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100 + If raw data size = 100 and compressed data size = 25, the CompressionRate + is 75% + + The OnProgress event is called each time the output buffer is filled and + written to the output stream. This is useful for updating a progress + indicator when you are writing a large chunk of data to the compression + stream in a single call.} + + + TCompressionLevel = (clNone, clFastest, clDefault, clMax); + + TCompressionStream = class(TCustomZlibStream) + private + function GetCompressionRate: Single; + public + constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream); + destructor Destroy; override; + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; + property CompressionRate: Single read GetCompressionRate; + property OnProgress; + end; + +{ TDecompressionStream decompresses data on the fly as data is read from it. + + Compressed data comes from a separate source stream. TDecompressionStream + is read-only and unidirectional; you can seek forward in the stream, but not + backwards. The special case of setting the stream position to zero is + allowed. Seeking forward decompresses data until the requested position in + the uncompressed data has been reached. Seeking backwards, seeking relative + to the end of the stream, requesting the size of the stream, and writing to + the stream will raise an exception. + + The Position property returns the number of bytes of uncompressed data that + have been read from the stream so far. + + The OnProgress event is called each time the internal input buffer of + compressed data is exhausted and the next block is read from the input stream. + This is useful for updating a progress indicator when you are reading a + large chunk of data from the decompression stream in a single call.} + + TDecompressionStream = class(TCustomZlibStream) + public + constructor Create(Source: TStream); + destructor Destroy; override; + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; + property OnProgress; + end; + + + +{ CompressBuf compresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + Out: OutBuf = ptr to newly allocated buffer containing decompressed data + OutBytes = number of bytes in OutBuf } +procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; + var OutBuf: Pointer; var OutBytes: Integer; + CompressLevel: Integer = Z_DEFAULT_COMPRESSION; + CompressStrategy: Integer = Z_DEFAULT_STRATEGY); + +{ DecompressBuf decompresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + OutEstimate = zero, or est. size of the decompressed data + Out: OutBuf = ptr to newly allocated buffer containing decompressed data + OutBytes = number of bytes in OutBuf } +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; var OutBuf: Pointer; var OutBytes: Integer); + + +type + EZlibError = class(Exception); + ECompressionError = class(EZlibError); + EDecompressionError = class(EZlibError); + +implementation + +const + ZErrorMessages: array[0..9] of PAnsiChar = ( + 'need dictionary', // Z_NEED_DICT (2) + 'stream end', // Z_STREAM_END (1) + '', // Z_OK (0) + 'file error', // Z_ERRNO (-1) + 'stream error', // Z_STREAM_ERROR (-2) + 'data error', // Z_DATA_ERROR (-3) + 'insufficient memory', // Z_MEM_ERROR (-4) + 'buffer error', // Z_BUF_ERROR (-5) + 'incompatible version', // Z_VERSION_ERROR (-6) + ''); + +function zlibAllocMem(AppData: Pointer; Items, Size: Cardinal): Pointer; +begin + GetMem(Result, Items*Size); +end; + +procedure zlibFreeMem(AppData, Block: Pointer); +begin + FreeMem(Block); +end; + +function CCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise ECompressionError.Create('zlib: ' + ZErrorMessages[2 - code]); +end; + +function DCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise EDecompressionError.Create('zlib: ' + ZErrorMessages[2 - code]); +end; + +procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; + var OutBuf: Pointer; var OutBytes: Integer; + CompressLevel, CompressStrategy: Integer); +var + strm: TZStreamRec; + P: Pointer; +begin + FillChar(strm, sizeof(strm), 0); +{$IFNDEF FPCPASZLIB} + strm.zalloc := @zlibAllocMem; + strm.zfree := @zlibFreeMem; +{$ENDIF} + OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + + CCheck(deflateInit2(strm, CompressLevel, Z_DEFLATED, MAX_WBITS, + DEF_MEM_LEVEL, CompressStrategy)); + + try + while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, 256); + ReallocMem(OutBuf, OutBytes); + strm.next_out := Pointer(PtrUInt(OutBuf) + (PtrUInt(strm.next_out) - PtrUInt(P))); + strm.avail_out := 256; + end; + finally + CCheck(deflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + zlibFreeMem(nil, OutBuf); + raise + end; +end; + +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; var OutBuf: Pointer; var OutBytes: Integer); +var + strm: TZStreamRec; + P: Pointer; + BufInc: Integer; +begin + FillChar(strm, sizeof(strm), 0); +{$IFNDEF FPCPASZLIB} + strm.zalloc := @zlibAllocMem; + strm.zfree := @zlibFreeMem; +{$ENDIF} + BufInc := (InBytes + 255) and not 255; + if OutEstimate = 0 then + OutBytes := BufInc + else + OutBytes := OutEstimate; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); + try + while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, BufInc); + ReallocMem(OutBuf, OutBytes); + strm.next_out := Pointer(PtrUInt(OutBuf) + (PtrUInt(strm.next_out) - PtrUInt(P))); + strm.avail_out := BufInc; + end; + finally + DCheck(inflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + zlibFreeMem(nil, OutBuf); + raise + end; +end; + + +{ TCustomZlibStream } + +constructor TCustomZLibStream.Create(Strm: TStream); +begin + inherited Create; + FStrm := Strm; + FStrmPos := Strm.Position; +{$IFNDEF FPCPASZLIB} + FZRec.zalloc := @zlibAllocMem; + FZRec.zfree := @zlibFreeMem; +{$ENDIF} +end; + +procedure TCustomZLibStream.Progress(Sender: TObject); +begin + if Assigned(FOnProgress) then FOnProgress(Sender); +end; + +{ TCompressionStream } + +constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; + Dest: TStream); +const + Levels: array [TCompressionLevel] of ShortInt = + (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); +begin + inherited Create(Dest); + FZRec.next_out := @FBuffer; + FZRec.avail_out := sizeof(FBuffer); + CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); +end; + +destructor TCompressionStream.Destroy; +begin + FZRec.next_in := nil; + FZRec.avail_in := 0; + try + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) + and (FZRec.avail_out = 0) do + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := @FBuffer; + FZRec.avail_out := sizeof(FBuffer); + end; + if FZRec.avail_out < sizeof(FBuffer) then + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); + finally + deflateEnd(FZRec); + end; + inherited Destroy; +end; + +function TCompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + raise ECompressionError.Create('Invalid stream operation'); +end; + +function TCompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + FZRec.next_in := @Buffer; + FZRec.avail_in := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_in > 0) do + begin + CCheck(deflate(FZRec, 0)); + if FZRec.avail_out = 0 then + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := @FBuffer; + FZRec.avail_out := sizeof(FBuffer); + FStrmPos := FStrm.Position; + Progress(Self); + end; + end; + Result := Count; +end; + +function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +begin + if (Offset = 0) and (Origin = soFromCurrent) then + Result := FZRec.total_in + else + raise ECompressionError.Create('Invalid stream operation'); +end; + +function TCompressionStream.GetCompressionRate: Single; +begin + if FZRec.total_in = 0 then + Result := 0 + else + Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; +end; + +{ TDecompressionStream } + +constructor TDecompressionStream.Create(Source: TStream); +begin + inherited Create(Source); + FZRec.next_in := @FBuffer; + FZRec.avail_in := 0; + DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); +end; + +destructor TDecompressionStream.Destroy; +begin + inflateEnd(FZRec); + inherited Destroy; +end; + +function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + FZRec.next_out := @Buffer; + FZRec.avail_out := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_out > 0) do + begin + if FZRec.avail_in = 0 then + begin + FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); + if FZRec.avail_in = 0 then + begin + Result := Count - Integer(FZRec.avail_out); + Exit; + end; + FZRec.next_in := @FBuffer; + FStrmPos := FStrm.Position; + Progress(Self); + end; + CCheck(inflate(FZRec, 0)); + end; + Result := Count; +end; + +function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + raise EDecompressionError.Create('Invalid stream operation'); +end; + +function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +var + I: Integer; + Buf: array [0..4095] of Byte; +begin + if (Offset = 0) and (Origin = soFromBeginning) then + begin + DCheck(inflateReset(FZRec)); + FZRec.next_in := @FBuffer; + FZRec.avail_in := 0; + FStrm.Position := 0; + FStrmPos := 0; + end + else if ( (Offset >= 0) and (Origin = soFromCurrent)) or + ( ((Offset - Integer(FZRec.total_out)) > 0) and (Origin = soFromBeginning)) then + begin + if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); + if Offset > 0 then + begin + for I := 1 to Offset div sizeof(Buf) do + ReadBuffer(Buf, sizeof(Buf)); + ReadBuffer(Buf, Offset mod sizeof(Buf)); + end; + end + else + raise EDecompressionError.Create('Invalid stream operation'); + Result := FZRec.total_out; +end; + +end. diff --git a/src/lib/vampimg/ZLib/imadler.pas b/src/lib/vampimg/ZLib/imadler.pas new file mode 100644 index 0000000..ff769a2 --- /dev/null +++ b/src/lib/vampimg/ZLib/imadler.pas @@ -0,0 +1,113 @@ +Unit imadler; + +{ + adler32.c -- compute the Adler-32 checksum of a data stream + Copyright (C) 1995-1998 Mark Adler + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +interface + +{$I imzconf.inc} + +uses + imzutil; + +function adler32(adler : uLong; buf : pBytef; len : uInt) : uLong; + +{ Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NIL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + var + adler : uLong; + begin + adler := adler32(0, Z_NULL, 0); + + while (read_buffer(buffer, length) <> EOF) do + adler := adler32(adler, buffer, length); + + if (adler <> original_adler) then + error(); + end; +} + +implementation + +const + BASE = uLong(65521); { largest prime smaller than 65536 } + {NMAX = 5552; original code with unsigned 32 bit integer } + { NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 } + NMAX = 3854; { code with signed 32 bit integer } + { NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^31-1 } + { The penalty is the time loss in the extra MOD-calls. } + + +{ ========================================================================= } + +function adler32(adler : uLong; buf : pBytef; len : uInt) : uLong; +var + s1, s2 : uLong; + k : int; +begin + s1 := adler and $ffff; + s2 := (adler shr 16) and $ffff; + + if not Assigned(buf) then + begin + adler32 := uLong(1); + exit; + end; + + while (len > 0) do + begin + if len < NMAX then + k := len + else + k := NMAX; + Dec(len, k); + { + while (k >= 16) do + begin + DO16(buf); + Inc(buf, 16); + Dec(k, 16); + end; + if (k <> 0) then + repeat + Inc(s1, buf^); + Inc(puf); + Inc(s2, s1); + Dec(k); + until (k = 0); + } + while (k > 0) do + begin + Inc(s1, buf^); + Inc(s2, s1); + Inc(buf); + Dec(k); + end; + s1 := s1 mod BASE; + s2 := s2 mod BASE; + end; + adler32 := (s2 shl 16) or s1; +end; + +{ +#define DO1(buf,i) + begin + Inc(s1, buf[i]); + Inc(s2, s1); + end; +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); +} +end. diff --git a/src/lib/vampimg/ZLib/iminfblock.pas b/src/lib/vampimg/ZLib/iminfblock.pas new file mode 100644 index 0000000..413e9b6 --- /dev/null +++ b/src/lib/vampimg/ZLib/iminfblock.pas @@ -0,0 +1,951 @@ +Unit iminfblock; + +{ infblock.h and + infblock.c -- interpret and process block types to last block + Copyright (C) 1995-1998 Mark Adler + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +interface + +{$I imzconf.inc} + +uses + {$IFDEF DEBUG} + SysUtils, strutils, + {$ENDIF} + imzutil, impaszlib; + +function inflate_blocks_new(var z : z_stream; + c : check_func; { check function } + w : uInt { window size } + ) : pInflate_blocks_state; + +function inflate_blocks (var s : inflate_blocks_state; + var z : z_stream; + r : int { initial return code } + ) : int; + +procedure inflate_blocks_reset (var s : inflate_blocks_state; + var z : z_stream; + c : puLong); { check value on output } + + +function inflate_blocks_free(s : pInflate_blocks_state; + var z : z_stream) : int; + +procedure inflate_set_dictionary(var s : inflate_blocks_state; + const d : array of byte; { dictionary } + n : uInt); { dictionary length } + +function inflate_blocks_sync_point(var s : inflate_blocks_state) : int; + +implementation + +uses + iminfcodes, iminftrees, iminfutil; + +{ Tables for deflate from PKZIP's appnote.txt. } +Const + border : Array [0..18] Of Word { Order of the bit length code lengths } + = (16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15); + +{ Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. } + + +procedure inflate_blocks_reset (var s : inflate_blocks_state; + var z : z_stream; + c : puLong); { check value on output } +begin + if (c <> Z_NULL) then + c^ := s.check; + if (s.mode = BTREE) or (s.mode = DTREE) then + ZFREE(z, s.sub.trees.blens); + if (s.mode = CODES) then + inflate_codes_free(s.sub.decode.codes, z); + + s.mode := ZTYPE; + s.bitk := 0; + s.bitb := 0; + + s.write := s.window; + s.read := s.window; + if Assigned(s.checkfn) then + begin + s.check := s.checkfn(uLong(0), pBytef(NIL), 0); + z.adler := s.check; + end; + {$IFDEF DEBUG} + Tracev('inflate: blocks reset'); + {$ENDIF} +end; + + +function inflate_blocks_new(var z : z_stream; + c : check_func; { check function } + w : uInt { window size } + ) : pInflate_blocks_state; +var + s : pInflate_blocks_state; +begin + s := pInflate_blocks_state( ZALLOC(z,1, sizeof(inflate_blocks_state)) ); + if (s = Z_NULL) then + begin + inflate_blocks_new := s; + exit; + end; + s^.hufts := huft_ptr( ZALLOC(z, sizeof(inflate_huft), MANY) ); + + if (s^.hufts = Z_NULL) then + begin + ZFREE(z, s); + inflate_blocks_new := Z_NULL; + exit; + end; + + s^.window := pBytef( ZALLOC(z, 1, w) ); + if (s^.window = Z_NULL) then + begin + ZFREE(z, s^.hufts); + ZFREE(z, s); + inflate_blocks_new := Z_NULL; + exit; + end; + s^.zend := s^.window; + Inc(s^.zend, w); + s^.checkfn := c; + s^.mode := ZTYPE; + {$IFDEF DEBUG} + Tracev('inflate: blocks allocated'); + {$ENDIF} + inflate_blocks_reset(s^, z, Z_NULL); + inflate_blocks_new := s; +end; + + +function inflate_blocks (var s : inflate_blocks_state; + var z : z_stream; + r : int) : int; { initial return code } +label + start_btree, start_dtree, + start_blkdone, start_dry, + start_codes; + +var + t : uInt; { temporary storage } + b : uLong; { bit buffer } + k : uInt; { bits in bit buffer } + p : pBytef; { input data pointer } + n : uInt; { bytes available there } + q : pBytef; { output window write pointer } + m : uInt; { bytes to end of window or read pointer } +{ fixed code blocks } +var + bl, bd : uInt; + tl, td : pInflate_huft; +var + h : pInflate_huft; + i, j, c : uInt; +var + cs : pInflate_codes_state; +begin + { copy input/output information to locals } + p := z.next_in; + n := z.avail_in; + b := s.bitb; + k := s.bitk; + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + +{ decompress an inflated block } + + + { process input based on current state } + while True do + Case s.mode of + ZTYPE: + begin + {NEEDBITS(3);} + while (k < 3) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + t := uInt(b) and 7; + s.last := boolean(t and 1); + case (t shr 1) of + 0: { stored } + begin + {$IFDEF DEBUG} + if s.last then + Tracev('inflate: stored block (last)') + else + Tracev('inflate: stored block'); + {$ENDIF} + {DUMPBITS(3);} + b := b shr 3; + Dec(k, 3); + + t := k and 7; { go to byte boundary } + {DUMPBITS(t);} + b := b shr t; + Dec(k, t); + + s.mode := LENS; { get length of stored block } + end; + 1: { fixed } + begin + begin + {$IFDEF DEBUG} + if s.last then + Tracev('inflate: fixed codes blocks (last)') + else + Tracev('inflate: fixed codes blocks'); + {$ENDIF} + inflate_trees_fixed(bl, bd, tl, td, z); + s.sub.decode.codes := inflate_codes_new(bl, bd, tl, td, z); + if (s.sub.decode.codes = Z_NULL) then + begin + r := Z_MEM_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + end; + {DUMPBITS(3);} + b := b shr 3; + Dec(k, 3); + + s.mode := CODES; + end; + 2: { dynamic } + begin + {$IFDEF DEBUG} + if s.last then + Tracev('inflate: dynamic codes block (last)') + else + Tracev('inflate: dynamic codes block'); + {$ENDIF} + {DUMPBITS(3);} + b := b shr 3; + Dec(k, 3); + + s.mode := TABLE; + end; + 3: + begin { illegal } + {DUMPBITS(3);} + b := b shr 3; + Dec(k, 3); + + s.mode := BLKBAD; + z.msg := 'invalid block type'; + r := Z_DATA_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + end; + end; + LENS: + begin + {NEEDBITS(32);} + while (k < 32) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + if (((not b) shr 16) and $ffff) <> (b and $ffff) then + begin + s.mode := BLKBAD; + z.msg := 'invalid stored block lengths'; + r := Z_DATA_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + s.sub.left := uInt(b) and $ffff; + k := 0; + b := 0; { dump bits } + {$IFDEF DEBUG} + Tracev('inflate: stored length '+IntToStr(s.sub.left)); + {$ENDIF} + if s.sub.left <> 0 then + s.mode := STORED + else + if s.last then + s.mode := DRY + else + s.mode := ZTYPE; + end; + STORED: + begin + if (n = 0) then + begin + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + {NEEDOUT} + if (m = 0) then + begin + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + end; + + if (m = 0) then + begin + {FLUSH} + s.write := q; + r := inflate_flush(s,z,r); + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + end; + + if (m = 0) then + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + end; + end; + r := Z_OK; + + t := s.sub.left; + if (t > n) then + t := n; + if (t > m) then + t := m; + zmemcpy(q, p, t); + Inc(p, t); Dec(n, t); + Inc(q, t); Dec(m, t); + Dec(s.sub.left, t); + if (s.sub.left = 0) then + begin + {$IFDEF DEBUG} + if (ptr2int(q) >= ptr2int(s.read)) then + Tracev('inflate: stored end '+ + IntToStr(z.total_out + ptr2int(q) - ptr2int(s.read)) + ' total out') + else + Tracev('inflate: stored end '+ + IntToStr(z.total_out + ptr2int(s.zend) - ptr2int(s.read) + + ptr2int(q) - ptr2int(s.window)) + ' total out'); + {$ENDIF} + if s.last then + s.mode := DRY + else + s.mode := ZTYPE; + end; + end; + TABLE: + begin + {NEEDBITS(14);} + while (k < 14) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + t := uInt(b) and $3fff; + s.sub.trees.table := t; + {$ifndef PKZIP_BUG_WORKAROUND} + if ((t and $1f) > 29) or (((t shr 5) and $1f) > 29) then + begin + s.mode := BLKBAD; + z.msg := 'too many length or distance symbols'; + r := Z_DATA_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + {$endif} + t := 258 + (t and $1f) + ((t shr 5) and $1f); + s.sub.trees.blens := puIntArray( ZALLOC(z, t, sizeof(uInt)) ); + if (s.sub.trees.blens = Z_NULL) then + begin + r := Z_MEM_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + {DUMPBITS(14);} + b := b shr 14; + Dec(k, 14); + + s.sub.trees.index := 0; + {$IFDEF DEBUG} + Tracev('inflate: table sizes ok'); + {$ENDIF} + s.mode := BTREE; + { fall trough case is handled by the while } + { try GOTO for speed - Nomssi } + goto start_btree; + end; + BTREE: + begin + start_btree: + while (s.sub.trees.index < 4 + (s.sub.trees.table shr 10)) do + begin + {NEEDBITS(3);} + while (k < 3) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + s.sub.trees.blens^[border[s.sub.trees.index]] := uInt(b) and 7; + Inc(s.sub.trees.index); + {DUMPBITS(3);} + b := b shr 3; + Dec(k, 3); + end; + while (s.sub.trees.index < 19) do + begin + s.sub.trees.blens^[border[s.sub.trees.index]] := 0; + Inc(s.sub.trees.index); + end; + s.sub.trees.bb := 7; + t := inflate_trees_bits(s.sub.trees.blens^, s.sub.trees.bb, + s.sub.trees.tb, s.hufts^, z); + if (t <> Z_OK) then + begin + ZFREE(z, s.sub.trees.blens); + r := t; + if (r = Z_DATA_ERROR) then + s.mode := BLKBAD; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + s.sub.trees.index := 0; + {$IFDEF DEBUG} + Tracev('inflate: bits tree ok'); + {$ENDIF} + s.mode := DTREE; + { fall through again } + goto start_dtree; + end; + DTREE: + begin + start_dtree: + while TRUE do + begin + t := s.sub.trees.table; + if not (s.sub.trees.index < 258 + + (t and $1f) + ((t shr 5) and $1f)) then + break; + t := s.sub.trees.bb; + {NEEDBITS(t);} + while (k < t) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + h := s.sub.trees.tb; + Inc(h, uInt(b) and inflate_mask[t]); + t := h^.Bits; + c := h^.Base; + + if (c < 16) then + begin + {DUMPBITS(t);} + b := b shr t; + Dec(k, t); + + s.sub.trees.blens^[s.sub.trees.index] := c; + Inc(s.sub.trees.index); + end + else { c = 16..18 } + begin + if c = 18 then + begin + i := 7; + j := 11; + end + else + begin + i := c - 14; + j := 3; + end; + {NEEDBITS(t + i);} + while (k < t + i) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + {DUMPBITS(t);} + b := b shr t; + Dec(k, t); + + Inc(j, uInt(b) and inflate_mask[i]); + {DUMPBITS(i);} + b := b shr i; + Dec(k, i); + + i := s.sub.trees.index; + t := s.sub.trees.table; + if (i + j > 258 + (t and $1f) + ((t shr 5) and $1f)) or + ((c = 16) and (i < 1)) then + begin + ZFREE(z, s.sub.trees.blens); + s.mode := BLKBAD; + z.msg := 'invalid bit length repeat'; + r := Z_DATA_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + if c = 16 then + c := s.sub.trees.blens^[i - 1] + else + c := 0; + repeat + s.sub.trees.blens^[i] := c; + Inc(i); + Dec(j); + until (j=0); + s.sub.trees.index := i; + end; + end; { while } + s.sub.trees.tb := Z_NULL; + begin + bl := 9; { must be <= 9 for lookahead assumptions } + bd := 6; { must be <= 9 for lookahead assumptions } + t := s.sub.trees.table; + t := inflate_trees_dynamic(257 + (t and $1f), + 1 + ((t shr 5) and $1f), + s.sub.trees.blens^, bl, bd, tl, td, s.hufts^, z); + ZFREE(z, s.sub.trees.blens); + if (t <> Z_OK) then + begin + if (t = uInt(Z_DATA_ERROR)) then + s.mode := BLKBAD; + r := t; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + {$IFDEF DEBUG} + Tracev('inflate: trees ok'); + {$ENDIF} + { c renamed to cs } + cs := inflate_codes_new(bl, bd, tl, td, z); + if (cs = Z_NULL) then + begin + r := Z_MEM_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + s.sub.decode.codes := cs; + end; + s.mode := CODES; + { yet another falltrough } + goto start_codes; + end; + CODES: + begin + start_codes: + { update pointers } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + + r := inflate_codes(s, z, r); + if (r <> Z_STREAM_END) then + begin + inflate_blocks := inflate_flush(s, z, r); + exit; + end; + r := Z_OK; + inflate_codes_free(s.sub.decode.codes, z); + { load local pointers } + p := z.next_in; + n := z.avail_in; + b := s.bitb; + k := s.bitk; + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + {$IFDEF DEBUG} + if (ptr2int(q) >= ptr2int(s.read)) then + Tracev('inflate: codes end '+ + IntToStr(z.total_out + ptr2int(q) - ptr2int(s.read)) + ' total out') + else + Tracev('inflate: codes end '+ + IntToStr(z.total_out + ptr2int(s.zend) - ptr2int(s.read) + + ptr2int(q) - ptr2int(s.window)) + ' total out'); + {$ENDIF} + if (not s.last) then + begin + s.mode := ZTYPE; + continue; { break for switch statement in C-code } + end; + {$ifndef patch112} + if (k > 7) then { return unused byte, if any } + begin + {$IFDEF DEBUG} + Assert(k < 16, 'inflate_codes grabbed too many bytes'); + {$ENDIF} + Dec(k, 8); + Inc(n); + Dec(p); { can always return one } + end; + {$endif} + s.mode := DRY; + { another falltrough } + goto start_dry; + end; + DRY: + begin + start_dry: + {FLUSH} + s.write := q; + r := inflate_flush(s,z,r); + q := s.write; + + { not needed anymore, we are done: + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + } + + if (s.read <> s.write) then + begin + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + s.mode := BLKDONE; + goto start_blkdone; + end; + BLKDONE: + begin + start_blkdone: + r := Z_STREAM_END; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + BLKBAD: + begin + r := Z_DATA_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + else + begin + r := Z_STREAM_ERROR; + { update pointers and return } + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_blocks := inflate_flush(s,z,r); + exit; + end; + end; { Case s.mode of } + +end; + + +function inflate_blocks_free(s : pInflate_blocks_state; + var z : z_stream) : int; +begin + inflate_blocks_reset(s^, z, Z_NULL); + ZFREE(z, s^.window); + ZFREE(z, s^.hufts); + ZFREE(z, s); + {$IFDEF DEBUG} + Trace('inflate: blocks freed'); + {$ENDIF} + inflate_blocks_free := Z_OK; +end; + + +procedure inflate_set_dictionary(var s : inflate_blocks_state; + const d : array of byte; { dictionary } + n : uInt); { dictionary length } +begin + zmemcpy(s.window, pBytef(@d), n); + s.write := s.window; + Inc(s.write, n); + s.read := s.write; +end; + + +{ Returns true if inflate is currently at the end of a block generated + by Z_SYNC_FLUSH or Z_FULL_FLUSH. + IN assertion: s <> Z_NULL } + +function inflate_blocks_sync_point(var s : inflate_blocks_state) : int; +begin + inflate_blocks_sync_point := int(s.mode = LENS); +end; + +end. diff --git a/src/lib/vampimg/ZLib/iminfcodes.pas b/src/lib/vampimg/ZLib/iminfcodes.pas new file mode 100644 index 0000000..1396e13 --- /dev/null +++ b/src/lib/vampimg/ZLib/iminfcodes.pas @@ -0,0 +1,576 @@ +Unit iminfcodes; + +{ infcodes.c -- process literals and length/distance pairs + Copyright (C) 1995-1998 Mark Adler + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +interface + +{$I imzconf.inc} + +uses + {$IFDEF DEBUG} + SysUtils, strutils, + {$ENDIF} + imzutil, impaszlib; + +function inflate_codes_new (bl : uInt; + bd : uInt; + tl : pInflate_huft; + td : pInflate_huft; + var z : z_stream): pInflate_codes_state; + +function inflate_codes(var s : inflate_blocks_state; + var z : z_stream; + r : int) : int; + +procedure inflate_codes_free(c : pInflate_codes_state; + var z : z_stream); + +implementation + +uses + iminfutil, iminffast; + + +function inflate_codes_new (bl : uInt; + bd : uInt; + tl : pInflate_huft; + td : pInflate_huft; + var z : z_stream): pInflate_codes_state; +var + c : pInflate_codes_state; +begin + c := pInflate_codes_state( ZALLOC(z,1,sizeof(inflate_codes_state)) ); + if (c <> Z_NULL) then + begin + c^.mode := START; + c^.lbits := Byte(bl); + c^.dbits := Byte(bd); + c^.ltree := tl; + c^.dtree := td; + {$IFDEF DEBUG} + Tracev('inflate: codes new'); + {$ENDIF} + end; + inflate_codes_new := c; +end; + + +function inflate_codes(var s : inflate_blocks_state; + var z : z_stream; + r : int) : int; +var + j : uInt; { temporary storage } + t : pInflate_huft; { temporary pointer } + e : uInt; { extra bits or operation } + b : uLong; { bit buffer } + k : uInt; { bits in bit buffer } + p : pBytef; { input data pointer } + n : uInt; { bytes available there } + q : pBytef; { output window write pointer } + m : uInt; { bytes to end of window or read pointer } + f : pBytef; { pointer to copy strings from } +var + c : pInflate_codes_state; +begin + c := s.sub.decode.codes; { codes state } + + { copy input/output information to locals } + p := z.next_in; + n := z.avail_in; + b := s.bitb; + k := s.bitk; + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + + { process input and output based on current state } + while True do + case (c^.mode) of + { waiting for "i:"=input, "o:"=output, "x:"=nothing } + START: { x: set up for LEN } + begin +{$ifndef SLOW} + if (m >= 258) and (n >= 10) then + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + + r := inflate_fast(c^.lbits, c^.dbits, c^.ltree, c^.dtree, s, z); + {LOAD} + p := z.next_in; + n := z.avail_in; + b := s.bitb; + k := s.bitk; + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + + if (r <> Z_OK) then + begin + if (r = Z_STREAM_END) then + c^.mode := WASH + else + c^.mode := BADCODE; + continue; { break for switch-statement in C } + end; + end; +{$endif} { not SLOW } + c^.sub.code.need := c^.lbits; + c^.sub.code.tree := c^.ltree; + c^.mode := LEN; { falltrough } + end; + LEN: { i: get length/literal/eob next } + begin + j := c^.sub.code.need; + {NEEDBITS(j);} + while (k < j) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + t := c^.sub.code.tree; + Inc(t, uInt(b) and inflate_mask[j]); + {DUMPBITS(t^.bits);} + b := b shr t^.bits; + Dec(k, t^.bits); + + e := uInt(t^.exop); + if (e = 0) then { literal } + begin + c^.sub.lit := t^.base; + {$IFDEF DEBUG} + if (t^.base >= $20) and (t^.base < $7f) then + Tracevv('inflate: literal '+AnsiChar(t^.base)) + else + Tracevv('inflate: literal '+IntToStr(t^.base)); + {$ENDIF} + c^.mode := LIT; + continue; { break switch statement } + end; + if (e and 16 <> 0) then { length } + begin + c^.sub.copy.get := e and 15; + c^.len := t^.base; + c^.mode := LENEXT; + continue; { break C-switch statement } + end; + if (e and 64 = 0) then { next table } + begin + c^.sub.code.need := e; + c^.sub.code.tree := @huft_ptr(t)^[t^.base]; + continue; { break C-switch statement } + end; + if (e and 32 <> 0) then { end of block } + begin + {$IFDEF DEBUG} + Tracevv('inflate: end of block'); + {$ENDIF} + c^.mode := WASH; + continue; { break C-switch statement } + end; + c^.mode := BADCODE; { invalid code } + z.msg := 'invalid literal/length code'; + r := Z_DATA_ERROR; + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + LENEXT: { i: getting length extra (have base) } + begin + j := c^.sub.copy.get; + {NEEDBITS(j);} + while (k < j) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + Inc(c^.len, uInt(b and inflate_mask[j])); + {DUMPBITS(j);} + b := b shr j; + Dec(k, j); + + c^.sub.code.need := c^.dbits; + c^.sub.code.tree := c^.dtree; + {$IFDEF DEBUG} + Tracevv('inflate: length '+IntToStr(c^.len)); + {$ENDIF} + c^.mode := DIST; + { falltrough } + end; + DIST: { i: get distance next } + begin + j := c^.sub.code.need; + {NEEDBITS(j);} + while (k < j) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + t := @huft_ptr(c^.sub.code.tree)^[uInt(b) and inflate_mask[j]]; + {DUMPBITS(t^.bits);} + b := b shr t^.bits; + Dec(k, t^.bits); + + e := uInt(t^.exop); + if (e and 16 <> 0) then { distance } + begin + c^.sub.copy.get := e and 15; + c^.sub.copy.dist := t^.base; + c^.mode := DISTEXT; + continue; { break C-switch statement } + end; + if (e and 64 = 0) then { next table } + begin + c^.sub.code.need := e; + c^.sub.code.tree := @huft_ptr(t)^[t^.base]; + continue; { break C-switch statement } + end; + c^.mode := BADCODE; { invalid code } + z.msg := 'invalid distance code'; + r := Z_DATA_ERROR; + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + DISTEXT: { i: getting distance extra } + begin + j := c^.sub.copy.get; + {NEEDBITS(j);} + while (k < j) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + Inc(c^.sub.copy.dist, uInt(b) and inflate_mask[j]); + {DUMPBITS(j);} + b := b shr j; + Dec(k, j); + {$IFDEF DEBUG} + Tracevv('inflate: distance '+ IntToStr(c^.sub.copy.dist)); + {$ENDIF} + c^.mode := COPY; + { falltrough } + end; + COPY: { o: copying bytes in window, waiting for space } + begin + f := q; + Dec(f, c^.sub.copy.dist); + if (uInt(ptr2int(q) - ptr2int(s.window)) < c^.sub.copy.dist) then + begin + f := s.zend; + Dec(f, c^.sub.copy.dist - uInt(ptr2int(q) - ptr2int(s.window))); + end; + + while (c^.len <> 0) do + begin + {NEEDOUT} + if (m = 0) then + begin + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + end; + + if (m = 0) then + begin + {FLUSH} + s.write := q; + r := inflate_flush(s,z,r); + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + end; + + if (m = 0) then + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + end; + end; + r := Z_OK; + + {OUTBYTE( *f++)} + q^ := f^; + Inc(q); + Inc(f); + Dec(m); + + if (f = s.zend) then + f := s.window; + Dec(c^.len); + end; + c^.mode := START; + { C-switch break; not needed } + end; + LIT: { o: got literal, waiting for output space } + begin + {NEEDOUT} + if (m = 0) then + begin + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + end; + + if (m = 0) then + begin + {FLUSH} + s.write := q; + r := inflate_flush(s,z,r); + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + end; + + if (m = 0) then + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + end; + end; + r := Z_OK; + + {OUTBYTE(c^.sub.lit);} + q^ := c^.sub.lit; + Inc(q); + Dec(m); + + c^.mode := START; + {break;} + end; + WASH: { o: got eob, possibly more output } + begin + {$ifdef patch112} + if (k > 7) then { return unused byte, if any } + begin + {$IFDEF DEBUG} + Assert(k < 16, 'inflate_codes grabbed too many bytes'); + {$ENDIF} + Dec(k, 8); + Inc(n); + Dec(p); { can always return one } + end; + {$endif} + {FLUSH} + s.write := q; + r := inflate_flush(s,z,r); + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + + if (s.read <> s.write) then + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + c^.mode := ZEND; + { falltrough } + end; + + ZEND: + begin + r := Z_STREAM_END; + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + BADCODE: { x: got error } + begin + r := Z_DATA_ERROR; + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + else + begin + r := Z_STREAM_ERROR; + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_codes := inflate_flush(s,z,r); + exit; + end; + end; +{NEED_DUMMY_RETURN - Delphi2+ dumb compilers complain without this } + inflate_codes := Z_STREAM_ERROR; +end; + + +procedure inflate_codes_free(c : pInflate_codes_state; + var z : z_stream); +begin + ZFREE(z, c); + {$IFDEF DEBUG} + Tracev('inflate: codes free'); + {$ENDIF} +end; + +end. diff --git a/src/lib/vampimg/ZLib/iminffast.pas b/src/lib/vampimg/ZLib/iminffast.pas new file mode 100644 index 0000000..936c922 --- /dev/null +++ b/src/lib/vampimg/ZLib/iminffast.pas @@ -0,0 +1,318 @@ +Unit iminffast; + +{ + inffast.h and + inffast.c -- process literals and length/distance pairs fast + Copyright (C) 1995-1998 Mark Adler + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + + +interface + +{$I imzconf.inc} + +uses + {$ifdef DEBUG} + SysUtils, strutils, + {$ENDIF} + imzutil, impaszlib; + +function inflate_fast( bl : uInt; + bd : uInt; + tl : pInflate_huft; + td : pInflate_huft; + var s : inflate_blocks_state; + var z : z_stream) : int; + + +implementation + +uses + iminfutil; + + +{ Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. } + +function inflate_fast( bl : uInt; + bd : uInt; + tl : pInflate_huft; + td : pInflate_huft; + var s : inflate_blocks_state; + var z : z_stream) : int; + +var + t : pInflate_huft; { temporary pointer } + e : uInt; { extra bits or operation } + b : uLong; { bit buffer } + k : uInt; { bits in bit buffer } + p : pBytef; { input data pointer } + n : uInt; { bytes available there } + q : pBytef; { output window write pointer } + m : uInt; { bytes to end of window or read pointer } + ml : uInt; { mask for literal/length tree } + md : uInt; { mask for distance tree } + c : uInt; { bytes to copy } + d : uInt; { distance back to copy from } + r : pBytef; { copy source pointer } +begin + { load input, output, bit values (macro LOAD) } + p := z.next_in; + n := z.avail_in; + b := s.bitb; + k := s.bitk; + q := s.write; + if ptr2int(q) < ptr2int(s.read) then + m := uInt(ptr2int(s.read)-ptr2int(q)-1) + else + m := uInt(ptr2int(s.zend)-ptr2int(q)); + + { initialize masks } + ml := inflate_mask[bl]; + md := inflate_mask[bd]; + + { do until not enough input or output space for fast loop } + repeat { assume called with (m >= 258) and (n >= 10) } + { get literal/length code } + {GRABBITS(20);} { max bits for literal/length code } + while (k < 20) do + begin + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + t := @(huft_ptr(tl)^[uInt(b) and ml]); + + e := t^.exop; + if (e = 0) then + begin + {DUMPBITS(t^.bits);} + b := b shr t^.bits; + Dec(k, t^.bits); + {$IFDEF DEBUG} + if (t^.base >= $20) and (t^.base < $7f) then + Tracevv('inflate: * literal '+AnsiChar(t^.base)) + else + Tracevv('inflate: * literal '+ IntToStr(t^.base)); + {$ENDIF} + q^ := Byte(t^.base); + Inc(q); + Dec(m); + continue; + end; + repeat + {DUMPBITS(t^.bits);} + b := b shr t^.bits; + Dec(k, t^.bits); + + if (e and 16 <> 0) then + begin + { get extra bits for length } + e := e and 15; + c := t^.base + (uInt(b) and inflate_mask[e]); + {DUMPBITS(e);} + b := b shr e; + Dec(k, e); + {$IFDEF DEBUG} + Tracevv('inflate: * length ' + IntToStr(c)); + {$ENDIF} + { decode distance base of block to copy } + {GRABBITS(15);} { max bits for distance code } + while (k < 15) do + begin + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + t := @huft_ptr(td)^[uInt(b) and md]; + e := t^.exop; + repeat + {DUMPBITS(t^.bits);} + b := b shr t^.bits; + Dec(k, t^.bits); + + if (e and 16 <> 0) then + begin + { get extra bits to add to distance base } + e := e and 15; + {GRABBITS(e);} { get extra bits (up to 13) } + while (k < e) do + begin + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + + d := t^.base + (uInt(b) and inflate_mask[e]); + {DUMPBITS(e);} + b := b shr e; + Dec(k, e); + + {$IFDEF DEBUG} + Tracevv('inflate: * distance '+IntToStr(d)); + {$ENDIF} + { do the copy } + Dec(m, c); + if (uInt(ptr2int(q) - ptr2int(s.window)) >= d) then { offset before dest } + begin { just copy } + r := q; + Dec(r, d); + q^ := r^; Inc(q); Inc(r); Dec(c); { minimum count is three, } + q^ := r^; Inc(q); Inc(r); Dec(c); { so unroll loop a little } + end + else { else offset after destination } + begin + e := d - uInt(ptr2int(q) - ptr2int(s.window)); { bytes from offset to end } + r := s.zend; + Dec(r, e); { pointer to offset } + if (c > e) then { if source crosses, } + begin + Dec(c, e); { copy to end of window } + repeat + q^ := r^; + Inc(q); + Inc(r); + Dec(e); + until (e=0); + r := s.window; { copy rest from start of window } + end; + end; + repeat { copy all or what's left } + q^ := r^; + Inc(q); + Inc(r); + Dec(c); + until (c = 0); + break; + end + else + if (e and 64 = 0) then + begin + Inc(t, t^.base + (uInt(b) and inflate_mask[e])); + e := t^.exop; + end + else + begin + z.msg := 'invalid distance code'; + {UNGRAB} + c := z.avail_in-n; + if (k shr 3) < c then + c := k shr 3; + Inc(n, c); + Dec(p, c); + Dec(k, c shl 3); + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + + inflate_fast := Z_DATA_ERROR; + exit; + end; + until FALSE; + break; + end; + if (e and 64 = 0) then + begin + {t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop;} + + Inc(t, t^.base + (uInt(b) and inflate_mask[e])); + e := t^.exop; + if (e = 0) then + begin + {DUMPBITS(t^.bits);} + b := b shr t^.bits; + Dec(k, t^.bits); + + {$IFDEF DEBUG} + if (t^.base >= $20) and (t^.base < $7f) then + Tracevv('inflate: * literal '+AnsiChar(t^.base)) + else + Tracevv('inflate: * literal '+IntToStr(t^.base)); + {$ENDIF} + q^ := Byte(t^.base); + Inc(q); + Dec(m); + break; + end; + end + else + if (e and 32 <> 0) then + begin + {$IFDEF DEBUG} + Tracevv('inflate: * end of block'); + {$ENDIF} + {UNGRAB} + c := z.avail_in-n; + if (k shr 3) < c then + c := k shr 3; + Inc(n, c); + Dec(p, c); + Dec(k, c shl 3); + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_fast := Z_STREAM_END; + exit; + end + else + begin + z.msg := 'invalid literal/length code'; + {UNGRAB} + c := z.avail_in-n; + if (k shr 3) < c then + c := k shr 3; + Inc(n, c); + Dec(p, c); + Dec(k, c shl 3); + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_fast := Z_DATA_ERROR; + exit; + end; + until FALSE; + until (m < 258) or (n < 10); + + { not enough input or output--restore pointers and return } + {UNGRAB} + c := z.avail_in-n; + if (k shr 3) < c then + c := k shr 3; + Inc(n, c); + Dec(p, c); + Dec(k, c shl 3); + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, ptr2int(p)-ptr2int(z.next_in)); + z.next_in := p; + s.write := q; + inflate_fast := Z_OK; +end; + +end. diff --git a/src/lib/vampimg/ZLib/iminftrees.pas b/src/lib/vampimg/ZLib/iminftrees.pas new file mode 100644 index 0000000..af545a7 --- /dev/null +++ b/src/lib/vampimg/ZLib/iminftrees.pas @@ -0,0 +1,781 @@ +Unit iminftrees; + +{ inftrees.h -- header to use inftrees.c + inftrees.c -- generate Huffman trees for efficient decoding + Copyright (C) 1995-1998 Mark Adler + + WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +Interface + +{$I imzconf.inc} + +uses + imzutil, impaszlib; + + +{ Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. } +const + MANY = 1440; + + +{$ifdef DEBUG} +var + inflate_hufts : uInt; +{$endif} + +function inflate_trees_bits( + var c : array of uIntf; { 19 code lengths } + var bb : uIntf; { bits tree desired/actual depth } + var tb : pinflate_huft; { bits tree result } + var hp : array of Inflate_huft; { space for trees } + var z : z_stream { for messages } + ) : int; + +function inflate_trees_dynamic( + nl : uInt; { number of literal/length codes } + nd : uInt; { number of distance codes } + var c : Array of uIntf; { that many (total) code lengths } + var bl : uIntf; { literal desired/actual bit depth } + var bd : uIntf; { distance desired/actual bit depth } +var tl : pInflate_huft; { literal/length tree result } +var td : pInflate_huft; { distance tree result } +var hp : array of Inflate_huft; { space for trees } +var z : z_stream { for messages } + ) : int; + +function inflate_trees_fixed ( + var bl : uInt; { literal desired/actual bit depth } + var bd : uInt; { distance desired/actual bit depth } + var tl : pInflate_huft; { literal/length tree result } + var td : pInflate_huft; { distance tree result } + var z : z_stream { for memory allocation } + ) : int; + + +implementation + +const + inflate_copyright = 'inflate 1.1.2 Copyright 1995-1998 Mark Adler'; + +{ + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. +} + + +const +{ Tables for deflate from PKZIP's appnote.txt. } + cplens : Array [0..30] Of uInt { Copy lengths for literal codes 257..285 } + = (3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0); + { actually lengths - 2; also see note #13 above about 258 } + + invalid_code = 112; + + cplext : Array [0..30] Of uInt { Extra bits for literal codes 257..285 } + = (0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, invalid_code, invalid_code); + + cpdist : Array [0..29] Of uInt { Copy offsets for distance codes 0..29 } + = (1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577); + + cpdext : Array [0..29] Of uInt { Extra bits for distance codes } + = (0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13); + +{ Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. } + + +{ If BMAX needs to be larger than 16, then h and x[] should be uLong. } +const + BMAX = 15; { maximum bit length of any code } + +{$DEFINE USE_PTR} + +function huft_build( +var b : array of uIntf; { code lengths in bits (all assumed <= BMAX) } + n : uInt; { number of codes (assumed <= N_MAX) } + s : uInt; { number of simple-valued codes (0..s-1) } +const d : array of uIntf; { list of base values for non-simple codes } +{ array of word } +const e : array of uIntf; { list of extra bits for non-simple codes } +{ array of byte } + t : ppInflate_huft; { result: starting table } +var m : uIntf; { maximum lookup bits, returns actual } +var hp : array of inflate_huft; { space for trees } +var hn : uInt; { hufts used in space } +var v : array of uIntf { working area: values in order of bit length } + ) : int; +{ Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + lengths), or Z_MEM_ERROR if not enough memory. } +Var + a : uInt; { counter for codes of length k } + c : Array [0..BMAX] Of uInt; { bit length count table } + f : uInt; { i repeats in table every f entries } + g : int; { maximum code length } + h : int; { table level } + i : uInt; {register} { counter, current code } + j : uInt; {register} { counter } + k : Int; {register} { number of bits in current code } + l : int; { bits per table (returned in m) } + mask : uInt; { (1 shl w) - 1, to avoid cc -O bug on HP } + p : ^uIntf; {register} { pointer into c[], b[], or v[] } + q : pInflate_huft; { points to current table } + r : inflate_huft; { table entry for structure assignment } + u : Array [0..BMAX-1] Of pInflate_huft; { table stack } + w : int; {register} { bits before this table = (l*h) } + x : Array [0..BMAX] Of uInt; { bit offsets, then code stack } + {$IFDEF USE_PTR} + xp : puIntf; { pointer into x } + {$ELSE} + xp : uInt; + {$ENDIF} + y : int; { number of dummy codes added } + z : uInt; { number of entries in current table } +Begin + { Generate counts for each bit length } + FillChar(c,SizeOf(c),0) ; { clear c[] } + + for i := 0 to n-1 do + Inc (c[b[i]]); { assume all entries <= BMAX } + + If (c[0] = n) Then { null input--all zero length codes } + Begin + t^ := pInflate_huft(NIL); + m := 0 ; + huft_build := Z_OK ; + Exit; + End ; + + { Find minimum and maximum length, bound [m] by those } + l := m; + for j:=1 To BMAX do + if (c[j] <> 0) then + break; + k := j ; { minimum code length } + if (uInt(l) < j) then + l := j; + for i := BMAX downto 1 do + if (c[i] <> 0) then + break ; + g := i ; { maximum code length } + if (uInt(l) > i) then + l := i; + m := l; + + { Adjust last length count to fill out codes, if needed } + y := 1 shl j ; + while (j < i) do + begin + Dec(y, c[j]) ; + if (y < 0) then + begin + huft_build := Z_DATA_ERROR; { bad input: more codes than bits } + exit; + end ; + Inc(j) ; + y := y shl 1 + end; + Dec (y, c[i]) ; + if (y < 0) then + begin + huft_build := Z_DATA_ERROR; { bad input: more codes than bits } + exit; + end; + Inc(c[i], y); + + { Generate starting offsets into the value table FOR each length } + {$IFDEF USE_PTR} + x[1] := 0; + j := 0; + + p := @c[1]; + xp := @x[2]; + + dec(i); { note that i = g from above } + WHILE (i > 0) DO + BEGIN + inc(j, p^); + xp^ := j; + inc(p); + inc(xp); + dec(i); + END; + {$ELSE} + x[1] := 0; + j := 0 ; + for i := 1 to g do + begin + x[i] := j; + Inc(j, c[i]); + end; + {$ENDIF} + + { Make a table of values in order of bit lengths } + for i := 0 to n-1 do + begin + j := b[i]; + if (j <> 0) then + begin + v[ x[j] ] := i; + Inc(x[j]); + end; + end; + n := x[g]; { set n to length of v } + + { Generate the Huffman codes and for each, make the table entries } + i := 0 ; + x[0] := 0 ; { first Huffman code is zero } + p := Addr(v) ; { grab values in bit order } + h := -1 ; { no tables yet--level -1 } + w := -l ; { bits decoded = (l*h) } + + u[0] := pInflate_huft(NIL); { just to keep compilers happy } + q := pInflate_huft(NIL); { ditto } + z := 0 ; { ditto } + + { go through the bit lengths (k already is bits in shortest code) } + while (k <= g) Do + begin + a := c[k] ; + while (a<>0) Do + begin + Dec (a) ; + { here i is the Huffman code of length k bits for value p^ } + { make tables up to required level } + while (k > w + l) do + begin + + Inc (h) ; + Inc (w, l); { add bits already decoded } + { previous table always l bits } + { compute minimum size table less than or equal to l bits } + + { table size upper limit } + z := g - w; + If (z > uInt(l)) Then + z := l; + + { try a k-w bit table } + j := k - w; + f := 1 shl j; + if (f > a+1) Then { too few codes for k-w bit table } + begin + Dec(f, a+1); { deduct codes from patterns left } + {$IFDEF USE_PTR} + xp := Addr(c[k]); + + if (j < z) then + begin + Inc(j); + while (j < z) do + begin { try smaller tables up to z bits } + f := f shl 1; + Inc (xp) ; + If (f <= xp^) Then + break; { enough codes to use up j bits } + Dec(f, xp^); { else deduct codes from patterns } + Inc(j); + end; + end; + {$ELSE} + xp := k; + + if (j < z) then + begin + Inc (j) ; + While (j < z) Do + begin { try smaller tables up to z bits } + f := f * 2; + Inc (xp) ; + if (f <= c[xp]) then + Break ; { enough codes to use up j bits } + Dec (f, c[xp]) ; { else deduct codes from patterns } + Inc (j); + end; + end; + {$ENDIF} + end; + + z := 1 shl j; { table entries for j-bit table } + + { allocate new table } + if (hn + z > MANY) then { (note: doesn't matter for fixed) } + begin + huft_build := Z_MEM_ERROR; { not enough memory } + exit; + end; + + q := @hp[hn]; + u[h] := q; + Inc(hn, z); + + { connect to last table, if there is one } + if (h <> 0) then + begin + x[h] := i; { save pattern for backing up } + r.bits := Byte(l); { bits to dump before this table } + r.exop := Byte(j); { bits in this table } + j := i shr (w - l); + {r.base := uInt( q - u[h-1] -j);} { offset to this table } + r.base := (ptr2int(q) - ptr2int(u[h-1]) ) div sizeof(q^) - j; + huft_Ptr(u[h-1])^[j] := r; { connect to last table } + end + else + t^ := q; { first table is returned result } + end; + + { set up table entry in r } + r.bits := Byte(k - w); + + { C-code: if (p >= v + n) - see ZUTIL.PAS for comments } + + if ptr2int(p)>=ptr2int(@(v[n])) then { also works under DPMI ?? } + r.exop := 128 + 64 { out of values--invalid code } + else + if (p^ < s) then + begin + if (p^ < 256) then { 256 is end-of-block code } + r.exop := 0 + Else + r.exop := 32 + 64; { EOB_code; } + r.base := p^; { simple code is just the value } + Inc(p); + end + Else + begin + r.exop := Byte(e[p^-s] + 16 + 64); { non-simple--look up in lists } + r.base := d[p^-s]; + Inc (p); + end ; + + { fill code-like entries with r } + f := 1 shl (k - w); + j := i shr w; + while (j < z) do + begin + huft_Ptr(q)^[j] := r; + Inc(j, f); + end; + + { backwards increment the k-bit code i } + j := 1 shl (k-1) ; + while (i and j) <> 0 do + begin + i := i xor j; { bitwise exclusive or } + j := j shr 1 + end ; + i := i xor j; + + { backup over finished tables } + mask := (1 shl w) - 1; { needed on HP, cc -O bug } + while ((i and mask) <> x[h]) do + begin + Dec(h); { don't need to update q } + Dec(w, l); + mask := (1 shl w) - 1; + end; + + end; + + Inc(k); + end; + + { Return Z_BUF_ERROR if we were given an incomplete table } + if (y <> 0) And (g <> 1) then + huft_build := Z_BUF_ERROR + else + huft_build := Z_OK; +end; { huft_build} + + +function inflate_trees_bits( + var c : array of uIntf; { 19 code lengths } + var bb : uIntf; { bits tree desired/actual depth } + var tb : pinflate_huft; { bits tree result } + var hp : array of Inflate_huft; { space for trees } + var z : z_stream { for messages } + ) : int; +var + r : int; + hn : uInt; { hufts used in space } + v : PuIntArray; { work area for huft_build } +begin + hn := 0; + v := PuIntArray( ZALLOC(z, 19, sizeof(uInt)) ); + if (v = Z_NULL) then + begin + inflate_trees_bits := Z_MEM_ERROR; + exit; + end; + + r := huft_build(c, 19, 19, cplens, cplext, + {puIntf(Z_NULL), puIntf(Z_NULL),} + @tb, bb, hp, hn, v^); + if (r = Z_DATA_ERROR) then + z.msg := 'oversubscribed dynamic bit lengths tree' + else + if (r = Z_BUF_ERROR) or (bb = 0) then + begin + z.msg := 'incomplete dynamic bit lengths tree'; + r := Z_DATA_ERROR; + end; + ZFREE(z, v); + inflate_trees_bits := r; +end; + + +function inflate_trees_dynamic( + nl : uInt; { number of literal/length codes } + nd : uInt; { number of distance codes } + var c : Array of uIntf; { that many (total) code lengths } + var bl : uIntf; { literal desired/actual bit depth } + var bd : uIntf; { distance desired/actual bit depth } +var tl : pInflate_huft; { literal/length tree result } +var td : pInflate_huft; { distance tree result } +var hp : array of Inflate_huft; { space for trees } +var z : z_stream { for messages } + ) : int; +var + r : int; + hn : uInt; { hufts used in space } + v : PuIntArray; { work area for huft_build } +begin + hn := 0; + { allocate work area } + v := PuIntArray( ZALLOC(z, 288, sizeof(uInt)) ); + if (v = Z_NULL) then + begin + inflate_trees_dynamic := Z_MEM_ERROR; + exit; + end; + + { build literal/length tree } + r := huft_build(c, nl, 257, cplens, cplext, @tl, bl, hp, hn, v^); + if (r <> Z_OK) or (bl = 0) then + begin + if (r = Z_DATA_ERROR) then + z.msg := 'oversubscribed literal/length tree' + else + if (r <> Z_MEM_ERROR) then + begin + z.msg := 'incomplete literal/length tree'; + r := Z_DATA_ERROR; + end; + + ZFREE(z, v); + inflate_trees_dynamic := r; + exit; + end; + + { build distance tree } + r := huft_build(puIntArray(@c[nl])^, nd, 0, + cpdist, cpdext, @td, bd, hp, hn, v^); + if (r <> Z_OK) or ((bd = 0) and (nl > 257)) then + begin + if (r = Z_DATA_ERROR) then + z.msg := 'oversubscribed literal/length tree' + else + if (r = Z_BUF_ERROR) then + begin +{$ifdef PKZIP_BUG_WORKAROUND} + r := Z_OK; + end; +{$else} + z.msg := 'incomplete literal/length tree'; + r := Z_DATA_ERROR; + end + else + if (r <> Z_MEM_ERROR) then + begin + z.msg := 'empty distance tree with lengths'; + r := Z_DATA_ERROR; + end; + ZFREE(z, v); + inflate_trees_dynamic := r; + exit; +{$endif} + end; + + { done } + ZFREE(z, v); + inflate_trees_dynamic := Z_OK; +end; + +{$UNDEF BUILDFIXED} + +{ build fixed tables only once--keep them here } +{$IFNDEF BUILDFIXED} +{ locals } +var + fixed_built : Boolean = false; +const + FIXEDH = 544; { number of hufts used by fixed tables } +var + fixed_mem : array[0..FIXEDH-1] of inflate_huft; + fixed_bl : uInt; + fixed_bd : uInt; + fixed_tl : pInflate_huft; + fixed_td : pInflate_huft; + +{$ELSE} + +{ inffixed.h -- table for decoding fixed codes } + +{local} +const + fixed_bl = uInt(9); +{local} +const + fixed_bd = uInt(5); +{local} +const + fixed_tl : array [0..288-1] of inflate_huft = ( + Exop, { number of extra bits or operation } + bits : Byte; { number of bits in this code or subcode } + {pad : uInt;} { pad structure to a power of 2 (4 bytes for } + { 16-bit, 8 bytes for 32-bit int's) } + base : uInt; { literal, length base, or distance base } + { or table offset } + + ((96,7),256), ((0,8),80), ((0,8),16), ((84,8),115), ((82,7),31), + ((0,8),112), ((0,8),48), ((0,9),192), ((80,7),10), ((0,8),96), + ((0,8),32), ((0,9),160), ((0,8),0), ((0,8),128), ((0,8),64), + ((0,9),224), ((80,7),6), ((0,8),88), ((0,8),24), ((0,9),144), + ((83,7),59), ((0,8),120), ((0,8),56), ((0,9),208), ((81,7),17), + ((0,8),104), ((0,8),40), ((0,9),176), ((0,8),8), ((0,8),136), + ((0,8),72), ((0,9),240), ((80,7),4), ((0,8),84), ((0,8),20), + ((85,8),227), ((83,7),43), ((0,8),116), ((0,8),52), ((0,9),200), + ((81,7),13), ((0,8),100), ((0,8),36), ((0,9),168), ((0,8),4), + ((0,8),132), ((0,8),68), ((0,9),232), ((80,7),8), ((0,8),92), + ((0,8),28), ((0,9),152), ((84,7),83), ((0,8),124), ((0,8),60), + ((0,9),216), ((82,7),23), ((0,8),108), ((0,8),44), ((0,9),184), + ((0,8),12), ((0,8),140), ((0,8),76), ((0,9),248), ((80,7),3), + ((0,8),82), ((0,8),18), ((85,8),163), ((83,7),35), ((0,8),114), + ((0,8),50), ((0,9),196), ((81,7),11), ((0,8),98), ((0,8),34), + ((0,9),164), ((0,8),2), ((0,8),130), ((0,8),66), ((0,9),228), + ((80,7),7), ((0,8),90), ((0,8),26), ((0,9),148), ((84,7),67), + ((0,8),122), ((0,8),58), ((0,9),212), ((82,7),19), ((0,8),106), + ((0,8),42), ((0,9),180), ((0,8),10), ((0,8),138), ((0,8),74), + ((0,9),244), ((80,7),5), ((0,8),86), ((0,8),22), ((192,8),0), + ((83,7),51), ((0,8),118), ((0,8),54), ((0,9),204), ((81,7),15), + ((0,8),102), ((0,8),38), ((0,9),172), ((0,8),6), ((0,8),134), + ((0,8),70), ((0,9),236), ((80,7),9), ((0,8),94), ((0,8),30), + ((0,9),156), ((84,7),99), ((0,8),126), ((0,8),62), ((0,9),220), + ((82,7),27), ((0,8),110), ((0,8),46), ((0,9),188), ((0,8),14), + ((0,8),142), ((0,8),78), ((0,9),252), ((96,7),256), ((0,8),81), + ((0,8),17), ((85,8),131), ((82,7),31), ((0,8),113), ((0,8),49), + ((0,9),194), ((80,7),10), ((0,8),97), ((0,8),33), ((0,9),162), + ((0,8),1), ((0,8),129), ((0,8),65), ((0,9),226), ((80,7),6), + ((0,8),89), ((0,8),25), ((0,9),146), ((83,7),59), ((0,8),121), + ((0,8),57), ((0,9),210), ((81,7),17), ((0,8),105), ((0,8),41), + ((0,9),178), ((0,8),9), ((0,8),137), ((0,8),73), ((0,9),242), + ((80,7),4), ((0,8),85), ((0,8),21), ((80,8),258), ((83,7),43), + ((0,8),117), ((0,8),53), ((0,9),202), ((81,7),13), ((0,8),101), + ((0,8),37), ((0,9),170), ((0,8),5), ((0,8),133), ((0,8),69), + ((0,9),234), ((80,7),8), ((0,8),93), ((0,8),29), ((0,9),154), + ((84,7),83), ((0,8),125), ((0,8),61), ((0,9),218), ((82,7),23), + ((0,8),109), ((0,8),45), ((0,9),186), ((0,8),13), ((0,8),141), + ((0,8),77), ((0,9),250), ((80,7),3), ((0,8),83), ((0,8),19), + ((85,8),195), ((83,7),35), ((0,8),115), ((0,8),51), ((0,9),198), + ((81,7),11), ((0,8),99), ((0,8),35), ((0,9),166), ((0,8),3), + ((0,8),131), ((0,8),67), ((0,9),230), ((80,7),7), ((0,8),91), + ((0,8),27), ((0,9),150), ((84,7),67), ((0,8),123), ((0,8),59), + ((0,9),214), ((82,7),19), ((0,8),107), ((0,8),43), ((0,9),182), + ((0,8),11), ((0,8),139), ((0,8),75), ((0,9),246), ((80,7),5), + ((0,8),87), ((0,8),23), ((192,8),0), ((83,7),51), ((0,8),119), + ((0,8),55), ((0,9),206), ((81,7),15), ((0,8),103), ((0,8),39), + ((0,9),174), ((0,8),7), ((0,8),135), ((0,8),71), ((0,9),238), + ((80,7),9), ((0,8),95), ((0,8),31), ((0,9),158), ((84,7),99), + ((0,8),127), ((0,8),63), ((0,9),222), ((82,7),27), ((0,8),111), + ((0,8),47), ((0,9),190), ((0,8),15), ((0,8),143), ((0,8),79), + ((0,9),254), ((96,7),256), ((0,8),80), ((0,8),16), ((84,8),115), + ((82,7),31), ((0,8),112), ((0,8),48), ((0,9),193), ((80,7),10), + ((0,8),96), ((0,8),32), ((0,9),161), ((0,8),0), ((0,8),128), + ((0,8),64), ((0,9),225), ((80,7),6), ((0,8),88), ((0,8),24), + ((0,9),145), ((83,7),59), ((0,8),120), ((0,8),56), ((0,9),209), + ((81,7),17), ((0,8),104), ((0,8),40), ((0,9),177), ((0,8),8), + ((0,8),136), ((0,8),72), ((0,9),241), ((80,7),4), ((0,8),84), + ((0,8),20), ((85,8),227), ((83,7),43), ((0,8),116), ((0,8),52), + ((0,9),201), ((81,7),13), ((0,8),100), ((0,8),36), ((0,9),169), + ((0,8),4), ((0,8),132), ((0,8),68), ((0,9),233), ((80,7),8), + ((0,8),92), ((0,8),28), ((0,9),153), ((84,7),83), ((0,8),124), + ((0,8),60), ((0,9),217), ((82,7),23), ((0,8),108), ((0,8),44), + ((0,9),185), ((0,8),12), ((0,8),140), ((0,8),76), ((0,9),249), + ((80,7),3), ((0,8),82), ((0,8),18), ((85,8),163), ((83,7),35), + ((0,8),114), ((0,8),50), ((0,9),197), ((81,7),11), ((0,8),98), + ((0,8),34), ((0,9),165), ((0,8),2), ((0,8),130), ((0,8),66), + ((0,9),229), ((80,7),7), ((0,8),90), ((0,8),26), ((0,9),149), + ((84,7),67), ((0,8),122), ((0,8),58), ((0,9),213), ((82,7),19), + ((0,8),106), ((0,8),42), ((0,9),181), ((0,8),10), ((0,8),138), + ((0,8),74), ((0,9),245), ((80,7),5), ((0,8),86), ((0,8),22), + ((192,8),0), ((83,7),51), ((0,8),118), ((0,8),54), ((0,9),205), + ((81,7),15), ((0,8),102), ((0,8),38), ((0,9),173), ((0,8),6), + ((0,8),134), ((0,8),70), ((0,9),237), ((80,7),9), ((0,8),94), + ((0,8),30), ((0,9),157), ((84,7),99), ((0,8),126), ((0,8),62), + ((0,9),221), ((82,7),27), ((0,8),110), ((0,8),46), ((0,9),189), + ((0,8),14), ((0,8),142), ((0,8),78), ((0,9),253), ((96,7),256), + ((0,8),81), ((0,8),17), ((85,8),131), ((82,7),31), ((0,8),113), + ((0,8),49), ((0,9),195), ((80,7),10), ((0,8),97), ((0,8),33), + ((0,9),163), ((0,8),1), ((0,8),129), ((0,8),65), ((0,9),227), + ((80,7),6), ((0,8),89), ((0,8),25), ((0,9),147), ((83,7),59), + ((0,8),121), ((0,8),57), ((0,9),211), ((81,7),17), ((0,8),105), + ((0,8),41), ((0,9),179), ((0,8),9), ((0,8),137), ((0,8),73), + ((0,9),243), ((80,7),4), ((0,8),85), ((0,8),21), ((80,8),258), + ((83,7),43), ((0,8),117), ((0,8),53), ((0,9),203), ((81,7),13), + ((0,8),101), ((0,8),37), ((0,9),171), ((0,8),5), ((0,8),133), + ((0,8),69), ((0,9),235), ((80,7),8), ((0,8),93), ((0,8),29), + ((0,9),155), ((84,7),83), ((0,8),125), ((0,8),61), ((0,9),219), + ((82,7),23), ((0,8),109), ((0,8),45), ((0,9),187), ((0,8),13), + ((0,8),141), ((0,8),77), ((0,9),251), ((80,7),3), ((0,8),83), + ((0,8),19), ((85,8),195), ((83,7),35), ((0,8),115), ((0,8),51), + ((0,9),199), ((81,7),11), ((0,8),99), ((0,8),35), ((0,9),167), + ((0,8),3), ((0,8),131), ((0,8),67), ((0,9),231), ((80,7),7), + ((0,8),91), ((0,8),27), ((0,9),151), ((84,7),67), ((0,8),123), + ((0,8),59), ((0,9),215), ((82,7),19), ((0,8),107), ((0,8),43), + ((0,9),183), ((0,8),11), ((0,8),139), ((0,8),75), ((0,9),247), + ((80,7),5), ((0,8),87), ((0,8),23), ((192,8),0), ((83,7),51), + ((0,8),119), ((0,8),55), ((0,9),207), ((81,7),15), ((0,8),103), + ((0,8),39), ((0,9),175), ((0,8),7), ((0,8),135), ((0,8),71), + ((0,9),239), ((80,7),9), ((0,8),95), ((0,8),31), ((0,9),159), + ((84,7),99), ((0,8),127), ((0,8),63), ((0,9),223), ((82,7),27), + ((0,8),111), ((0,8),47), ((0,9),191), ((0,8),15), ((0,8),143), + ((0,8),79), ((0,9),255) + ); + +{local} +const + fixed_td : array[0..32-1] of inflate_huft = ( +(Exop:80;bits:5;base:1), (Exop:87;bits:5;base:257), (Exop:83;bits:5;base:17), +(Exop:91;bits:5;base:4097), (Exop:81;bits:5;base), (Exop:89;bits:5;base:1025), +(Exop:85;bits:5;base:65), (Exop:93;bits:5;base:16385), (Exop:80;bits:5;base:3), +(Exop:88;bits:5;base:513), (Exop:84;bits:5;base:33), (Exop:92;bits:5;base:8193), +(Exop:82;bits:5;base:9), (Exop:90;bits:5;base:2049), (Exop:86;bits:5;base:129), +(Exop:192;bits:5;base:24577), (Exop:80;bits:5;base:2), (Exop:87;bits:5;base:385), +(Exop:83;bits:5;base:25), (Exop:91;bits:5;base:6145), (Exop:81;bits:5;base:7), +(Exop:89;bits:5;base:1537), (Exop:85;bits:5;base:97), (Exop:93;bits:5;base:24577), +(Exop:80;bits:5;base:4), (Exop:88;bits:5;base:769), (Exop:84;bits:5;base:49), +(Exop:92;bits:5;base:12289), (Exop:82;bits:5;base:13), (Exop:90;bits:5;base:3073), +(Exop:86;bits:5;base:193), (Exop:192;bits:5;base:24577) + ); +{$ENDIF} + +function inflate_trees_fixed( +var bl : uInt; { literal desired/actual bit depth } +var bd : uInt; { distance desired/actual bit depth } +var tl : pInflate_huft; { literal/length tree result } +var td : pInflate_huft; { distance tree result } +var z : z_stream { for memory allocation } + ) : int; +type + pFixed_table = ^fixed_table; + fixed_table = array[0..288-1] of uIntf; +var + k : int; { temporary variable } + c : pFixed_table; { length list for huft_build } + v : PuIntArray; { work area for huft_build } +var + f : uInt; { number of hufts used in fixed_mem } +begin + { build fixed tables if not already (multiple overlapped executions ok) } + if not fixed_built then + begin + f := 0; + + { allocate memory } + c := pFixed_table( ZALLOC(z, 288, sizeof(uInt)) ); + if (c = Z_NULL) then + begin + inflate_trees_fixed := Z_MEM_ERROR; + exit; + end; + v := PuIntArray( ZALLOC(z, 288, sizeof(uInt)) ); + if (v = Z_NULL) then + begin + ZFREE(z, c); + inflate_trees_fixed := Z_MEM_ERROR; + exit; + end; + + { literal table } + for k := 0 to Pred(144) do + c^[k] := 8; + for k := 144 to Pred(256) do + c^[k] := 9; + for k := 256 to Pred(280) do + c^[k] := 7; + for k := 280 to Pred(288) do + c^[k] := 8; + fixed_bl := 9; + huft_build(c^, 288, 257, cplens, cplext, @fixed_tl, fixed_bl, + fixed_mem, f, v^); + + { distance table } + for k := 0 to Pred(30) do + c^[k] := 5; + fixed_bd := 5; + huft_build(c^, 30, 0, cpdist, cpdext, @fixed_td, fixed_bd, + fixed_mem, f, v^); + + { done } + ZFREE(z, v); + ZFREE(z, c); + fixed_built := True; + end; + bl := fixed_bl; + bd := fixed_bd; + tl := fixed_tl; + td := fixed_td; + inflate_trees_fixed := Z_OK; +end; { inflate_trees_fixed } + + +end. diff --git a/src/lib/vampimg/ZLib/iminfutil.pas b/src/lib/vampimg/ZLib/iminfutil.pas new file mode 100644 index 0000000..384f0d3 --- /dev/null +++ b/src/lib/vampimg/ZLib/iminfutil.pas @@ -0,0 +1,222 @@ +Unit iminfutil; + +{ types and macros common to blocks and codes + Copyright (C) 1995-1998 Mark Adler + + WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +interface + +{$I imzconf.inc} + +uses + imzutil, impaszlib; + +{ copy as much as possible from the sliding window to the output area } +function inflate_flush(var s : inflate_blocks_state; + var z : z_stream; + r : int) : int; + +{ And'ing with mask[n] masks the lower n bits } +const + inflate_mask : array[0..17-1] of uInt = ( + $0000, + $0001, $0003, $0007, $000f, $001f, $003f, $007f, $00ff, + $01ff, $03ff, $07ff, $0fff, $1fff, $3fff, $7fff, $ffff); + +{procedure GRABBITS(j : int);} +{procedure DUMPBITS(j : int);} +{procedure NEEDBITS(j : int);} + +implementation + +{ macros for bit input with no checking and for returning unused bytes } +procedure GRABBITS(j : int); +begin + {while (k < j) do + begin + Dec(z^.avail_in); + Inc(z^.total_in); + b := b or (uLong(z^.next_in^) shl k); + Inc(z^.next_in); + Inc(k, 8); + end;} +end; + +procedure DUMPBITS(j : int); +begin + {b := b shr j; + Dec(k, j);} +end; + +procedure NEEDBITS(j : int); +begin + (* + while (k < j) do + begin + {NEEDBYTE;} + if (n <> 0) then + r :=Z_OK + else + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, LongInt(p)-LongInt(z.next_in)); + z.next_in := p; + s.write := q; + result := inflate_flush(s,z,r); + exit; + end; + Dec(n); + b := b or (uLong(p^) shl k); + Inc(p); + Inc(k, 8); + end; + *) +end; + +procedure NEEDOUT; +begin + (* + if (m = 0) then + begin + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if LongInt(q) < LongInt(s.read) then + m := uInt(LongInt(s.read)-LongInt(q)-1) + else + m := uInt(LongInt(s.zend)-LongInt(q)); + end; + + if (m = 0) then + begin + {FLUSH} + s.write := q; + r := inflate_flush(s,z,r); + q := s.write; + if LongInt(q) < LongInt(s.read) then + m := uInt(LongInt(s.read)-LongInt(q)-1) + else + m := uInt(LongInt(s.zend)-LongInt(q)); + + {WRAP} + if (q = s.zend) and (s.read <> s.window) then + begin + q := s.window; + if LongInt(q) < LongInt(s.read) then + m := uInt(LongInt(s.read)-LongInt(q)-1) + else + m := uInt(LongInt(s.zend)-LongInt(q)); + end; + + if (m = 0) then + begin + {UPDATE} + s.bitb := b; + s.bitk := k; + z.avail_in := n; + Inc(z.total_in, LongInt(p)-LongInt(z.next_in)); + z.next_in := p; + s.write := q; + result := inflate_flush(s,z,r); + exit; + end; + end; + end; + r := Z_OK; + *) +end; + +{ copy as much as possible from the sliding window to the output area } +function inflate_flush(var s : inflate_blocks_state; + var z : z_stream; + r : int) : int; +var + n : uInt; + p : pBytef; + q : pBytef; +begin + { local copies of source and destination pointers } + p := z.next_out; + q := s.read; + + { compute number of bytes to copy as far as end of window } + if ptr2int(q) <= ptr2int(s.write) then + n := uInt(ptr2int(s.write) - ptr2int(q)) + else + n := uInt(ptr2int(s.zend) - ptr2int(q)); + if (n > z.avail_out) then + n := z.avail_out; + if (n <> 0) and (r = Z_BUF_ERROR) then + r := Z_OK; + + { update counters } + Dec(z.avail_out, n); + Inc(z.total_out, n); + + + { update check information } + if Assigned(s.checkfn) then + begin + s.check := s.checkfn(s.check, q, n); + z.adler := s.check; + end; + + { copy as far as end of window } + zmemcpy(p, q, n); + Inc(p, n); + Inc(q, n); + + { see if more to copy at beginning of window } + if (q = s.zend) then + begin + { wrap pointers } + q := s.window; + if (s.write = s.zend) then + s.write := s.window; + + { compute bytes to copy } + n := uInt(ptr2int(s.write) - ptr2int(q)); + if (n > z.avail_out) then + n := z.avail_out; + if (n <> 0) and (r = Z_BUF_ERROR) then + r := Z_OK; + + { update counters } + Dec( z.avail_out, n); + Inc( z.total_out, n); + + { update check information } + if Assigned(s.checkfn) then + begin + s.check := s.checkfn(s.check, q, n); + z.adler := s.check; + end; + + { copy } + zmemcpy(p, q, n); + Inc(p, n); + Inc(q, n); + end; + + + { update pointers } + z.next_out := p; + s.read := q; + + { done } + inflate_flush := r; +end; + +end. diff --git a/src/lib/vampimg/ZLib/impaszlib.pas b/src/lib/vampimg/ZLib/impaszlib.pas new file mode 100644 index 0000000..7827dec --- /dev/null +++ b/src/lib/vampimg/ZLib/impaszlib.pas @@ -0,0 +1,520 @@ +Unit impaszlib; + + +{ Original: + zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.0, Feb 24th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +interface + +{$I imzconf.inc} + +uses + imzutil; + +{ zconf.h -- configuration of the zlib compression library } +{ zutil.c -- target dependent utility functions for the compression library } + +{ The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. } + + + +{ Compile with -DMAXSEG_64K if the alloc function cannot allocate more + than 64k bytes at a time (needed on systems with 16-bit int). } + +{ Maximum value for memLevel in deflateInit2 } +const + MAX_MEM_LEVEL = 9; + DEF_MEM_LEVEL = 8; { if MAX_MEM_LEVEL > 8 } + +{ Maximum value for windowBits in deflateInit2 and inflateInit2 } +const + MAX_WBITS = 15; { 32K LZ77 window } + +{ default windowBits for decompression. MAX_WBITS is for compression only } +const + DEF_WBITS = MAX_WBITS; + +{ The memory requirements for deflate are (in bytes): + 1 shl (windowBits+2) + 1 shl (memLevel+9) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + DMAX_WBITS=14 DMAX_MEM_LEVEL=7 + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 shl windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. } + + +{ Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). } + +type + pInflate_huft = ^inflate_huft; + inflate_huft = Record + Exop, { number of extra bits or operation } + bits : Byte; { number of bits in this code or subcode } + {pad : uInt;} { pad structure to a power of 2 (4 bytes for } + { 16-bit, 8 bytes for 32-bit int's) } + base : uInt; { literal, length base, or distance base } + { or table offset } + End; + +type + huft_field = Array[0..(MaxInt div SizeOf(inflate_huft))-1] of inflate_huft; + huft_ptr = ^huft_field; +type + ppInflate_huft = ^pInflate_huft; + +type + inflate_codes_mode = ( { waiting for "i:"=input, "o:"=output, "x:"=nothing } + START, { x: set up for LEN } + LEN, { i: get length/literal/eob next } + LENEXT, { i: getting length extra (have base) } + DIST, { i: get distance next } + DISTEXT, { i: getting distance extra } + COPY, { o: copying bytes in window, waiting for space } + LIT, { o: got literal, waiting for output space } + WASH, { o: got eob, possibly still output waiting } + ZEND, { x: got eob and all data flushed } + BADCODE); { x: got error } + +{ inflate codes private state } +type + pInflate_codes_state = ^inflate_codes_state; + inflate_codes_state = record + + mode : inflate_codes_mode; { current inflate_codes mode } + + { mode dependent information } + len : uInt; + sub : record { submode } + Case Byte of + 0:(code : record { if LEN or DIST, where in tree } + tree : pInflate_huft; { pointer into tree } + need : uInt; { bits needed } + end); + 1:(lit : uInt); { if LIT, literal } + 2:(copy: record { if EXT or COPY, where and how much } + get : uInt; { bits to get for extra } + dist : uInt; { distance back to copy from } + end); + end; + + { mode independent information } + lbits : Byte; { ltree bits decoded per branch } + dbits : Byte; { dtree bits decoder per branch } + ltree : pInflate_huft; { literal/length/eob tree } + dtree : pInflate_huft; { distance tree } + end; + +type + check_func = function(check : uLong; + buf : pBytef; + {const buf : array of byte;} + len : uInt) : uLong; +type + inflate_block_mode = + (ZTYPE, { get type bits (3, including end bit) } + LENS, { get lengths for stored } + STORED, { processing stored block } + TABLE, { get table lengths } + BTREE, { get bit lengths tree for a dynamic block } + DTREE, { get length, distance trees for a dynamic block } + CODES, { processing fixed or dynamic block } + DRY, { output remaining window bytes } + BLKDONE, { finished last block, done } + BLKBAD); { got a data error--stuck here } + +type + pInflate_blocks_state = ^inflate_blocks_state; + +{ inflate blocks semi-private state } + inflate_blocks_state = record + + mode : inflate_block_mode; { current inflate_block mode } + + { mode dependent information } + sub : record { submode } + case Byte of + 0:(left : uInt); { if STORED, bytes left to copy } + 1:(trees : record { if DTREE, decoding info for trees } + table : uInt; { table lengths (14 bits) } + index : uInt; { index into blens (or border) } + blens : PuIntArray; { bit lengths of codes } + bb : uInt; { bit length tree depth } + tb : pInflate_huft; { bit length decoding tree } + end); + 2:(decode : record { if CODES, current state } + tl : pInflate_huft; + td : pInflate_huft; { trees to free } + codes : pInflate_codes_state; + end); + end; + last : boolean; { true if this block is the last block } + + { mode independent information } + bitk : uInt; { bits in bit buffer } + bitb : uLong; { bit buffer } + hufts : huft_ptr; {pInflate_huft;} { single malloc for tree space } + window : pBytef; { sliding window } + zend : pBytef; { one byte after sliding window } + read : pBytef; { window read pointer } + write : pBytef; { window write pointer } + checkfn : check_func; { check function } + check : uLong; { check on output } + end; + +type + inflate_mode = ( + METHOD, { waiting for method byte } + FLAG, { waiting for flag byte } + DICT4, { four dictionary check bytes to go } + DICT3, { three dictionary check bytes to go } + DICT2, { two dictionary check bytes to go } + DICT1, { one dictionary check byte to go } + DICT0, { waiting for inflateSetDictionary } + BLOCKS, { decompressing blocks } + CHECK4, { four check bytes to go } + CHECK3, { three check bytes to go } + CHECK2, { two check bytes to go } + CHECK1, { one check byte to go } + DONE, { finished check, done } + BAD); { got an error--stay here } + +{ inflate private state } +type + pInternal_state = ^internal_state; { or point to a deflate_state record } + internal_state = record + + mode : inflate_mode; { current inflate mode } + + { mode dependent information } + sub : record { submode } + case byte of + 0:(method : uInt); { if FLAGS, method byte } + 1:(check : record { if CHECK, check values to compare } + was : uLong; { computed check value } + need : uLong; { stream check value } + end); + 2:(marker : uInt); { if BAD, inflateSync's marker bytes count } + end; + + { mode independent information } + nowrap : boolean; { flag for no wrapper } + wbits : uInt; { log2(window size) (8..15, defaults to 15) } + blocks : pInflate_blocks_state; { current inflate_blocks state } + end; + +type + alloc_func = function(opaque : voidpf; items : uInt; size : uInt) : voidpf; + free_func = procedure(opaque : voidpf; address : voidpf); + +type + z_streamp = ^z_stream; + z_stream = record + next_in : pBytef; { next input byte } + avail_in : uInt; { number of bytes available at next_in } + total_in : uLong; { total nb of input bytes read so far } + + next_out : pBytef; { next output byte should be put there } + avail_out : uInt; { remaining free space at next_out } + total_out : uLong; { total nb of bytes output so far } + + msg : string[255]; { last error message, '' if no error } + state : pInternal_state; { not visible by applications } + + zalloc : alloc_func; { used to allocate the internal state } + zfree : free_func; { used to free the internal state } + opaque : voidpf; { private data object passed to zalloc and zfree } + + data_type : int; { best guess about the data type: ascii or binary } + adler : uLong; { adler32 value of the uncompressed data } + reserved : uLong; { reserved for future use } + end; + + +{ The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). } + +const { constants } + Z_NO_FLUSH = 0; + Z_PARTIAL_FLUSH = 1; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; +{ Allowed flush values; see deflate() below for details } + + Z_OK = 0; + Z_STREAM_END = 1; + Z_NEED_DICT = 2; + Z_ERRNO = (-1); + Z_STREAM_ERROR = (-2); + Z_DATA_ERROR = (-3); + Z_MEM_ERROR = (-4); + Z_BUF_ERROR = (-5); + Z_VERSION_ERROR = (-6); +{ Return codes for the compression/decompression functions. Negative + values are errors, positive values are used for special but normal events.} + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = (-1); +{ compression levels } + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_DEFAULT_STRATEGY = 0; +{ compression strategy; see deflateInit2() below for details } + + Z_BINARY = 0; + Z_ASCII = 1; + Z_UNKNOWN = 2; +{ Possible values of the data_type field } + + Z_DEFLATED = 8; +{ The deflate compression method (the only one supported in this version) } + + Z_NULL = NIL; { for initializing zalloc, zfree, opaque } + + {$IFDEF GZIO} +var + errno : int; + {$ENDIF} + + { common constants } + + +{ The three kinds of block type } +const + STORED_BLOCK = 0; + STATIC_TREES = 1; + DYN_TREES = 2; +{ The minimum and maximum match lengths } +const + MIN_MATCH = 3; + MAX_MATCH = 258; + +const + PRESET_DICT = $20; { preset dictionary flag in zlib header } + + + {$IFDEF DEBUG} + procedure Assert(cond : boolean; msg : AnsiString); + {$ENDIF} + + procedure Trace(x : AnsiString); + procedure Tracev(x : AnsiString); + procedure Tracevv(x : AnsiString); + procedure Tracevvv(x : AnsiString); + procedure Tracec(c : boolean; x : AnsiString); + procedure Tracecv(c : boolean; x : AnsiString); + +function zlibVersion : AnsiString; +{ The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. } + +function zError(err : int) : AnsiString; +function ZALLOC (var strm : z_stream; items : uInt; size : uInt) : voidpf; +procedure ZFREE (var strm : z_stream; ptr : voidpf); +procedure TRY_FREE (var strm : z_stream; ptr : voidpf); + +const + ZLIB_VERSION : string[10] = '1.1.2'; + +const + z_errbase = Z_NEED_DICT; + z_errmsg : Array[0..9] of string[21] = { indexed by 2-zlib_error } + ('need dictionary', { Z_NEED_DICT 2 } + 'stream end', { Z_STREAM_END 1 } + '', { Z_OK 0 } + 'file error', { Z_ERRNO (-1) } + 'stream error', { Z_STREAM_ERROR (-2) } + 'data error', { Z_DATA_ERROR (-3) } + 'insufficient memory', { Z_MEM_ERROR (-4) } + 'buffer error', { Z_BUF_ERROR (-5) } + 'incompatible version',{ Z_VERSION_ERROR (-6) } + ''); +const + z_verbose : int = 1; + +function deflateInit_(var Stream: z_stream; Level: LongInt; const Version: AnsiString; + Stream_size: LongInt): LongInt; +function inflateInit_(var Stream: z_stream; const Version: AnsiString; + Stream_size: Longint): LongInt; + +{$IFDEF DEBUG} +procedure z_error (m : string); +{$ENDIF} + +implementation + +uses + imzdeflate, imzinflate; + +function deflateInit_(var Stream: z_stream; Level: LongInt; const Version: AnsiString; + Stream_size: LongInt): LongInt; +begin + Result := imzdeflate.deflateInit_(@Stream, Level, Version, Stream_size); +end; + +function inflateInit_(var Stream: z_stream; const Version: AnsiString; + Stream_size: Longint): LongInt; +begin + Result := imzinflate.inflateInit_(@Stream, Version, Stream_size); +end; + +function zError(err : int) : AnsiString; +begin + zError := z_errmsg[Z_NEED_DICT-err]; +end; + +function zlibVersion : AnsiString; +begin + zlibVersion := ZLIB_VERSION; +end; + +procedure z_error (m : AnsiString); +begin + WriteLn(output, m); + Write('Zlib - Halt...'); + ReadLn; + Halt(1); +end; + +procedure Assert(cond : boolean; msg : AnsiString); +begin + if not cond then + z_error(msg); +end; + +procedure Trace(x : AnsiString); +begin + WriteLn(x); +end; + +procedure Tracev(x : AnsiString); +begin + if (z_verbose>0) then + WriteLn(x); +end; + +procedure Tracevv(x : AnsiString); +begin + if (z_verbose>1) then + WriteLn(x); +end; + +procedure Tracevvv(x : AnsiString); +begin + if (z_verbose>2) then + WriteLn(x); +end; + +procedure Tracec(c : boolean; x : AnsiString); +begin + if (z_verbose>0) and (c) then + WriteLn(x); +end; + +procedure Tracecv(c : boolean; x : AnsiString); +begin + if (z_verbose>1) and c then + WriteLn(x); +end; + +function ZALLOC (var strm : z_stream; items : uInt; size : uInt) : voidpf; +begin + ZALLOC := strm.zalloc(strm.opaque, items, size); +end; + +procedure ZFREE (var strm : z_stream; ptr : voidpf); +begin + strm.zfree(strm.opaque, ptr); +end; + +procedure TRY_FREE (var strm : z_stream; ptr : voidpf); +begin + {if @strm <> Z_NULL then} + strm.zfree(strm.opaque, ptr); +end; + +end. diff --git a/src/lib/vampimg/ZLib/imtrees.pas b/src/lib/vampimg/ZLib/imtrees.pas new file mode 100644 index 0000000..8f1f559 --- /dev/null +++ b/src/lib/vampimg/ZLib/imtrees.pas @@ -0,0 +1,2249 @@ +Unit imtrees; + +{$T-} +{$define ORG_DEBUG} +{ + trees.c -- output deflated data using Huffman coding + Copyright (C) 1995-1998 Jean-loup Gailly + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +{ + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + } + +interface + +{$I imzconf.inc} + +uses + {$ifdef DEBUG} + SysUtils, strutils, + {$ENDIF} + imzutil, impaszlib; + +{ =========================================================================== + Internal compression state. } + +const + LENGTH_CODES = 29; +{ number of length codes, not counting the special END_BLOCK code } + + LITERALS = 256; +{ number of literal bytes 0..255 } + + L_CODES = (LITERALS+1+LENGTH_CODES); +{ number of Literal or Length codes, including the END_BLOCK code } + + D_CODES = 30; +{ number of distance codes } + + BL_CODES = 19; +{ number of codes used to transfer the bit lengths } + + HEAP_SIZE = (2*L_CODES+1); +{ maximum heap size } + + MAX_BITS = 15; +{ All codes must not exceed MAX_BITS bits } + +const + INIT_STATE = 42; + BUSY_STATE = 113; + FINISH_STATE = 666; +{ Stream status } + + +{ Data structure describing a single value and its code string. } +type + ct_data_ptr = ^ct_data; + ct_data = record + fc : record + case byte of + 0:(freq : ush); { frequency count } + 1:(code : ush); { bit string } + end; + dl : record + case byte of + 0:(dad : ush); { father node in Huffman tree } + 1:(len : ush); { length of bit string } + end; + end; + +{ Freq = fc.freq + Code = fc.code + Dad = dl.dad + Len = dl.len } + +type + ltree_type = array[0..HEAP_SIZE-1] of ct_data; { literal and length tree } + dtree_type = array[0..2*D_CODES+1-1] of ct_data; { distance tree } + htree_type = array[0..2*BL_CODES+1-1] of ct_data; { Huffman tree for bit lengths } + { generic tree type } + tree_type = array[0..(MaxInt div SizeOf(ct_data))-1] of ct_data; + + tree_ptr = ^tree_type; + ltree_ptr = ^ltree_type; + dtree_ptr = ^dtree_type; + htree_ptr = ^htree_type; + + +type + static_tree_desc_ptr = ^static_tree_desc; + static_tree_desc = + record + {const} static_tree : tree_ptr; { static tree or NIL } + {const} extra_bits : pzIntfArray; { extra bits for each code or NIL } + extra_base : int; { base index for extra_bits } + elems : int; { max number of elements in the tree } + max_length : int; { max bit length for the codes } + end; + + tree_desc_ptr = ^tree_desc; + tree_desc = record + dyn_tree : tree_ptr; { the dynamic tree } + max_code : int; { largest code with non zero frequency } + stat_desc : static_tree_desc_ptr; { the corresponding static tree } + end; + +type + Pos = ush; + Posf = Pos; {FAR} + IPos = uInt; + + pPosf = ^Posf; + + zPosfArray = array[0..(MaxInt div SizeOf(Posf))-1] of Posf; + pzPosfArray = ^zPosfArray; + +{ A Pos is an index in the character window. We use short instead of int to + save space in the various tables. IPos is used only for parameter passing.} + +type + deflate_state_ptr = ^deflate_state; + deflate_state = record + strm : z_streamp; { pointer back to this zlib stream } + status : int; { as the name implies } + pending_buf : pzByteArray; { output still pending } + pending_buf_size : ulg; { size of pending_buf } + pending_out : pBytef; { next pending byte to output to the stream } + pending : int; { nb of bytes in the pending buffer } + noheader : int; { suppress zlib header and adler32 } + data_type : Byte; { UNKNOWN, BINARY or ASCII } + method : Byte; { STORED (for zip only) or DEFLATED } + last_flush : int; { value of flush param for previous deflate call } + + { used by deflate.pas: } + + w_size : uInt; { LZ77 window size (32K by default) } + w_bits : uInt; { log2(w_size) (8..16) } + w_mask : uInt; { w_size - 1 } + + window : pzByteArray; + { Sliding window. Input bytes are read into the second half of the window, + and move to the first half later to keep a dictionary of at least wSize + bytes. With this organization, matches are limited to a distance of + wSize-MAX_MATCH bytes, but this ensures that IO is always + performed with a length multiple of the block size. Also, it limits + the window size to 64K, which is quite useful on MSDOS. + To do: use the user input buffer as sliding window. } + + window_size : ulg; + { Actual size of window: 2*wSize, except when the user input buffer + is directly used as sliding window. } + + prev : pzPosfArray; + { Link to older string with same hash index. To limit the size of this + array to 64K, this link is maintained only for the last 32K strings. + An index in this array is thus a window index modulo 32K. } + + head : pzPosfArray; { Heads of the hash chains or NIL. } + + ins_h : uInt; { hash index of string to be inserted } + hash_size : uInt; { number of elements in hash table } + hash_bits : uInt; { log2(hash_size) } + hash_mask : uInt; { hash_size-1 } + + hash_shift : uInt; + { Number of bits by which ins_h must be shifted at each input + step. It must be such that after MIN_MATCH steps, the oldest + byte no longer takes part in the hash key, that is: + hash_shift * MIN_MATCH >= hash_bits } + + block_start : long; + { Window position at the beginning of the current output block. Gets + negative when the window is moved backwards. } + + match_length : uInt; { length of best match } + prev_match : IPos; { previous match } + match_available : boolean; { set if previous match exists } + strstart : uInt; { start of string to insert } + match_start : uInt; { start of matching string } + lookahead : uInt; { number of valid bytes ahead in window } + + prev_length : uInt; + { Length of the best match at previous step. Matches not greater than this + are discarded. This is used in the lazy match evaluation. } + + max_chain_length : uInt; + { To speed up deflation, hash chains are never searched beyond this + length. A higher limit improves compression ratio but degrades the + speed. } + + { moved to the end because Borland Pascal won't accept the following: + max_lazy_match : uInt; + max_insert_length : uInt absolute max_lazy_match; + } + + level : int; { compression level (1..9) } + strategy : int; { favor or force Huffman coding} + + good_match : uInt; + { Use a faster search when the previous match is longer than this } + + nice_match : int; { Stop searching when current match exceeds this } + + { used by trees.pas: } + { Didn't use ct_data typedef below to supress compiler warning } + dyn_ltree : ltree_type; { literal and length tree } + dyn_dtree : dtree_type; { distance tree } + bl_tree : htree_type; { Huffman tree for bit lengths } + + l_desc : tree_desc; { desc. for literal tree } + d_desc : tree_desc; { desc. for distance tree } + bl_desc : tree_desc; { desc. for bit length tree } + + bl_count : array[0..MAX_BITS+1-1] of ush; + { number of codes at each bit length for an optimal tree } + + heap : array[0..2*L_CODES+1-1] of int; { heap used to build the Huffman trees } + heap_len : int; { number of elements in the heap } + heap_max : int; { element of largest frequency } + { The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + The same heap array is used to build all trees. } + + depth : array[0..2*L_CODES+1-1] of uch; + { Depth of each subtree used as tie breaker for trees of equal frequency } + + + l_buf : puchfArray; { buffer for literals or lengths } + + lit_bufsize : uInt; + { Size of match buffer for literals/lengths. There are 4 reasons for + limiting lit_bufsize to 64K: + - frequencies can be kept in 16 bit counters + - if compression is not successful for the first block, all input + data is still in the window so we can still emit a stored block even + when input comes from standard input. (This can also be done for + all blocks if lit_bufsize is not greater than 32K.) + - if compression is not successful for a file smaller than 64K, we can + even emit a stored file instead of a stored block (saving 5 bytes). + This is applicable only for zip (not gzip or zlib). + - creating new Huffman trees less frequently may not provide fast + adaptation to changes in the input data statistics. (Take for + example a binary file with poorly compressible code followed by + a highly compressible string table.) Smaller buffer sizes give + fast adaptation but have of course the overhead of transmitting + trees more frequently. + - I can't count above 4 } + + + last_lit : uInt; { running index in l_buf } + + d_buf : pushfArray; + { Buffer for distances. To simplify the code, d_buf and l_buf have + the same number of elements. To use different lengths, an extra flag + array would be necessary. } + + opt_len : ulg; { bit length of current block with optimal trees } + static_len : ulg; { bit length of current block with static trees } + compressed_len : ulg; { total bit length of compressed file } + matches : uInt; { number of string matches in current block } + last_eob_len : int; { bit length of EOB code for last block } + +{$ifdef DEBUG} + bits_sent : ulg; { bit length of the compressed data } +{$endif} + + bi_buf : ush; + { Output buffer. bits are inserted starting at the bottom (least + significant bits). } + + bi_valid : int; + { Number of valid bits in bi_buf. All bits above the last valid bit + are always zero. } + + case byte of + 0:(max_lazy_match : uInt); + { Attempt to find a better match only when the current match is strictly + smaller than this value. This mechanism is used only for compression + levels >= 4. } + + 1:(max_insert_length : uInt); + { Insert new strings in the hash table only if the match length is not + greater than this length. This saves time but degrades compression. + max_insert_length is used only for compression levels <= 3. } + end; + +procedure _tr_init (var s : deflate_state); + +function _tr_tally (var s : deflate_state; + dist : unsigned; + lc : unsigned) : boolean; + +function _tr_flush_block (var s : deflate_state; + buf : pcharf; + stored_len : ulg; + eof : boolean) : ulg; + +procedure _tr_align(var s : deflate_state); + +procedure _tr_stored_block(var s : deflate_state; + buf : pcharf; + stored_len : ulg; + eof : boolean); + +implementation + +{ #define GEN_TREES_H } + +{$ifndef GEN_TREES_H} +{ header created automatically with -DGEN_TREES_H } + +const + DIST_CODE_LEN = 512; { see definition of array dist_code below } + +{ The static literal tree. Since the bit lengths are imposed, there is no + need for the L_CODES extra codes used during heap construction. However + The codes 286 and 287 are needed to build a canonical tree (see _tr_init + below). } +var + static_ltree : array[0..L_CODES+2-1] of ct_data = ( +{ fc:(freq, code) dl:(dad,len) } +(fc:(freq: 12);dl:(len: 8)), (fc:(freq:140);dl:(len: 8)), (fc:(freq: 76);dl:(len: 8)), +(fc:(freq:204);dl:(len: 8)), (fc:(freq: 44);dl:(len: 8)), (fc:(freq:172);dl:(len: 8)), +(fc:(freq:108);dl:(len: 8)), (fc:(freq:236);dl:(len: 8)), (fc:(freq: 28);dl:(len: 8)), +(fc:(freq:156);dl:(len: 8)), (fc:(freq: 92);dl:(len: 8)), (fc:(freq:220);dl:(len: 8)), +(fc:(freq: 60);dl:(len: 8)), (fc:(freq:188);dl:(len: 8)), (fc:(freq:124);dl:(len: 8)), +(fc:(freq:252);dl:(len: 8)), (fc:(freq: 2);dl:(len: 8)), (fc:(freq:130);dl:(len: 8)), +(fc:(freq: 66);dl:(len: 8)), (fc:(freq:194);dl:(len: 8)), (fc:(freq: 34);dl:(len: 8)), +(fc:(freq:162);dl:(len: 8)), (fc:(freq: 98);dl:(len: 8)), (fc:(freq:226);dl:(len: 8)), +(fc:(freq: 18);dl:(len: 8)), (fc:(freq:146);dl:(len: 8)), (fc:(freq: 82);dl:(len: 8)), +(fc:(freq:210);dl:(len: 8)), (fc:(freq: 50);dl:(len: 8)), (fc:(freq:178);dl:(len: 8)), +(fc:(freq:114);dl:(len: 8)), (fc:(freq:242);dl:(len: 8)), (fc:(freq: 10);dl:(len: 8)), +(fc:(freq:138);dl:(len: 8)), (fc:(freq: 74);dl:(len: 8)), (fc:(freq:202);dl:(len: 8)), +(fc:(freq: 42);dl:(len: 8)), (fc:(freq:170);dl:(len: 8)), (fc:(freq:106);dl:(len: 8)), +(fc:(freq:234);dl:(len: 8)), (fc:(freq: 26);dl:(len: 8)), (fc:(freq:154);dl:(len: 8)), +(fc:(freq: 90);dl:(len: 8)), (fc:(freq:218);dl:(len: 8)), (fc:(freq: 58);dl:(len: 8)), +(fc:(freq:186);dl:(len: 8)), (fc:(freq:122);dl:(len: 8)), (fc:(freq:250);dl:(len: 8)), +(fc:(freq: 6);dl:(len: 8)), (fc:(freq:134);dl:(len: 8)), (fc:(freq: 70);dl:(len: 8)), +(fc:(freq:198);dl:(len: 8)), (fc:(freq: 38);dl:(len: 8)), (fc:(freq:166);dl:(len: 8)), +(fc:(freq:102);dl:(len: 8)), (fc:(freq:230);dl:(len: 8)), (fc:(freq: 22);dl:(len: 8)), +(fc:(freq:150);dl:(len: 8)), (fc:(freq: 86);dl:(len: 8)), (fc:(freq:214);dl:(len: 8)), +(fc:(freq: 54);dl:(len: 8)), (fc:(freq:182);dl:(len: 8)), (fc:(freq:118);dl:(len: 8)), +(fc:(freq:246);dl:(len: 8)), (fc:(freq: 14);dl:(len: 8)), (fc:(freq:142);dl:(len: 8)), +(fc:(freq: 78);dl:(len: 8)), (fc:(freq:206);dl:(len: 8)), (fc:(freq: 46);dl:(len: 8)), +(fc:(freq:174);dl:(len: 8)), (fc:(freq:110);dl:(len: 8)), (fc:(freq:238);dl:(len: 8)), +(fc:(freq: 30);dl:(len: 8)), (fc:(freq:158);dl:(len: 8)), (fc:(freq: 94);dl:(len: 8)), +(fc:(freq:222);dl:(len: 8)), (fc:(freq: 62);dl:(len: 8)), (fc:(freq:190);dl:(len: 8)), +(fc:(freq:126);dl:(len: 8)), (fc:(freq:254);dl:(len: 8)), (fc:(freq: 1);dl:(len: 8)), +(fc:(freq:129);dl:(len: 8)), (fc:(freq: 65);dl:(len: 8)), (fc:(freq:193);dl:(len: 8)), +(fc:(freq: 33);dl:(len: 8)), (fc:(freq:161);dl:(len: 8)), (fc:(freq: 97);dl:(len: 8)), +(fc:(freq:225);dl:(len: 8)), (fc:(freq: 17);dl:(len: 8)), (fc:(freq:145);dl:(len: 8)), +(fc:(freq: 81);dl:(len: 8)), (fc:(freq:209);dl:(len: 8)), (fc:(freq: 49);dl:(len: 8)), +(fc:(freq:177);dl:(len: 8)), (fc:(freq:113);dl:(len: 8)), (fc:(freq:241);dl:(len: 8)), +(fc:(freq: 9);dl:(len: 8)), (fc:(freq:137);dl:(len: 8)), (fc:(freq: 73);dl:(len: 8)), +(fc:(freq:201);dl:(len: 8)), (fc:(freq: 41);dl:(len: 8)), (fc:(freq:169);dl:(len: 8)), +(fc:(freq:105);dl:(len: 8)), (fc:(freq:233);dl:(len: 8)), (fc:(freq: 25);dl:(len: 8)), +(fc:(freq:153);dl:(len: 8)), (fc:(freq: 89);dl:(len: 8)), (fc:(freq:217);dl:(len: 8)), +(fc:(freq: 57);dl:(len: 8)), (fc:(freq:185);dl:(len: 8)), (fc:(freq:121);dl:(len: 8)), +(fc:(freq:249);dl:(len: 8)), (fc:(freq: 5);dl:(len: 8)), (fc:(freq:133);dl:(len: 8)), +(fc:(freq: 69);dl:(len: 8)), (fc:(freq:197);dl:(len: 8)), (fc:(freq: 37);dl:(len: 8)), +(fc:(freq:165);dl:(len: 8)), (fc:(freq:101);dl:(len: 8)), (fc:(freq:229);dl:(len: 8)), +(fc:(freq: 21);dl:(len: 8)), (fc:(freq:149);dl:(len: 8)), (fc:(freq: 85);dl:(len: 8)), +(fc:(freq:213);dl:(len: 8)), (fc:(freq: 53);dl:(len: 8)), (fc:(freq:181);dl:(len: 8)), +(fc:(freq:117);dl:(len: 8)), (fc:(freq:245);dl:(len: 8)), (fc:(freq: 13);dl:(len: 8)), +(fc:(freq:141);dl:(len: 8)), (fc:(freq: 77);dl:(len: 8)), (fc:(freq:205);dl:(len: 8)), +(fc:(freq: 45);dl:(len: 8)), (fc:(freq:173);dl:(len: 8)), (fc:(freq:109);dl:(len: 8)), +(fc:(freq:237);dl:(len: 8)), (fc:(freq: 29);dl:(len: 8)), (fc:(freq:157);dl:(len: 8)), +(fc:(freq: 93);dl:(len: 8)), (fc:(freq:221);dl:(len: 8)), (fc:(freq: 61);dl:(len: 8)), +(fc:(freq:189);dl:(len: 8)), (fc:(freq:125);dl:(len: 8)), (fc:(freq:253);dl:(len: 8)), +(fc:(freq: 19);dl:(len: 9)), (fc:(freq:275);dl:(len: 9)), (fc:(freq:147);dl:(len: 9)), +(fc:(freq:403);dl:(len: 9)), (fc:(freq: 83);dl:(len: 9)), (fc:(freq:339);dl:(len: 9)), +(fc:(freq:211);dl:(len: 9)), (fc:(freq:467);dl:(len: 9)), (fc:(freq: 51);dl:(len: 9)), +(fc:(freq:307);dl:(len: 9)), (fc:(freq:179);dl:(len: 9)), (fc:(freq:435);dl:(len: 9)), +(fc:(freq:115);dl:(len: 9)), (fc:(freq:371);dl:(len: 9)), (fc:(freq:243);dl:(len: 9)), +(fc:(freq:499);dl:(len: 9)), (fc:(freq: 11);dl:(len: 9)), (fc:(freq:267);dl:(len: 9)), +(fc:(freq:139);dl:(len: 9)), (fc:(freq:395);dl:(len: 9)), (fc:(freq: 75);dl:(len: 9)), +(fc:(freq:331);dl:(len: 9)), (fc:(freq:203);dl:(len: 9)), (fc:(freq:459);dl:(len: 9)), +(fc:(freq: 43);dl:(len: 9)), (fc:(freq:299);dl:(len: 9)), (fc:(freq:171);dl:(len: 9)), +(fc:(freq:427);dl:(len: 9)), (fc:(freq:107);dl:(len: 9)), (fc:(freq:363);dl:(len: 9)), +(fc:(freq:235);dl:(len: 9)), (fc:(freq:491);dl:(len: 9)), (fc:(freq: 27);dl:(len: 9)), +(fc:(freq:283);dl:(len: 9)), (fc:(freq:155);dl:(len: 9)), (fc:(freq:411);dl:(len: 9)), +(fc:(freq: 91);dl:(len: 9)), (fc:(freq:347);dl:(len: 9)), (fc:(freq:219);dl:(len: 9)), +(fc:(freq:475);dl:(len: 9)), (fc:(freq: 59);dl:(len: 9)), (fc:(freq:315);dl:(len: 9)), +(fc:(freq:187);dl:(len: 9)), (fc:(freq:443);dl:(len: 9)), (fc:(freq:123);dl:(len: 9)), +(fc:(freq:379);dl:(len: 9)), (fc:(freq:251);dl:(len: 9)), (fc:(freq:507);dl:(len: 9)), +(fc:(freq: 7);dl:(len: 9)), (fc:(freq:263);dl:(len: 9)), (fc:(freq:135);dl:(len: 9)), +(fc:(freq:391);dl:(len: 9)), (fc:(freq: 71);dl:(len: 9)), (fc:(freq:327);dl:(len: 9)), +(fc:(freq:199);dl:(len: 9)), (fc:(freq:455);dl:(len: 9)), (fc:(freq: 39);dl:(len: 9)), +(fc:(freq:295);dl:(len: 9)), (fc:(freq:167);dl:(len: 9)), (fc:(freq:423);dl:(len: 9)), +(fc:(freq:103);dl:(len: 9)), (fc:(freq:359);dl:(len: 9)), (fc:(freq:231);dl:(len: 9)), +(fc:(freq:487);dl:(len: 9)), (fc:(freq: 23);dl:(len: 9)), (fc:(freq:279);dl:(len: 9)), +(fc:(freq:151);dl:(len: 9)), (fc:(freq:407);dl:(len: 9)), (fc:(freq: 87);dl:(len: 9)), +(fc:(freq:343);dl:(len: 9)), (fc:(freq:215);dl:(len: 9)), (fc:(freq:471);dl:(len: 9)), +(fc:(freq: 55);dl:(len: 9)), (fc:(freq:311);dl:(len: 9)), (fc:(freq:183);dl:(len: 9)), +(fc:(freq:439);dl:(len: 9)), (fc:(freq:119);dl:(len: 9)), (fc:(freq:375);dl:(len: 9)), +(fc:(freq:247);dl:(len: 9)), (fc:(freq:503);dl:(len: 9)), (fc:(freq: 15);dl:(len: 9)), +(fc:(freq:271);dl:(len: 9)), (fc:(freq:143);dl:(len: 9)), (fc:(freq:399);dl:(len: 9)), +(fc:(freq: 79);dl:(len: 9)), (fc:(freq:335);dl:(len: 9)), (fc:(freq:207);dl:(len: 9)), +(fc:(freq:463);dl:(len: 9)), (fc:(freq: 47);dl:(len: 9)), (fc:(freq:303);dl:(len: 9)), +(fc:(freq:175);dl:(len: 9)), (fc:(freq:431);dl:(len: 9)), (fc:(freq:111);dl:(len: 9)), +(fc:(freq:367);dl:(len: 9)), (fc:(freq:239);dl:(len: 9)), (fc:(freq:495);dl:(len: 9)), +(fc:(freq: 31);dl:(len: 9)), (fc:(freq:287);dl:(len: 9)), (fc:(freq:159);dl:(len: 9)), +(fc:(freq:415);dl:(len: 9)), (fc:(freq: 95);dl:(len: 9)), (fc:(freq:351);dl:(len: 9)), +(fc:(freq:223);dl:(len: 9)), (fc:(freq:479);dl:(len: 9)), (fc:(freq: 63);dl:(len: 9)), +(fc:(freq:319);dl:(len: 9)), (fc:(freq:191);dl:(len: 9)), (fc:(freq:447);dl:(len: 9)), +(fc:(freq:127);dl:(len: 9)), (fc:(freq:383);dl:(len: 9)), (fc:(freq:255);dl:(len: 9)), +(fc:(freq:511);dl:(len: 9)), (fc:(freq: 0);dl:(len: 7)), (fc:(freq: 64);dl:(len: 7)), +(fc:(freq: 32);dl:(len: 7)), (fc:(freq: 96);dl:(len: 7)), (fc:(freq: 16);dl:(len: 7)), +(fc:(freq: 80);dl:(len: 7)), (fc:(freq: 48);dl:(len: 7)), (fc:(freq:112);dl:(len: 7)), +(fc:(freq: 8);dl:(len: 7)), (fc:(freq: 72);dl:(len: 7)), (fc:(freq: 40);dl:(len: 7)), +(fc:(freq:104);dl:(len: 7)), (fc:(freq: 24);dl:(len: 7)), (fc:(freq: 88);dl:(len: 7)), +(fc:(freq: 56);dl:(len: 7)), (fc:(freq:120);dl:(len: 7)), (fc:(freq: 4);dl:(len: 7)), +(fc:(freq: 68);dl:(len: 7)), (fc:(freq: 36);dl:(len: 7)), (fc:(freq:100);dl:(len: 7)), +(fc:(freq: 20);dl:(len: 7)), (fc:(freq: 84);dl:(len: 7)), (fc:(freq: 52);dl:(len: 7)), +(fc:(freq:116);dl:(len: 7)), (fc:(freq: 3);dl:(len: 8)), (fc:(freq:131);dl:(len: 8)), +(fc:(freq: 67);dl:(len: 8)), (fc:(freq:195);dl:(len: 8)), (fc:(freq: 35);dl:(len: 8)), +(fc:(freq:163);dl:(len: 8)), (fc:(freq: 99);dl:(len: 8)), (fc:(freq:227);dl:(len: 8)) +); + + +{ The static distance tree. (Actually a trivial tree since all lens use + 5 bits.) } + static_dtree : array[0..D_CODES-1] of ct_data = ( +(fc:(freq: 0); dl:(len:5)), (fc:(freq:16); dl:(len:5)), (fc:(freq: 8); dl:(len:5)), +(fc:(freq:24); dl:(len:5)), (fc:(freq: 4); dl:(len:5)), (fc:(freq:20); dl:(len:5)), +(fc:(freq:12); dl:(len:5)), (fc:(freq:28); dl:(len:5)), (fc:(freq: 2); dl:(len:5)), +(fc:(freq:18); dl:(len:5)), (fc:(freq:10); dl:(len:5)), (fc:(freq:26); dl:(len:5)), +(fc:(freq: 6); dl:(len:5)), (fc:(freq:22); dl:(len:5)), (fc:(freq:14); dl:(len:5)), +(fc:(freq:30); dl:(len:5)), (fc:(freq: 1); dl:(len:5)), (fc:(freq:17); dl:(len:5)), +(fc:(freq: 9); dl:(len:5)), (fc:(freq:25); dl:(len:5)), (fc:(freq: 5); dl:(len:5)), +(fc:(freq:21); dl:(len:5)), (fc:(freq:13); dl:(len:5)), (fc:(freq:29); dl:(len:5)), +(fc:(freq: 3); dl:(len:5)), (fc:(freq:19); dl:(len:5)), (fc:(freq:11); dl:(len:5)), +(fc:(freq:27); dl:(len:5)), (fc:(freq: 7); dl:(len:5)), (fc:(freq:23); dl:(len:5)) +); + +{ Distance codes. The first 256 values correspond to the distances + 3 .. 258, the last 256 values correspond to the top 8 bits of + the 15 bit distances. } + _dist_code : array[0..DIST_CODE_LEN-1] of uch = ( + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +); + +{ length code for each normalized match length (0 == MIN_MATCH) } + _length_code : array[0..MAX_MATCH-MIN_MATCH+1-1] of uch = ( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +); + + +{ First normalized length for each code (0 = MIN_MATCH) } + base_length : array[0..LENGTH_CODES-1] of int = ( +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +); + + +{ First normalized distance for each code (0 = distance of 1) } + base_dist : array[0..D_CODES-1] of int = ( + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +); +{$endif} + +{ Output a byte on the stream. + IN assertion: there is enough room in pending_buf. +macro put_byte(s, c) +begin + s^.pending_buf^[s^.pending] := (c); + Inc(s^.pending); +end +} + +const + MIN_LOOKAHEAD = (MAX_MATCH+MIN_MATCH+1); +{ Minimum amount of lookahead, except at the end of the input file. + See deflate.c for comments about the MIN_MATCH+1. } + +{macro d_code(dist) + if (dist) < 256 then + := _dist_code[dist] + else + := _dist_code[256+((dist) shr 7)]); + Mapping from a distance to a distance code. dist is the distance - 1 and + must not have side effects. _dist_code[256] and _dist_code[257] are never + used. } + +{$ifndef ORG_DEBUG} +{ Inline versions of _tr_tally for speed: } + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +macro _tr_tally_lit(s, c, flush) +var + cc : uch; +begin + cc := (c); + s^.d_buf[s^.last_lit] := 0; + s^.l_buf[s^.last_lit] := cc; + Inc(s^.last_lit); + Inc(s^.dyn_ltree[cc].fc.Freq); + flush := (s^.last_lit = s^.lit_bufsize-1); +end; + +macro _tr_tally_dist(s, distance, length, flush) \ +var + len : uch; + dist : ush; +begin + len := (length); + dist := (distance); + s^.d_buf[s^.last_lit] := dist; + s^.l_buf[s^.last_lit] = len; + Inc(s^.last_lit); + Dec(dist); + Inc(s^.dyn_ltree[_length_code[len]+LITERALS+1].fc.Freq); + Inc(s^.dyn_dtree[d_code(dist)].Freq); + flush := (s^.last_lit = s^.lit_bufsize-1); +end; + +{$endif} + +{ =========================================================================== + Constants } + +const + MAX_BL_BITS = 7; +{ Bit length codes must not exceed MAX_BL_BITS bits } + +const + END_BLOCK = 256; +{ end of block literal code } + +const + REP_3_6 = 16; +{ repeat previous bit length 3-6 times (2 bits of repeat count) } + +const + REPZ_3_10 = 17; +{ repeat a zero length 3-10 times (3 bits of repeat count) } + +const + REPZ_11_138 = 18; +{ repeat a zero length 11-138 times (7 bits of repeat count) } + +{local} +const + extra_lbits : array[0..LENGTH_CODES-1] of int + { extra bits for each length code } + = (0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0); + +{local} +const + extra_dbits : array[0..D_CODES-1] of int + { extra bits for each distance code } + = (0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13); + +{local} +const + extra_blbits : array[0..BL_CODES-1] of int { extra bits for each bit length code } + = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7); + +{local} +const + bl_order : array[0..BL_CODES-1] of uch + = (16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15); +{ The lengths of the bit length codes are sent in order of decreasing + probability, to avoid transmitting the lengths for unused bit length codes. + } + +const + Buf_size = (8 * 2*sizeof(uch)); +{ Number of bits used within bi_buf. (bi_buf might be implemented on + more than 16 bits on some systems.) } + +{ =========================================================================== + Local data. These are initialized only once. } + + +{$ifdef GEN_TREES_H)} +{ non ANSI compilers may not accept trees.h } + +const + DIST_CODE_LEN = 512; { see definition of array dist_code below } + +{local} +var + static_ltree : array[0..L_CODES+2-1] of ct_data; +{ The static literal tree. Since the bit lengths are imposed, there is no + need for the L_CODES extra codes used during heap construction. However + The codes 286 and 287 are needed to build a canonical tree (see _tr_init + below). } + +{local} + static_dtree : array[0..D_CODES-1] of ct_data; +{ The static distance tree. (Actually a trivial tree since all codes use + 5 bits.) } + + _dist_code : array[0..DIST_CODE_LEN-1] of uch; +{ Distance codes. The first 256 values correspond to the distances + 3 .. 258, the last 256 values correspond to the top 8 bits of + the 15 bit distances. } + + _length_code : array[0..MAX_MATCH-MIN_MATCH+1-1] of uch; +{ length code for each normalized match length (0 == MIN_MATCH) } + +{local} + base_length : array[0..LENGTH_CODES-1] of int; +{ First normalized length for each code (0 = MIN_MATCH) } + +{local} + base_dist : array[0..D_CODES-1] of int; +{ First normalized distance for each code (0 = distance of 1) } + +{$endif} { GEN_TREES_H } + +{local} +const + static_l_desc : static_tree_desc = + (static_tree: {tree_ptr}(@(static_ltree)); { pointer to array of ct_data } + extra_bits: {pzIntfArray}(@(extra_lbits)); { pointer to array of int } + extra_base: LITERALS+1; + elems: L_CODES; + max_length: MAX_BITS); + +{local} +const + static_d_desc : static_tree_desc = + (static_tree: {tree_ptr}(@(static_dtree)); + extra_bits: {pzIntfArray}(@(extra_dbits)); + extra_base : 0; + elems: D_CODES; + max_length: MAX_BITS); + +{local} +const + static_bl_desc : static_tree_desc = + (static_tree: {tree_ptr}(NIL); + extra_bits: {pzIntfArray}@(extra_blbits); + extra_base : 0; + elems: BL_CODES; + max_length: MAX_BL_BITS); + +(* =========================================================================== + Local (static) routines in this file. } + +procedure tr_static_init; +procedure init_block(var deflate_state); +procedure pqdownheap(var s : deflate_state; + var tree : ct_data; + k : int); +procedure gen_bitlen(var s : deflate_state; + var desc : tree_desc); +procedure gen_codes(var tree : ct_data; + max_code : int; + bl_count : pushf); +procedure build_tree(var s : deflate_state; + var desc : tree_desc); +procedure scan_tree(var s : deflate_state; + var tree : ct_data; + max_code : int); +procedure send_tree(var s : deflate_state; + var tree : ct_data; + max_code : int); +function build_bl_tree(var deflate_state) : int; +procedure send_all_trees(var deflate_state; + lcodes : int; + dcodes : int; + blcodes : int); +procedure compress_block(var s : deflate_state; + var ltree : ct_data; + var dtree : ct_data); +procedure set_data_type(var s : deflate_state); +function bi_reverse(value : unsigned; + length : int) : unsigned; +procedure bi_windup(var deflate_state); +procedure bi_flush(var deflate_state); +procedure copy_block(var deflate_state; + buf : pcharf; + len : unsigned; + header : int); +*) + +{$ifdef GEN_TREES_H} +{local} +procedure gen_trees_header; +{$endif} + +(* +{ =========================================================================== + Output a short LSB first on the stream. + IN assertion: there is enough room in pendingBuf. } + +macro put_short(s, w) +begin + {put_byte(s, (uch)((w) & 0xff));} + s.pending_buf^[s.pending] := uch((w) and $ff); + Inc(s.pending); + + {put_byte(s, (uch)((ush)(w) >> 8));} + s.pending_buf^[s.pending] := uch(ush(w) shr 8);; + Inc(s.pending); +end +*) + +{ =========================================================================== + Send a value on a given number of bits. + IN assertion: length <= 16 and value fits in length bits. } + +{$ifdef ORG_DEBUG} + +{local} +procedure send_bits(var s : deflate_state; + value : int; { value to send } + length : int); { number of bits } +begin + {$ifdef DEBUG} + Tracevv(' l '+IntToStr(length)+ ' v '+IntToStr(value)); + Assert((length > 0) and (length <= 15), 'invalid length'); + Inc(s.bits_sent, ulg(length)); + {$ENDIF} + + { If not enough room in bi_buf, use (valid) bits from bi_buf and + (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + unused bits in value. } + {$IFOPT Q+} {$Q-} {$DEFINE NoOverflowCheck} {$ENDIF} + {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF} + if (s.bi_valid > int(Buf_size) - length) then + begin + s.bi_buf := s.bi_buf or int(value shl s.bi_valid); + {put_short(s, s.bi_buf);} + s.pending_buf^[s.pending] := uch(s.bi_buf and $ff); + Inc(s.pending); + s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);; + Inc(s.pending); + + s.bi_buf := ush(value) shr (Buf_size - s.bi_valid); + Inc(s.bi_valid, length - Buf_size); + end + else + begin + s.bi_buf := s.bi_buf or int(value shl s.bi_valid); + Inc(s.bi_valid, length); + end; + {$IFDEF NoOverflowCheck} {$Q+} {$UNDEF NoOverflowCheck} {$ENDIF} + {$IFDEF NoRangeCheck} {$Q+} {$UNDEF NoRangeCheck} {$ENDIF} +end; + +{$else} { !DEBUG } + + +macro send_code(s, c, tree) +begin + send_bits(s, tree[c].Code, tree[c].Len); + { Send a code of the given tree. c and tree must not have side effects } +end + +macro send_bits(s, value, length) \ +begin int len := length;\ + if (s^.bi_valid > (int)Buf_size - len) begin\ + int val := value;\ + s^.bi_buf |= (val << s^.bi_valid);\ + {put_short(s, s.bi_buf);} + s.pending_buf^[s.pending] := uch(s.bi_buf and $ff); + Inc(s.pending); + s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);; + Inc(s.pending); + + s^.bi_buf := (ush)val >> (Buf_size - s^.bi_valid);\ + s^.bi_valid += len - Buf_size;\ + end else begin\ + s^.bi_buf |= (value) << s^.bi_valid;\ + s^.bi_valid += len;\ + end\ +end; +{$endif} { DEBUG } + +{ =========================================================================== + Reverse the first len bits of a code, using straightforward code (a faster + method would use a table) + IN assertion: 1 <= len <= 15 } + +{local} +function bi_reverse(code : unsigned; { the value to invert } + len : int) : unsigned; { its bit length } + +var + res : unsigned; {register} +begin + res := 0; + repeat + res := res or (code and 1); + code := code shr 1; + res := res shl 1; + Dec(len); + until (len <= 0); + bi_reverse := res shr 1; +end; + +{ =========================================================================== + Generate the codes for a given tree and bit counts (which need not be + optimal). + IN assertion: the array bl_count contains the bit length statistics for + the given tree and the field len is set for all tree elements. + OUT assertion: the field code is set for all tree elements of non + zero code length. } + +{local} +procedure gen_codes(tree : tree_ptr; { the tree to decorate } + max_code : int; { largest code with non zero frequency } + var bl_count : array of ushf); { number of codes at each bit length } + +var + next_code : array[0..MAX_BITS+1-1] of ush; { next code value for each bit length } + code : ush; { running code value } + bits : int; { bit index } + n : int; { code index } +var + len : int; +begin + code := 0; + + { The distribution counts are first used to generate the code values + without bit reversal. } + + for bits := 1 to MAX_BITS do + begin + code := ((code + bl_count[bits-1]) shl 1); + next_code[bits] := code; + end; + { Check that the bit counts in bl_count are consistent. The last code + must be all ones. } + + {$IFDEF DEBUG} + Assert (code + bl_count[MAX_BITS]-1 = (1 shl MAX_BITS)-1, + 'inconsistent bit counts'); + Tracev(#13'gen_codes: max_code '+IntToStr(max_code)); + {$ENDIF} + + for n := 0 to max_code do + begin + len := tree^[n].dl.Len; + if (len = 0) then + continue; + { Now reverse the bits } + tree^[n].fc.Code := bi_reverse(next_code[len], len); + Inc(next_code[len]); + {$ifdef DEBUG} + if (n>31) and (n<128) then + Tracecv(tree <> tree_ptr(@static_ltree), + (^M'n #'+IntToStr(n)+' '+AnsiChar(n)+' l '+IntToStr(len)+' c '+ + IntToStr(tree^[n].fc.Code)+' ('+IntToStr(next_code[len]-1)+')')) + else + Tracecv(tree <> tree_ptr(@static_ltree), + (^M'n #'+IntToStr(n)+' l '+IntToStr(len)+' c '+ + IntToStr(tree^[n].fc.Code)+' ('+IntToStr(next_code[len]-1)+')')); + {$ENDIF} + end; +end; + +{ =========================================================================== + Genererate the file trees.h describing the static trees. } +{$ifdef GEN_TREES_H} + +macro SEPARATOR(i, last, width) + if (i) = (last) then + ( ^M');'^M^M + else \ + if (i) mod (width) = (width)-1 then + ','^M + else + ', ' + +procedure gen_trees_header; +var + header : system.text; + i : int; +begin + system.assign(header, 'trees.inc'); + {$I-} + ReWrite(header); + {$I+} + Assert (IOresult <> 0, 'Can''t open trees.h'); + WriteLn(header, + '{ header created automatically with -DGEN_TREES_H }'^M); + + WriteLn(header, 'local const ct_data static_ltree[L_CODES+2] := ('); + for i := 0 to L_CODES+2-1 do + begin + WriteLn(header, '((%3u),(%3u))%s', static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + end; + + WriteLn(header, 'local const ct_data static_dtree[D_CODES] := ('); + for i := 0 to D_CODES-1 do + begin + WriteLn(header, '((%2u),(%2u))%s', static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + end; + + WriteLn(header, 'const uch _dist_code[DIST_CODE_LEN] := ('); + for i := 0 to DIST_CODE_LEN-1 do + begin + WriteLn(header, '%2u%s', _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + end; + + WriteLn(header, 'const uch _length_code[MAX_MATCH-MIN_MATCH+1]= ('); + for i := 0 to MAX_MATCH-MIN_MATCH+1-1 do + begin + WriteLn(header, '%2u%s', _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + end; + + WriteLn(header, 'local const int base_length[LENGTH_CODES] := ('); + for i := 0 to LENGTH_CODES-1 do + begin + WriteLn(header, '%1u%s', base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + end; + + WriteLn(header, 'local const int base_dist[D_CODES] := ('); + for i := 0 to D_CODES-1 do + begin + WriteLn(header, '%5u%s', base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + end; + + close(header); +end; +{$endif} { GEN_TREES_H } + + +{ =========================================================================== + Initialize the various 'constant' tables. } + +{local} +procedure tr_static_init; + +{$ifdef GEN_TREES_H} +const + static_init_done : boolean = FALSE; +var + n : int; { iterates over tree elements } + bits : int; { bit counter } + length : int; { length value } + code : int; { code value } + dist : int; { distance index } + bl_count : array[0..MAX_BITS+1-1] of ush; + { number of codes at each bit length for an optimal tree } +begin + if (static_init_done) then + exit; + + { Initialize the mapping length (0..255) -> length code (0..28) } + length := 0; + for code := 0 to LENGTH_CODES-1-1 do + begin + base_length[code] := length; + for n := 0 to (1 shl extra_lbits[code])-1 do + begin + _length_code[length] := uch(code); + Inc(length); + end; + end; + Assert (length = 256, 'tr_static_init: length <> 256'); + { Note that the length 255 (match length 258) can be represented + in two different ways: code 284 + 5 bits or code 285, so we + overwrite length_code[255] to use the best encoding: } + + _length_code[length-1] := uch(code); + + { Initialize the mapping dist (0..32K) -> dist code (0..29) } + dist := 0; + for code := 0 to 16-1 do + begin + base_dist[code] := dist; + for n := 0 to (1 shl extra_dbits[code])-1 do + begin + _dist_code[dist] := uch(code); + Inc(dist); + end; + end; + Assert (dist = 256, 'tr_static_init: dist <> 256'); + dist := dist shr 7; { from now on, all distances are divided by 128 } + for code := 16 to D_CODES-1 do + begin + base_dist[code] := dist shl 7; + for n := 0 to (1 shl (extra_dbits[code]-7))-1 do + begin + _dist_code[256 + dist] := uch(code); + Inc(dist); + end; + end; + Assert (dist = 256, 'tr_static_init: 256+dist <> 512'); + + { Construct the codes of the static literal tree } + for bits := 0 to MAX_BITS do + bl_count[bits] := 0; + n := 0; + while (n <= 143) do + begin + static_ltree[n].dl.Len := 8; + Inc(n); + Inc(bl_count[8]); + end; + while (n <= 255) do + begin + static_ltree[n].dl.Len := 9; + Inc(n); + Inc(bl_count[9]); + end; + while (n <= 279) do + begin + static_ltree[n].dl.Len := 7; + Inc(n); + Inc(bl_count[7]); + end; + while (n <= 287) do + begin + static_ltree[n].dl.Len := 8; + Inc(n); + Inc(bl_count[8]); + end; + + { Codes 286 and 287 do not exist, but we must include them in the + tree construction to get a canonical Huffman tree (longest code + all ones) } + + gen_codes(tree_ptr(@static_ltree), L_CODES+1, bl_count); + + { The static distance tree is trivial: } + for n := 0 to D_CODES-1 do + begin + static_dtree[n].dl.Len := 5; + static_dtree[n].fc.Code := bi_reverse(unsigned(n), 5); + end; + static_init_done := TRUE; + + gen_trees_header; { save to include file } +{$else} +begin +{$endif} { GEN_TREES_H) } +end; + +{ =========================================================================== + Initialize a new block. } +{local} + +procedure init_block(var s : deflate_state); +var + n : int; { iterates over tree elements } +begin + { Initialize the trees. } + for n := 0 to L_CODES-1 do + s.dyn_ltree[n].fc.Freq := 0; + for n := 0 to D_CODES-1 do + s.dyn_dtree[n].fc.Freq := 0; + for n := 0 to BL_CODES-1 do + s.bl_tree[n].fc.Freq := 0; + + s.dyn_ltree[END_BLOCK].fc.Freq := 1; + s.static_len := Long(0); + s.opt_len := Long(0); + s.matches := 0; + s.last_lit := 0; +end; + +const + SMALLEST = 1; +{ Index within the heap array of least frequent node in the Huffman tree } + +{ =========================================================================== + Initialize the tree data structures for a new zlib stream. } +procedure _tr_init(var s : deflate_state); +begin + tr_static_init; + + s.compressed_len := Long(0); + + s.l_desc.dyn_tree := tree_ptr(@s.dyn_ltree); + s.l_desc.stat_desc := @static_l_desc; + + s.d_desc.dyn_tree := tree_ptr(@s.dyn_dtree); + s.d_desc.stat_desc := @static_d_desc; + + s.bl_desc.dyn_tree := tree_ptr(@s.bl_tree); + s.bl_desc.stat_desc := @static_bl_desc; + + s.bi_buf := 0; + s.bi_valid := 0; + s.last_eob_len := 8; { enough lookahead for inflate } +{$ifdef DEBUG} + s.bits_sent := Long(0); +{$endif} + + { Initialize the first block of the first file: } + init_block(s); +end; + +{ =========================================================================== + Remove the smallest element from the heap and recreate the heap with + one less element. Updates heap and heap_len. + +macro pqremove(s, tree, top) +begin + top := s.heap[SMALLEST]; + s.heap[SMALLEST] := s.heap[s.heap_len]; + Dec(s.heap_len); + pqdownheap(s, tree, SMALLEST); +end +} + +{ =========================================================================== + Compares to subtrees, using the tree depth as tie breaker when + the subtrees have equal frequency. This minimizes the worst case length. + +macro smaller(tree, n, m, depth) + ( (tree[n].Freq < tree[m].Freq) or + ((tree[n].Freq = tree[m].Freq) and (depth[n] <= depth[m])) ) +} + +{ =========================================================================== + Restore the heap property by moving down the tree starting at node k, + exchanging a node with the smallest of its two sons if necessary, stopping + when the heap property is re-established (each father smaller than its + two sons). } +{local} + +procedure pqdownheap(var s : deflate_state; + var tree : tree_type; { the tree to restore } + k : int); { node to move down } +var + v : int; + j : int; +begin + v := s.heap[k]; + j := k shl 1; { left son of k } + while (j <= s.heap_len) do + begin + { Set j to the smallest of the two sons: } + if (j < s.heap_len) and + {smaller(tree, s.heap[j+1], s.heap[j], s.depth)} + ( (tree[s.heap[j+1]].fc.Freq < tree[s.heap[j]].fc.Freq) or + ((tree[s.heap[j+1]].fc.Freq = tree[s.heap[j]].fc.Freq) and + (s.depth[s.heap[j+1]] <= s.depth[s.heap[j]])) ) then + begin + Inc(j); + end; + { Exit if v is smaller than both sons } + if {(smaller(tree, v, s.heap[j], s.depth))} + ( (tree[v].fc.Freq < tree[s.heap[j]].fc.Freq) or + ((tree[v].fc.Freq = tree[s.heap[j]].fc.Freq) and + (s.depth[v] <= s.depth[s.heap[j]])) ) then + break; + { Exchange v with the smallest son } + s.heap[k] := s.heap[j]; + k := j; + + { And continue down the tree, setting j to the left son of k } + j := j shl 1; + end; + s.heap[k] := v; +end; + +{ =========================================================================== + Compute the optimal bit lengths for a tree and update the total bit length + for the current block. + IN assertion: the fields freq and dad are set, heap[heap_max] and + above are the tree nodes sorted by increasing frequency. + OUT assertions: the field len is set to the optimal bit length, the + array bl_count contains the frequencies for each bit length. + The length opt_len is updated; static_len is also updated if stree is + not null. } + +{local} +procedure gen_bitlen(var s : deflate_state; + var desc : tree_desc); { the tree descriptor } +var + tree : tree_ptr; + max_code : int; + stree : tree_ptr; {const} + extra : pzIntfArray; {const} + base : int; + max_length : int; + h : int; { heap index } + n, m : int; { iterate over the tree elements } + bits : int; { bit length } + xbits : int; { extra bits } + f : ush; { frequency } + overflow : int; { number of elements with bit length too large } +begin + tree := desc.dyn_tree; + max_code := desc.max_code; + stree := desc.stat_desc^.static_tree; + extra := desc.stat_desc^.extra_bits; + base := desc.stat_desc^.extra_base; + max_length := desc.stat_desc^.max_length; + overflow := 0; + + for bits := 0 to MAX_BITS do + s.bl_count[bits] := 0; + + { In a first pass, compute the optimal bit lengths (which may + overflow in the case of the bit length tree). } + + tree^[s.heap[s.heap_max]].dl.Len := 0; { root of the heap } + + for h := s.heap_max+1 to HEAP_SIZE-1 do + begin + n := s.heap[h]; + bits := tree^[tree^[n].dl.Dad].dl.Len + 1; + if (bits > max_length) then + begin + bits := max_length; + Inc(overflow); + end; + tree^[n].dl.Len := ush(bits); + { We overwrite tree[n].dl.Dad which is no longer needed } + + if (n > max_code) then + continue; { not a leaf node } + + Inc(s.bl_count[bits]); + xbits := 0; + if (n >= base) then + xbits := extra^[n-base]; + f := tree^[n].fc.Freq; + Inc(s.opt_len, ulg(f) * (bits + xbits)); + if (stree <> NIL) then + Inc(s.static_len, ulg(f) * (stree^[n].dl.Len + xbits)); + end; + if (overflow = 0) then + exit; + {$ifdef DEBUG} + Tracev(^M'bit length overflow'); + {$endif} + { This happens for example on obj2 and pic of the Calgary corpus } + + { Find the first bit length which could increase: } + repeat + bits := max_length-1; + while (s.bl_count[bits] = 0) do + Dec(bits); + Dec(s.bl_count[bits]); { move one leaf down the tree } + Inc(s.bl_count[bits+1], 2); { move one overflow item as its brother } + Dec(s.bl_count[max_length]); + { The brother of the overflow item also moves one step up, + but this does not affect bl_count[max_length] } + + Dec(overflow, 2); + until (overflow <= 0); + + { Now recompute all bit lengths, scanning in increasing frequency. + h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + lengths instead of fixing only the wrong ones. This idea is taken + from 'ar' written by Haruhiko Okumura.) } + h := HEAP_SIZE; { Delphi3: compiler warning w/o this } + for bits := max_length downto 1 do + begin + n := s.bl_count[bits]; + while (n <> 0) do + begin + Dec(h); + m := s.heap[h]; + if (m > max_code) then + continue; + if (tree^[m].dl.Len <> unsigned(bits)) then + begin + {$ifdef DEBUG} + Trace('code '+IntToStr(m)+' bits '+IntToStr(tree^[m].dl.Len) + +'.'+IntToStr(bits)); + {$ENDIF} + Inc(s.opt_len, (long(bits) - long(tree^[m].dl.Len)) + * long(tree^[m].fc.Freq) ); + tree^[m].dl.Len := ush(bits); + end; + Dec(n); + end; + end; +end; + +{ =========================================================================== + Construct one Huffman tree and assigns the code bit strings and lengths. + Update the total bit length for the current block. + IN assertion: the field freq is set for all tree elements. + OUT assertions: the fields len and code are set to the optimal bit length + and corresponding code. The length opt_len is updated; static_len is + also updated if stree is not null. The field max_code is set. } + +{local} +procedure build_tree(var s : deflate_state; + var desc : tree_desc); { the tree descriptor } + +var + tree : tree_ptr; + stree : tree_ptr; {const} + elems : int; + n, m : int; { iterate over heap elements } + max_code : int; { largest code with non zero frequency } + node : int; { new node being created } +begin + tree := desc.dyn_tree; + stree := desc.stat_desc^.static_tree; + elems := desc.stat_desc^.elems; + max_code := -1; + + { Construct the initial heap, with least frequent element in + heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + heap[0] is not used. } + s.heap_len := 0; + s.heap_max := HEAP_SIZE; + + for n := 0 to elems-1 do + begin + if (tree^[n].fc.Freq <> 0) then + begin + max_code := n; + Inc(s.heap_len); + s.heap[s.heap_len] := n; + s.depth[n] := 0; + end + else + begin + tree^[n].dl.Len := 0; + end; + end; + + { The pkzip format requires that at least one distance code exists, + and that at least one bit should be sent even if there is only one + possible code. So to avoid special checks later on we force at least + two codes of non zero frequency. } + + while (s.heap_len < 2) do + begin + Inc(s.heap_len); + if (max_code < 2) then + begin + Inc(max_code); + s.heap[s.heap_len] := max_code; + node := max_code; + end + else + begin + s.heap[s.heap_len] := 0; + node := 0; + end; + tree^[node].fc.Freq := 1; + s.depth[node] := 0; + Dec(s.opt_len); + if (stree <> NIL) then + Dec(s.static_len, stree^[node].dl.Len); + { node is 0 or 1 so it does not have extra bits } + end; + desc.max_code := max_code; + + { The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + establish sub-heaps of increasing lengths: } + + for n := s.heap_len div 2 downto 1 do + pqdownheap(s, tree^, n); + + { Construct the Huffman tree by repeatedly combining the least two + frequent nodes. } + + node := elems; { next internal node of the tree } + repeat + {pqremove(s, tree, n);} { n := node of least frequency } + n := s.heap[SMALLEST]; + s.heap[SMALLEST] := s.heap[s.heap_len]; + Dec(s.heap_len); + pqdownheap(s, tree^, SMALLEST); + + m := s.heap[SMALLEST]; { m := node of next least frequency } + + Dec(s.heap_max); + s.heap[s.heap_max] := n; { keep the nodes sorted by frequency } + Dec(s.heap_max); + s.heap[s.heap_max] := m; + + { Create a new node father of n and m } + tree^[node].fc.Freq := tree^[n].fc.Freq + tree^[m].fc.Freq; + { maximum } + if (s.depth[n] >= s.depth[m]) then + s.depth[node] := uch (s.depth[n] + 1) + else + s.depth[node] := uch (s.depth[m] + 1); + + tree^[m].dl.Dad := ush(node); + tree^[n].dl.Dad := ush(node); +{$ifdef DUMP_BL_TREE} + if (tree = tree_ptr(@s.bl_tree)) then + begin + WriteLn(#13'node ',node,'(',tree^[node].fc.Freq,') sons ',n, + '(',tree^[n].fc.Freq,') ', m, '(',tree^[m].fc.Freq,')'); + end; +{$endif} + { and insert the new node in the heap } + s.heap[SMALLEST] := node; + Inc(node); + pqdownheap(s, tree^, SMALLEST); + + until (s.heap_len < 2); + + Dec(s.heap_max); + s.heap[s.heap_max] := s.heap[SMALLEST]; + + { At this point, the fields freq and dad are set. We can now + generate the bit lengths. } + + gen_bitlen(s, desc); + + { The field len is now set, we can generate the bit codes } + gen_codes (tree, max_code, s.bl_count); +end; + +{ =========================================================================== + Scan a literal or distance tree to determine the frequencies of the codes + in the bit length tree. } + +{local} +procedure scan_tree(var s : deflate_state; + var tree : array of ct_data; { the tree to be scanned } + max_code : int); { and its largest code of non zero frequency } +var + n : int; { iterates over all tree elements } + prevlen : int; { last emitted length } + curlen : int; { length of current code } + nextlen : int; { length of next code } + count : int; { repeat count of the current code } + max_count : int; { max repeat count } + min_count : int; { min repeat count } +begin + prevlen := -1; + nextlen := tree[0].dl.Len; + count := 0; + max_count := 7; + min_count := 4; + + if (nextlen = 0) then + begin + max_count := 138; + min_count := 3; + end; + tree[max_code+1].dl.Len := ush($ffff); { guard } + + for n := 0 to max_code do + begin + curlen := nextlen; + nextlen := tree[n+1].dl.Len; + Inc(count); + if (count < max_count) and (curlen = nextlen) then + continue + else + if (count < min_count) then + Inc(s.bl_tree[curlen].fc.Freq, count) + else + if (curlen <> 0) then + begin + if (curlen <> prevlen) then + Inc(s.bl_tree[curlen].fc.Freq); + Inc(s.bl_tree[REP_3_6].fc.Freq); + end + else + if (count <= 10) then + Inc(s.bl_tree[REPZ_3_10].fc.Freq) + else + Inc(s.bl_tree[REPZ_11_138].fc.Freq); + + count := 0; + prevlen := curlen; + if (nextlen = 0) then + begin + max_count := 138; + min_count := 3; + end + else + if (curlen = nextlen) then + begin + max_count := 6; + min_count := 3; + end + else + begin + max_count := 7; + min_count := 4; + end; + end; +end; + +{ =========================================================================== + Send a literal or distance tree in compressed form, using the codes in + bl_tree. } + +{local} +procedure send_tree(var s : deflate_state; + var tree : array of ct_data; { the tree to be scanned } + max_code : int); { and its largest code of non zero frequency } + +var + n : int; { iterates over all tree elements } + prevlen : int; { last emitted length } + curlen : int; { length of current code } + nextlen : int; { length of next code } + count : int; { repeat count of the current code } + max_count : int; { max repeat count } + min_count : int; { min repeat count } +begin + prevlen := -1; + nextlen := tree[0].dl.Len; + count := 0; + max_count := 7; + min_count := 4; + + { tree[max_code+1].dl.Len := -1; } { guard already set } + if (nextlen = 0) then + begin + max_count := 138; + min_count := 3; + end; + + for n := 0 to max_code do + begin + curlen := nextlen; + nextlen := tree[n+1].dl.Len; + Inc(count); + if (count < max_count) and (curlen = nextlen) then + continue + else + if (count < min_count) then + begin + repeat + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(curlen)); + {$ENDIF} + send_bits(s, s.bl_tree[curlen].fc.Code, s.bl_tree[curlen].dl.Len); + Dec(count); + until (count = 0); + end + else + if (curlen <> 0) then + begin + if (curlen <> prevlen) then + begin + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(curlen)); + {$ENDIF} + send_bits(s, s.bl_tree[curlen].fc.Code, s.bl_tree[curlen].dl.Len); + Dec(count); + end; + {$IFDEF DEBUG} + Assert((count >= 3) and (count <= 6), ' 3_6?'); + {$ENDIF} + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(REP_3_6)); + {$ENDIF} + send_bits(s, s.bl_tree[REP_3_6].fc.Code, s.bl_tree[REP_3_6].dl.Len); + send_bits(s, count-3, 2); + end + else + if (count <= 10) then + begin + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(REPZ_3_10)); + {$ENDIF} + send_bits(s, s.bl_tree[REPZ_3_10].fc.Code, s.bl_tree[REPZ_3_10].dl.Len); + send_bits(s, count-3, 3); + end + else + begin + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(REPZ_11_138)); + {$ENDIF} + send_bits(s, s.bl_tree[REPZ_11_138].fc.Code, s.bl_tree[REPZ_11_138].dl.Len); + send_bits(s, count-11, 7); + end; + count := 0; + prevlen := curlen; + if (nextlen = 0) then + begin + max_count := 138; + min_count := 3; + end + else + if (curlen = nextlen) then + begin + max_count := 6; + min_count := 3; + end + else + begin + max_count := 7; + min_count := 4; + end; + end; +end; + +{ =========================================================================== + Construct the Huffman tree for the bit lengths and return the index in + bl_order of the last bit length code to send. } + +{local} +function build_bl_tree(var s : deflate_state) : int; +var + max_blindex : int; { index of last bit length code of non zero freq } +begin + { Determine the bit length frequencies for literal and distance trees } + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + { Build the bit length tree: } + build_tree(s, s.bl_desc); + { opt_len now includes the length of the tree representations, except + the lengths of the bit lengths codes and the 5+5+4 bits for the counts. } + + { Determine the number of bit length codes to send. The pkzip format + requires that at least 4 bit length codes be sent. (appnote.txt says + 3 but the actual value used is 4.) } + + for max_blindex := BL_CODES-1 downto 3 do + begin + if (s.bl_tree[bl_order[max_blindex]].dl.Len <> 0) then + break; + end; + { Update opt_len to include the bit length tree and counts } + Inc(s.opt_len, 3*(max_blindex+1) + 5+5+4); + {$ifdef DEBUG} + Tracev(^M'dyn trees: dyn %ld, stat %ld {s.opt_len, s.static_len}'); + {$ENDIF} + + build_bl_tree := max_blindex; +end; + +{ =========================================================================== + Send the header for a block using dynamic Huffman trees: the counts, the + lengths of the bit length codes, the literal tree and the distance tree. + IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. } + +{local} +procedure send_all_trees(var s : deflate_state; + lcodes : int; + dcodes : int; + blcodes : int); { number of codes for each tree } +var + rank : int; { index in bl_order } +begin + {$IFDEF DEBUG} + Assert ((lcodes >= 257) and (dcodes >= 1) and (blcodes >= 4), + 'not enough codes'); + Assert ((lcodes <= L_CODES) and (dcodes <= D_CODES) + and (blcodes <= BL_CODES), 'too many codes'); + Tracev(^M'bl counts: '); + {$ENDIF} + send_bits(s, lcodes-257, 5); { not +255 as stated in appnote.txt } + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); { not -3 as stated in appnote.txt } + for rank := 0 to blcodes-1 do + begin + {$ifdef DEBUG} + Tracev(^M'bl code '+IntToStr(bl_order[rank])); + {$ENDIF} + send_bits(s, s.bl_tree[bl_order[rank]].dl.Len, 3); + end; + {$ifdef DEBUG} + Tracev(^M'bl tree: sent '+IntToStr(s.bits_sent)); + {$ENDIF} + + send_tree(s, s.dyn_ltree, lcodes-1); { literal tree } + {$ifdef DEBUG} + Tracev(^M'lit tree: sent '+IntToStr(s.bits_sent)); + {$ENDIF} + + send_tree(s, s.dyn_dtree, dcodes-1); { distance tree } + {$ifdef DEBUG} + Tracev(^M'dist tree: sent '+IntToStr(s.bits_sent)); + {$ENDIF} +end; + +{ =========================================================================== + Flush the bit buffer and align the output on a byte boundary } + +{local} +procedure bi_windup(var s : deflate_state); +begin + if (s.bi_valid > 8) then + begin + {put_short(s, s.bi_buf);} + s.pending_buf^[s.pending] := uch(s.bi_buf and $ff); + Inc(s.pending); + s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);; + Inc(s.pending); + end + else + if (s.bi_valid > 0) then + begin + {put_byte(s, (Byte)s^.bi_buf);} + s.pending_buf^[s.pending] := Byte(s.bi_buf); + Inc(s.pending); + end; + s.bi_buf := 0; + s.bi_valid := 0; +{$ifdef DEBUG} + s.bits_sent := (s.bits_sent+7) and (not 7); +{$endif} +end; + +{ =========================================================================== + Copy a stored block, storing first the length and its + one's complement if requested. } + +{local} +procedure copy_block(var s : deflate_state; + buf : pcharf; { the input data } + len : unsigned; { its length } + header : boolean); { true if block header must be written } +begin + bi_windup(s); { align on byte boundary } + s.last_eob_len := 8; { enough lookahead for inflate } + + if (header) then + begin + {put_short(s, (ush)len);} + s.pending_buf^[s.pending] := uch(ush(len) and $ff); + Inc(s.pending); + s.pending_buf^[s.pending] := uch(ush(len) shr 8);; + Inc(s.pending); + {put_short(s, (ush)~len);} + s.pending_buf^[s.pending] := uch(ush(not len) and $ff); + Inc(s.pending); + s.pending_buf^[s.pending] := uch(ush(not len) shr 8);; + Inc(s.pending); + +{$ifdef DEBUG} + Inc(s.bits_sent, 2*16); +{$endif} + end; +{$ifdef DEBUG} + Inc(s.bits_sent, ulg(len shl 3)); +{$endif} + while (len <> 0) do + begin + Dec(len); + {put_byte(s, *buf++);} + s.pending_buf^[s.pending] := buf^; + Inc(buf); + Inc(s.pending); + end; +end; + + +{ =========================================================================== + Send a stored block } + +procedure _tr_stored_block(var s : deflate_state; + buf : pcharf; { input block } + stored_len : ulg; { length of input block } + eof : boolean); { true if this is the last block for a file } + +begin + send_bits(s, (STORED_BLOCK shl 1)+ord(eof), 3); { send block type } + s.compressed_len := (s.compressed_len + 3 + 7) and ulg(not Long(7)); + Inc(s.compressed_len, (stored_len + 4) shl 3); + + copy_block(s, buf, unsigned(stored_len), TRUE); { with header } +end; + +{ =========================================================================== + Flush the bit buffer, keeping at most 7 bits in it. } + +{local} +procedure bi_flush(var s : deflate_state); +begin + if (s.bi_valid = 16) then + begin + {put_short(s, s.bi_buf);} + s.pending_buf^[s.pending] := uch(s.bi_buf and $ff); + Inc(s.pending); + s.pending_buf^[s.pending] := uch(ush(s.bi_buf) shr 8);; + Inc(s.pending); + + s.bi_buf := 0; + s.bi_valid := 0; + end + else + if (s.bi_valid >= 8) then + begin + {put_byte(s, (Byte)s^.bi_buf);} + s.pending_buf^[s.pending] := Byte(s.bi_buf); + Inc(s.pending); + + s.bi_buf := s.bi_buf shr 8; + Dec(s.bi_valid, 8); + end; +end; + + +{ =========================================================================== + Send one empty static block to give enough lookahead for inflate. + This takes 10 bits, of which 7 may remain in the bit buffer. + The current inflate code requires 9 bits of lookahead. If the + last two codes for the previous block (real code plus EOB) were coded + on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + the last real code. In this case we send two empty static blocks instead + of one. (There are no problems if the previous block is stored or fixed.) + To simplify the code, we assume the worst case of last real code encoded + on one bit only. } + +procedure _tr_align(var s : deflate_state); +begin + send_bits(s, STATIC_TREES shl 1, 3); + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(END_BLOCK)); + {$ENDIF} + send_bits(s, static_ltree[END_BLOCK].fc.Code, static_ltree[END_BLOCK].dl.Len); + Inc(s.compressed_len, Long(10)); { 3 for block type, 7 for EOB } + bi_flush(s); + { Of the 10 bits for the empty block, we have already sent + (10 - bi_valid) bits. The lookahead for the last real code (before + the EOB of the previous block) was thus at least one plus the length + of the EOB plus what we have just sent of the empty static block. } + if (1 + s.last_eob_len + 10 - s.bi_valid < 9) then + begin + send_bits(s, STATIC_TREES shl 1, 3); + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(END_BLOCK)); + {$ENDIF} + send_bits(s, static_ltree[END_BLOCK].fc.Code, static_ltree[END_BLOCK].dl.Len); + Inc(s.compressed_len, Long(10)); + bi_flush(s); + end; + s.last_eob_len := 7; +end; + +{ =========================================================================== + Set the data type to ASCII or BINARY, using a crude approximation: + binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + IN assertion: the fields freq of dyn_ltree are set and the total of all + frequencies does not exceed 64K (to fit in an int on 16 bit machines). } + +{local} +procedure set_data_type(var s : deflate_state); +var + n : int; + ascii_freq : unsigned; + bin_freq : unsigned; +begin + n := 0; + ascii_freq := 0; + bin_freq := 0; + + while (n < 7) do + begin + Inc(bin_freq, s.dyn_ltree[n].fc.Freq); + Inc(n); + end; + while (n < 128) do + begin + Inc(ascii_freq, s.dyn_ltree[n].fc.Freq); + Inc(n); + end; + while (n < LITERALS) do + begin + Inc(bin_freq, s.dyn_ltree[n].fc.Freq); + Inc(n); + end; + if (bin_freq > (ascii_freq shr 2)) then + s.data_type := Byte(Z_BINARY) + else + s.data_type := Byte(Z_ASCII); +end; + +{ =========================================================================== + Send the block data compressed using the given Huffman trees } + +{local} +procedure compress_block(var s : deflate_state; + var ltree : array of ct_data; { literal tree } + var dtree : array of ct_data); { distance tree } +var + dist : unsigned; { distance of matched string } + lc : int; { match length or unmatched char (if dist == 0) } + lx : unsigned; { running index in l_buf } + code : unsigned; { the code to send } + extra : int; { number of extra bits to send } +begin + lx := 0; + if (s.last_lit <> 0) then + repeat + dist := s.d_buf^[lx]; + lc := s.l_buf^[lx]; + Inc(lx); + if (dist = 0) then + begin + { send a literal byte } + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(lc)); + Tracecv((lc > 31) and (lc < 128), ' '+AnsiChar(lc)+' '); + {$ENDIF} + send_bits(s, ltree[lc].fc.Code, ltree[lc].dl.Len); + end + else + begin + { Here, lc is the match length - MIN_MATCH } + code := _length_code[lc]; + { send the length code } + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(code+LITERALS+1)); + {$ENDIF} + send_bits(s, ltree[code+LITERALS+1].fc.Code, ltree[code+LITERALS+1].dl.Len); + extra := extra_lbits[code]; + if (extra <> 0) then + begin + Dec(lc, base_length[code]); + send_bits(s, lc, extra); { send the extra length bits } + end; + Dec(dist); { dist is now the match distance - 1 } + {code := d_code(dist);} + if (dist < 256) then + code := _dist_code[dist] + else + code := _dist_code[256+(dist shr 7)]; + + {$IFDEF DEBUG} + Assert (code < D_CODES, 'bad d_code'); + {$ENDIF} + + { send the distance code } + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(code)); + {$ENDIF} + send_bits(s, dtree[code].fc.Code, dtree[code].dl.Len); + extra := extra_dbits[code]; + if (extra <> 0) then + begin + Dec(dist, base_dist[code]); + send_bits(s, dist, extra); { send the extra distance bits } + end; + end; { literal or match pair ? } + + { Check that the overlay between pending_buf and d_buf+l_buf is ok: } + {$IFDEF DEBUG} + Assert(s.pending < s.lit_bufsize + 2*lx, 'pendingBuf overflow'); + {$ENDIF} + until (lx >= s.last_lit); + + {$ifdef DEBUG} + Tracevvv(#13'cd '+IntToStr(END_BLOCK)); + {$ENDIF} + send_bits(s, ltree[END_BLOCK].fc.Code, ltree[END_BLOCK].dl.Len); + s.last_eob_len := ltree[END_BLOCK].dl.Len; +end; + + +{ =========================================================================== + Determine the best encoding for the current block: dynamic trees, static + trees or store, and output the encoded block to the zip file. This function + returns the total compressed length for the file so far. } + +function _tr_flush_block (var s : deflate_state; + buf : pcharf; { input block, or NULL if too old } + stored_len : ulg; { length of input block } + eof : boolean) : ulg; { true if this is the last block for a file } +var + opt_lenb, static_lenb : ulg; { opt_len and static_len in bytes } + max_blindex : int; { index of last bit length code of non zero freq } +begin + max_blindex := 0; + + { Build the Huffman trees unless a stored block is forced } + if (s.level > 0) then + begin + { Check if the file is ascii or binary } + if (s.data_type = Z_UNKNOWN) then + set_data_type(s); + + { Construct the literal and distance trees } + build_tree(s, s.l_desc); + {$ifdef DEBUG} + Tracev(^M'lit data: dyn %ld, stat %ld {s.opt_len, s.static_len}'); + {$ENDIF} + + build_tree(s, s.d_desc); + {$ifdef DEBUG} + Tracev(^M'dist data: dyn %ld, stat %ld {s.opt_len, s.static_len}'); + {$ENDIF} + { At this point, opt_len and static_len are the total bit lengths of + the compressed block data, excluding the tree representations. } + + { Build the bit length tree for the above two trees, and get the index + in bl_order of the last bit length code to send. } + max_blindex := build_bl_tree(s); + + { Determine the best encoding. Compute first the block length in bytes} + opt_lenb := (s.opt_len+3+7) shr 3; + static_lenb := (s.static_len+3+7) shr 3; + + {$ifdef DEBUG} + Tracev(^M'opt %lu(%lu) stat %lu(%lu) stored %lu lit %u '+ + '{opt_lenb, s.opt_len, static_lenb, s.static_len, stored_len,'+ + 's.last_lit}'); + {$ENDIF} + + if (static_lenb <= opt_lenb) then + opt_lenb := static_lenb; + + end + else + begin + {$IFDEF DEBUG} + Assert(buf <> pcharf(NIL), 'lost buf'); + {$ENDIF} + static_lenb := stored_len + 5; + opt_lenb := static_lenb; { force a stored block } + end; + + { If compression failed and this is the first and last block, + and if the .zip file can be seeked (to rewrite the local header), + the whole file is transformed into a stored file: } + +{$ifdef STORED_FILE_OK} +{$ifdef FORCE_STORED_FILE} + if eof and (s.compressed_len = Long(0)) then + begin { force stored file } +{$else} + if (stored_len <= opt_lenb) and eof and (s.compressed_len=Long(0)) + and seekable()) do + begin +{$endif} + { Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: } + if (buf = pcharf(0)) then + error ('block vanished'); + + copy_block(buf, unsigned(stored_len), 0); { without header } + s.compressed_len := stored_len shl 3; + s.method := STORED; + end + else +{$endif} { STORED_FILE_OK } + +{$ifdef FORCE_STORED} + if (buf <> pcharf(0)) then + begin { force stored block } +{$else} + if (stored_len+4 <= opt_lenb) and (buf <> pcharf(0)) then + begin + { 4: two words for the lengths } +{$endif} + { The test buf <> NULL is only necessary if LIT_BUFSIZE > WSIZE. + Otherwise we can't have processed more than WSIZE input bytes since + the last block flush, because compression would have been + successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + transform a block into a stored block. } + + _tr_stored_block(s, buf, stored_len, eof); + +{$ifdef FORCE_STATIC} + end + else + if (static_lenb >= 0) then + begin { force static trees } +{$else} + end + else + if (static_lenb = opt_lenb) then + begin +{$endif} + send_bits(s, (STATIC_TREES shl 1)+ord(eof), 3); + compress_block(s, static_ltree, static_dtree); + Inc(s.compressed_len, 3 + s.static_len); + end + else + begin + send_bits(s, (DYN_TREES shl 1)+ord(eof), 3); + send_all_trees(s, s.l_desc.max_code+1, s.d_desc.max_code+1, + max_blindex+1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + Inc(s.compressed_len, 3 + s.opt_len); + end; + {$ifdef DEBUG} + Assert (s.compressed_len = s.bits_sent, 'bad compressed size'); + {$ENDIF} + init_block(s); + + if (eof) then + begin + bi_windup(s); + Inc(s.compressed_len, 7); { align on byte boundary } + end; + {$ifdef DEBUG} + Tracev(#13'comprlen %lu(%lu) {s.compressed_len shr 3,'+ + 's.compressed_len-7*ord(eof)}'); + {$ENDIF} + + _tr_flush_block := s.compressed_len shr 3; +end; + + +{ =========================================================================== + Save the match info and tally the frequency counts. Return true if + the current block must be flushed. } + +function _tr_tally (var s : deflate_state; + dist : unsigned; { distance of matched string } + lc : unsigned) : boolean; { match length-MIN_MATCH or unmatched char (if dist=0) } +var + {$IFDEF DEBUG} + MAX_DIST : ush; + {$ENDIF} + code : ush; +{$ifdef TRUNCATE_BLOCK} +var + out_length : ulg; + in_length : ulg; + dcode : int; +{$endif} +begin + s.d_buf^[s.last_lit] := ush(dist); + s.l_buf^[s.last_lit] := uch(lc); + Inc(s.last_lit); + if (dist = 0) then + begin + { lc is the unmatched char } + Inc(s.dyn_ltree[lc].fc.Freq); + end + else + begin + Inc(s.matches); + { Here, lc is the match length - MIN_MATCH } + Dec(dist); { dist := match distance - 1 } + + {macro d_code(dist)} + if (dist) < 256 then + code := _dist_code[dist] + else + code := _dist_code[256+(dist shr 7)]; + {$IFDEF DEBUG} +{macro MAX_DIST(s) <=> ((s)^.w_size-MIN_LOOKAHEAD) + In order to simplify the code, particularly on 16 bit machines, match + distances are limited to MAX_DIST instead of WSIZE. } + MAX_DIST := ush(s.w_size-MIN_LOOKAHEAD); + Assert((dist < ush(MAX_DIST)) and + (ush(lc) <= ush(MAX_MATCH-MIN_MATCH)) and + (ush(code) < ush(D_CODES)), '_tr_tally: bad match'); + {$ENDIF} + Inc(s.dyn_ltree[_length_code[lc]+LITERALS+1].fc.Freq); + {s.dyn_dtree[d_code(dist)].Freq++;} + Inc(s.dyn_dtree[code].fc.Freq); + end; + +{$ifdef TRUNCATE_BLOCK} + { Try to guess if it is profitable to stop the current block here } + if (s.last_lit and $1fff = 0) and (s.level > 2) then + begin + { Compute an upper bound for the compressed length } + out_length := ulg(s.last_lit)*Long(8); + in_length := ulg(long(s.strstart) - s.block_start); + for dcode := 0 to D_CODES-1 do + begin + Inc(out_length, ulg(s.dyn_dtree[dcode].fc.Freq * + (Long(5)+extra_dbits[dcode])) ); + end; + out_length := out_length shr 3; + {$ifdef DEBUG} + Tracev(^M'last_lit %u, in %ld, out ~%ld(%ld%%) '); + { s.last_lit, in_length, out_length, + Long(100) - out_length*Long(100) div in_length)); } + {$ENDIF} + if (s.matches < s.last_lit div 2) and (out_length < in_length div 2) then + begin + _tr_tally := TRUE; + exit; + end; + end; +{$endif} + _tr_tally := (s.last_lit = s.lit_bufsize-1); + { We avoid equality with lit_bufsize because of wraparound at 64K + on 16 bit machines and because stored blocks are restricted to + 64K-1 bytes. } +end; + +end. diff --git a/src/lib/vampimg/ZLib/imzconf.inc b/src/lib/vampimg/ZLib/imzconf.inc new file mode 100644 index 0000000..ffb585d --- /dev/null +++ b/src/lib/vampimg/ZLib/imzconf.inc @@ -0,0 +1,23 @@ +{ -------------------------------------------------------------------- } + +{$DEFINE MAX_MATCH_IS_258} + +{ Compile with -DMAXSEG_64K if the alloc function cannot allocate more + than 64k bytes at a time (needed on systems with 16-bit int). } + +{$UNDEF MAXSEG_64K} +{$DEFINE UNALIGNED_OK} { requires SizeOf(ush) = 2 ! } +{$UNDEF DYNAMIC_CRC_TABLE} +{$UNDEF FASTEST} +{$DEFINE Use32} +{$DEFINE patch112} { apply patch from the zlib home page } + +{$IFDEF FPC} + {$MODE DELPHI} +{$ENDIF} + +{$UNDEF DEBUG} // for Delphi 2007 in DEBUG mode + +{$RANGECHECKS OFF} +{$OVERFLOWCHECKS OFF} +{ -------------------------------------------------------------------- } diff --git a/src/lib/vampimg/ZLib/imzdeflate.pas b/src/lib/vampimg/ZLib/imzdeflate.pas new file mode 100644 index 0000000..e0d8218 --- /dev/null +++ b/src/lib/vampimg/ZLib/imzdeflate.pas @@ -0,0 +1,2129 @@ +Unit imzdeflate; + +{ Orginal: deflate.h -- internal compression state + deflate.c -- compress data using the deflation algorithm + Copyright (C) 1995-1996 Jean-loup Gailly. + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + + +{ ALGORITHM + + The "deflation" process depends on being able to identify portions + of the input text which are identical to earlier input (within a + sliding window trailing behind the input currently being processed). + + The most straightforward technique turns out to be the fastest for + most input files: try all possible matches and select the longest. + The key feature of this algorithm is that insertions into the string + dictionary are very simple and thus fast, and deletions are avoided + completely. Insertions are performed at each input character, whereas + string matches are performed only when the previous match ends. So it + is preferable to spend more time in matches to allow very fast string + insertions and avoid deletions. The matching algorithm for small + strings is inspired from that of Rabin & Karp. A brute force approach + is used to find longer strings when a small match has been found. + A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + (by Leonid Broukhis). + A previous version of this file used a more sophisticated algorithm + (by Fiala and Greene) which is guaranteed to run in linear amortized + time, but has a larger average cost, uses more memory and is patented. + However the F&G algorithm may be faster for some highly redundant + files if the parameter max_chain_length (described below) is too large. + + ACKNOWLEDGEMENTS + + The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + I found it in 'freeze' written by Leonid Broukhis. + Thanks to many people for bug reports and testing. + + REFERENCES + + Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + + A description of the Rabin and Karp algorithm is given in the book + "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + + Fiala,E.R., and Greene,D.H. + Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595} + +interface + +{$I imzconf.inc} + +uses + imzutil, impaszlib; + + +function deflateInit_(strm : z_streamp; + level : int; + const version : AnsiString; + stream_size : int) : int; + + +function deflateInit (var strm : z_stream; level : int) : int; + +{ Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). } + + +{EXPORT} +function deflate (var strm : z_stream; flush : int) : int; + +{ Performs one or both of the following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression + block is terminated and flushed to the output buffer so that the + decompressor can get all input data available so far. For method 9, a future + variant on method 8, the current block will be flushed but not terminated. + Z_SYNC_FLUSH has the same effect as partial flush except that the compressed + output is byte aligned (the compressor can clear its internal bit buffer) + and the current block is always terminated; this can be useful if the + compressor has to be restarted from scratch after an interruption (in which + case the internal state of the compressor may be lost). + If flush is set to Z_FULL_FLUSH, the compression block is terminated, a + special marker is output and the compression dictionary is discarded; this + is useful to allow the decompressor to synchronize if one compressed block + has been damaged (see inflateSync below). Flushing degrades compression and + so should be used only when necessary. Using Z_FULL_FLUSH too often can + seriously degrade the compression. If deflate returns with avail_out == 0, + this function must be called again with the same value of the flush + parameter and more output space (updated avail_out), until the flush is + complete (deflate returns with non-zero avail_out). + + If the parameter flush is set to Z_FINISH, all pending input is processed, + all pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible. } + + +function deflateEnd (var strm : z_stream) : int; + +{ All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). } + + + + + { Advanced functions } + +{ The following functions are needed only in some special applications. } + + +{EXPORT} +function deflateInit2 (var strm : z_stream; + level : int; + method : int; + windowBits : int; + memLevel : int; + strategy : int) : int; + +{ This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. (Method 9 will allow a 64K history buffer and + partial block flushes.) + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library (the value 16 will be allowed for method 9). Larger + values of this parameter result in better compression at the expense of + memory usage. The default value is 15 if deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + If next_in is not null, the library will use this buffer to hold also + some history information; the buffer must either hold the entire input + data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in + is null, the library will allocate its own history buffer (and leave next_in + null). next_out need not be provided here but must be provided by the + application for the next call of deflate(). + + If the history buffer is provided by the application, next_in must + must never be changed by the application since the compressor maintains + information inside this buffer from call to call; the application + must provide more input only by increasing avail_in. next_in is always + reset by the library in this case. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was + not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as + an invalid method). msg is set to null if there is no error message. + deflateInit2 does not perform any compression: this will be done by + deflate(). } + + +{EXPORT} +function deflateSetDictionary (var strm : z_stream; + dictionary : pBytef; {const bytes} + dictLength : uint) : int; + +{ Initializes the compression dictionary (history buffer) from the given + byte sequence without producing any compressed output. This function must + be called immediately after deflateInit or deflateInit2, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and + can be predicted with good accuracy; the data can then be compressed better + than with the default empty dictionary. In this version of the library, + only the last 32K bytes of the dictionary are used. + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state + is inconsistent (for example if deflate has already been called for this + stream). deflateSetDictionary does not perform any compression: this will + be done by deflate(). } + +{EXPORT} +function deflateCopy (dest : z_streamp; + source : z_streamp) : int; + +{ Sets the destination stream as a complete copy of the source stream. If + the source stream is using an application-supplied history buffer, a new + buffer is allocated for the destination stream. The compressed output + buffer is always application-supplied. It's the responsibility of the + application to provide the correct values of next_out and avail_out for the + next call of deflate. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. } + +{EXPORT} +function deflateReset (var strm : z_stream) : int; + +{ This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NIL). } + + +{EXPORT} +function deflateParams (var strm : z_stream; level : int; strategy : int) : int; + +{ Dynamically update the compression level and compression strategy. + This can be used to switch between compression and straight copy of + the input data, or to switch to a different kind of input data requiring + a different strategy. If the compression level is changed, the input + available so far is compressed with the old level (and may be flushed); + the new level will take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. } + + +const + deflate_copyright : string = ' deflate 1.1.2 Copyright 1995-1998 Jean-loup Gailly '; + +{ If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. } + +implementation + +uses + imtrees, imadler; + +{ =========================================================================== + Function prototypes. } + +type + block_state = ( + need_more, { block not completed, need more input or more output } + block_done, { block flush performed } + finish_started, { finish started, need only more output at next deflate } + finish_done); { finish done, accept no more input or output } + +{ Compression function. Returns the block state after the call. } +type + compress_func = function(var s : deflate_state; flush : int) : block_state; + +{local} +procedure fill_window(var s : deflate_state); forward; +{local} +function deflate_stored(var s : deflate_state; flush : int) : block_state; forward; +{local} +function deflate_fast(var s : deflate_state; flush : int) : block_state; forward; +{local} +function deflate_slow(var s : deflate_state; flush : int) : block_state; forward; +{local} +procedure lm_init(var s : deflate_state); forward; + +{local} +procedure putShortMSB(var s : deflate_state; b : uInt); forward; +{local} +procedure flush_pending (var strm : z_stream); forward; +{local} +function read_buf(strm : z_streamp; + buf : pBytef; + size : unsigned) : int; forward; +{$ifdef ASMV} +procedure match_init; { asm code initialization } +function longest_match(var deflate_state; cur_match : IPos) : uInt; forward; +{$else} +{local} +function longest_match(var s : deflate_state; cur_match : IPos) : uInt; + forward; +{$endif} + +{$ifdef DEBUG} +{local} +procedure check_match(var s : deflate_state; + start, match : IPos; + length : int); forward; +{$endif} + +{ ========================================================================== + local data } + +const + ZNIL = 0; +{ Tail of hash chains } + +const + TOO_FAR = 4096; +{ Matches of length 3 are discarded if their distance exceeds TOO_FAR } + +const + MIN_LOOKAHEAD = (MAX_MATCH+MIN_MATCH+1); +{ Minimum amount of lookahead, except at the end of the input file. + See deflate.c for comments about the MIN_MATCH+1. } + +{macro MAX_DIST(var s : deflate_state) : uInt; +begin + MAX_DIST := (s.w_size - MIN_LOOKAHEAD); +end; + In order to simplify the code, particularly on 16 bit machines, match + distances are limited to MAX_DIST instead of WSIZE. } + + +{ Values for max_lazy_match, good_match and max_chain_length, depending on + the desired pack level (0..9). The values given below have been tuned to + exclude worst case performance for pathological files. Better values may be + found for specific files. } + +type + config = record + good_length : ush; { reduce lazy search above this match length } + max_lazy : ush; { do not perform lazy search above this match length } + nice_length : ush; { quit search above this match length } + max_chain : ush; + func : compress_func; + end; + +{local} +const + configuration_table : array[0..10-1] of config = ( +{ good lazy nice chain } +{0} (good_length:0; max_lazy:0; nice_length:0; max_chain:0; func:deflate_stored), { store only } +{1} (good_length:4; max_lazy:4; nice_length:8; max_chain:4; func:deflate_fast), { maximum speed, no lazy matches } +{2} (good_length:4; max_lazy:5; nice_length:16; max_chain:8; func:deflate_fast), +{3} (good_length:4; max_lazy:6; nice_length:32; max_chain:32; func:deflate_fast), + +{4} (good_length:4; max_lazy:4; nice_length:16; max_chain:16; func:deflate_slow), { lazy matches } +{5} (good_length:8; max_lazy:16; nice_length:32; max_chain:32; func:deflate_slow), +{6} (good_length:8; max_lazy:16; nice_length:128; max_chain:128; func:deflate_slow), +{7} (good_length:8; max_lazy:32; nice_length:128; max_chain:256; func:deflate_slow), +{8} (good_length:32; max_lazy:128; nice_length:258; max_chain:1024; func:deflate_slow), +{9} (good_length:32; max_lazy:258; nice_length:258; max_chain:4096; func:deflate_slow)); { maximum compression } + +{ Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + For deflate_fast() (levels <= 3) good is ignored and lazy has a different + meaning. } + +const + EQUAL = 0; +{ result of memcmp for equal strings } + +{ ========================================================================== + Update a hash value with the given input byte + IN assertion: all calls to to UPDATE_HASH are made with consecutive + input characters, so that a running hash key can be computed from the + previous key instead of complete recalculation each time. + +macro UPDATE_HASH(s,h,c) + h := (( (h) shl s^.hash_shift) xor (c)) and s^.hash_mask; +} + +{ =========================================================================== + Insert string str in the dictionary and set match_head to the previous head + of the hash chain (the most recent string with same hash key). Return + the previous length of the hash chain. + If this file is compiled with -DFASTEST, the compression level is forced + to 1, and no hash chains are maintained. + IN assertion: all calls to to INSERT_STRING are made with consecutive + input characters and the first MIN_MATCH bytes of str are valid + (except for the last MIN_MATCH-1 bytes of the input file). } + +procedure INSERT_STRING(var s : deflate_state; + str : uInt; + var match_head : IPos); +begin +{$ifdef FASTEST} + {UPDATE_HASH(s, s.ins_h, s.window[(str) + (MIN_MATCH-1)])} + s.ins_h := ((s.ins_h shl s.hash_shift) xor + (s.window^[(str) + (MIN_MATCH-1)])) and s.hash_mask; + match_head := s.head[s.ins_h] + s.head[s.ins_h] := Pos(str); +{$else} + {UPDATE_HASH(s, s.ins_h, s.window[(str) + (MIN_MATCH-1)])} + s.ins_h := ((s.ins_h shl s.hash_shift) xor + (s.window^[(str) + (MIN_MATCH-1)])) and s.hash_mask; + + match_head := s.head^[s.ins_h]; + s.prev^[(str) and s.w_mask] := match_head; + s.head^[s.ins_h] := Pos(str); +{$endif} +end; + +{ ========================================================================= + Initialize the hash table (avoiding 64K overflow for 16 bit systems). + prev[] will be initialized on the fly. + +macro CLEAR_HASH(s) + s^.head[s^.hash_size-1] := ZNIL; + zmemzero(pBytef(s^.head), unsigned(s^.hash_size-1)*sizeof(s^.head^[0])); +} + +{ ======================================================================== } + +function deflateInit2_(var strm : z_stream; + level : int; + method : int; + windowBits : int; + memLevel : int; + strategy : int; + const version : AnsiString; + stream_size : int) : int; +var + s : deflate_state_ptr; + noheader : int; + + overlay : pushfArray; + { We overlay pending_buf and d_buf+l_buf. This works since the average + output size for (length,distance) codes is <= 24 bits. } +begin + noheader := 0; + if (version = '') or (version[1] <> ZLIB_VERSION[1]) or + (stream_size <> sizeof(z_stream)) then + begin + deflateInit2_ := Z_VERSION_ERROR; + exit; + end; + { + if (strm = Z_NULL) then + begin + deflateInit2_ := Z_STREAM_ERROR; + exit; + end; + } + { SetLength(strm.msg, 255); } + strm.msg := ''; + if not Assigned(strm.zalloc) then + begin + {$IFDEF FPC} strm.zalloc := @zcalloc; {$ELSE} + strm.zalloc := zcalloc; + {$ENDIF} + strm.opaque := voidpf(0); + end; + if not Assigned(strm.zfree) then + {$IFDEF FPC} strm.zfree := @zcfree; {$ELSE} + strm.zfree := zcfree; + {$ENDIF} + + if (level = Z_DEFAULT_COMPRESSION) then + level := 6; +{$ifdef FASTEST} + level := 1; +{$endif} + + if (windowBits < 0) then { undocumented feature: suppress zlib header } + begin + noheader := 1; + windowBits := -windowBits; + end; + if (memLevel < 1) or (memLevel > MAX_MEM_LEVEL) or (method <> Z_DEFLATED) + or (windowBits < 8) or (windowBits > 15) or (level < 0) + or (level > 9) or (strategy < 0) or (strategy > Z_HUFFMAN_ONLY) then + begin + deflateInit2_ := Z_STREAM_ERROR; + exit; + end; + + s := deflate_state_ptr (ZALLOC(strm, 1, sizeof(deflate_state))); + if (s = Z_NULL) then + begin + deflateInit2_ := Z_MEM_ERROR; + exit; + end; + strm.state := pInternal_state(s); + s^.strm := @strm; + + s^.noheader := noheader; + s^.w_bits := windowBits; + s^.w_size := 1 shl s^.w_bits; + s^.w_mask := s^.w_size - 1; + + s^.hash_bits := memLevel + 7; + s^.hash_size := 1 shl s^.hash_bits; + s^.hash_mask := s^.hash_size - 1; + s^.hash_shift := ((s^.hash_bits+MIN_MATCH-1) div MIN_MATCH); + + s^.window := pzByteArray (ZALLOC(strm, s^.w_size, 2*sizeof(Byte))); + s^.prev := pzPosfArray (ZALLOC(strm, s^.w_size, sizeof(Pos))); + s^.head := pzPosfArray (ZALLOC(strm, s^.hash_size, sizeof(Pos))); + + s^.lit_bufsize := 1 shl (memLevel + 6); { 16K elements by default } + + overlay := pushfArray (ZALLOC(strm, s^.lit_bufsize, sizeof(ush)+2)); + s^.pending_buf := pzByteArray (overlay); + s^.pending_buf_size := ulg(s^.lit_bufsize) * (sizeof(ush)+Long(2)); + + if (s^.window = Z_NULL) or (s^.prev = Z_NULL) or (s^.head = Z_NULL) + or (s^.pending_buf = Z_NULL) then + begin + {ERR_MSG(Z_MEM_ERROR);} + strm.msg := z_errmsg[z_errbase-Z_MEM_ERROR]; + deflateEnd (strm); + deflateInit2_ := Z_MEM_ERROR; + exit; + end; + s^.d_buf := pushfArray( @overlay^[s^.lit_bufsize div sizeof(ush)] ); + s^.l_buf := puchfArray( @s^.pending_buf^[(1+sizeof(ush))*s^.lit_bufsize] ); + + s^.level := level; + s^.strategy := strategy; + s^.method := Byte(method); + + deflateInit2_ := deflateReset(strm); +end; + +{ ========================================================================= } + +function deflateInit2(var strm : z_stream; + level : int; + method : int; + windowBits : int; + memLevel : int; + strategy : int) : int; +{ a macro } +begin + deflateInit2 := deflateInit2_(strm, level, method, windowBits, + memLevel, strategy, ZLIB_VERSION, sizeof(z_stream)); +end; + +{ ========================================================================= } + +function deflateInit_(strm : z_streamp; + level : int; + const version : AnsiString; + stream_size : int) : int; +begin + if (strm = Z_NULL) then + deflateInit_ := Z_STREAM_ERROR + else + deflateInit_ := deflateInit2_(strm^, level, Z_DEFLATED, MAX_WBITS, + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); + { To do: ignore strm^.next_in if we use it as window } +end; + +{ ========================================================================= } + +function deflateInit(var strm : z_stream; level : int) : int; +{ deflateInit is a macro to allow checking the zlib version + and the compiler's view of z_stream: } +begin + deflateInit := deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, ZLIB_VERSION, sizeof(z_stream)); +end; + +{ ======================================================================== } +function deflateSetDictionary (var strm : z_stream; + dictionary : pBytef; + dictLength : uInt) : int; +var + s : deflate_state_ptr; + length : uInt; + n : uInt; + hash_head : IPos; +var + MAX_DIST : uInt; {macro} +begin + length := dictLength; + hash_head := 0; + + if {(@strm = Z_NULL) or} + (strm.state = Z_NULL) or (dictionary = Z_NULL) + or (deflate_state_ptr(strm.state)^.status <> INIT_STATE) then + begin + deflateSetDictionary := Z_STREAM_ERROR; + exit; + end; + + s := deflate_state_ptr(strm.state); + strm.adler := adler32(strm.adler, dictionary, dictLength); + + if (length < MIN_MATCH) then + begin + deflateSetDictionary := Z_OK; + exit; + end; + MAX_DIST := (s^.w_size - MIN_LOOKAHEAD); + if (length > MAX_DIST) then + begin + length := MAX_DIST; +{$ifndef USE_DICT_HEAD} + Inc(dictionary, dictLength - length); { use the tail of the dictionary } +{$endif} + end; + + zmemcpy( pBytef(s^.window), dictionary, length); + s^.strstart := length; + s^.block_start := long(length); + + { Insert all strings in the hash table (except for the last two bytes). + s^.lookahead stays null, so s^.ins_h will be recomputed at the next + call of fill_window. } + + s^.ins_h := s^.window^[0]; + {UPDATE_HASH(s, s^.ins_h, s^.window[1]);} + s^.ins_h := ((s^.ins_h shl s^.hash_shift) xor (s^.window^[1])) + and s^.hash_mask; + + for n := 0 to length - MIN_MATCH do + begin + INSERT_STRING(s^, n, hash_head); + end; + {if (hash_head <> 0) then + hash_head := 0; - to make compiler happy } + deflateSetDictionary := Z_OK; +end; + +{ ======================================================================== } +function deflateReset (var strm : z_stream) : int; +var + s : deflate_state_ptr; +begin + if {(@strm = Z_NULL) or} + (strm.state = Z_NULL) + or (not Assigned(strm.zalloc)) or (not Assigned(strm.zfree)) then + begin + deflateReset := Z_STREAM_ERROR; + exit; + end; + + strm.total_out := 0; + strm.total_in := 0; + strm.msg := ''; { use zfree if we ever allocate msg dynamically } + strm.data_type := Z_UNKNOWN; + + s := deflate_state_ptr(strm.state); + s^.pending := 0; + s^.pending_out := pBytef(s^.pending_buf); + + if (s^.noheader < 0) then + begin + s^.noheader := 0; { was set to -1 by deflate(..., Z_FINISH); } + end; + if s^.noheader <> 0 then + s^.status := BUSY_STATE + else + s^.status := INIT_STATE; + strm.adler := 1; + s^.last_flush := Z_NO_FLUSH; + + _tr_init(s^); + lm_init(s^); + + deflateReset := Z_OK; +end; + +{ ======================================================================== } +function deflateParams(var strm : z_stream; + level : int; + strategy : int) : int; +var + s : deflate_state_ptr; + func : compress_func; + err : int; +begin + err := Z_OK; + if {(@strm = Z_NULL) or} (strm.state = Z_NULL) then + begin + deflateParams := Z_STREAM_ERROR; + exit; + end; + + s := deflate_state_ptr(strm.state); + + if (level = Z_DEFAULT_COMPRESSION) then + begin + level := 6; + end; + if (level < 0) or (level > 9) or (strategy < 0) + or (strategy > Z_HUFFMAN_ONLY) then + begin + deflateParams := Z_STREAM_ERROR; + exit; + end; + func := configuration_table[s^.level].func; + + if (@func <> @configuration_table[level].func) + and (strm.total_in <> 0) then + begin + { Flush the last buffer: } + err := deflate(strm, Z_PARTIAL_FLUSH); + end; + if (s^.level <> level) then + begin + s^.level := level; + s^.max_lazy_match := configuration_table[level].max_lazy; + s^.good_match := configuration_table[level].good_length; + s^.nice_match := configuration_table[level].nice_length; + s^.max_chain_length := configuration_table[level].max_chain; + end; + s^.strategy := strategy; + deflateParams := err; +end; + +{ ========================================================================= + Put a short in the pending buffer. The 16-bit value is put in MSB order. + IN assertion: the stream state is correct and there is enough room in + pending_buf. } + +{local} +procedure putShortMSB (var s : deflate_state; b : uInt); +begin + s.pending_buf^[s.pending] := Byte(b shr 8); + Inc(s.pending); + s.pending_buf^[s.pending] := Byte(b and $ff); + Inc(s.pending); +end; + +{ ========================================================================= + Flush as much pending output as possible. All deflate() output goes + through this function so some applications may wish to modify it + to avoid allocating a large strm^.next_out buffer and copying into it. + (See also read_buf()). } + +{local} +procedure flush_pending(var strm : z_stream); +var + len : unsigned; + s : deflate_state_ptr; +begin + s := deflate_state_ptr(strm.state); + len := s^.pending; + + if (len > strm.avail_out) then + len := strm.avail_out; + if (len = 0) then + exit; + + zmemcpy(strm.next_out, s^.pending_out, len); + Inc(strm.next_out, len); + Inc(s^.pending_out, len); + Inc(strm.total_out, len); + Dec(strm.avail_out, len); + Dec(s^.pending, len); + if (s^.pending = 0) then + begin + s^.pending_out := pBytef(s^.pending_buf); + end; +end; + +{ ========================================================================= } +function deflate (var strm : z_stream; flush : int) : int; +var + old_flush : int; { value of flush param for previous deflate call } + s : deflate_state_ptr; +var + header : uInt; + level_flags : uInt; +var + bstate : block_state; +begin + if {(@strm = Z_NULL) or} (strm.state = Z_NULL) + or (flush > Z_FINISH) or (flush < 0) then + begin + deflate := Z_STREAM_ERROR; + exit; + end; + s := deflate_state_ptr(strm.state); + + if (strm.next_out = Z_NULL) or + ((strm.next_in = Z_NULL) and (strm.avail_in <> 0)) or + ((s^.status = FINISH_STATE) and (flush <> Z_FINISH)) then + begin + {ERR_RETURN(strm^, Z_STREAM_ERROR);} + strm.msg := z_errmsg[z_errbase - Z_STREAM_ERROR]; + deflate := Z_STREAM_ERROR; + exit; + end; + if (strm.avail_out = 0) then + begin + {ERR_RETURN(strm^, Z_BUF_ERROR);} + strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR]; + deflate := Z_BUF_ERROR; + exit; + end; + + s^.strm := @strm; { just in case } + old_flush := s^.last_flush; + s^.last_flush := flush; + + { Write the zlib header } + if (s^.status = INIT_STATE) then + begin + + header := (Z_DEFLATED + ((s^.w_bits-8) shl 4)) shl 8; + level_flags := (s^.level-1) shr 1; + + if (level_flags > 3) then + level_flags := 3; + header := header or (level_flags shl 6); + if (s^.strstart <> 0) then + header := header or PRESET_DICT; + Inc(header, 31 - (header mod 31)); + + s^.status := BUSY_STATE; + putShortMSB(s^, header); + + { Save the adler32 of the preset dictionary: } + if (s^.strstart <> 0) then + begin + putShortMSB(s^, uInt(strm.adler shr 16)); + putShortMSB(s^, uInt(strm.adler and $ffff)); + end; + strm.adler := long(1); + end; + + { Flush as much pending output as possible } + if (s^.pending <> 0) then + begin + flush_pending(strm); + if (strm.avail_out = 0) then + begin + { Since avail_out is 0, deflate will be called again with + more output space, but possibly with both pending and + avail_in equal to zero. There won't be anything to do, + but this is not an error situation so make sure we + return OK instead of BUF_ERROR at next call of deflate: } + + s^.last_flush := -1; + deflate := Z_OK; + exit; + end; + + { Make sure there is something to do and avoid duplicate consecutive + flushes. For repeated and useless calls with Z_FINISH, we keep + returning Z_STREAM_END instead of Z_BUFF_ERROR. } + + end + else + if (strm.avail_in = 0) and (flush <= old_flush) + and (flush <> Z_FINISH) then + begin + {ERR_RETURN(strm^, Z_BUF_ERROR);} + strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR]; + deflate := Z_BUF_ERROR; + exit; + end; + + { User must not provide more input after the first FINISH: } + if (s^.status = FINISH_STATE) and (strm.avail_in <> 0) then + begin + {ERR_RETURN(strm^, Z_BUF_ERROR);} + strm.msg := z_errmsg[z_errbase - Z_BUF_ERROR]; + deflate := Z_BUF_ERROR; + exit; + end; + + { Start a new block or continue the current one. } + if (strm.avail_in <> 0) or (s^.lookahead <> 0) + or ((flush <> Z_NO_FLUSH) and (s^.status <> FINISH_STATE)) then + begin + bstate := configuration_table[s^.level].func(s^, flush); + + if (bstate = finish_started) or (bstate = finish_done) then + s^.status := FINISH_STATE; + + if (bstate = need_more) or (bstate = finish_started) then + begin + if (strm.avail_out = 0) then + s^.last_flush := -1; { avoid BUF_ERROR next call, see above } + + deflate := Z_OK; + exit; + { If flush != Z_NO_FLUSH && avail_out == 0, the next call + of deflate should use the same flush parameter to make sure + that the flush is complete. So we don't have to output an + empty block here, this will be done at next call. This also + ensures that for a very small output buffer, we emit at most + one empty block. } + end; + if (bstate = block_done) then + begin + if (flush = Z_PARTIAL_FLUSH) then + _tr_align(s^) + else + begin { FULL_FLUSH or SYNC_FLUSH } + _tr_stored_block(s^, pcharf(NIL), Long(0), FALSE); + { For a full flush, this empty block will be recognized + as a special marker by inflate_sync(). } + + if (flush = Z_FULL_FLUSH) then + begin + {macro CLEAR_HASH(s);} { forget history } + s^.head^[s^.hash_size-1] := ZNIL; + zmemzero(pBytef(s^.head), unsigned(s^.hash_size-1)*sizeof(s^.head^[0])); + end; + end; + + flush_pending(strm); + if (strm.avail_out = 0) then + begin + s^.last_flush := -1; { avoid BUF_ERROR at next call, see above } + deflate := Z_OK; + exit; + end; + + end; + end; + {$IFDEF DEBUG} + Assert(strm.avail_out > 0, 'bug2'); + {$ENDIF} + if (flush <> Z_FINISH) then + begin + deflate := Z_OK; + exit; + end; + + if (s^.noheader <> 0) then + begin + deflate := Z_STREAM_END; + exit; + end; + + { Write the zlib trailer (adler32) } + putShortMSB(s^, uInt(strm.adler shr 16)); + putShortMSB(s^, uInt(strm.adler and $ffff)); + flush_pending(strm); + { If avail_out is zero, the application will call deflate again + to flush the rest. } + + s^.noheader := -1; { write the trailer only once! } + if s^.pending <> 0 then + deflate := Z_OK + else + deflate := Z_STREAM_END; +end; + +{ ========================================================================= } +function deflateEnd (var strm : z_stream) : int; +var + status : int; + s : deflate_state_ptr; +begin + if {(@strm = Z_NULL) or} (strm.state = Z_NULL) then + begin + deflateEnd := Z_STREAM_ERROR; + exit; + end; + + s := deflate_state_ptr(strm.state); + status := s^.status; + if (status <> INIT_STATE) and (status <> BUSY_STATE) and + (status <> FINISH_STATE) then + begin + deflateEnd := Z_STREAM_ERROR; + exit; + end; + + { Deallocate in reverse order of allocations: } + TRY_FREE(strm, s^.pending_buf); + TRY_FREE(strm, s^.head); + TRY_FREE(strm, s^.prev); + TRY_FREE(strm, s^.window); + + ZFREE(strm, s); + strm.state := Z_NULL; + + if status = BUSY_STATE then + deflateEnd := Z_DATA_ERROR + else + deflateEnd := Z_OK; +end; + +{ ========================================================================= + Copy the source state to the destination state. + To simplify the source, this is not supported for 16-bit MSDOS (which + doesn't have enough memory anyway to duplicate compression states). } + + +{ ========================================================================= } +function deflateCopy (dest, source : z_streamp) : int; +{$ifndef MAXSEG_64K} +var + ds : deflate_state_ptr; + ss : deflate_state_ptr; + overlay : pushfArray; +{$endif} +begin +{$ifdef MAXSEG_64K} + deflateCopy := Z_STREAM_ERROR; + exit; +{$else} + + if (source = Z_NULL) or (dest = Z_NULL) or (source^.state = Z_NULL) then + begin + deflateCopy := Z_STREAM_ERROR; + exit; + end; + ss := deflate_state_ptr(source^.state); + dest^ := source^; + + ds := deflate_state_ptr( ZALLOC(dest^, 1, sizeof(deflate_state)) ); + if (ds = Z_NULL) then + begin + deflateCopy := Z_MEM_ERROR; + exit; + end; + dest^.state := pInternal_state(ds); + ds^ := ss^; + ds^.strm := dest; + + ds^.window := pzByteArray ( ZALLOC(dest^, ds^.w_size, 2*sizeof(Byte)) ); + ds^.prev := pzPosfArray ( ZALLOC(dest^, ds^.w_size, sizeof(Pos)) ); + ds^.head := pzPosfArray ( ZALLOC(dest^, ds^.hash_size, sizeof(Pos)) ); + overlay := pushfArray ( ZALLOC(dest^, ds^.lit_bufsize, sizeof(ush)+2) ); + ds^.pending_buf := pzByteArray ( overlay ); + + if (ds^.window = Z_NULL) or (ds^.prev = Z_NULL) or (ds^.head = Z_NULL) + or (ds^.pending_buf = Z_NULL) then + begin + deflateEnd (dest^); + deflateCopy := Z_MEM_ERROR; + exit; + end; + { following zmemcpy do not work for 16-bit MSDOS } + zmemcpy(pBytef(ds^.window), pBytef(ss^.window), ds^.w_size * 2 * sizeof(Byte)); + zmemcpy(pBytef(ds^.prev), pBytef(ss^.prev), ds^.w_size * sizeof(Pos)); + zmemcpy(pBytef(ds^.head), pBytef(ss^.head), ds^.hash_size * sizeof(Pos)); + zmemcpy(pBytef(ds^.pending_buf), pBytef(ss^.pending_buf), uInt(ds^.pending_buf_size)); + + ds^.pending_out := @ds^.pending_buf^[ptr2int(ss^.pending_out) - ptr2int(ss^.pending_buf)]; + ds^.d_buf := pushfArray (@overlay^[ds^.lit_bufsize div sizeof(ush)] ); + ds^.l_buf := puchfArray (@ds^.pending_buf^[(1+sizeof(ush))*ds^.lit_bufsize]); + + ds^.l_desc.dyn_tree := tree_ptr(@ds^.dyn_ltree); + ds^.d_desc.dyn_tree := tree_ptr(@ds^.dyn_dtree); + ds^.bl_desc.dyn_tree := tree_ptr(@ds^.bl_tree); + + deflateCopy := Z_OK; +{$endif} +end; + + +{ =========================================================================== + Read a new buffer from the current input stream, update the adler32 + and total number of bytes read. All deflate() input goes through + this function so some applications may wish to modify it to avoid + allocating a large strm^.next_in buffer and copying from it. + (See also flush_pending()). } + +{local} +function read_buf(strm : z_streamp; buf : pBytef; size : unsigned) : int; +var + len : unsigned; +begin + len := strm^.avail_in; + + if (len > size) then + len := size; + if (len = 0) then + begin + read_buf := 0; + exit; + end; + + Dec(strm^.avail_in, len); + + if deflate_state_ptr(strm^.state)^.noheader = 0 then + begin + strm^.adler := adler32(strm^.adler, strm^.next_in, len); + end; + zmemcpy(buf, strm^.next_in, len); + Inc(strm^.next_in, len); + Inc(strm^.total_in, len); + + read_buf := int(len); +end; + +{ =========================================================================== + Initialize the "longest match" routines for a new zlib stream } + +{local} +procedure lm_init (var s : deflate_state); +begin + s.window_size := ulg( uLong(2)*s.w_size); + + {macro CLEAR_HASH(s);} + s.head^[s.hash_size-1] := ZNIL; + zmemzero(pBytef(s.head), unsigned(s.hash_size-1)*sizeof(s.head^[0])); + + { Set the default configuration parameters: } + + s.max_lazy_match := configuration_table[s.level].max_lazy; + s.good_match := configuration_table[s.level].good_length; + s.nice_match := configuration_table[s.level].nice_length; + s.max_chain_length := configuration_table[s.level].max_chain; + + s.strstart := 0; + s.block_start := long(0); + s.lookahead := 0; + s.prev_length := MIN_MATCH-1; + s.match_length := MIN_MATCH-1; + s.match_available := FALSE; + s.ins_h := 0; +{$ifdef ASMV} + match_init; { initialize the asm code } +{$endif} +end; + +{ =========================================================================== + Set match_start to the longest match starting at the given string and + return its length. Matches shorter or equal to prev_length are discarded, + in which case the result is equal to prev_length and match_start is + garbage. + IN assertions: cur_match is the head of the hash chain for the current + string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + OUT assertion: the match length is not greater than s^.lookahead. } + + +{$ifndef ASMV} +{ For 80x86 and 680x0, an optimized version will be provided in match.asm or + match.S. The code will be functionally equivalent. } + +{$ifndef FASTEST} + +{local} +function longest_match(var s : deflate_state; + cur_match : IPos { current match } + ) : uInt; +label + nextstep; +var + chain_length : unsigned; { max hash chain length } + {register} scan : pBytef; { current string } + {register} match : pBytef; { matched string } + {register} len : int; { length of current match } + best_len : int; { best match length so far } + nice_match : int; { stop if match long enough } + limit : IPos; + + prev : pzPosfArray; + wmask : uInt; +{$ifdef UNALIGNED_OK} + {register} strend : pBytef; + {register} scan_start : ush; + {register} scan_end : ush; +{$else} + {register} strend : pBytef; + {register} scan_end1 : Byte; + {register} scan_end : Byte; +{$endif} +var + MAX_DIST : uInt; +begin + chain_length := s.max_chain_length; { max hash chain length } + scan := @(s.window^[s.strstart]); + best_len := s.prev_length; { best match length so far } + nice_match := s.nice_match; { stop if match long enough } + + + MAX_DIST := s.w_size - MIN_LOOKAHEAD; +{In order to simplify the code, particularly on 16 bit machines, match +distances are limited to MAX_DIST instead of WSIZE. } + + if s.strstart > IPos(MAX_DIST) then + limit := s.strstart - IPos(MAX_DIST) + else + limit := ZNIL; + { Stop when cur_match becomes <= limit. To simplify the code, + we prevent matches with the string of window index 0. } + + prev := s.prev; + wmask := s.w_mask; + +{$ifdef UNALIGNED_OK} + { Compare two bytes at a time. Note: this is not always beneficial. + Try with and without -DUNALIGNED_OK to check. } + + strend := pBytef(@(s.window^[s.strstart + MAX_MATCH - 1])); + scan_start := pushf(scan)^; + scan_end := pushfArray(scan)^[best_len-1]; { fix } +{$else} + strend := pBytef(@(s.window^[s.strstart + MAX_MATCH])); + {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF} + scan_end1 := pzByteArray(scan)^[best_len-1]; + {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF} + scan_end := pzByteArray(scan)^[best_len]; +{$endif} + + { The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + It is easy to get rid of this optimization if necessary. } + {$IFDEF DEBUG} + Assert((s.hash_bits >= 8) and (MAX_MATCH = 258), 'Code too clever'); + {$ENDIF} + { Do not waste too much time if we already have a good match: } + if (s.prev_length >= s.good_match) then + begin + chain_length := chain_length shr 2; + end; + + { Do not look for matches beyond the end of the input. This is necessary + to make deflate deterministic. } + + if (uInt(nice_match) > s.lookahead) then + nice_match := s.lookahead; + {$IFDEF DEBUG} + Assert(ulg(s.strstart) <= s.window_size-MIN_LOOKAHEAD, 'need lookahead'); + {$ENDIF} + repeat + {$IFDEF DEBUG} + Assert(cur_match < s.strstart, 'no future'); + {$ENDIF} + match := @(s.window^[cur_match]); + + { Skip to next match if the match length cannot increase + or if the match length is less than 2: } + +{$undef DO_UNALIGNED_OK} +{$ifdef UNALIGNED_OK} + {$ifdef MAX_MATCH_IS_258} + {$define DO_UNALIGNED_OK} + {$endif} +{$endif} + +{$ifdef DO_UNALIGNED_OK} + { This code assumes sizeof(unsigned short) = 2. Do not use + UNALIGNED_OK if your compiler uses a different size. } + {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF} + if (pushfArray(match)^[best_len-1] <> scan_end) or + (pushf(match)^ <> scan_start) then + goto nextstep; {continue;} + {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF} + + { It is not necessary to compare scan[2] and match[2] since they are + always equal when the other bytes match, given that the hash keys + are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + strstart+3, +5, ... up to strstart+257. We check for insufficient + lookahead only every 4th comparison; the 128th check will be made + at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + necessary to put more guard bytes at the end of the window, or + to check more often for insufficient lookahead. } + {$IFDEF DEBUG} + Assert(pzByteArray(scan)^[2] = pzByteArray(match)^[2], 'scan[2]?'); + {$ENDIF} + Inc(scan); + Inc(match); + + repeat + Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break; + Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break; + Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break; + Inc(scan,2); Inc(match,2); if (pushf(scan)^<>pushf(match)^) then break; + until (ptr2int(scan) >= ptr2int(strend)); + { The funny "do while" generates better code on most compilers } + + { Here, scan <= window+strstart+257 } + {$IFDEF DEBUG} + {$ifopt R+} {$define RangeCheck} {$endif} {$R-} + Assert(ptr2int(scan) <= + ptr2int(@(s.window^[unsigned(s.window_size-1)])), + 'wild scan'); + {$ifdef RangeCheck} {$R+} {$undef RangeCheck} {$endif} + {$ENDIF} + if (scan^ = match^) then + Inc(scan); + + len := (MAX_MATCH - 1) - int(ptr2int(strend)) + int(ptr2int(scan)); + scan := strend; + Dec(scan, (MAX_MATCH-1)); + +{$else} { UNALIGNED_OK } + + {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF} + if (pzByteArray(match)^[best_len] <> scan_end) or + (pzByteArray(match)^[best_len-1] <> scan_end1) or + (match^ <> scan^) then + goto nextstep; {continue;} + {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF} + Inc(match); + if (match^ <> pzByteArray(scan)^[1]) then + goto nextstep; {continue;} + + { The check at best_len-1 can be removed because it will be made + again later. (This heuristic is not always a win.) + It is not necessary to compare scan[2] and match[2] since they + are always equal when the other bytes match, given that + the hash keys are equal and that HASH_BITS >= 8. } + + Inc(scan, 2); + Inc(match); + {$IFDEF DEBUG} + Assert( scan^ = match^, 'match[2]?'); + {$ENDIF} + { We check for insufficient lookahead only every 8th comparison; + the 256th check will be made at strstart+258. } + + repeat + Inc(scan); Inc(match); if (scan^ <> match^) then break; + Inc(scan); Inc(match); if (scan^ <> match^) then break; + Inc(scan); Inc(match); if (scan^ <> match^) then break; + Inc(scan); Inc(match); if (scan^ <> match^) then break; + Inc(scan); Inc(match); if (scan^ <> match^) then break; + Inc(scan); Inc(match); if (scan^ <> match^) then break; + Inc(scan); Inc(match); if (scan^ <> match^) then break; + Inc(scan); Inc(match); if (scan^ <> match^) then break; + until (ptr2int(scan) >= ptr2int(strend)); + + {$IFDEF DEBUG} + Assert(ptr2int(scan) <= + ptr2int(@(s.window^[unsigned(s.window_size-1)])), + 'wild scan'); + {$ENDIF} + + len := MAX_MATCH - int(ptr2int(strend) - ptr2int(scan)); + scan := strend; + Dec(scan, MAX_MATCH); + +{$endif} { UNALIGNED_OK } + + if (len > best_len) then + begin + s.match_start := cur_match; + best_len := len; + if (len >= nice_match) then + break; + {$IFOPT R+} {$R-} {$DEFINE NoRangeCheck} {$ENDIF} +{$ifdef UNALIGNED_OK} + scan_end := pzByteArray(scan)^[best_len-1]; +{$else} + scan_end1 := pzByteArray(scan)^[best_len-1]; + scan_end := pzByteArray(scan)^[best_len]; +{$endif} + {$IFDEF NoRangeCheck} {$R+} {$UNDEF NoRangeCheck} {$ENDIF} + end; + nextstep: + cur_match := prev^[cur_match and wmask]; + Dec(chain_length); + until (cur_match <= limit) or (chain_length = 0); + + if (uInt(best_len) <= s.lookahead) then + longest_match := uInt(best_len) + else + longest_match := s.lookahead; +end; +{$endif} { ASMV } + +{$else} { FASTEST } +{ --------------------------------------------------------------------------- + Optimized version for level = 1 only } + +{local} +function longest_match(var s : deflate_state; + cur_match : IPos { current match } + ) : uInt; +var + {register} scan : pBytef; { current string } + {register} match : pBytef; { matched string } + {register} len : int; { length of current match } + {register} strend : pBytef; +begin + scan := @s.window^[s.strstart]; + strend := @s.window^[s.strstart + MAX_MATCH]; + + + { The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + It is easy to get rid of this optimization if necessary. } + {$IFDEF DEBUG} + Assert((s.hash_bits >= 8) and (MAX_MATCH = 258), 'Code too clever'); + + Assert(ulg(s.strstart) <= s.window_size-MIN_LOOKAHEAD, 'need lookahead'); + + Assert(cur_match < s.strstart, 'no future'); + {$ENDIF} + match := s.window + cur_match; + + { Return failure if the match length is less than 2: } + + if (match[0] <> scan[0]) or (match[1] <> scan[1]) then + begin + longest_match := MIN_MATCH-1; + exit; + end; + + { The check at best_len-1 can be removed because it will be made + again later. (This heuristic is not always a win.) + It is not necessary to compare scan[2] and match[2] since they + are always equal when the other bytes match, given that + the hash keys are equal and that HASH_BITS >= 8. } + + scan += 2, match += 2; + Assert(scan^ = match^, 'match[2]?'); + + { We check for insufficient lookahead only every 8th comparison; + the 256th check will be made at strstart+258. } + + repeat + Inc(scan); Inc(match); if scan^<>match^ then break; + Inc(scan); Inc(match); if scan^<>match^ then break; + Inc(scan); Inc(match); if scan^<>match^ then break; + Inc(scan); Inc(match); if scan^<>match^ then break; + Inc(scan); Inc(match); if scan^<>match^ then break; + Inc(scan); Inc(match); if scan^<>match^ then break; + Inc(scan); Inc(match); if scan^<>match^ then break; + Inc(scan); Inc(match); if scan^<>match^ then break; + until (ptr2int(scan) >= ptr2int(strend)); + + Assert(scan <= s.window+unsigned(s.window_size-1), 'wild scan'); + + len := MAX_MATCH - int(strend - scan); + + if (len < MIN_MATCH) then + begin + return := MIN_MATCH - 1; + exit; + end; + + s.match_start := cur_match; + if len <= s.lookahead then + longest_match := len + else + longest_match := s.lookahead; +end; +{$endif} { FASTEST } + +{$ifdef DEBUG} +{ =========================================================================== + Check that the match at match_start is indeed a match. } + +{local} +procedure check_match(var s : deflate_state; + start, match : IPos; + length : int); +begin + exit; + { check that the match is indeed a match } + if (zmemcmp(pBytef(@s.window^[match]), + pBytef(@s.window^[start]), length) <> EQUAL) then + begin + WriteLn(' start ',start,', match ',match ,' length ', length); + repeat + Write(AnsiChar(s.window^[match]), AnsiChar(s.window^[start])); + Inc(match); + Inc(start); + Dec(length); + Until (length = 0); + z_error('invalid match'); + end; + if (z_verbose > 1) then + begin + Write('\\[',start-match,',',length,']'); + repeat + Write(AnsiChar(s.window^[start])); + Inc(start); + Dec(length); + Until (length = 0); + end; +end; +{$endif} + +{ =========================================================================== + Fill the window when the lookahead becomes insufficient. + Updates strstart and lookahead. + + IN assertion: lookahead < MIN_LOOKAHEAD + OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + At least one byte has been read, or avail_in = 0; reads are + performed for at least two bytes (required for the zip translate_eol + option -- not supported here). } + +{local} +procedure fill_window(var s : deflate_state); +var + {register} n, m : unsigned; + {register} p : pPosf; + more : unsigned; { Amount of free space at the end of the window. } + wsize : uInt; +begin + wsize := s.w_size; + repeat + more := unsigned(s.window_size -ulg(s.lookahead) -ulg(s.strstart)); + + { Deal with !@#$% 64K limit: } + if (more = 0) and (s.strstart = 0) and (s.lookahead = 0) then + more := wsize + else + if (more = unsigned(-1)) then + begin + { Very unlikely, but possible on 16 bit machine if strstart = 0 + and lookahead = 1 (input done one byte at time) } + Dec(more); + + { If the window is almost full and there is insufficient lookahead, + move the upper half to the lower one to make room in the upper half.} + end + else + if (s.strstart >= wsize+ {MAX_DIST}(wsize-MIN_LOOKAHEAD)) then + begin + zmemcpy( pBytef(s.window), pBytef(@(s.window^[wsize])), + unsigned(wsize)); + Dec(s.match_start, wsize); + Dec(s.strstart, wsize); { we now have strstart >= MAX_DIST } + Dec(s.block_start, long(wsize)); + + { Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level = 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) } + + n := s.hash_size; + p := @s.head^[n]; + repeat + Dec(p); + m := p^; + if (m >= wsize) then + p^ := Pos(m-wsize) + else + p^ := Pos(ZNIL); + Dec(n); + Until (n=0); + + n := wsize; +{$ifndef FASTEST} + p := @s.prev^[n]; + repeat + Dec(p); + m := p^; + if (m >= wsize) then + p^ := Pos(m-wsize) + else + p^:= Pos(ZNIL); + { If n is not on any hash chain, prev^[n] is garbage but + its value will never be used. } + Dec(n); + Until (n=0); +{$endif} + Inc(more, wsize); + end; + if (s.strm^.avail_in = 0) then + exit; + + {* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. } + + {$IFDEF DEBUG} + Assert(more >= 2, 'more < 2'); + {$ENDIF} + + n := read_buf(s.strm, pBytef(@(s.window^[s.strstart + s.lookahead])), + more); + Inc(s.lookahead, n); + + { Initialize the hash value now that we have some input: } + if (s.lookahead >= MIN_MATCH) then + begin + s.ins_h := s.window^[s.strstart]; + {UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]);} + s.ins_h := ((s.ins_h shl s.hash_shift) xor s.window^[s.strstart+1]) + and s.hash_mask; +{$ifdef MIN_MATCH <> 3} + Call UPDATE_HASH() MIN_MATCH-3 more times +{$endif} + end; + { If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + but this is not important since only literal bytes will be emitted. } + + until (s.lookahead >= MIN_LOOKAHEAD) or (s.strm^.avail_in = 0); +end; + +{ =========================================================================== + Flush the current block, with given end-of-file flag. + IN assertion: strstart is set to the end of the current match. } + +procedure FLUSH_BLOCK_ONLY(var s : deflate_state; eof : boolean); {macro} +begin + if (s.block_start >= Long(0)) then + _tr_flush_block(s, pcharf(@s.window^[unsigned(s.block_start)]), + ulg(long(s.strstart) - s.block_start), eof) + else + _tr_flush_block(s, pcharf(Z_NULL), + ulg(long(s.strstart) - s.block_start), eof); + + s.block_start := s.strstart; + flush_pending(s.strm^); + {$IFDEF DEBUG} + Tracev('[FLUSH]'); + {$ENDIF} +end; + +{ Same but force premature exit if necessary. +macro FLUSH_BLOCK(var s : deflate_state; eof : boolean) : boolean; +var + result : block_state; +begin + FLUSH_BLOCK_ONLY(s, eof); + if (s.strm^.avail_out = 0) then + begin + if eof then + result := finish_started + else + result := need_more; + exit; + end; +end; +} + +{ =========================================================================== + Copy without compression as much as possible from the input stream, return + the current block state. + This function does not insert new strings in the dictionary since + uncompressible data is probably not useful. This function is used + only for the level=0 compression option. + NOTE: this function should be optimized to avoid extra copying from + window to pending_buf. } + + +{local} +function deflate_stored(var s : deflate_state; flush : int) : block_state; +{ Stored blocks are limited to 0xffff bytes, pending_buf is limited + to pending_buf_size, and each stored block has a 5 byte header: } +var + max_block_size : ulg; + max_start : ulg; +begin + max_block_size := $ffff; + if (max_block_size > s.pending_buf_size - 5) then + max_block_size := s.pending_buf_size - 5; + + { Copy as much as possible from input to output: } + while TRUE do + begin + { Fill the window as much as possible: } + if (s.lookahead <= 1) then + begin + {$IFDEF DEBUG} + Assert( (s.strstart < s.w_size + {MAX_DIST}s.w_size-MIN_LOOKAHEAD) or + (s.block_start >= long(s.w_size)), 'slide too late'); + {$ENDIF} + fill_window(s); + if (s.lookahead = 0) and (flush = Z_NO_FLUSH) then + begin + deflate_stored := need_more; + exit; + end; + + if (s.lookahead = 0) then + break; { flush the current block } + end; + {$IFDEF DEBUG} + Assert(s.block_start >= long(0), 'block gone'); + {$ENDIF} + Inc(s.strstart, s.lookahead); + s.lookahead := 0; + + { Emit a stored block if pending_buf will be full: } + max_start := s.block_start + max_block_size; + if (s.strstart = 0) or (ulg(s.strstart) >= max_start) then + begin + { strstart = 0 is possible when wraparound on 16-bit machine } + s.lookahead := s.strstart - uInt(max_start); + s.strstart := uInt(max_start); + {FLUSH_BLOCK(s, FALSE);} + FLUSH_BLOCK_ONLY(s, FALSE); + if (s.strm^.avail_out = 0) then + begin + deflate_stored := need_more; + exit; + end; + end; + + { Flush if we may have to slide, otherwise block_start may become + negative and the data will be gone: } + + if (s.strstart - uInt(s.block_start) >= {MAX_DIST} + s.w_size-MIN_LOOKAHEAD) then + begin + {FLUSH_BLOCK(s, FALSE);} + FLUSH_BLOCK_ONLY(s, FALSE); + if (s.strm^.avail_out = 0) then + begin + deflate_stored := need_more; + exit; + end; + end; + end; + + {FLUSH_BLOCK(s, flush = Z_FINISH);} + FLUSH_BLOCK_ONLY(s, flush = Z_FINISH); + if (s.strm^.avail_out = 0) then + begin + if flush = Z_FINISH then + deflate_stored := finish_started + else + deflate_stored := need_more; + exit; + end; + + if flush = Z_FINISH then + deflate_stored := finish_done + else + deflate_stored := block_done; +end; + +{ =========================================================================== + Compress as much as possible from the input stream, return the current + block state. + This function does not perform lazy evaluation of matches and inserts + new strings in the dictionary only for unmatched strings or for short + matches. It is used only for the fast compression options. } + +{local} +function deflate_fast(var s : deflate_state; flush : int) : block_state; +var + hash_head : IPos; { head of the hash chain } + bflush : boolean; { set if current block must be flushed } +begin + hash_head := ZNIL; + while TRUE do + begin + { Make sure that we always have enough lookahead, except + at the end of the input file. We need MAX_MATCH bytes + for the next match, plus MIN_MATCH bytes to insert the + string following the next match. } + + if (s.lookahead < MIN_LOOKAHEAD) then + begin + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then + begin + deflate_fast := need_more; + exit; + end; + + if (s.lookahead = 0) then + break; { flush the current block } + end; + + + { Insert the string window[strstart .. strstart+2] in the + dictionary, and set hash_head to the head of the hash chain: } + + if (s.lookahead >= MIN_MATCH) then + begin + INSERT_STRING(s, s.strstart, hash_head); + end; + + { Find the longest match, discarding those <= prev_length. + At this point we have always match_length < MIN_MATCH } + if (hash_head <> ZNIL) and + (s.strstart - hash_head <= (s.w_size-MIN_LOOKAHEAD){MAX_DIST}) then + begin + { To simplify the code, we prevent matches with the string + of window index 0 (in particular we have to avoid a match + of the string with itself at the start of the input file). } + if (s.strategy <> Z_HUFFMAN_ONLY) then + begin + s.match_length := longest_match (s, hash_head); + end; + { longest_match() sets match_start } + end; + if (s.match_length >= MIN_MATCH) then + begin + {$IFDEF DEBUG} + check_match(s, s.strstart, s.match_start, s.match_length); + {$ENDIF} + + {_tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush);} + bflush := _tr_tally(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH); + + Dec(s.lookahead, s.match_length); + + { Insert new strings in the hash table only if the match length + is not too large. This saves time but degrades compression. } + +{$ifndef FASTEST} + if (s.match_length <= s.max_insert_length) + and (s.lookahead >= MIN_MATCH) then + begin + Dec(s.match_length); { string at strstart already in hash table } + repeat + Inc(s.strstart); + INSERT_STRING(s, s.strstart, hash_head); + { strstart never exceeds WSIZE-MAX_MATCH, so there are + always MIN_MATCH bytes ahead. } + Dec(s.match_length); + until (s.match_length = 0); + Inc(s.strstart); + end + else +{$endif} + + begin + Inc(s.strstart, s.match_length); + s.match_length := 0; + s.ins_h := s.window^[s.strstart]; + {UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]);} + s.ins_h := (( s.ins_h shl s.hash_shift) xor + s.window^[s.strstart+1]) and s.hash_mask; +if MIN_MATCH <> 3 then { the linker removes this } +begin + {Call UPDATE_HASH() MIN_MATCH-3 more times} +end; + + { If lookahead < MIN_MATCH, ins_h is garbage, but it does not + matter since it will be recomputed at next deflate call. } + + end; + end + else + begin + { No match, output a literal byte } + {$IFDEF DEBUG} + Tracevv(AnsiChar(s.window^[s.strstart])); + {$ENDIF} + {_tr_tally_lit (s, 0, s.window^[s.strstart], bflush);} + bflush := _tr_tally (s, 0, s.window^[s.strstart]); + + Dec(s.lookahead); + Inc(s.strstart); + end; + if bflush then + begin {FLUSH_BLOCK(s, FALSE);} + FLUSH_BLOCK_ONLY(s, FALSE); + if (s.strm^.avail_out = 0) then + begin + deflate_fast := need_more; + exit; + end; + end; + end; + {FLUSH_BLOCK(s, flush = Z_FINISH);} + FLUSH_BLOCK_ONLY(s, flush = Z_FINISH); + if (s.strm^.avail_out = 0) then + begin + if flush = Z_FINISH then + deflate_fast := finish_started + else + deflate_fast := need_more; + exit; + end; + + if flush = Z_FINISH then + deflate_fast := finish_done + else + deflate_fast := block_done; +end; + +{ =========================================================================== + Same as above, but achieves better compression. We use a lazy + evaluation for matches: a match is finally adopted only if there is + no better match at the next window position. } + +{local} +function deflate_slow(var s : deflate_state; flush : int) : block_state; +var + hash_head : IPos; { head of hash chain } + bflush : boolean; { set if current block must be flushed } +var + max_insert : uInt; +begin + hash_head := ZNIL; + + { Process the input block. } + while TRUE do + begin + { Make sure that we always have enough lookahead, except + at the end of the input file. We need MAX_MATCH bytes + for the next match, plus MIN_MATCH bytes to insert the + string following the next match. } + + if (s.lookahead < MIN_LOOKAHEAD) then + begin + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD) and (flush = Z_NO_FLUSH) then + begin + deflate_slow := need_more; + exit; + end; + + if (s.lookahead = 0) then + break; { flush the current block } + end; + + { Insert the string window[strstart .. strstart+2] in the + dictionary, and set hash_head to the head of the hash chain: } + + if (s.lookahead >= MIN_MATCH) then + begin + INSERT_STRING(s, s.strstart, hash_head); + end; + + { Find the longest match, discarding those <= prev_length. } + + s.prev_length := s.match_length; + s.prev_match := s.match_start; + s.match_length := MIN_MATCH-1; + + if (hash_head <> ZNIL) and (s.prev_length < s.max_lazy_match) and + (s.strstart - hash_head <= {MAX_DIST}(s.w_size-MIN_LOOKAHEAD)) then + begin + { To simplify the code, we prevent matches with the string + of window index 0 (in particular we have to avoid a match + of the string with itself at the start of the input file). } + + if (s.strategy <> Z_HUFFMAN_ONLY) then + begin + s.match_length := longest_match (s, hash_head); + end; + { longest_match() sets match_start } + + if (s.match_length <= 5) and ((s.strategy = Z_FILTERED) or + ((s.match_length = MIN_MATCH) and + (s.strstart - s.match_start > TOO_FAR))) then + begin + { If prev_match is also MIN_MATCH, match_start is garbage + but we will ignore the current match anyway. } + + s.match_length := MIN_MATCH-1; + end; + end; + { If there was a match at the previous step and the current + match is not better, output the previous match: } + + if (s.prev_length >= MIN_MATCH) + and (s.match_length <= s.prev_length) then + begin + max_insert := s.strstart + s.lookahead - MIN_MATCH; + { Do not insert strings in hash table beyond this. } + {$ifdef DEBUG} + check_match(s, s.strstart-1, s.prev_match, s.prev_length); + {$endif} + + {_tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush);} + bflush := _tr_tally(s, s.strstart -1 - s.prev_match, + s.prev_length - MIN_MATCH); + + { Insert in hash table all strings up to the end of the match. + strstart-1 and strstart are already inserted. If there is not + enough lookahead, the last two strings are not inserted in + the hash table. } + + Dec(s.lookahead, s.prev_length-1); + Dec(s.prev_length, 2); + repeat + Inc(s.strstart); + if (s.strstart <= max_insert) then + begin + INSERT_STRING(s, s.strstart, hash_head); + end; + Dec(s.prev_length); + until (s.prev_length = 0); + s.match_available := FALSE; + s.match_length := MIN_MATCH-1; + Inc(s.strstart); + + if (bflush) then {FLUSH_BLOCK(s, FALSE);} + begin + FLUSH_BLOCK_ONLY(s, FALSE); + if (s.strm^.avail_out = 0) then + begin + deflate_slow := need_more; + exit; + end; + end; + end + else + if (s.match_available) then + begin + { If there was no match at the previous position, output a + single literal. If there was a match but the current match + is longer, truncate the previous match to a single literal. } + {$IFDEF DEBUG} + Tracevv(AnsiChar(s.window^[s.strstart-1])); + {$ENDIF} + bflush := _tr_tally (s, 0, s.window^[s.strstart-1]); + + if bflush then + begin + FLUSH_BLOCK_ONLY(s, FALSE); + end; + Inc(s.strstart); + Dec(s.lookahead); + if (s.strm^.avail_out = 0) then + begin + deflate_slow := need_more; + exit; + end; + end + else + begin + { There is no previous match to compare with, wait for + the next step to decide. } + + s.match_available := TRUE; + Inc(s.strstart); + Dec(s.lookahead); + end; + end; + + {$IFDEF DEBUG} + Assert (flush <> Z_NO_FLUSH, 'no flush?'); + {$ENDIF} + if (s.match_available) then + begin + {$IFDEF DEBUG} + Tracevv(AnsiChar(s.window^[s.strstart-1])); + bflush := + {$ENDIF} + _tr_tally (s, 0, s.window^[s.strstart-1]); + s.match_available := FALSE; + end; + {FLUSH_BLOCK(s, flush = Z_FINISH);} + FLUSH_BLOCK_ONLY(s, flush = Z_FINISH); + if (s.strm^.avail_out = 0) then + begin + if flush = Z_FINISH then + deflate_slow := finish_started + else + deflate_slow := need_more; + exit; + end; + if flush = Z_FINISH then + deflate_slow := finish_done + else + deflate_slow := block_done; +end; + +end. diff --git a/src/lib/vampimg/ZLib/imzinflate.pas b/src/lib/vampimg/ZLib/imzinflate.pas new file mode 100644 index 0000000..6376510 --- /dev/null +++ b/src/lib/vampimg/ZLib/imzinflate.pas @@ -0,0 +1,750 @@ +Unit imzinflate; + +{ inflate.c -- zlib interface to inflate modules + Copyright (C) 1995-1998 Mark Adler + + Pascal tranlastion + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +interface + +{$I imzconf.inc} + +uses + imzutil, impaszlib, iminfblock, iminfutil; + +function inflateInit(var z : z_stream) : int; + +{ Initializes the internal stream state for decompression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, inflateInit updates them to use default + allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_VERSION_ERROR if the zlib library version is incompatible + with the version assumed by the caller. msg is set to null if there is no + error message. inflateInit does not perform any decompression: this will be + done by inflate(). } + + + +function inflateInit_(z : z_streamp; + const version : AnsiString; + stream_size : int) : int; + + +function inflateInit2_(var z: z_stream; + w : int; + const version : AnsiString; + stream_size : int) : int; + +function inflateInit2(var z: z_stream; + windowBits : int) : int; + +{ + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +} + + + +function inflateEnd(var z : z_stream) : int; + +{ + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +} + +function inflateReset(var z : z_stream) : int; + +{ + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +} + + +function inflate(var z : z_stream; + f : int) : int; +{ + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +} + + +function inflateSetDictionary(var z : z_stream; + dictionary : pBytef; {const array of byte} + dictLength : uInt) : int; + +{ + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +} + +function inflateSync(var z : z_stream) : int; + +{ + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +} + + +function inflateSyncPoint(var z : z_stream) : int; + + +implementation + +uses + imadler; + +function inflateReset(var z : z_stream) : int; +begin + if (z.state = Z_NULL) then + begin + inflateReset := Z_STREAM_ERROR; + exit; + end; + z.total_out := 0; + z.total_in := 0; + z.msg := ''; + if z.state^.nowrap then + z.state^.mode := BLOCKS + else + z.state^.mode := METHOD; + inflate_blocks_reset(z.state^.blocks^, z, Z_NULL); + {$IFDEF DEBUG} + Tracev('inflate: reset'); + {$ENDIF} + inflateReset := Z_OK; +end; + + +function inflateEnd(var z : z_stream) : int; +begin + if (z.state = Z_NULL) or not Assigned(z.zfree) then + begin + inflateEnd := Z_STREAM_ERROR; + exit; + end; + if (z.state^.blocks <> Z_NULL) then + inflate_blocks_free(z.state^.blocks, z); + ZFREE(z, z.state); + z.state := Z_NULL; + {$IFDEF DEBUG} + Tracev('inflate: end'); + {$ENDIF} + inflateEnd := Z_OK; +end; + + +function inflateInit2_(var z: z_stream; + w : int; + const version : AnsiString; + stream_size : int) : int; +begin + if (version = '') or (version[1] <> ZLIB_VERSION[1]) or + (stream_size <> sizeof(z_stream)) then + begin + inflateInit2_ := Z_VERSION_ERROR; + exit; + end; + { initialize state } + { SetLength(strm.msg, 255); } + z.msg := ''; + if not Assigned(z.zalloc) then + begin + {$IFDEF FPC} z.zalloc := @zcalloc; {$ELSE} + z.zalloc := zcalloc; + {$endif} + z.opaque := voidpf(0); + end; + if not Assigned(z.zfree) then + {$IFDEF FPC} z.zfree := @zcfree; {$ELSE} + z.zfree := zcfree; + {$ENDIF} + + z.state := pInternal_state( ZALLOC(z,1,sizeof(internal_state)) ); + if (z.state = Z_NULL) then + begin + inflateInit2_ := Z_MEM_ERROR; + exit; + end; + + z.state^.blocks := Z_NULL; + + { handle undocumented nowrap option (no zlib header or check) } + z.state^.nowrap := FALSE; + if (w < 0) then + begin + w := - w; + z.state^.nowrap := TRUE; + end; + + { set window size } + if (w < 8) or (w > 15) then + begin + inflateEnd(z); + inflateInit2_ := Z_STREAM_ERROR; + exit; + end; + z.state^.wbits := uInt(w); + + { create inflate_blocks state } + if z.state^.nowrap then + z.state^.blocks := inflate_blocks_new(z, NIL, uInt(1) shl w) + else + {$IFDEF FPC} + z.state^.blocks := inflate_blocks_new(z, @adler32, uInt(1) shl w); + {$ELSE} + z.state^.blocks := inflate_blocks_new(z, adler32, uInt(1) shl w); + {$ENDIF} + if (z.state^.blocks = Z_NULL) then + begin + inflateEnd(z); + inflateInit2_ := Z_MEM_ERROR; + exit; + end; + {$IFDEF DEBUG} + Tracev('inflate: allocated'); + {$ENDIF} + { reset state } + inflateReset(z); + inflateInit2_ := Z_OK; +end; + +function inflateInit2(var z: z_stream; windowBits : int) : int; +begin + inflateInit2 := inflateInit2_(z, windowBits, ZLIB_VERSION, sizeof(z_stream)); +end; + + +function inflateInit(var z : z_stream) : int; +{ inflateInit is a macro to allow checking the zlib version + and the compiler's view of z_stream: } +begin + inflateInit := inflateInit2_(z, DEF_WBITS, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit_(z : z_streamp; + const version : AnsiString; + stream_size : int) : int; +begin + { initialize state } + if (z = Z_NULL) then + inflateInit_ := Z_STREAM_ERROR + else + inflateInit_ := inflateInit2_(z^, DEF_WBITS, version, stream_size); +end; + +function inflate(var z : z_stream; + f : int) : int; +var + r : int; + b : uInt; +begin + if (z.state = Z_NULL) or (z.next_in = Z_NULL) then + begin + inflate := Z_STREAM_ERROR; + exit; + end; + if f = Z_FINISH then + f := Z_BUF_ERROR + else + f := Z_OK; + r := Z_BUF_ERROR; + while True do + case (z.state^.mode) of + BLOCKS: + begin + r := inflate_blocks(z.state^.blocks^, z, r); + if (r = Z_DATA_ERROR) then + begin + z.state^.mode := BAD; + z.state^.sub.marker := 0; { can try inflateSync } + continue; { break C-switch } + end; + if (r = Z_OK) then + r := f; + if (r <> Z_STREAM_END) then + begin + inflate := r; + exit; + end; + r := f; + inflate_blocks_reset(z.state^.blocks^, z, @z.state^.sub.check.was); + if (z.state^.nowrap) then + begin + z.state^.mode := DONE; + continue; { break C-switch } + end; + z.state^.mode := CHECK4; { falltrough } + end; + CHECK4: + begin + {NEEDBYTE} + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; + + {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;} + Dec(z.avail_in); + Inc(z.total_in); + z.state^.sub.check.need := uLong(z.next_in^) shl 24; + Inc(z.next_in); + + z.state^.mode := CHECK3; { falltrough } + end; + CHECK3: + begin + {NEEDBYTE} + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; + {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);} + Dec(z.avail_in); + Inc(z.total_in); + Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16); + Inc(z.next_in); + + z.state^.mode := CHECK2; { falltrough } + end; + CHECK2: + begin + {NEEDBYTE} + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; + + {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);} + Dec(z.avail_in); + Inc(z.total_in); + Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8); + Inc(z.next_in); + + z.state^.mode := CHECK1; { falltrough } + end; + CHECK1: + begin + {NEEDBYTE} + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; + {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) );} + Dec(z.avail_in); + Inc(z.total_in); + Inc(z.state^.sub.check.need, uLong(z.next_in^) ); + Inc(z.next_in); + + + if (z.state^.sub.check.was <> z.state^.sub.check.need) then + begin + z.state^.mode := BAD; + z.msg := 'incorrect data check'; + z.state^.sub.marker := 5; { can't try inflateSync } + continue; { break C-switch } + end; + {$IFDEF DEBUG} + Tracev('inflate: zlib check ok'); + {$ENDIF} + z.state^.mode := DONE; { falltrough } + end; + DONE: + begin + inflate := Z_STREAM_END; + exit; + end; + METHOD: + begin + {NEEDBYTE} + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; {} + + {z.state^.sub.method := NEXTBYTE(z);} + Dec(z.avail_in); + Inc(z.total_in); + z.state^.sub.method := z.next_in^; + Inc(z.next_in); + + if ((z.state^.sub.method and $0f) <> Z_DEFLATED) then + begin + z.state^.mode := BAD; + z.msg := 'unknown compression method'; + z.state^.sub.marker := 5; { can't try inflateSync } + continue; { break C-switch } + end; + if ((z.state^.sub.method shr 4) + 8 > z.state^.wbits) then + begin + z.state^.mode := BAD; + z.msg := 'invalid window size'; + z.state^.sub.marker := 5; { can't try inflateSync } + continue; { break C-switch } + end; + z.state^.mode := FLAG; + { fall trough } + end; + FLAG: + begin + {NEEDBYTE} + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; {} + {b := NEXTBYTE(z);} + Dec(z.avail_in); + Inc(z.total_in); + b := z.next_in^; + Inc(z.next_in); + + if (((z.state^.sub.method shl 8) + b) mod 31) <> 0 then {% mod ?} + begin + z.state^.mode := BAD; + z.msg := 'incorrect header check'; + z.state^.sub.marker := 5; { can't try inflateSync } + continue; { break C-switch } + end; + {$IFDEF DEBUG} + Tracev('inflate: zlib header ok'); + {$ENDIF} + if ((b and PRESET_DICT) = 0) then + begin + z.state^.mode := BLOCKS; + continue; { break C-switch } + end; + z.state^.mode := DICT4; + { falltrough } + end; + DICT4: + begin + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; + + {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;} + Dec(z.avail_in); + Inc(z.total_in); + z.state^.sub.check.need := uLong(z.next_in^) shl 24; + Inc(z.next_in); + + z.state^.mode := DICT3; { falltrough } + end; + DICT3: + begin + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; + {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);} + Dec(z.avail_in); + Inc(z.total_in); + Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16); + Inc(z.next_in); + + z.state^.mode := DICT2; { falltrough } + end; + DICT2: + begin + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + r := f; + + {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);} + Dec(z.avail_in); + Inc(z.total_in); + Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8); + Inc(z.next_in); + + z.state^.mode := DICT1; { falltrough } + end; + DICT1: + begin + if (z.avail_in = 0) then + begin + inflate := r; + exit; + end; + { r := f; --- wird niemals benutzt } + {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) );} + Dec(z.avail_in); + Inc(z.total_in); + Inc(z.state^.sub.check.need, uLong(z.next_in^) ); + Inc(z.next_in); + + z.adler := z.state^.sub.check.need; + z.state^.mode := DICT0; + inflate := Z_NEED_DICT; + exit; + end; + DICT0: + begin + z.state^.mode := BAD; + z.msg := 'need dictionary'; + z.state^.sub.marker := 0; { can try inflateSync } + inflate := Z_STREAM_ERROR; + exit; + end; + BAD: + begin + inflate := Z_DATA_ERROR; + exit; + end; + else + begin + inflate := Z_STREAM_ERROR; + exit; + end; + end; +{$ifdef NEED_DUMMY_result} + result := Z_STREAM_ERROR; { Some dumb compilers complain without this } +{$endif} +end; + +function inflateSetDictionary(var z : z_stream; + dictionary : pBytef; {const array of byte} + dictLength : uInt) : int; +var + length : uInt; +begin + length := dictLength; + + if (z.state = Z_NULL) or (z.state^.mode <> DICT0) then + begin + inflateSetDictionary := Z_STREAM_ERROR; + exit; + end; + if (adler32(Long(1), dictionary, dictLength) <> z.adler) then + begin + inflateSetDictionary := Z_DATA_ERROR; + exit; + end; + z.adler := Long(1); + + if (length >= (uInt(1) shl z.state^.wbits)) then + begin + length := (1 shl z.state^.wbits)-1; + Inc( dictionary, dictLength - length); + end; + inflate_set_dictionary(z.state^.blocks^, dictionary^, length); + z.state^.mode := BLOCKS; + inflateSetDictionary := Z_OK; +end; + + +function inflateSync(var z : z_stream) : int; +const + mark : packed array[0..3] of byte = (0, 0, $ff, $ff); +var + n : uInt; { number of bytes to look at } + p : pBytef; { pointer to bytes } + m : uInt; { number of marker bytes found in a row } + r, w : uLong; { temporaries to save total_in and total_out } +begin + { set up } + if (z.state = Z_NULL) then + begin + inflateSync := Z_STREAM_ERROR; + exit; + end; + if (z.state^.mode <> BAD) then + begin + z.state^.mode := BAD; + z.state^.sub.marker := 0; + end; + n := z.avail_in; + if (n = 0) then + begin + inflateSync := Z_BUF_ERROR; + exit; + end; + p := z.next_in; + m := z.state^.sub.marker; + + { search } + while (n <> 0) and (m < 4) do + begin + if (p^ = mark[m]) then + Inc(m) + else + if (p^ <> 0) then + m := 0 + else + m := 4 - m; + Inc(p); + Dec(n); + end; + + { restore } + Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in)); + z.next_in := p; + z.avail_in := n; + z.state^.sub.marker := m; + + + { return no joy or set up to restart on a new block } + if (m <> 4) then + begin + inflateSync := Z_DATA_ERROR; + exit; + end; + r := z.total_in; + w := z.total_out; + inflateReset(z); + z.total_in := r; + z.total_out := w; + z.state^.mode := BLOCKS; + inflateSync := Z_OK; +end; + + +{ + returns true if inflate is currently at the end of a block generated + by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + but removes the length bytes of the resulting empty stored block. When + decompressing, PPP checks that at the end of input packet, inflate is + waiting for these length bytes. +} + +function inflateSyncPoint(var z : z_stream) : int; +begin + if (z.state = Z_NULL) or (z.state^.blocks = Z_NULL) then + begin + inflateSyncPoint := Z_STREAM_ERROR; + exit; + end; + inflateSyncPoint := inflate_blocks_sync_point(z.state^.blocks^); +end; + +end. diff --git a/src/lib/vampimg/ZLib/imzutil.pas b/src/lib/vampimg/ZLib/imzutil.pas new file mode 100644 index 0000000..701b5a2 --- /dev/null +++ b/src/lib/vampimg/ZLib/imzutil.pas @@ -0,0 +1,190 @@ +Unit imzutil; + +{ + Copyright (C) 1998 by Jacques Nomssi Nzali + For conditions of distribution and use, see copyright notice in readme.txt +} + +interface + +{$I imzconf.inc} + +{ Type declarations } + +type + {Byte = usigned char; 8 bits} + Bytef = byte; + charf = byte; + + int = longint; + intf = int; + uInt = cardinal; { 16 bits or more } + uIntf = uInt; + + Long = longint; + uLong = Cardinal; + uLongf = uLong; + + voidp = pointer; + voidpf = voidp; + pBytef = ^Bytef; + pIntf = ^intf; + puIntf = ^uIntf; + puLong = ^uLongf; + + ptr2int = uInt; +{ a pointer to integer casting is used to do pointer arithmetic. + ptr2int must be an integer type and sizeof(ptr2int) must be less + than sizeof(pointer) - Nomssi } + +type + zByteArray = array[0..(MaxInt div SizeOf(Bytef))-1] of Bytef; + pzByteArray = ^zByteArray; +type + zIntfArray = array[0..(MaxInt div SizeOf(Intf))-1] of Intf; + pzIntfArray = ^zIntfArray; +type + zuIntArray = array[0..(MaxInt div SizeOf(uInt))-1] of uInt; + PuIntArray = ^zuIntArray; + +{ Type declarations - only for deflate } + +type + uch = Byte; + uchf = uch; { FAR } + ush = Word; + ushf = ush; + ulg = LongInt; + + unsigned = uInt; + + pcharf = ^charf; + puchf = ^uchf; + pushf = ^ushf; + +type + zuchfArray = zByteArray; + puchfArray = ^zuchfArray; +type + zushfArray = array[0..(MaxInt div SizeOf(ushf))-1] of ushf; + pushfArray = ^zushfArray; + +procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt); +function zmemcmp(s1p, s2p : pBytef; len : uInt) : int; +procedure zmemzero(destp : pBytef; len : uInt); +procedure zcfree(opaque : voidpf; ptr : voidpf); +function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf; + +implementation + +procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt); +begin + Move(sourcep^, destp^, len); +end; + +function zmemcmp(s1p, s2p : pBytef; len : uInt) : int; +var + j : uInt; + source, + dest : pBytef; +begin + source := s1p; + dest := s2p; + for j := 0 to pred(len) do + begin + if (source^ <> dest^) then + begin + zmemcmp := 2*Ord(source^ > dest^)-1; + exit; + end; + Inc(source); + Inc(dest); + end; + zmemcmp := 0; +end; + +procedure zmemzero(destp : pBytef; len : uInt); +begin + FillChar(destp^, len, 0); +end; + +procedure zcfree(opaque : voidpf; ptr : voidpf); +{$ifdef Delphi16} +var + Handle : THandle; +{$endif} +{$IFDEF FPC} +var + memsize : uint; +{$ENDIF} +begin + (* + {$IFDEF DPMI} + {h :=} GlobalFreePtr(ptr); + {$ELSE} + {$IFDEF CALL_DOS} + dosFree(ptr); + {$ELSE} + {$ifdef HugeMem} + FreeMemHuge(ptr); + {$else} + {$ifdef Delphi16} + Handle := GlobalHandle(LH(ptr).H); { HiWord(LongInt(ptr)) } + GlobalUnLock(Handle); + GlobalFree(Handle); + {$else} + {$IFDEF FPC} + Dec(puIntf(ptr)); + memsize := puIntf(ptr)^; + FreeMem(ptr, memsize+SizeOf(uInt)); + {$ELSE} + FreeMem(ptr); { Delphi 2,3,4 } + {$ENDIF} + {$endif} + {$endif} + {$ENDIF} + {$ENDIF} + *) + FreeMem(ptr); +end; + +function zcalloc (opaque : voidpf; items : uInt; size : uInt) : voidpf; +var + p : voidpf; + memsize : uLong; +{$ifdef Delphi16} + handle : THandle; +{$endif} +begin + memsize := uLong(items) * size; + (* + { $IFDEF DPMI} + p := GlobalAllocPtr(gmem_moveable, memsize); + { $ELSE} + { $IFDEF CALLDOS} + p := dosAlloc(memsize); + { $ELSE} + {$ifdef HugeMem} + GetMemHuge(p, memsize); + { $else} + { $ifdef Delphi16} + Handle := GlobalAlloc(HeapAllocFlags, memsize); + p := GlobalLock(Handle); + { $else} + { $IFDEF FPC} + GetMem(p, memsize+SizeOf(uInt)); + puIntf(p)^:= memsize; + Inc(puIntf(p)); + { $ELSE} + GetMem(p, memsize); { Delphi: p := AllocMem(memsize); } + { $ENDIF} + { $endif} + { $endif} + { $ENDIF} + { $ENDIF} + *) + GetMem(p, memsize); + zcalloc := p; +end; + +end. diff --git a/src/lib/vampimg/ZLib/readme.txt b/src/lib/vampimg/ZLib/readme.txt new file mode 100644 index 0000000..ffd4f89 --- /dev/null +++ b/src/lib/vampimg/ZLib/readme.txt @@ -0,0 +1,129 @@ +_____________________________________________________________________________ + +PASZLIB 1.0 May 11th, 1998 + +Based on the zlib 1.1.2, a general purpose data compression library. + +Copyright (C) 1998,1999,2000 by NOMSSI NZALI Jacques H. C. +[kn&n DES] See "Legal issues" for conditions of distribution and use. +_____________________________________________________________________________ + + +Introduction +============ + +The 'zlib' compression library provides in-memory compression and +decompression functions, including integrity checks of the uncompressed +data. This version of the library supports only one compression method +(deflation) but other algorithms will be added later and will have the same +stream interface. + +Compression can be done in a single step if the buffers are large +enough (for example if an input file is mmap'ed), or can be done by +repeated calls of the compression function. In the latter case, the +application must provide more input and/or consume the output +(providing more output space) before each call. + +The default memory requirements for deflate are 256K plus a few kilobytes +for small objects. The default memory requirements for inflate are 32K +plus a few kilobytes for small objects. + +Change Log +========== + +March 24th 2000 - minizip code by Gilles Vollant ported to Pascal. + z_stream.msg defined as string[255] to avoid problems + with Delphi 2+ dynamic string handling. + changes to silence Delphi 5 compiler warning. If you + have Delphi 5, defines Delphi5 in zconf.inc + +May 7th 1999 - Some changes for FPC + deflateCopy() has new parameters + trees.pas - record constant definition +June 17th 1998 - Applied official 1.1.2 patch. + Memcheck turned off by default. + zutil.pas patch for Delphi 1 memory allocation corrected. + dzlib.txt file added. + compress2() is now exported + +June 25th 1998 - fixed a conversion bug: in inftrees.pas, ZFREE(z, v) was + missing in line 574; + +File list +========= + +Here is a road map to the files in the Paszlib distribution. + +readme.txt Introduction, Documentation +dzlib.txt Changes to Delphi sources for Paszlib stream classes + +include file + +zconf.inc Configuration declarations. + +Pascal source code files: + +adler.pas compute the Adler-32 checksum of a data stream +crc.pas compute the CRC-32 of a data stream +gzio.pas IO on .gz files +infblock.pas interpret and process block types to last block +infcodes.pas process literals and length/distance pairs +inffast.pas process literals and length/distance pairs fast +inftrees.pas generate Huffman trees for efficient decoding +infutil.pas types and macros common to blocks and codes +strutils.pas string utilities +trees.pas output deflated data using Huffman coding +zcompres.pas compress a memory buffer +zdeflate.pas compress data using the deflation algorithm +zinflate.pas zlib interface to inflate modules +zlib.pas zlib data structures. read the comments there! +zuncompr.pas decompress a memory buffer +zutil.pas + +minizip/ziputils.pas data structure and IO on .zip file +minizip/unzip.pas +minizip/zip.pas + +Test applications + +example.pas usage example of the zlib compression library +minigzip.pas simulate gzip using the zlib compression library +minizip/miniunz.pas simulates unzip using the zlib compression library +minizip/minizip.pas simulates zip using the zlib compression library + +Legal issues +============ + +Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +Archive Locations: +================== + +Check the Paszlib home page with links + + http://www.tu-chemnitz.de/~nomssi/paszlib.html + +The data format used by the zlib library is described by RFCs (Request for +Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt +(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +These documents are also available in other formats from +ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html. +____________________________________________________________________________ +Jacques Nomssi Nzali March 24th, 2000 diff --git a/src/shared/WADEDITOR.pas b/src/shared/WADEDITOR.pas index b533664..3c6c1a3 100644 --- a/src/shared/WADEDITOR.pas +++ b/src/shared/WADEDITOR.pas @@ -1,12 +1,10 @@ unit WADEDITOR; -{$MODE Delphi} - { ----------------------------------- -WADEDITOR.PAS ВЕРСИЯ ОТ 26.08.08 +WADEDITOR.PAS ÂÅÐÑÈß ÎÒ 26.08.08 -Поддержка вадов версии 1 +Ïîääåðæêà âàäîâ âåðñèè 1 ----------------------------------- } diff --git a/src/shared/WADSTRUCT.pas b/src/shared/WADSTRUCT.pas index 9e2fd06..d7d7b06 100644 --- a/src/shared/WADSTRUCT.pas +++ b/src/shared/WADSTRUCT.pas @@ -1,15 +1,13 @@ unit WADSTRUCT; -{$MODE Delphi} - { ----------------------------------- -WADSTRUCT.PAS ВЕРСИЯ ОТ 24.09.06 +WADSTRUCT.PAS ÂÅÐÑÈß ÎÒ 24.09.06 -Поддержка вадов версии 1 +Ïîääåðæêà âàäîâ âåðñèè 1 ----------------------------------- -Структура DFWAD-файла версии 1: +Ñòðóêòóðà DFWAD-ôàéëà âåðñèè 1: ------------------------------------------ SIGNATURE | Byte[5] | 'DFWAD' VERSION | Byte | $01 diff --git a/src/shared/mapstructio.inc b/src/shared/mapstructio.inc new file mode 100644 index 0000000..ae432b9 --- /dev/null +++ b/src/shared/mapstructio.inc @@ -0,0 +1,685 @@ +procedure getBytesAt (var dest; const buf; ofs, len: Integer); +begin + Move((PChar(@buf)+ofs)^, dest, len); +end; + +procedure getWordAt (var dest; const buf; ofs: Integer); +type PWord = ^Word; PByte = ^Byte; +var + p: PByte; + d: PWord; +begin + p := PByte(@buf); Inc(p, ofs); + d := PWord(@dest); + d^ := p^; + Inc(p); + d^ := (d^) or ((p^) shl 8); +end; + +procedure getIntAt (var dest; const buf; ofs: Integer); +type PInt = ^LongWord; PByte = ^Byte; +var + p: PByte; + d: PInt; +begin + p := PByte(@buf); Inc(p, ofs); + d := PInt(@dest); + d^ := p^; + Inc(p); + d^ := (d^) or ((p^) shl 8); + Inc(p); + d^ := (d^) or ((p^) shl 16); + Inc(p); + d^ := (d^) or ((p^) shl 24); +end; + +procedure putBytesAt (var buf; ofs: Integer; const src; len: Integer); +begin + Move(src, (PChar(@buf)+ofs)^, len); +end; + +procedure putWordAt (var buf; ofs: Integer; const src); +type PWord = ^Word; PByte = ^Byte; +var + p: PByte; + d: PWord; +begin + p := PByte(PChar(@buf)+ofs); + d := PWord(@src); + p^ := (d^) and $ff; + Inc(p); + p^ := ((d^) shr 8) and $ff; +end; + +procedure putIntAt (var buf; ofs: Integer; const src); +type PInt = ^LongWord; PByte = ^Byte; +var + p: PByte; + d: PInt; +begin + p := PByte(PChar(@buf)+ofs); + d := PInt(@src); + p^ := (d^) and $ff; + Inc(p); + p^ := ((d^) shr 8) and $ff; + Inc(p); + p^ := ((d^) shr 16) and $ff; + Inc(p); + p^ := ((d^) shr 24) and $ff; +end; + +procedure mb_Read_TriggerData (var tr: TTriggerData; ttype: Integer; const buf; bufsize: Integer); + procedure xreadExit (); + begin + getBytesAt(tr.MapName, buf, 0, 16); + end; + + procedure xreadTeleport (); + begin + getIntAt(tr.TargetPoint.x, buf, 0); + getIntAt(tr.TargetPoint.y, buf, 4); + getBytesAt(tr.d2d_teleport, buf, 8, 1); + getBytesAt(tr.silent_teleport, buf, 9, 1); + getBytesAt(tr.TlpDir, buf, 10, 1); + end; + + procedure xreadOpendoor (); + begin + getIntAt(tr.PanelID, buf, 0); + getBytesAt(tr.NoSound, buf, 4, 1); + getBytesAt(tr.d2d_doors, buf, 5, 1); + end; + + procedure xreadPress (); + begin + getIntAt(tr.tX, buf, 0); + getIntAt(tr.tY, buf, 4); + getWordAt(tr.tWidth, buf, 8); + getWordAt(tr.tHeight, buf, 10); + getWordAt(tr.Wait, buf, 12); + getWordAt(tr.Count, buf, 14); + getIntAt(tr.MonsterID, buf, 16); + getBytesAt(tr.ExtRandom, buf, 20, 1); + end; + + procedure xreadSecret (); + begin + end; + + procedure xreadTexture (); + begin + getBytesAt(tr.ActivateOnce, buf, 0, 1); + getBytesAt(tr.AnimOnce, buf, 1, 1); + end; + + procedure xreadSound (); + begin + getBytesAt(tr.SoundName, buf, 0, 64); + getBytesAt(tr.Volume, buf, 64, 1); + getBytesAt(tr.Pan, buf, 65, 1); + getBytesAt(tr.Local, buf, 66, 1); + getBytesAt(tr.PlayCount, buf, 67, 1); + getBytesAt(tr.SoundSwitch, buf, 68, 1); + end; + + procedure xreadSpawnmonster (); + begin + getIntAt(tr.MonPos.x, buf, 0); + getIntAt(tr.MonPos.y, buf, 4); + getBytesAt(tr.MonType, buf, 8, 1); + getIntAt(tr.MonHealth, buf, 12); + getBytesAt(tr.MonDir, buf, 16, 1); + getBytesAt(tr.MonActive, buf, 17, 1); + getIntAt(tr.MonCount, buf, 20); + getBytesAt(tr.MonEffect, buf, 24, 1); + getWordAt(tr.MonMax, buf, 26); + getWordAt(tr.MonDelay, buf, 28); + getBytesAt(tr.MonBehav, buf, 30, 1); + end; + + procedure xreadSpawnitem (); + begin + getIntAt(tr.ItemPos.x, buf, 0); + getIntAt(tr.ItemPos.y, buf, 4); + getBytesAt(tr.ItemType, buf, 8, 1); + getBytesAt(tr.ItemFalls, buf, 9, 1); + getBytesAt(tr.ItemOnlyDM, buf, 10, 1); + getIntAt(tr.ItemCount, buf, 12); + getBytesAt(tr.ItemEffect, buf, 16, 1); + getWordAt(tr.ItemMax, buf, 18); + getWordAt(tr.ItemDelay, buf, 20); + end; + + procedure xreadMusic (); + begin + getBytesAt(tr.MusicName, buf, 0, 64); + getBytesAt(tr.MusicAction, buf, 64, 1); + end; + + procedure xreadPush (); + begin + getWordAt(tr.PushAngle, buf, 0); + getBytesAt(tr.PushForce, buf, 2, 1); + getBytesAt(tr.ResetVel, buf, 3, 1); + end; + + procedure xreadScore (); + begin + getBytesAt(tr.ScoreAction, buf, 0, 1); + getBytesAt(tr.ScoreCount, buf, 1, 1); + getBytesAt(tr.ScoreTeam, buf, 2, 1); + getBytesAt(tr.ScoreCon, buf, 3, 1); + getBytesAt(tr.ScoreMsg, buf, 4, 1); + end; + + procedure xreadMessage (); + begin + getBytesAt(tr.MessageKind, buf, 0, 1); + getBytesAt(tr.MessageSendTo, buf, 1, 1); + getBytesAt(tr.MessageText, buf, 2, 100); + getWordAt(tr.MessageTime, buf, 102); + end; + + procedure xreadDamage (); + begin + getWordAt(tr.DamageValue, buf, 0); + getWordAt(tr.DamageInterval, buf, 2); + end; + + procedure xreadHealth (); + begin + getWordAt(tr.HealValue, buf, 0); + getWordAt(tr.HealInterval, buf, 2); + getBytesAt(tr.HealMax, buf, 4, 1); + getBytesAt(tr.HealSilent, buf, 5, 1); + end; + + procedure xreadShot (); + begin + getIntAt(tr.ShotPos.x, buf, 0); + getIntAt(tr.ShotPos.y, buf, 4); + getBytesAt(tr.ShotType, buf, 8, 1); + getBytesAt(tr.ShotTarget, buf, 9, 1); + getBytesAt(tr.ShotSound, buf, 10, 1); + getBytesAt(tr.ShotAllMap, buf, 11, 1); + getIntAt(tr.ShotPanelID, buf, 12); + getWordAt(tr.ShotIntSight, buf, 16); + getWordAt(tr.ShotAngle, buf, 18); + getWordAt(tr.ShotWait, buf, 20); + getWordAt(tr.ShotAccuracy, buf, 22); + getWordAt(tr.ShotAmmo, buf, 24); + getWordAt(tr.ShotIntReload, buf, 26); + end; + + procedure xreadEffect (); + begin + getBytesAt(tr.FXCount, buf, 0, 1); + getBytesAt(tr.FXType, buf, 1, 1); + getBytesAt(tr.FXSubType, buf, 2, 1); + getBytesAt(tr.FXColorR, buf, 3, 1); + getBytesAt(tr.FXColorG, buf, 4, 1); + getBytesAt(tr.FXColorB, buf, 5, 1); + getBytesAt(tr.FXPos, buf, 6, 1); + getWordAt(tr.FXWait, buf, 8); + getBytesAt(tr.FXVelX, buf, 10, 1); + getBytesAt(tr.FXVelY, buf, 11, 1); + getBytesAt(tr.FXSpreadL, buf, 12, 1); + getBytesAt(tr.FXSpreadR, buf, 13, 1); + getBytesAt(tr.FXSpreadU, buf, 14, 1); + getBytesAt(tr.FXSpreadD, buf, 15, 1); + end; + + procedure xreadScript (); + begin + getBytesAt(tr.SCRProc, buf, 0, 64); + getIntAt(tr.SCRArg, buf, 64); + end; + +begin + if (bufsize < 104) then raise Exception.Create('invalid buffer size in mb_Read_TriggerData'); + if (ttype = TRIGGER_EXIT) then begin xreadExit(); exit; end; + if (ttype = TRIGGER_TELEPORT) then begin xreadTeleport(); exit; end; + if (ttype = TRIGGER_OPENDOOR) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_CLOSEDOOR) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_DOOR) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_DOOR5) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_CLOSETRAP) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_TRAP) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_LIFTUP) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_LIFTDOWN) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_LIFT) then begin xreadOpendoor(); exit; end; + if (ttype = TRIGGER_PRESS) then begin xreadPress(); exit; end; + if (ttype = TRIGGER_ON) then begin xreadPress(); exit; end; + if (ttype = TRIGGER_OFF) then begin xreadPress(); exit; end; + if (ttype = TRIGGER_ONOFF) then begin xreadPress(); exit; end; + if (ttype = TRIGGER_SECRET) then begin xreadSecret(); exit; end; + if (ttype = TRIGGER_TEXTURE) then begin xreadTexture(); exit; end; + if (ttype = TRIGGER_SOUND) then begin xreadSound(); exit; end; + if (ttype = TRIGGER_SPAWNMONSTER) then begin xreadSpawnmonster(); exit; end; + if (ttype = TRIGGER_SPAWNITEM) then begin xreadSpawnitem(); exit; end; + if (ttype = TRIGGER_MUSIC) then begin xreadMusic(); exit; end; + if (ttype = TRIGGER_PUSH) then begin xreadPush(); exit; end; + if (ttype = TRIGGER_SCORE) then begin xreadScore(); exit; end; + if (ttype = TRIGGER_MESSAGE) then begin xreadMessage(); exit; end; + if (ttype = TRIGGER_DAMAGE) then begin xreadDamage(); exit; end; + if (ttype = TRIGGER_HEALTH) then begin xreadHealth(); exit; end; + if (ttype = TRIGGER_SHOT) then begin xreadShot(); exit; end; + if (ttype = TRIGGER_EFFECT) then begin xreadEffect(); exit; end; + if (ttype = TRIGGER_SCRIPT) then begin xreadScript(); exit; end; + raise Exception.Create('invalid trigger type in mb_Read_TriggerData'); +end; + + +procedure mb_Read_TMapHeaderRec_1 (var tr: TMapHeaderRec_1; const buf; bufsize: Integer); + procedure xreadTmapheaderrec_1 (); + begin + getBytesAt(tr.MapName, buf, 0, 32); + getBytesAt(tr.MapAuthor, buf, 32, 32); + getBytesAt(tr.MapDescription, buf, 64, 256); + getBytesAt(tr.MusicName, buf, 320, 64); + getBytesAt(tr.SkyName, buf, 384, 64); + getWordAt(tr.Width, buf, 448); + getWordAt(tr.Height, buf, 450); + end; + +begin + if (bufsize < 452) then raise Exception.Create('invalid buffer size in readTMapHeaderRec_1'); + xreadTmapheaderrec_1(); +end; + +procedure mb_Read_TTextureRec_1 (var tr: TTextureRec_1; const buf; bufsize: Integer); + procedure xreadTtexturerec_1 (); + begin + getBytesAt(tr.Resource, buf, 0, 64); + getBytesAt(tr.Anim, buf, 64, 1); + end; + +begin + if (bufsize < 65) then raise Exception.Create('invalid buffer size in readTTextureRec_1'); + xreadTtexturerec_1(); +end; + +procedure mb_Read_TPanelRec_1 (var tr: TPanelRec_1; const buf; bufsize: Integer); + procedure xreadTpanelrec_1 (); + begin + getIntAt(tr.X, buf, 0); + getIntAt(tr.Y, buf, 4); + getWordAt(tr.Width, buf, 8); + getWordAt(tr.Height, buf, 10); + getWordAt(tr.TextureNum, buf, 12); + getWordAt(tr.PanelType, buf, 14); + getBytesAt(tr.Alpha, buf, 16, 1); + getBytesAt(tr.Flags, buf, 17, 1); + end; + +begin + if (bufsize < 18) then raise Exception.Create('invalid buffer size in readTPanelRec_1'); + xreadTpanelrec_1(); +end; + +procedure mb_Read_TItemRec_1 (var tr: TItemRec_1; const buf; bufsize: Integer); + procedure xreadTitemrec_1 (); + begin + getIntAt(tr.X, buf, 0); + getIntAt(tr.Y, buf, 4); + getBytesAt(tr.ItemType, buf, 8, 1); + getBytesAt(tr.Options, buf, 9, 1); + end; + +begin + if (bufsize < 10) then raise Exception.Create('invalid buffer size in readTItemRec_1'); + xreadTitemrec_1(); +end; + +procedure mb_Read_TMonsterRec_1 (var tr: TMonsterRec_1; const buf; bufsize: Integer); + procedure xreadTmonsterrec_1 (); + begin + getIntAt(tr.X, buf, 0); + getIntAt(tr.Y, buf, 4); + getBytesAt(tr.MonsterType, buf, 8, 1); + getBytesAt(tr.Direction, buf, 9, 1); + end; + +begin + if (bufsize < 10) then raise Exception.Create('invalid buffer size in readTMonsterRec_1'); + xreadTmonsterrec_1(); +end; + +procedure mb_Read_TAreaRec_1 (var tr: TAreaRec_1; const buf; bufsize: Integer); + procedure xreadTarearec_1 (); + begin + getIntAt(tr.X, buf, 0); + getIntAt(tr.Y, buf, 4); + getBytesAt(tr.AreaType, buf, 8, 1); + getBytesAt(tr.Direction, buf, 9, 1); + end; + +begin + if (bufsize < 10) then raise Exception.Create('invalid buffer size in readTAreaRec_1'); + xreadTarearec_1(); +end; + +procedure mb_Read_TTriggerRec_1 (var tr: TTriggerRec_1; const buf; bufsize: Integer); + procedure xreadTtriggerrec_1 (); + begin + getIntAt(tr.X, buf, 0); + getIntAt(tr.Y, buf, 4); + getWordAt(tr.Width, buf, 8); + getWordAt(tr.Height, buf, 10); + getBytesAt(tr.Enabled, buf, 12, 1); + getIntAt(tr.TexturePanel, buf, 13); + getBytesAt(tr.TriggerType, buf, 17, 1); + getBytesAt(tr.ActivateType, buf, 18, 1); + getBytesAt(tr.Keys, buf, 19, 1); + getBytesAt(tr.DATA, buf, 20, 128); + end; + +begin + if (bufsize < 148) then raise Exception.Create('invalid buffer size in readTTriggerRec_1'); + xreadTtriggerrec_1(); +end; + +procedure mb_Write_TriggerData (var buf; bufsize: Integer; ttype: Integer; var tr: TTriggerData); + procedure xwriteExit (); + begin + putBytesAt(buf, 0, tr.MapName, 16); + end; + + procedure xwriteTeleport (); + begin + putIntAt(buf, 0, tr.TargetPoint.x); + putIntAt(buf, 4, tr.TargetPoint.y); + putBytesAt(buf, 8, tr.d2d_teleport, 1); + putBytesAt(buf, 9, tr.silent_teleport, 1); + putBytesAt(buf, 10, tr.TlpDir, 1); + end; + + procedure xwriteOpendoor (); + begin + putIntAt(buf, 0, tr.PanelID); + putBytesAt(buf, 4, tr.NoSound, 1); + putBytesAt(buf, 5, tr.d2d_doors, 1); + end; + + procedure xwritePress (); + begin + putIntAt(buf, 0, tr.tX); + putIntAt(buf, 4, tr.tY); + putWordAt(buf, 8, tr.tWidth); + putWordAt(buf, 10, tr.tHeight); + putWordAt(buf, 12, tr.Wait); + putWordAt(buf, 14, tr.Count); + putIntAt(buf, 16, tr.MonsterID); + putBytesAt(buf, 20, tr.ExtRandom, 1); + end; + + procedure xwriteSecret (); + begin + end; + + procedure xwriteTexture (); + begin + putBytesAt(buf, 0, tr.ActivateOnce, 1); + putBytesAt(buf, 1, tr.AnimOnce, 1); + end; + + procedure xwriteSound (); + begin + putBytesAt(buf, 0, tr.SoundName, 64); + putBytesAt(buf, 64, tr.Volume, 1); + putBytesAt(buf, 65, tr.Pan, 1); + putBytesAt(buf, 66, tr.Local, 1); + putBytesAt(buf, 67, tr.PlayCount, 1); + putBytesAt(buf, 68, tr.SoundSwitch, 1); + end; + + procedure xwriteSpawnmonster (); + begin + putIntAt(buf, 0, tr.MonPos.x); + putIntAt(buf, 4, tr.MonPos.y); + putBytesAt(buf, 8, tr.MonType, 1); + putIntAt(buf, 12, tr.MonHealth); + putBytesAt(buf, 16, tr.MonDir, 1); + putBytesAt(buf, 17, tr.MonActive, 1); + putIntAt(buf, 20, tr.MonCount); + putBytesAt(buf, 24, tr.MonEffect, 1); + putWordAt(buf, 26, tr.MonMax); + putWordAt(buf, 28, tr.MonDelay); + putBytesAt(buf, 30, tr.MonBehav, 1); + end; + + procedure xwriteSpawnitem (); + begin + putIntAt(buf, 0, tr.ItemPos.x); + putIntAt(buf, 4, tr.ItemPos.y); + putBytesAt(buf, 8, tr.ItemType, 1); + putBytesAt(buf, 9, tr.ItemFalls, 1); + putBytesAt(buf, 10, tr.ItemOnlyDM, 1); + putIntAt(buf, 12, tr.ItemCount); + putBytesAt(buf, 16, tr.ItemEffect, 1); + putWordAt(buf, 18, tr.ItemMax); + putWordAt(buf, 20, tr.ItemDelay); + end; + + procedure xwriteMusic (); + begin + putBytesAt(buf, 0, tr.MusicName, 64); + putBytesAt(buf, 64, tr.MusicAction, 1); + end; + + procedure xwritePush (); + begin + putWordAt(buf, 0, tr.PushAngle); + putBytesAt(buf, 2, tr.PushForce, 1); + putBytesAt(buf, 3, tr.ResetVel, 1); + end; + + procedure xwriteScore (); + begin + putBytesAt(buf, 0, tr.ScoreAction, 1); + putBytesAt(buf, 1, tr.ScoreCount, 1); + putBytesAt(buf, 2, tr.ScoreTeam, 1); + putBytesAt(buf, 3, tr.ScoreCon, 1); + putBytesAt(buf, 4, tr.ScoreMsg, 1); + end; + + procedure xwriteMessage (); + begin + putBytesAt(buf, 0, tr.MessageKind, 1); + putBytesAt(buf, 1, tr.MessageSendTo, 1); + putBytesAt(buf, 2, tr.MessageText, 100); + putWordAt(buf, 102, tr.MessageTime); + end; + + procedure xwriteDamage (); + begin + putWordAt(buf, 0, tr.DamageValue); + putWordAt(buf, 2, tr.DamageInterval); + end; + + procedure xwriteHealth (); + begin + putWordAt(buf, 0, tr.HealValue); + putWordAt(buf, 2, tr.HealInterval); + putBytesAt(buf, 4, tr.HealMax, 1); + putBytesAt(buf, 5, tr.HealSilent, 1); + end; + + procedure xwriteShot (); + begin + putIntAt(buf, 0, tr.ShotPos.x); + putIntAt(buf, 4, tr.ShotPos.y); + putBytesAt(buf, 8, tr.ShotType, 1); + putBytesAt(buf, 9, tr.ShotTarget, 1); + putBytesAt(buf, 10, tr.ShotSound, 1); + putBytesAt(buf, 11, tr.ShotAllMap, 1); + putIntAt(buf, 12, tr.ShotPanelID); + putWordAt(buf, 16, tr.ShotIntSight); + putWordAt(buf, 18, tr.ShotAngle); + putWordAt(buf, 20, tr.ShotWait); + putWordAt(buf, 22, tr.ShotAccuracy); + putWordAt(buf, 24, tr.ShotAmmo); + putWordAt(buf, 26, tr.ShotIntReload); + end; + + procedure xwriteEffect (); + begin + putBytesAt(buf, 0, tr.FXCount, 1); + putBytesAt(buf, 1, tr.FXType, 1); + putBytesAt(buf, 2, tr.FXSubType, 1); + putBytesAt(buf, 3, tr.FXColorR, 1); + putBytesAt(buf, 4, tr.FXColorG, 1); + putBytesAt(buf, 5, tr.FXColorB, 1); + putBytesAt(buf, 6, tr.FXPos, 1); + putWordAt(buf, 8, tr.FXWait); + putBytesAt(buf, 10, tr.FXVelX, 1); + putBytesAt(buf, 11, tr.FXVelY, 1); + putBytesAt(buf, 12, tr.FXSpreadL, 1); + putBytesAt(buf, 13, tr.FXSpreadR, 1); + putBytesAt(buf, 14, tr.FXSpreadU, 1); + putBytesAt(buf, 15, tr.FXSpreadD, 1); + end; + +begin + if (bufsize < 104) then raise Exception.Create('invalid buffer size in mb_Write_TriggerData'); + if (ttype = TRIGGER_EXIT) then begin xwriteExit(); exit; end; + if (ttype = TRIGGER_TELEPORT) then begin xwriteTeleport(); exit; end; + if (ttype = TRIGGER_OPENDOOR) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_CLOSEDOOR) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_DOOR) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_DOOR5) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_CLOSETRAP) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_TRAP) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_LIFTUP) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_LIFTDOWN) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_LIFT) then begin xwriteOpendoor(); exit; end; + if (ttype = TRIGGER_PRESS) then begin xwritePress(); exit; end; + if (ttype = TRIGGER_ON) then begin xwritePress(); exit; end; + if (ttype = TRIGGER_OFF) then begin xwritePress(); exit; end; + if (ttype = TRIGGER_ONOFF) then begin xwritePress(); exit; end; + if (ttype = TRIGGER_SECRET) then begin xwriteSecret(); exit; end; + if (ttype = TRIGGER_TEXTURE) then begin xwriteTexture(); exit; end; + if (ttype = TRIGGER_SOUND) then begin xwriteSound(); exit; end; + if (ttype = TRIGGER_SPAWNMONSTER) then begin xwriteSpawnmonster(); exit; end; + if (ttype = TRIGGER_SPAWNITEM) then begin xwriteSpawnitem(); exit; end; + if (ttype = TRIGGER_MUSIC) then begin xwriteMusic(); exit; end; + if (ttype = TRIGGER_PUSH) then begin xwritePush(); exit; end; + if (ttype = TRIGGER_SCORE) then begin xwriteScore(); exit; end; + if (ttype = TRIGGER_MESSAGE) then begin xwriteMessage(); exit; end; + if (ttype = TRIGGER_DAMAGE) then begin xwriteDamage(); exit; end; + if (ttype = TRIGGER_HEALTH) then begin xwriteHealth(); exit; end; + if (ttype = TRIGGER_SHOT) then begin xwriteShot(); exit; end; + if (ttype = TRIGGER_EFFECT) then begin xwriteEffect(); exit; end; + raise Exception.Create('invalid trigger type in mb_Write_TriggerData'); +end; + + +procedure mb_Write_TMapHeaderRec_1 (var buf; bufsize: Integer; var tr: TMapHeaderRec_1); + procedure xwriteTmapheaderrec_1 (); + begin + putBytesAt(buf, 0, tr.MapName, 32); + putBytesAt(buf, 32, tr.MapAuthor, 32); + putBytesAt(buf, 64, tr.MapDescription, 256); + putBytesAt(buf, 320, tr.MusicName, 64); + putBytesAt(buf, 384, tr.SkyName, 64); + putWordAt(buf, 448, tr.Width); + putWordAt(buf, 450, tr.Height); + end; + +begin + if (bufsize < 452) then raise Exception.Create('invalid buffer size in writeTMapHeaderRec_1'); + xwriteTmapheaderrec_1(); +end; + +procedure mb_Write_TTextureRec_1 (var buf; bufsize: Integer; var tr: TTextureRec_1); + procedure xwriteTtexturerec_1 (); + begin + putBytesAt(buf, 0, tr.Resource, 64); + putBytesAt(buf, 64, tr.Anim, 1); + end; + +begin + if (bufsize < 65) then raise Exception.Create('invalid buffer size in writeTTextureRec_1'); + xwriteTtexturerec_1(); +end; + +procedure mb_Write_TPanelRec_1 (var buf; bufsize: Integer; var tr: TPanelRec_1); + procedure xwriteTpanelrec_1 (); + begin + putIntAt(buf, 0, tr.X); + putIntAt(buf, 4, tr.Y); + putWordAt(buf, 8, tr.Width); + putWordAt(buf, 10, tr.Height); + putWordAt(buf, 12, tr.TextureNum); + putWordAt(buf, 14, tr.PanelType); + putBytesAt(buf, 16, tr.Alpha, 1); + putBytesAt(buf, 17, tr.Flags, 1); + end; + +begin + if (bufsize < 18) then raise Exception.Create('invalid buffer size in writeTPanelRec_1'); + xwriteTpanelrec_1(); +end; + +procedure mb_Write_TItemRec_1 (var buf; bufsize: Integer; var tr: TItemRec_1); + procedure xwriteTitemrec_1 (); + begin + putIntAt(buf, 0, tr.X); + putIntAt(buf, 4, tr.Y); + putBytesAt(buf, 8, tr.ItemType, 1); + putBytesAt(buf, 9, tr.Options, 1); + end; + +begin + if (bufsize < 10) then raise Exception.Create('invalid buffer size in writeTItemRec_1'); + xwriteTitemrec_1(); +end; + +procedure mb_Write_TMonsterRec_1 (var buf; bufsize: Integer; var tr: TMonsterRec_1); + procedure xwriteTmonsterrec_1 (); + begin + putIntAt(buf, 0, tr.X); + putIntAt(buf, 4, tr.Y); + putBytesAt(buf, 8, tr.MonsterType, 1); + putBytesAt(buf, 9, tr.Direction, 1); + end; + +begin + if (bufsize < 10) then raise Exception.Create('invalid buffer size in writeTMonsterRec_1'); + xwriteTmonsterrec_1(); +end; + +procedure mb_Write_TAreaRec_1 (var buf; bufsize: Integer; var tr: TAreaRec_1); + procedure xwriteTarearec_1 (); + begin + putIntAt(buf, 0, tr.X); + putIntAt(buf, 4, tr.Y); + putBytesAt(buf, 8, tr.AreaType, 1); + putBytesAt(buf, 9, tr.Direction, 1); + end; + +begin + if (bufsize < 10) then raise Exception.Create('invalid buffer size in writeTAreaRec_1'); + xwriteTarearec_1(); +end; + +procedure mb_Write_TTriggerRec_1 (var buf; bufsize: Integer; var tr: TTriggerRec_1); + procedure xwriteTtriggerrec_1 (); + begin + putIntAt(buf, 0, tr.X); + putIntAt(buf, 4, tr.Y); + putWordAt(buf, 8, tr.Width); + putWordAt(buf, 10, tr.Height); + putBytesAt(buf, 12, tr.Enabled, 1); + putIntAt(buf, 13, tr.TexturePanel); + putBytesAt(buf, 17, tr.TriggerType, 1); + putBytesAt(buf, 18, tr.ActivateType, 1); + putBytesAt(buf, 19, tr.Keys, 1); + putBytesAt(buf, 20, tr.DATA, 128); + end; + +begin + if (bufsize < 148) then raise Exception.Create('invalid buffer size in writeTTriggerRec_1'); + xwriteTtriggerrec_1(); +end; + diff --git a/src/shared/mapstructsizes.inc b/src/shared/mapstructsizes.inc new file mode 100644 index 0000000..e793c06 --- /dev/null +++ b/src/shared/mapstructsizes.inc @@ -0,0 +1,25 @@ +const + SizeOf_TMapHeaderRec_1 = 452; + SizeOf_TTextureRec_1 = 65; + SizeOf_TPanelRec_1 = 18; + SizeOf_TItemRec_1 = 10; + SizeOf_TMonsterRec_1 = 10; + SizeOf_TAreaRec_1 = 10; + SizeOf_TTriggerRec_1 = 148; + +procedure mb_Read_TriggerData (var tr: TTriggerData; ttype: Integer; const buf; bufsize: Integer); +procedure mb_Write_TriggerData (var buf; bufsize: Integer; ttype: Integer; var tr: TTriggerData); +procedure mb_Read_TMapHeaderRec_1 (var tr: TMapHeaderRec_1; const buf; bufsize: Integer); +procedure mb_Write_TMapHeaderRec_1 (var buf; bufsize: Integer; var tr: TMapHeaderRec_1); +procedure mb_Read_TTextureRec_1 (var tr: TTextureRec_1; const buf; bufsize: Integer); +procedure mb_Write_TTextureRec_1 (var buf; bufsize: Integer; var tr: TTextureRec_1); +procedure mb_Read_TPanelRec_1 (var tr: TPanelRec_1; const buf; bufsize: Integer); +procedure mb_Write_TPanelRec_1 (var buf; bufsize: Integer; var tr: TPanelRec_1); +procedure mb_Read_TItemRec_1 (var tr: TItemRec_1; const buf; bufsize: Integer); +procedure mb_Write_TItemRec_1 (var buf; bufsize: Integer; var tr: TItemRec_1); +procedure mb_Read_TMonsterRec_1 (var tr: TMonsterRec_1; const buf; bufsize: Integer); +procedure mb_Write_TMonsterRec_1 (var buf; bufsize: Integer; var tr: TMonsterRec_1); +procedure mb_Read_TAreaRec_1 (var tr: TAreaRec_1; const buf; bufsize: Integer); +procedure mb_Write_TAreaRec_1 (var buf; bufsize: Integer; var tr: TAreaRec_1); +procedure mb_Read_TTriggerRec_1 (var tr: TTriggerRec_1; const buf; bufsize: Integer); +procedure mb_Write_TTriggerRec_1 (var buf; bufsize: Integer; var tr: TTriggerRec_1); diff --git a/src/shared/utils.pas b/src/shared/utils.pas new file mode 100644 index 0000000..253e838 --- /dev/null +++ b/src/shared/utils.pas @@ -0,0 +1,527 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$MODE DELPHI} +unit utils; + +interface + +uses + SysUtils, Classes; + + +// does filename have one of ".wad", ".pk3", ".zip" extensions? +function hasWadExtension (fn: AnsiString): Boolean; + +// does filepath have ".XXX:\" in it? +function isWadPath (fn: AnsiString): Boolean; + +// adds ".wad" extension if filename doesn't have one of ".wad", ".pk3", ".zip" +function addWadExtension (fn: AnsiString): AnsiString; + +// convert number to strig with nice commas +function Int64ToStrComma (i: Int64): AnsiString; + +function UpCase1251 (ch: Char): Char; +function LoCase1251 (ch: Char): Char; + +// `true` if strings are equal; ignoring case for cp1251 +function StrEquCI1251 (const s0, s1: AnsiString): Boolean; + +function utf8Valid (const s: AnsiString): Boolean; + +function utf8to1251 (s: AnsiString): AnsiString; + +// `pathname` will be modified if path is valid +// `lastIsDir` should be `true` if we are searching for directory +// nobody cares about shitdoze, so i'll use the same code path for it +function findFileCI (var pathname: AnsiString; lastIsDir: Boolean=false): Boolean; + +// they throws +function openDiskFileRO (pathname: AnsiString): TStream; +function createDiskFile (pathname: AnsiString): TStream; + +// little endian +procedure writeInt (st: TStream; v: Byte); overload; +procedure writeInt (st: TStream; v: ShortInt); overload; +procedure writeInt (st: TStream; v: Word); overload; +procedure writeInt (st: TStream; v: SmallInt); overload; +procedure writeInt (st: TStream; v: LongWord); overload; +procedure writeInt (st: TStream; v: LongInt); overload; +procedure writeInt (st: TStream; v: Int64); overload; +procedure writeInt (st: TStream; v: UInt64); overload; + +function readByte (st: TStream): Byte; +function readShortInt (st: TStream): ShortInt; +function readWord (st: TStream): Word; +function readSmallInt (st: TStream): SmallInt; +function readLongWord (st: TStream): LongWord; +function readLongInt (st: TStream): LongInt; +function readInt64 (st: TStream): Int64; +function readUInt64 (st: TStream): UInt64; + +// big endian +procedure writeIntBE (st: TStream; v: Byte); overload; +procedure writeIntBE (st: TStream; v: ShortInt); overload; +procedure writeIntBE (st: TStream; v: Word); overload; +procedure writeIntBE (st: TStream; v: SmallInt); overload; +procedure writeIntBE (st: TStream; v: LongWord); overload; +procedure writeIntBE (st: TStream; v: LongInt); overload; +procedure writeIntBE (st: TStream; v: Int64); overload; +procedure writeIntBE (st: TStream; v: UInt64); overload; + +function readByteBE (st: TStream): Byte; +function readShortIntBE (st: TStream): ShortInt; +function readWordBE (st: TStream): Word; +function readSmallIntBE (st: TStream): SmallInt; +function readLongWordBE (st: TStream): LongWord; +function readLongIntBE (st: TStream): LongInt; +function readInt64BE (st: TStream): Int64; +function readUInt64BE (st: TStream): UInt64; + + +implementation + + +function hasWadExtension (fn: AnsiString): Boolean; +begin + fn := ExtractFileExt(fn); + result := StrEquCI1251(fn, '.wad') or StrEquCI1251(fn, '.pk3') or StrEquCI1251(fn, '.zip'); +end; + + +function addWadExtension (fn: AnsiString): AnsiString; +begin + result := fn; + if not hasWadExtension(result) then result := result+'.wad'; +end; + + +function isWadPath (fn: AnsiString): Boolean; +var + p: Integer; + s: AnsiString; +begin + result := false; + while true do + begin + p := Pos(':', fn); + if (p = 0) or (length(fn)-p < 1) then break; + if (p-4 > 1) and (fn[p-4] = '.') and ((fn[p+1] = '\') or (fn[p+1] = '/')) then + begin + s := Copy(fn, p-4, 4); + if StrEquCI1251(s, '.wad') or StrEquCI1251(s, '.pk3') or StrEquCI1251(s, '.zip') then + begin + result := true; + exit; + end; + end; + Delete(fn, 1, p); + end; +end; + + +function Int64ToStrComma (i: Int64): AnsiString; +var + f: Integer; +begin + Str(i, result); + f := Length(result)+1; + while f > 4 do + begin + Dec(f, 3); Insert(',', result, f); + end; +end; + + +function UpCase1251 (ch: Char): Char; +begin + if ch < #128 then + begin + if (ch >= 'a') and (ch <= 'z') then Dec(ch, 32); + end + else + begin + if (ch >= #224) and (ch <= #255) then + begin + Dec(ch, 32); + end + else + begin + case ch of + #184, #186, #191: Dec(ch, 16); + #162, #179: Dec(ch); + end; + end; + end; + result := ch; +end; + + +function LoCase1251 (ch: Char): Char; +begin + if ch < #128 then + begin + if (ch >= 'A') and (ch <= 'Z') then Inc(ch, 32); + end + else + begin + if (ch >= #192) and (ch <= #223) then + begin + Inc(ch, 32); + end + else + begin + case ch of + #168, #170, #175: Inc(ch, 16); + #161, #178: Inc(ch); + end; + end; + end; + result := ch; +end; + + +function StrEquCI1251 (const s0, s1: AnsiString): Boolean; +var + i: Integer; +begin + result := false; + if length(s0) <> length(s1) then exit; + for i := 1 to length(s0) do if UpCase1251(s0[i]) <> UpCase1251(s1[i]) then exit; + result := true; +end; + + +// ////////////////////////////////////////////////////////////////////////// // +// utils +// `ch`: utf8 start +// -1: invalid utf8 +function utf8CodeLen (ch: Word): Integer; +begin + if ch < $80 then begin result := 1; exit; end; + if (ch and $FE) = $FC then begin result := 6; exit; end; + if (ch and $FC) = $F8 then begin result := 5; exit; end; + if (ch and $F8) = $F0 then begin result := 4; exit; end; + if (ch and $F0) = $E0 then begin result := 3; exit; end; + if (ch and $E0) = $C0 then begin result := 2; exit; end; + result := -1; // invalid +end; + + +function utf8Valid (const s: AnsiString): Boolean; +var + pos, len: Integer; +begin + result := false; + pos := 1; + while pos <= length(s) do + begin + len := utf8CodeLen(Byte(s[pos])); + if len < 1 then exit; // invalid sequence start + if pos+len-1 > length(s) then exit; // out of chars in string + Dec(len); + Inc(pos); + // check other sequence bytes + while len > 0 do + begin + if (Byte(s[pos]) and $C0) <> $80 then exit; + Dec(len); + Inc(pos); + end; + end; + result := true; +end; + + +// ////////////////////////////////////////////////////////////////////////// // +const + uni2wint: array [128..255] of Word = ( + $0402,$0403,$201A,$0453,$201E,$2026,$2020,$2021,$20AC,$2030,$0409,$2039,$040A,$040C,$040B,$040F, + $0452,$2018,$2019,$201C,$201D,$2022,$2013,$2014,$003F,$2122,$0459,$203A,$045A,$045C,$045B,$045F, + $00A0,$040E,$045E,$0408,$00A4,$0490,$00A6,$00A7,$0401,$00A9,$0404,$00AB,$00AC,$00AD,$00AE,$0407, + $00B0,$00B1,$0406,$0456,$0491,$00B5,$00B6,$00B7,$0451,$2116,$0454,$00BB,$0458,$0405,$0455,$0457, + $0410,$0411,$0412,$0413,$0414,$0415,$0416,$0417,$0418,$0419,$041A,$041B,$041C,$041D,$041E,$041F, + $0420,$0421,$0422,$0423,$0424,$0425,$0426,$0427,$0428,$0429,$042A,$042B,$042C,$042D,$042E,$042F, + $0430,$0431,$0432,$0433,$0434,$0435,$0436,$0437,$0438,$0439,$043A,$043B,$043C,$043D,$043E,$043F, + $0440,$0441,$0442,$0443,$0444,$0445,$0446,$0447,$0448,$0449,$044A,$044B,$044C,$044D,$044E,$044F + ); + + +function decodeUtf8Char (s: AnsiString; var pos: Integer): char; +var + b, c: Integer; +begin + (* The following encodings are valid, except for the 5 and 6 byte + * combinations: + * 0xxxxxxx + * 110xxxxx 10xxxxxx + * 1110xxxx 10xxxxxx 10xxxxxx + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + *) + result := '?'; + if pos > length(s) then exit; + + b := Byte(s[pos]); + Inc(pos); + if b < $80 then begin result := char(b); exit; end; + + // mask out unused bits + if (b and $FE) = $FC then b := b and $01 + else if (b and $FC) = $F8 then b := b and $03 + else if (b and $F8) = $F0 then b := b and $07 + else if (b and $F0) = $E0 then b := b and $0F + else if (b and $E0) = $C0 then b := b and $1F + else exit; // invalid utf8 + + // now continue + while pos <= length(s) do + begin + c := Byte(s[pos]); + if (c and $C0) <> $80 then break; // no more + b := b shl 6; + b := b or (c and $3F); + Inc(pos); + end; + + // done, try 1251 + for c := 128 to 255 do if uni2wint[c] = b then begin result := char(c and $FF); exit; end; + // alas +end; + + +function utf8to1251 (s: AnsiString): AnsiString; +var + pos: Integer; +begin + if not utf8Valid(s) then begin result := s; exit; end; + pos := 1; + while pos <= length(s) do + begin + if Byte(s[pos]) >= $80 then break; + Inc(pos); + end; + if pos > length(s) then begin result := s; exit; end; // nothing to do here + result := ''; + pos := 1; + while pos <= length(s) do result := result+decodeUtf8Char(s, pos); +end; + + +// ////////////////////////////////////////////////////////////////////////// // +// `pathname` will be modified if path is valid +// `lastIsDir` should be `true` if we are searching for directory +// nobody cares about shitdoze, so i'll use the same code path for it +function findFileCI (var pathname: AnsiString; lastIsDir: Boolean=false): Boolean; +var + sr: TSearchRec; + npt: AnsiString; + newname: AnsiString = ''; + curname: AnsiString; + wantdir: Boolean; + attr: LongInt; + foundher: Boolean; +begin + npt := pathname; + result := (length(npt) > 0); + if (length(npt) > 0) and ((npt[1] = '/') or (npt[1] = '\')) then newname := '/'; + while length(npt) > 0 do + begin + // remove trailing slashes + while (length(npt) > 0) and ((npt[1] = '/') or (npt[1] = '\')) do Delete(npt, 1, 1); + if length(npt) = 0 then break; + // extract name + curname := ''; + while (length(npt) > 0) and (npt[1] <> '/') and (npt[1] <> '\') do + begin + curname := curname+npt[1]; + Delete(npt, 1, 1); + end; + // remove trailing slashes again + while (length(npt) > 0) and ((npt[1] = '/') or (npt[1] = '\')) do Delete(npt, 1, 1); + wantdir := lastIsDir or (length(npt) > 0); // do we want directory here? + //writeln(Format('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)])); + // try the easiest case first + attr := FileGetAttr(newname+curname); + if attr <> -1 then + begin + if wantdir = ((attr and faDirectory) <> 0) then + begin + // i found her! + newname := newname+curname; + if wantdir then newname := newname+'/'; + continue; + end; + end; + //writeln(Format('npt=[%s]; newname=[%s]; curname=[%s]; wantdir=%d', [npt, newname, curname, Integer(wantdir)])); + // alas, either not found, or invalid attributes + foundher := false; + try + if FindFirst(newname+'*', faAnyFile, sr) = 0 then + repeat + if (wantdir = ((sr.attr and faDirectory) <> 0)) and StrEquCI1251(sr.name, curname) then + begin + // i found her! + newname := newname+sr.name; + if wantdir then newname := newname+'/'; + foundher := true; + break; + end; + until FindNext(sr) <> 0; + finally + FindClose(sr); + end; + if not foundher then begin newname := ''; result := false; break; end; + end; + if result then pathname := newname; +end; + + +function openDiskFileRO (pathname: AnsiString): TStream; +begin + if not findFileCI(pathname) then raise Exception.Create('can''t open file "'+pathname+'"'); + result := TFileStream.Create(pathname, fmOpenRead or {fmShareDenyWrite}fmShareDenyNone); +end; + +function createDiskFile (pathname: AnsiString): TStream; +var + path: AnsiString; +begin + path := ExtractFilePath(pathname); + if length(path) > 0 then + begin + if not findFileCI(path, true) then raise Exception.Create('can''t create file "'+pathname+'"'); + end; + result := TFileStream.Create(path+ExtractFileName(pathname), fmCreate); +end; + + +procedure writeIntegerLE (st: TStream; vp: Pointer; size: Integer); +{$IFDEF ENDIAN_LITTLE} +begin + st.writeBuffer(vp^, size); +end; +{$ELSE} +var + p: PByte; +begin + p := PByte(vp)+size-1; + while size > 0 do + begin + st.writeBuffer(p^, 1); + Dec(size); + Dec(p); + end; +end; +{$ENDIF} + +procedure writeIntegerBE (st: TStream; vp: Pointer; size: Integer); +{$IFDEF ENDIAN_LITTLE} +var + p: PByte; +begin + p := PByte(vp)+size-1; + while size > 0 do + begin + st.writeBuffer(p^, 1); + Dec(size); + Dec(p); + end; +end; +{$ELSE} +begin + st.writeBuffer(vp^, size); +end; +{$ENDIF} + +procedure writeInt (st: TStream; v: Byte); overload; begin writeIntegerLE(st, @v, 1); end; +procedure writeInt (st: TStream; v: ShortInt); overload; begin writeIntegerLE(st, @v, 1); end; +procedure writeInt (st: TStream; v: Word); overload; begin writeIntegerLE(st, @v, 2); end; +procedure writeInt (st: TStream; v: SmallInt); overload; begin writeIntegerLE(st, @v, 2); end; +procedure writeInt (st: TStream; v: LongWord); overload; begin writeIntegerLE(st, @v, 4); end; +procedure writeInt (st: TStream; v: LongInt); overload; begin writeIntegerLE(st, @v, 4); end; +procedure writeInt (st: TStream; v: Int64); overload; begin writeIntegerLE(st, @v, 8); end; +procedure writeInt (st: TStream; v: UInt64); overload; begin writeIntegerLE(st, @v, 8); end; + +procedure writeIntBE (st: TStream; v: Byte); overload; begin writeIntegerBE(st, @v, 1); end; +procedure writeIntBE (st: TStream; v: ShortInt); overload; begin writeIntegerBE(st, @v, 1); end; +procedure writeIntBE (st: TStream; v: Word); overload; begin writeIntegerBE(st, @v, 2); end; +procedure writeIntBE (st: TStream; v: SmallInt); overload; begin writeIntegerBE(st, @v, 2); end; +procedure writeIntBE (st: TStream; v: LongWord); overload; begin writeIntegerBE(st, @v, 4); end; +procedure writeIntBE (st: TStream; v: LongInt); overload; begin writeIntegerBE(st, @v, 4); end; +procedure writeIntBE (st: TStream; v: Int64); overload; begin writeIntegerBE(st, @v, 8); end; +procedure writeIntBE (st: TStream; v: UInt64); overload; begin writeIntegerBE(st, @v, 8); end; + + +procedure readIntegerLE (st: TStream; vp: Pointer; size: Integer); +{$IFDEF ENDIAN_LITTLE} +begin + st.readBuffer(vp^, size); +end; +{$ELSE} +var + p: PByte; +begin + p := PByte(vp)+size-1; + while size > 0 do + begin + st.readBuffer(p^, 1); + Dec(size); + Dec(p); + end; +end; +{$ENDIF} + +procedure readIntegerBE (st: TStream; vp: Pointer; size: Integer); +{$IFDEF ENDIAN_LITTLE} +var + p: PByte; +begin + p := PByte(vp)+size-1; + while size > 0 do + begin + st.readBuffer(p^, 1); + Dec(size); + Dec(p); + end; +end; +{$ELSE} +begin + st.readBuffer(vp^, size); +end; +{$ENDIF} + +function readByte (st: TStream): Byte; begin readIntegerLE(st, @result, 1); end; +function readShortInt (st: TStream): ShortInt; begin readIntegerLE(st, @result, 1); end; +function readWord (st: TStream): Word; begin readIntegerLE(st, @result, 2); end; +function readSmallInt (st: TStream): SmallInt; begin readIntegerLE(st, @result, 2); end; +function readLongWord (st: TStream): LongWord; begin readIntegerLE(st, @result, 4); end; +function readLongInt (st: TStream): LongInt; begin readIntegerLE(st, @result, 4); end; +function readInt64 (st: TStream): Int64; begin readIntegerLE(st, @result, 8); end; +function readUInt64 (st: TStream): UInt64; begin readIntegerLE(st, @result, 8); end; + +function readByteBE (st: TStream): Byte; begin readIntegerBE(st, @result, 1); end; +function readShortIntBE (st: TStream): ShortInt; begin readIntegerBE(st, @result, 1); end; +function readWordBE (st: TStream): Word; begin readIntegerBE(st, @result, 2); end; +function readSmallIntBE (st: TStream): SmallInt; begin readIntegerBE(st, @result, 2); end; +function readLongWordBE (st: TStream): LongWord; begin readIntegerBE(st, @result, 4); end; +function readLongIntBE (st: TStream): LongInt; begin readIntegerBE(st, @result, 4); end; +function readInt64BE (st: TStream): Int64; begin readIntegerBE(st, @result, 8); end; +function readUInt64BE (st: TStream): UInt64; begin readIntegerBE(st, @result, 8); end; + + +end. -- 2.29.2