Skip to content

Commit

Permalink
Merge pull request #371 from DrAbcOfficial/main
Browse files Browse the repository at this point in the history
update for win32 GetIconImageForFullPath
  • Loading branch information
hzqst authored Jan 18, 2024
2 parents d0bcdcc + 844a3b1 commit 55badcb
Show file tree
Hide file tree
Showing 4 changed files with 413 additions and 1 deletion.
172 changes: 171 additions & 1 deletion Plugins/CaptionMod/Surface2.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#if defined( WIN32) && !defined( _X360 )
#include "winlite.h"
#include <shellapi.h>
#endif

#include <vgui/ISurface.h>
#include <vgui/Cursor.h>
#include <vgui_controls/MemoryBitmap.h>
#include "strtools.h"
#include "Surface2.h"
#include "DpiManager.h"

Expand Down Expand Up @@ -30,6 +37,11 @@ CSurface2::CSurface2()
//-----------------------------------------------------------------------------
void CSurface2::Shutdown(void)
{
for (int i = m_FileTypeImages.First(); i != m_FileTypeImages.InvalidIndex(); i = m_FileTypeImages.Next(i))
{
delete m_FileTypeImages[i];
}
m_FileTypeImages.RemoveAll();
if (g_pSurface_HL25)
return g_pSurface_HL25->Shutdown();

Expand Down Expand Up @@ -1290,9 +1302,167 @@ void CSurface2::ClearTemporaryFontCache(void)
{
}


#if defined( WIN32 ) && !defined( _X360 )
static bool GetIconSize(ICONINFO& iconInfo, int& w, int& h)
{
w = h = 0;

HBITMAP bitmap = iconInfo.hbmColor;
BITMAP bm;
if (0 == GetObject((HGDIOBJ)bitmap, sizeof(BITMAP), (LPVOID)&bm))
{
return false;
}

w = bm.bmWidth;
h = bm.bmHeight;

return true;
}

// If rgba is NULL, bufsize gets filled in w/ # of bytes required
static bool GetIconBits(HDC hdc, ICONINFO& iconInfo, int& w, int& h, unsigned char* rgba, size_t& bufsize)
{
if (!iconInfo.hbmColor || !iconInfo.hbmMask)
return false;

if (!rgba)
{
if (!GetIconSize(iconInfo, w, h))
return false;

bufsize = (size_t)((w * h) << 2);
return true;
}

bool bret = false;

Assert(w > 0);
Assert(h > 0);
Assert(bufsize == (size_t)((w * h) << 2));

DWORD* maskData = new DWORD[w * h];
DWORD* colorData = new DWORD[w * h];
DWORD* output = (DWORD*)rgba;

BITMAPINFO bmInfo;

memset(&bmInfo, 0, sizeof(bmInfo));
bmInfo.bmiHeader.biSize = sizeof(bmInfo.bmiHeader);
bmInfo.bmiHeader.biWidth = w;
bmInfo.bmiHeader.biHeight = h;
bmInfo.bmiHeader.biPlanes = 1;
bmInfo.bmiHeader.biBitCount = 32;
bmInfo.bmiHeader.biCompression = BI_RGB;

// Get the info about the bits
if (GetDIBits(hdc, iconInfo.hbmMask, 0, h, maskData, &bmInfo, DIB_RGB_COLORS) == h &&
GetDIBits(hdc, iconInfo.hbmColor, 0, h, colorData, &bmInfo, DIB_RGB_COLORS) == h)
{
bret = true;

for (int row = 0; row < h; ++row)
{
// Invert
int r = (h - row - 1);
int rowstart = r * w;

DWORD* color = &colorData[rowstart];
DWORD* mask = &maskData[rowstart];
DWORD* outdata = &output[row * w];

for (int col = 0; col < w; ++col)
{
unsigned char* cr = (unsigned char*)&color[col];

// Set alpha
cr[3] = mask[col] == 0 ? 0xff : 0x00;

// Swap blue and red
unsigned char t = cr[2];
cr[2] = cr[0];
cr[0] = t;

*(unsigned int*)&outdata[col] = *(unsigned int*)cr;
}
}
}

delete[] colorData;
delete[] maskData;

return bret;
}

static bool ShouldMakeUnique(char const* extension)
{
if (!stricmp(extension, "cur"))
return true;
if (!stricmp(extension, "ani"))
return true;
return false;
}
#endif // !_X360

IImage *CSurface2::GetIconImageForFullPath(const char *pFullPath)
{
return NULL;
vgui::IImage* newIcon = NULL;

#if defined( WIN32 ) && !defined( _X360 )
SHFILEINFO info = { 0 };
DWORD_PTR dwResult = SHGetFileInfo(
pFullPath,
0,
&info,
sizeof(info),
SHGFI_TYPENAME | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_SHELLICONSIZE
);
if (dwResult)
{
if (info.szTypeName[0] != 0)
{
char ext[32];
Q_ExtractFileExtension(pFullPath, ext, sizeof(ext));

char lookup[512];
Q_snprintf(lookup, sizeof(lookup), "%s", ShouldMakeUnique(ext) ? pFullPath : info.szTypeName);

// Now check the dictionary
unsigned short idx = m_FileTypeImages.Find(lookup);
if (idx == m_FileTypeImages.InvalidIndex())
{
ICONINFO iconInfo;
if (0 != GetIconInfo(info.hIcon, &iconInfo))
{
int w, h;
size_t bufsize = 0;

HDC hdc = CreateCompatibleDC(NULL);

if (GetIconBits(hdc, iconInfo, w, h, NULL, bufsize))
{
byte* bits = new byte[bufsize];
if (bits && GetIconBits(hdc, iconInfo, w, h, bits, bufsize))
{
newIcon = new MemoryBitmap(bits, w, h);
}
delete[] bits;
}

DeleteDC(hdc);
}

idx = m_FileTypeImages.Insert(lookup, newIcon);
}

newIcon = m_FileTypeImages[idx];
}

if (info.hIcon) DestroyIcon(info.hIcon);
}
#endif
return newIcon;
}

void CSurface2::DrawUnicodeString(const wchar_t *pwString, FontDrawType_t drawType)
Expand Down
2 changes: 2 additions & 0 deletions Plugins/CaptionMod/Surface2.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "VGUI.h"
#include "IHTML.h"
#include "utldict.h"
#include <mathlib/vector2d.h>
#include <Color.h>
#include <ISurface2.h>
Expand Down Expand Up @@ -246,6 +247,7 @@ class CSurface2 : public ISurface2

private:
float m_flAlphaMultiplier;
CUtlDict< vgui::IImage*, unsigned short > m_FileTypeImages;
};

}
Expand Down
173 changes: 173 additions & 0 deletions include/vgui_controls/MemoryBitmap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//


#if !defined(_STATIC_LINKED) || defined(_VGUI_DLL)

#include <vgui/ISurface.h>

#include "Memorybitmap.h"
#include "Controls.h"

#include <string.h>
#include <stdlib.h>

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

using namespace vgui;

//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : *filename - image file to load
//-----------------------------------------------------------------------------
MemoryBitmap::MemoryBitmap(unsigned char* texture, int wide, int tall)
{
_texture = texture;
_id = 0;
_uploaded = false;
_color = Color(255, 255, 255, 255);
_pos[0] = _pos[1] = 0;
_valid = true;
_w = wide;
_h = tall;
ForceUpload(texture, wide, tall);
}

//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
MemoryBitmap::~MemoryBitmap()
{
}

//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void MemoryBitmap::GetSize(int& wide, int& tall)
{
wide = 0;
tall = 0;

if (!_valid)
return;

surface()->DrawGetTextureSize(_id, wide, tall);
}

//-----------------------------------------------------------------------------
// Purpose: size of the bitmap
//-----------------------------------------------------------------------------
void MemoryBitmap::GetContentSize(int& wide, int& tall)
{
GetSize(wide, tall);
}

//-----------------------------------------------------------------------------
// Purpose: ignored
//-----------------------------------------------------------------------------
void MemoryBitmap::SetSize(int x, int y)
{
}

//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void MemoryBitmap::SetPos(int x, int y)
{
_pos[0] = x;
_pos[1] = y;
}

//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
void MemoryBitmap::SetColor(Color col)
{
_color = col;
}


//-----------------------------------------------------------------------------
// Purpose: returns the file name of the bitmap
//-----------------------------------------------------------------------------
const char* MemoryBitmap::GetName()
{
return "MemoryBitmap";
}


//-----------------------------------------------------------------------------
// Purpose: Renders the loaded image, uploading it if necessary
// Assumes a valid image is always returned from uploading
//-----------------------------------------------------------------------------
void MemoryBitmap::Paint()
{
if (!_valid)
return;

// if we don't have an _id then lets make one
if (!_id)
{
_id = surface()->CreateNewTextureID(true);
}

// if we have not uploaded yet, lets go ahead and do so
if (!_uploaded)
{
ForceUpload(_texture, _w, _h);
}

//set the texture current, set the color, and draw the biatch
surface()->DrawSetTexture(_id);
surface()->DrawSetColor(_color[0], _color[1], _color[2], _color[3]);

int wide, tall;
GetSize(wide, tall);
surface()->DrawTexturedRect(_pos[0], _pos[1], _pos[0] + wide, _pos[1] + tall);
}


//-----------------------------------------------------------------------------
// Purpose: ensures the bitmap has been uploaded
//-----------------------------------------------------------------------------
void MemoryBitmap::ForceUpload(unsigned char* texture, int wide, int tall)
{
_texture = texture;
_w = wide;
_h = tall;

if (!_valid)
return;

// if (_uploaded)
// return;

if (_w == 0 || _h == 0)
return;

if (!_id)
{
_id = surface()->CreateNewTextureID(true);
}
/* drawSetTextureRGBA(IE->textureID,static_cast<const char *>(lpvBits), w, h);
*/
surface()->DrawSetTextureRGBA(_id, _texture, _w, _h, false, true);
_uploaded = true;

_valid = surface()->IsTextureIDValid(_id);
}

//-----------------------------------------------------------------------------
// Purpose: data accessor
//-----------------------------------------------------------------------------
HTexture MemoryBitmap::GetID()
{
return _id;
}

#endif // _STATIC_LINKED && _VGUI_DLL
Loading

0 comments on commit 55badcb

Please sign in to comment.