mirror of
https://github.com/raysan5/raylib.git
synced 2026-02-15 02:09:17 -05:00
Update win32_clipboard.h
This commit is contained in:
152
src/external/win32_clipboard.h
vendored
152
src/external/win32_clipboard.h
vendored
@ -180,6 +180,10 @@ typedef struct tagRGBQUAD {
|
|||||||
#define BI_CMYKRLE8 0x000C
|
#define BI_CMYKRLE8 0x000C
|
||||||
#define BI_CMYKRLE4 0x000D
|
#define BI_CMYKRLE4 0x000D
|
||||||
|
|
||||||
|
// Bitmap not compressed and that the color table consists of four DWORD color masks,
|
||||||
|
// that specify the red, green, blue, and alpha components of each pixel
|
||||||
|
#define BI_ALPHABITFIELDS 0x0006
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// REF: https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
|
// REF: https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
|
||||||
@ -208,91 +212,70 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih);
|
|||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize)
|
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize)
|
||||||
{
|
{
|
||||||
HWND win = NULL; // Get from somewhere but is doesnt seem to matter
|
unsigned char *bmpData = NULL;
|
||||||
const char *msgString = "";
|
|
||||||
int severity = LOG_INFO;
|
|
||||||
BYTE *bmpData = NULL;
|
|
||||||
|
|
||||||
if (!OpenClipboardRetrying(win))
|
if (OpenClipboardRetrying(NULL))
|
||||||
{
|
{
|
||||||
severity = LOG_ERROR;
|
HGLOBAL clipHandle = (HGLOBAL)GetClipboardData(CF_DIB);
|
||||||
msgString = "Couldn't open clipboard";
|
if (clipHandle != NULL)
|
||||||
goto end;
|
{
|
||||||
|
BITMAPINFOHEADER *bmpInfoHeader = (BITMAPINFOHEADER *)GlobalLock(clipHandle);
|
||||||
|
if (bmpInfoHeader)
|
||||||
|
{
|
||||||
|
*width = bmpInfoHeader->biWidth;
|
||||||
|
*height = bmpInfoHeader->biHeight;
|
||||||
|
SIZE_T clipDataSize = GlobalSize(clipHandle);
|
||||||
|
if (clipDataSize >= sizeof(BITMAPINFOHEADER))
|
||||||
|
{
|
||||||
|
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
|
||||||
|
|
||||||
|
// Create the bytes for a correct BMP file and copy the data to a pointer
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
BITMAPFILEHEADER bmpFileHeader = { 0 };
|
||||||
|
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
|
||||||
|
*dataSize = bmpFileSize;
|
||||||
|
|
||||||
|
bmpFileHeader.bfType = 0x4D42; // BMP fil type constant
|
||||||
|
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
|
||||||
|
bmpFileHeader.bfOffBits = sizeof(bmpFileHeader) + pixelOffset;
|
||||||
|
|
||||||
|
bmpData = (unsigned char *)RL_MALLOC(sizeof(bmpFileHeader) + clipDataSize);
|
||||||
|
memcpy(bmpData, &bmpFileHeader, sizeof(bmpFileHeader)); // Add BMP file header data
|
||||||
|
memcpy(bmpData + sizeof(bmpFileHeader), bmpInfoHeader, clipDataSize); // Add BMP info header data
|
||||||
|
|
||||||
|
GlobalUnlock(clipHandle);
|
||||||
|
CloseClipboard();
|
||||||
|
|
||||||
|
TRACELOG(LOG_INFO, "Clipboad image acquired successfully");
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "Clipboard data is malformed");
|
||||||
|
GlobalUnlock(clipHandle);
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "Clipboard data failed to be locked");
|
||||||
|
GlobalUnlock(clipHandle);
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACELOG(LOG_WARNING, "Clipboard data is not an image");
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else TRACELOG(LOG_WARNING, "Clipboard can not be opened");
|
||||||
HGLOBAL clipHandle = (HGLOBAL)GetClipboardData(CF_DIB);
|
|
||||||
if (!clipHandle)
|
|
||||||
{
|
|
||||||
severity = LOG_ERROR;
|
|
||||||
msgString = "Clipboard data is not an Image";
|
|
||||||
goto close;
|
|
||||||
}
|
|
||||||
|
|
||||||
BITMAPINFOHEADER *bmpInfoHeader = (BITMAPINFOHEADER *)GlobalLock(clipHandle);
|
|
||||||
if (!bmpInfoHeader)
|
|
||||||
{
|
|
||||||
// Mapping from HGLOBAL to our local *address space* failed
|
|
||||||
severity = LOG_ERROR;
|
|
||||||
msgString = "Clipboard data failed to be locked";
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
*width = bmpInfoHeader->biWidth;
|
|
||||||
*height = bmpInfoHeader->biHeight;
|
|
||||||
|
|
||||||
SIZE_T clipDataSize = GlobalSize(clipHandle);
|
|
||||||
if (clipDataSize < sizeof(BITMAPINFOHEADER))
|
|
||||||
{
|
|
||||||
// Format CF_DIB needs space for BITMAPINFOHEADER struct.
|
|
||||||
msgString = "Clipboard has Malformed data";
|
|
||||||
severity = LOG_ERROR;
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Denotes where the pixel data starts from the bmpInfoHeader pointer
|
|
||||||
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------//
|
|
||||||
//
|
|
||||||
// The rest of the section is about create the bytes for a correct BMP file
|
|
||||||
// Then we copy the data and to a pointer
|
|
||||||
//
|
|
||||||
//--------------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
BITMAPFILEHEADER bmpFileHeader = { 0 };
|
|
||||||
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
|
|
||||||
*dataSize = bmpFileSize;
|
|
||||||
|
|
||||||
bmpFileHeader.bfType = 0x4D42; // REF: https://stackoverflow.com/questions/601430/multibyte-character-constants-and-bitmap-file-header-type-constants#601536
|
|
||||||
|
|
||||||
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
|
|
||||||
bmpFileHeader.bfOffBits = sizeof(bmpFileHeader) + pixelOffset;
|
|
||||||
|
|
||||||
// WARNING: Each process has a default heap provided by the system
|
|
||||||
// Memory objects allocated by GlobalAlloc and LocalAlloc are in private,
|
|
||||||
// committed pages with read/write access that cannot be accessed by other processes
|
|
||||||
//
|
|
||||||
// This may be wrong since we might be allocating in a DLL and freeing from another module, the main application
|
|
||||||
// that may cause heap corruption. We could create a FreeImage function
|
|
||||||
bmpData = (BYTE *)RL_MALLOC(sizeof(bmpFileHeader) + clipDataSize);
|
|
||||||
// First we add the header for a bmp file
|
|
||||||
memcpy(bmpData, &bmpFileHeader, sizeof(bmpFileHeader)); // Add BMP file header data
|
|
||||||
// Then we add the header for the bmp itself + the pixel data
|
|
||||||
memcpy(bmpData + sizeof(bmpFileHeader), bmpInfoHeader, clipDataSize); // Add BMP info header data
|
|
||||||
|
|
||||||
msgString = "Clipboad image acquired successfully";
|
|
||||||
|
|
||||||
unlock:
|
|
||||||
GlobalUnlock(clipHandle);
|
|
||||||
close:
|
|
||||||
CloseClipboard();
|
|
||||||
end:
|
|
||||||
|
|
||||||
TRACELOG(severity, msgString);
|
|
||||||
|
|
||||||
return bmpData;
|
return bmpData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open clipboard with several tries
|
||||||
|
// NOTE: If parameter is NULL, the open clipboard is associated with the current task
|
||||||
static BOOL OpenClipboardRetrying(HWND hWnd)
|
static BOOL OpenClipboardRetrying(HWND hWnd)
|
||||||
{
|
{
|
||||||
static const int maxTries = 20;
|
static const int maxTries = 20;
|
||||||
@ -320,22 +303,18 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih)
|
|||||||
|
|
||||||
// NOTE: biSize specifies the number of bytes required by the structure
|
// NOTE: biSize specifies the number of bytes required by the structure
|
||||||
// We expect to always be 40 because it should be packed
|
// We expect to always be 40 because it should be packed
|
||||||
if ((40 == bih.biSize) && (40 == sizeof(BITMAPINFOHEADER)))
|
if ((bih.biSize == 40) && (sizeof(BITMAPINFOHEADER) == 40))
|
||||||
{
|
{
|
||||||
// NOTE: biBitCount specifies the number of bits per pixel.
|
// NOTE: biBitCount specifies the number of bits per pixel
|
||||||
// Might exist some bit masks *after* the header and *before* the pixel offset
|
// Might exist some bit masks *after* the header and *before* the pixel offset
|
||||||
// we're looking, but only if we have more than
|
// we're looking, but only if we have more than
|
||||||
// 8 bits per pixel, so we need to ajust for that
|
// 8 bits per pixel, so we need to ajust for that
|
||||||
if (bih.biBitCount > 8)
|
if (bih.biBitCount > 8)
|
||||||
{
|
{
|
||||||
// if bih.biCompression is RBG we should NOT offset more
|
// If (bih.biCompression == BI_RGB) we should NOT offset more
|
||||||
|
|
||||||
if (bih.biCompression == BI_BITFIELDS) offset += 3*rgbaSize;
|
if (bih.biCompression == BI_BITFIELDS) offset += 3*rgbaSize;
|
||||||
else if (bih.biCompression == 6) // BI_ALPHABITFIELDS
|
else if (bih.biCompression == BI_ALPHABITFIELDS) offset += 4*rgbaSize; // Not widely supported, but valid
|
||||||
{
|
|
||||||
// Not widely supported, but valid
|
|
||||||
offset += 4*rgbaSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,4 +332,3 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih)
|
|||||||
return bih.biSize + offset;
|
return bih.biSize + offset;
|
||||||
}
|
}
|
||||||
#endif // WIN32_CLIPBOARD_IMPLEMENTATION
|
#endif // WIN32_CLIPBOARD_IMPLEMENTATION
|
||||||
// EOF
|
|
||||||
|
|||||||
Reference in New Issue
Block a user