⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rw_dib.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): rw_dib.c - This handles DIB section management under Windows.     }
{                                                                            }
{ Initial conversion (90%) by : Savage (Dominique@SavageSoftware.com.au)     }
{ Final conversion by : Massimo (max-67@libero.it)                           }
{ Initial conversion on : 09-Jan-2002                                        }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ 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 2             }
{ 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.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Updated on :                                                               }
{ Updated by :                                                               }
{                                                                            }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{ 1) ?                                                                       }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{ 1) ?                                                                       }
{----------------------------------------------------------------------------}

unit rw_dib;

interface

uses
  Windows,
  SysUtils,
  r_local,
  rw_win;

var
  d_8to24table: array[0..255] of Word;

var
  s_systemcolors_saved: Boolean; //qboolean;
  previously_selected_GDI_obj: HGDIOBJ;

type
  t_syspalindices = (
    COLOR_ACTIVEBORDER,
    COLOR_ACTIVECAPTION,
    COLOR_APPWORKSPACE,
    COLOR_BACKGROUND,
    COLOR_BTNFACE,
    COLOR_BTNSHADOW,
    COLOR_BTNTEXT,
    COLOR_CAPTIONTEXT,
    COLOR_GRAYTEXT,
    COLOR_HIGHLIGHT,
    COLOR_HIGHLIGHTTEXT,
    COLOR_INACTIVEBORDER,
    COLOR_INACTIVECAPTION,
    COLOR_MENU,
    COLOR_MENUTEXT,
    COLOR_SCROLLBAR,
    COLOR_WINDOW,
    COLOR_WINDOWFRAME,
    COLOR_WINDOWTEXT
    );

const
  NUM_SYS_COLORS = (20{SizeOf(s_syspalindices) div sizeof(integer)});
  s_syspalindices : array[0..19] of integer = (
    COLOR_ACTIVEBORDER,
    COLOR_ACTIVECAPTION,
    COLOR_APPWORKSPACE,
    COLOR_BACKGROUND,
    COLOR_BTNFACE,
    COLOR_BTNSHADOW,
    COLOR_BTNTEXT,
    COLOR_CAPTIONTEXT,
    COLOR_GRAYTEXT,
    COLOR_HIGHLIGHT,
    COLOR_HIGHLIGHTTEXT,
    COLOR_INACTIVEBORDER,
    COLOR_INACTIVECAPTION,
    COLOR_INACTIVECAPTIONTEXT,
    COLOR_MENU,
    COLOR_MENUTEXT,
    COLOR_SCROLLBAR,
    COLOR_WINDOW,
    COLOR_WINDOWFRAME,
    COLOR_WINDOWTEXT
    );

var
  s_oldsyscolors: array[0..NUM_SYS_COLORS - 1] of integer;

type
  dibinfo = record
    header: TBITMAPINFOHEADER;
    acolors: array[0..255] of TRGBQUAD;
  end;
  dibinfo_t = dibinfo;

  identitypalette = record
    palVersion: WORD;
    palNumEntries: WORD;
    palEntries: array[0..255] of PALETTEENTRY;
  end;
  identitypalette_t = identitypalette;

var
  s_ipal: identitypalette_t;

procedure DIB_SaveSystemColors;
procedure DIB_RestoreSystemColors;

(*
** DIB code
*)
function DIB_Init(ppbuffer: PByteArray; ppitch: Pinteger): Boolean; //qboolean;
procedure DIB_Shutdown;
procedure DIB_SetPalette(const palette: PByteArray);

implementation

(*
** DIB_Init
**
** Builds our DIB section
*)

function DIB_Init(ppbuffer: PByteArray; ppitch: Pinteger): Boolean; //qboolean;
var
  dibheader: dibinfo_t;
  i: integer;
  pbmiDIB: PBITMAPINFO;
begin

  pbmiDIB := PBITMAPINFO(@dibheader);

  FillChar(dibheader, sizeof(dibheader), 0);

  (*
  ** grab a DC
  *)
  if (sww_state.h_DC = 0) then
  begin
    sww_state.h_DC := GetDC(sww_state.h_Wnd);
    if (sww_state.h_DC = 0) then
    begin
      result := false;
      Exit;
    end;
  end;

  (*
  ** figure out if we're running in an 8-bit display mode
  *)
  if (GetDeviceCaps(sww_state.h_DC, RASTERCAPS) and RC_PALETTE) <> 0 then
  begin
    sww_state.palettized := true;

    // save system colors
    if (not s_systemcolors_saved) then
    begin
      DIB_SaveSystemColors;
      s_systemcolors_saved := true;
    end;
  end
  else
  begin
    sww_state.palettized := false;
  end;

  (*
  ** fill in the BITMAPINFO type = record
  *)
  pbmiDIB.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
  pbmiDIB.bmiHeader.biWidth := vid.width;
  pbmiDIB.bmiHeader.biHeight := vid.height;
  pbmiDIB.bmiHeader.biPlanes := 1;
  pbmiDIB.bmiHeader.biBitCount := 8;
  pbmiDIB.bmiHeader.biCompression := BI_RGB;
  pbmiDIB.bmiHeader.biSizeImage := 0;
  pbmiDIB.bmiHeader.biXPelsPerMeter := 0;
  pbmiDIB.bmiHeader.biYPelsPerMeter := 0;
  pbmiDIB.bmiHeader.biClrUsed := 256;
  pbmiDIB.bmiHeader.biClrImportant := 256;

  (*
  ** fill in the palette
  *)
  for i := 0 to 255 do
  begin
    dibheader.acolors[i].rgbRed := (d_8to24table[i] shr 0) and $FF;
    dibheader.acolors[i].rgbGreen := (d_8to24table[i] shr 8) and $FF;
    dibheader.acolors[i].rgbBlue := (d_8to24table[i] shr 16) and $FF;
  end;

  (*
  ** create the DIB section
  *)
  sww_state.hDIBSection := CreateDIBSection(sww_state.h_DC,
    pbmiDIB^,
    DIB_RGB_COLORS,
    sww_state.pDIBBase,
    0,
    0);

  if (sww_state.hDIBSection = 0) then
  begin
    ri.Con_Printf(PRINT_ALL, 'DIB_Init - CreateDIBSection failed ');
    DIB_Shutdown;
    result := False;
    Exit;
  end;

  if (pbmiDIB.bmiHeader.biHeight > 0) then
  begin
    // bottom up
    ppbuffer := PByteArray(PByte(sww_state.pDIBBase)^ + ( (vid.height - 1) * vid.Width ) );
    ppitch^ := -vid.width;
  end
  else
  begin
    // top down
    ppbuffer := @sww_state.pDIBBase;
    ppitch^ := vid.width;
  end;

  (*
  ** clear the DIB memory buffer
  *)
  FillChar(sww_state.pDIBBase, vid.width * vid.height, $FF);
  sww_state.hdcDIBSection := CreateCompatibleDC(sww_state.h_DC);
  if (sww_state.hdcDIBSection = 0) then
  begin
    ri.Con_Printf(PRINT_ALL, 'DIB_Init - CreateCompatibleDC failed ');
    DIB_Shutdown;
    result := False;
    Exit;
  end;

  previously_selected_GDI_obj := SelectObject(sww_state.hdcDIBSection,
    sww_state.hDIBSection);
  if (previously_selected_GDI_obj = 0) then
  begin
    ri.Con_Printf(PRINT_ALL, 'DIB_Init - SelectObject failed ');
    DIB_Shutdown;
    result := False;
    Exit;
  end;

  result := true;
end;

(*
** DIB_SetPalette
**
** Sets the color table in our DIB section, and also sets the system palette
** into an identity mode if we're running in an 8-bit palettized display mode.
**
** The palette is expected to be 1024 bytes, in the format:
**
** R := offset 0
** G := offset 1
** B := offset 2
** A := offset 3
*)

procedure DIB_SetPalette(const palette: PByteArray);
var
  pal: pByteArray;
  pLogPal: PLOGPALETTE;
  colors: array[0..255] of TRGBQUAD;
  i: integer;
  ret: integer;
  h_DC: HDC;
  hpalOld: HPALETTE;
begin
  pal := palette;
  pLogPal := PLOGPALETTE(@s_ipal);

  h_DC := sww_state.h_DC;

  (*
  ** set the DIB color table
  *)
  if (sww_state.hdcDIBSection <> 0) then
  begin
    for i := 0 to 255 do
    begin
      colors[i].rgbRed := pal[0];
      colors[i].rgbGreen := pal[1];
      colors[i].rgbBlue := pal[2];
      colors[i].rgbReserved := 0;
      Inc(pal, 4);
    end;

    colors[0].rgbRed := 0;
    colors[0].rgbGreen := 0;
    colors[0].rgbBlue := 0;

    colors[255].rgbRed := $FF;
    colors[255].rgbGreen := $FF;
    colors[255].rgbBlue := $FF;

    if (SetDIBColorTable(sww_state.hdcDIBSection, 0, 256, colors) = 0) then
    begin
      ri.Con_Printf(PRINT_ALL, 'DIB_SetPalette - SetDIBColorTable failed');
    end;
  end;

  (*
  ** for 8-bit color desktop modes we set up the palette for maximum
  ** speed by going into an identity palette mode.
  *)
  if (sww_state.palettized) then
  begin
    if (SetSystemPaletteUse(h_DC, SYSPAL_NOSTATIC) = SYSPAL_ERROR) then
    begin
      //ri.Sys_Error(ERR_FATAL, 'DIB_SetPalette - SetSystemPaletteUse failed ');
    end;

    (*
    ** destroy our old palette
    *)
    if (sww_state.hPal <> 0) then
    begin
      DeleteObject(sww_state.hPal);
      sww_state.hPal := 0;
    end;

    (*
    ** take up all physical palette entries to flush out anything that's currently
    ** in the palette
    *)
    pLogPal.palVersion := $300;
    pLogPal.palNumEntries := 256;
    i := 0;
    while (pal = palette) and (i < 256) do
    begin
      pLogPal.palPalEntry[i].peRed := pal[0];
      pLogPal.palPalEntry[i].peGreen := pal[1];
      pLogPal.palPalEntry[i].peBlue := pal[2];
      pLogPal.palPalEntry[i].peFlags := PC_RESERVED or PC_NOCOLLAPSE;
      Inc(i);
      Inc(pal, 4);
    end;

    pLogPal.palPalEntry[0].peRed := 0;
    pLogPal.palPalEntry[0].peGreen := 0;
    pLogPal.palPalEntry[0].peBlue := 0;
    pLogPal.palPalEntry[0].peFlags := 0;

    pLogPal.palPalEntry[255].peRed := $FF;
    pLogPal.palPalEntry[255].peGreen := $FF;
    pLogPal.palPalEntry[255].peBlue := $FF;
    pLogPal.palPalEntry[255].peFlags := 0;

    sww_state.hPal := CreatePalette(pLogPal^);
    if (sww_state.hPal = 0) then
    begin
      ri.Sys_Error(ERR_FATAL, 'DIB_SetPalette - CreatePalette failed(modx) ', GetLastError);
    end;

    hpalOld := SelectPalette(h_DC, sww_state.hPal, False);
    if (hpalOld = 0) then
    begin
      ri.Sys_Error(ERR_FATAL, 'DIB_SetPalette - SelectPalette failed(modx) ', GetLastError);
    end;

    if (sww_state.hpalOld = 0) then
      sww_state.hpalOld := hpalOld;

    ret := RealizePalette(h_DC);
    if (ret <> pLogPal.palNumEntries) then
    begin
      ri.Sys_Error(ERR_FATAL, 'DIB_SetPalette - RealizePalette set %d entries ', ret);
    end;
  end;
end;

(*
** DIB_Shutdown
*)

procedure DIB_Shutdown;
begin
  if (sww_state.palettized and s_systemcolors_saved) then
    DIB_RestoreSystemColors;

  if (sww_state.hPal <> 0) then
  begin
    DeleteObject(sww_state.hPal);
    sww_state.hPal := 0;
  end;

  if (sww_state.hpalOld <> 0 ) then
  begin
    SelectPalette(sww_state.h_DC, sww_state.hpalOld, FALSE);
    RealizePalette(sww_state.h_DC);
    sww_state.hpalOld := 0;
  end;

  if (sww_state.hdcDIBSection <> 0) then
  begin
    SelectObject(sww_state.hdcDIBSection, previously_selected_GDI_obj);
    DeleteDC(sww_state.hdcDIBSection);
    sww_state.hdcDIBSection := 0;
  end;

  if (sww_state.hDIBSection <> 0 ) then
  begin
    DeleteObject(sww_state.hDIBSection);
    sww_state.hDIBSection := 0;
    sww_state.pDIBBase := nil;
  end;

  if (sww_state.h_DC <> 0 ) then
  begin
    ReleaseDC(sww_state.h_Wnd, sww_state.h_DC);
    sww_state.h_DC := 0;
  end;
end;

(*
** DIB_Save/RestoreSystemColors
*)

procedure DIB_RestoreSystemColors;
begin
  SetSystemPaletteUse(sww_state.h_DC, SYSPAL_STATIC);
  SetSysColors(NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors);
end;

procedure DIB_SaveSystemColors;
var
  i: integer;
begin
  for i := 0 to NUM_SYS_COLORS - 1 do
    s_oldsyscolors[i] := GetSysColor(s_syspalindices[i]);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -