/* * synergy -- mouse and keyboard sharing utility * Copyright (C) 2004 Chris Schoeneman * * This package is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * found in the file COPYING that should have accompanied this file. * * This package 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. */ #include "CXWindowsClipboardAnyBitmapConverter.h" // BMP info header structure struct CBMPInfoHeader { public: UInt32 biSize; SInt32 biWidth; SInt32 biHeight; UInt16 biPlanes; UInt16 biBitCount; UInt32 biCompression; UInt32 biSizeImage; SInt32 biXPelsPerMeter; SInt32 biYPelsPerMeter; UInt32 biClrUsed; UInt32 biClrImportant; }; // BMP is little-endian static void toLE(UInt8*& dst, UInt16 src) { dst[0] = static_cast(src & 0xffu); dst[1] = static_cast((src >> 8) & 0xffu); dst += 2; } static void toLE(UInt8*& dst, SInt32 src) { dst[0] = static_cast(src & 0xffu); dst[1] = static_cast((src >> 8) & 0xffu); dst[2] = static_cast((src >> 16) & 0xffu); dst[3] = static_cast((src >> 24) & 0xffu); dst += 4; } static void toLE(UInt8*& dst, UInt32 src) { dst[0] = static_cast(src & 0xffu); dst[1] = static_cast((src >> 8) & 0xffu); dst[2] = static_cast((src >> 16) & 0xffu); dst[3] = static_cast((src >> 24) & 0xffu); dst += 4; } static inline UInt16 fromLEU16(const UInt8* data) { return static_cast(data[0]) | (static_cast(data[1]) << 8); } static inline SInt32 fromLES32(const UInt8* data) { return static_cast(static_cast(data[0]) | (static_cast(data[1]) << 8) | (static_cast(data[2]) << 16) | (static_cast(data[3]) << 24)); } static inline UInt32 fromLEU32(const UInt8* data) { return static_cast(data[0]) | (static_cast(data[1]) << 8) | (static_cast(data[2]) << 16) | (static_cast(data[3]) << 24); } // // CXWindowsClipboardAnyBitmapConverter // CXWindowsClipboardAnyBitmapConverter::CXWindowsClipboardAnyBitmapConverter() { // do nothing } CXWindowsClipboardAnyBitmapConverter::~CXWindowsClipboardAnyBitmapConverter() { // do nothing } IClipboard::EFormat CXWindowsClipboardAnyBitmapConverter::getFormat() const { return IClipboard::kBitmap; } int CXWindowsClipboardAnyBitmapConverter::getDataSize() const { return 8; } CString CXWindowsClipboardAnyBitmapConverter::fromIClipboard(const CString& bmp) const { // fill BMP info header with native-endian data CBMPInfoHeader infoHeader; const UInt8* rawBMPInfoHeader = reinterpret_cast(bmp.data()); infoHeader.biSize = fromLEU32(rawBMPInfoHeader + 0); infoHeader.biWidth = fromLES32(rawBMPInfoHeader + 4); infoHeader.biHeight = fromLES32(rawBMPInfoHeader + 8); infoHeader.biPlanes = fromLEU16(rawBMPInfoHeader + 12); infoHeader.biBitCount = fromLEU16(rawBMPInfoHeader + 14); infoHeader.biCompression = fromLEU32(rawBMPInfoHeader + 16); infoHeader.biSizeImage = fromLEU32(rawBMPInfoHeader + 20); infoHeader.biXPelsPerMeter = fromLES32(rawBMPInfoHeader + 24); infoHeader.biYPelsPerMeter = fromLES32(rawBMPInfoHeader + 28); infoHeader.biClrUsed = fromLEU32(rawBMPInfoHeader + 32); infoHeader.biClrImportant = fromLEU32(rawBMPInfoHeader + 36); // check that format is acceptable if (infoHeader.biSize != 40 || infoHeader.biWidth == 0 || infoHeader.biHeight == 0 || infoHeader.biPlanes != 0 || infoHeader.biCompression != 0 || (infoHeader.biBitCount != 24 && infoHeader.biBitCount != 32)) { return CString(); } // convert to image format const UInt8* rawBMPPixels = rawBMPInfoHeader + 40; if (infoHeader.biBitCount == 24) { return doBGRFromIClipboard(rawBMPPixels, infoHeader.biWidth, infoHeader.biHeight); } else { return doBGRAFromIClipboard(rawBMPPixels, infoHeader.biWidth, infoHeader.biHeight); } } CString CXWindowsClipboardAnyBitmapConverter::toIClipboard(const CString& image) const { // convert to raw BMP data UInt32 w, h, depth; CString rawBMP = doToIClipboard(image, w, h, depth); if (rawBMP.empty() || w == 0 || h == 0 || (depth != 24 && depth != 32)) { return CString(); } // fill BMP info header with little-endian data UInt8 infoHeader[40]; UInt8* dst = infoHeader; toLE(dst, static_cast(40)); toLE(dst, static_cast(w)); toLE(dst, static_cast(h)); toLE(dst, static_cast(1)); toLE(dst, static_cast(depth)); toLE(dst, static_cast(0)); // BI_RGB toLE(dst, static_cast(image.size())); toLE(dst, static_cast(2834)); // 72 dpi toLE(dst, static_cast(2834)); // 72 dpi toLE(dst, static_cast(0)); toLE(dst, static_cast(0)); // construct image return CString(reinterpret_cast(infoHeader), sizeof(infoHeader)) + rawBMP; }