Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SDL_GetClipboardData() for bitmap on Windows (SDL3). #11409

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions src/video/windows/SDL_windowsclipboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,51 @@
// Assume we can directly read and write BMP fields without byte swapping
SDL_COMPILE_TIME_ASSERT(verify_byte_order, SDL_BYTEORDER == SDL_LIL_ENDIAN);

static int WIN_GetPixelDataOffset(BITMAPINFOHEADER bih)
{
int offset = 0;
// biSize Specifies the number of bytes required by the structure
// We expect to always be 40 because it should be packed
if (40 == bih.biSize && 40 == sizeof(BITMAPINFOHEADER))
{
//
// biBitCount Specifies the number of bits per pixel.
// Might exist some bit masks *after* the header and *before* the pixel offset
// we're looking, but only if we have more than
// 8 bits per pixel, so we need to ajust for that
//
if (bih.biBitCount > 8)
{
// If bih.biCompression is RBG we should NOT offset more

if (bih.biCompression == BI_BITFIELDS)
{
offset += 3 * sizeof(RGBQUAD);
} else if (bih.biCompression == 6 /* BI_ALPHABITFIELDS */) {
// Not common, but still right
offset += 4 * sizeof(RGBQUAD);
}
}
}

//
// biClrUsed Specifies the number of color indices in the color table that are actually used by the bitmap.
// If this value is zero, the bitmap uses the maximum number of colors
// corresponding to the value of the biBitCount member for the compression mode specified by biCompression.
// If biClrUsed is nonzero and the biBitCount member is less than 16
// the biClrUsed member specifies the actual number of colors
//
if (bih.biClrUsed > 0) {
offset += bih.biClrUsed * sizeof(RGBQUAD);
} else {
if (bih.biBitCount < 16) {
offset = offset + (sizeof(RGBQUAD) << bih.biBitCount);
}
}
return bih.biSize + offset;
}


static BOOL WIN_OpenClipboard(SDL_VideoDevice *_this)
{
// Retry to open the clipboard in case another application has it open
Expand Down Expand Up @@ -114,16 +159,17 @@ static void *WIN_ConvertDIBtoBMP(HANDLE hMem, size_t *size)
BITMAPINFOHEADER *pbih = (BITMAPINFOHEADER *)dib;
size_t bih_size = pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD);
size_t dib_size = bih_size + pbih->biSizeImage;
int pixel_offset = WIN_GetPixelDataOffset(*pbih);
if (dib_size <= mem_size) {
size_t bmp_size = sizeof(BITMAPFILEHEADER) + dib_size;
size_t bmp_size = sizeof(BITMAPFILEHEADER) + mem_size;
bmp = SDL_malloc(bmp_size);
if (bmp) {
BITMAPFILEHEADER *pbfh = (BITMAPFILEHEADER *)bmp;
pbfh->bfType = BFT_BITMAP;
pbfh->bfSize = (DWORD)bmp_size;
pbfh->bfReserved1 = 0;
pbfh->bfReserved2 = 0;
pbfh->bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + bih_size);
pbfh->bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + pixel_offset);
SDL_memcpy((Uint8 *)bmp + sizeof(BITMAPFILEHEADER), dib, dib_size);
*size = bmp_size;
}
Expand Down
Loading