mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-26 22:48:19 +00:00
163 lines
4.9 KiB
C++
163 lines
4.9 KiB
C++
/*
|
|
Copyright (C) 2009 Red Hat, 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.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include <map>
|
|
#include "platform_utils.h"
|
|
#include "utils.h"
|
|
#include "threads.h"
|
|
|
|
void string_vprintf(std::string& str, const char* format, va_list ap)
|
|
{
|
|
int buf_size = 256;
|
|
for (;;) {
|
|
AutoArray<char> buf(new char[buf_size]);
|
|
int r = vsnprintf_s(buf.get(), buf_size, buf_size - 1, format, ap);
|
|
if (r != -1) {
|
|
str = buf.get();
|
|
return;
|
|
}
|
|
buf_size *= 2;
|
|
}
|
|
}
|
|
|
|
void wstring_vprintf(std::wstring& str, const wchar_t* format, va_list ap)
|
|
{
|
|
int buf_size = 256;
|
|
for (;;) {
|
|
AutoArray<wchar_t> buf(new wchar_t[buf_size]);
|
|
int r = vswprintf(buf.get(), buf_size, format, ap);
|
|
if (r != -1) {
|
|
str = buf.get();
|
|
return;
|
|
}
|
|
buf_size *= 2;
|
|
}
|
|
}
|
|
|
|
HDC create_compatible_dc()
|
|
{
|
|
HDC dc = CreateCompatibleDC(NULL);
|
|
if (!dc) {
|
|
THROW("create compatible DC failed");
|
|
}
|
|
return dc;
|
|
}
|
|
|
|
HBITMAP get_bitmap_res(int id)
|
|
{
|
|
HBITMAP bitmap = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(id));
|
|
if (!bitmap) {
|
|
THROW("get bitmpa #%d failed", id);
|
|
}
|
|
return bitmap;
|
|
}
|
|
|
|
HBITMAP get_alpha_bitmap_res(int id)
|
|
{
|
|
AutoGDIObject bitmap(LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(id), IMAGE_BITMAP, 0, 0,
|
|
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_SHARED));
|
|
if (!bitmap.valid()) {
|
|
THROW("get bitmpa #%d failed", id);
|
|
}
|
|
|
|
BITMAP src_info;
|
|
GetObject(bitmap.get(), sizeof(src_info), &src_info);
|
|
if (src_info.bmBitsPixel != 32 || src_info.bmPlanes != 1) {
|
|
THROW("invalid format #%d ", id);
|
|
}
|
|
|
|
LONG src_size = src_info.bmHeight * src_info.bmWidthBytes;
|
|
AutoArray<uint8_t> src_pixels(new uint8_t[src_size]);
|
|
LONG ncopy = GetBitmapBits((HBITMAP)bitmap.get(), src_size, src_pixels.get());
|
|
if (ncopy != src_size) {
|
|
THROW("get vitmap bits failed, %u", GetLastError());
|
|
}
|
|
|
|
AutoDC auto_dc(create_compatible_dc());
|
|
BITMAPINFO dest_info;
|
|
uint8_t* dest;
|
|
dest_info.bmiHeader.biSize = sizeof(dest_info.bmiHeader);
|
|
dest_info.bmiHeader.biWidth = src_info.bmWidth;
|
|
dest_info.bmiHeader.biHeight = -src_info.bmHeight;
|
|
dest_info.bmiHeader.biPlanes = 1;
|
|
dest_info.bmiHeader.biBitCount = 32;
|
|
dest_info.bmiHeader.biCompression = BI_RGB;
|
|
dest_info.bmiHeader.biSizeImage = 0;
|
|
dest_info.bmiHeader.biXPelsPerMeter = dest_info.bmiHeader.biYPelsPerMeter = 0;
|
|
dest_info.bmiHeader.biClrUsed = 0;
|
|
dest_info.bmiHeader.biClrImportant = 0;
|
|
|
|
HBITMAP ret = CreateDIBSection(auto_dc.get(), &dest_info, 0, (VOID**)&dest, NULL, 0);
|
|
if (!ret) {
|
|
THROW("create bitmap failed, %u", GetLastError());
|
|
}
|
|
|
|
uint8_t* src_line = src_pixels.get();
|
|
for (int i = 0; i < src_info.bmHeight; i++, src_line += src_info.bmWidthBytes) {
|
|
uint8_t* src = src_line;
|
|
for (int j = 0; j < src_info.bmWidth; j++) {
|
|
dest[3] = src[3];
|
|
double alpha = (double)dest[3] / 0xff;
|
|
dest[2] = (uint8_t)(alpha * src[2]);
|
|
dest[1] = (uint8_t)(alpha * src[1]);
|
|
dest[0] = (uint8_t)(alpha * src[0]);
|
|
src += 4;
|
|
dest += 4;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static std::map<int, const char*> errors_map;
|
|
static Mutex errors_map_mutex;
|
|
|
|
const char* sys_err_to_str(int error)
|
|
{
|
|
Lock lock(errors_map_mutex);
|
|
if (errors_map.find(error) == errors_map.end()) {
|
|
LPSTR msg;
|
|
if (!FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPSTR)&msg, 0, NULL)) {
|
|
const int BUF_SIZE = 20;
|
|
msg = new char[BUF_SIZE];
|
|
_snprintf(msg, BUF_SIZE, "errno %d", error);
|
|
} else {
|
|
char* new_line;
|
|
if ((new_line = strrchr(msg, '\r'))) {
|
|
*new_line = 0;
|
|
}
|
|
}
|
|
errors_map[error] = msg;
|
|
}
|
|
return errors_map[error];
|
|
}
|
|
|
|
int inet_aton(const char* ip, struct in_addr* in_addr)
|
|
{
|
|
unsigned long addr = inet_addr(ip);
|
|
|
|
if (addr == INADDR_NONE) {
|
|
return 0;
|
|
}
|
|
in_addr->S_un.S_addr = addr;
|
|
return 1;
|
|
}
|
|
|