diff options
Diffstat (limited to 'src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp')
| -rw-r--r-- | src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp new file mode 100644 index 0000000..493b1e8 --- /dev/null +++ b/src/lib/platform/XWindowsClipboardAnyBitmapConverter.cpp @@ -0,0 +1,191 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * 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 LICENSE 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. + * + * 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 "platform/XWindowsClipboardAnyBitmapConverter.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<UInt8>(src & 0xffu); + dst[1] = static_cast<UInt8>((src >> 8) & 0xffu); + dst += 2; +} + +static +void +toLE(UInt8*& dst, SInt32 src) +{ + dst[0] = static_cast<UInt8>(src & 0xffu); + dst[1] = static_cast<UInt8>((src >> 8) & 0xffu); + dst[2] = static_cast<UInt8>((src >> 16) & 0xffu); + dst[3] = static_cast<UInt8>((src >> 24) & 0xffu); + dst += 4; +} + +static +void +toLE(UInt8*& dst, UInt32 src) +{ + dst[0] = static_cast<UInt8>(src & 0xffu); + dst[1] = static_cast<UInt8>((src >> 8) & 0xffu); + dst[2] = static_cast<UInt8>((src >> 16) & 0xffu); + dst[3] = static_cast<UInt8>((src >> 24) & 0xffu); + dst += 4; +} + +static inline +UInt16 +fromLEU16(const UInt8* data) +{ + return static_cast<UInt16>(data[0]) | + (static_cast<UInt16>(data[1]) << 8); +} + +static inline +SInt32 +fromLES32(const UInt8* data) +{ + return static_cast<SInt32>(static_cast<UInt32>(data[0]) | + (static_cast<UInt32>(data[1]) << 8) | + (static_cast<UInt32>(data[2]) << 16) | + (static_cast<UInt32>(data[3]) << 24)); +} + +static inline +UInt32 +fromLEU32(const UInt8* data) +{ + return static_cast<UInt32>(data[0]) | + (static_cast<UInt32>(data[1]) << 8) | + (static_cast<UInt32>(data[2]) << 16) | + (static_cast<UInt32>(data[3]) << 24); +} + + +// +// XWindowsClipboardAnyBitmapConverter +// + +XWindowsClipboardAnyBitmapConverter::XWindowsClipboardAnyBitmapConverter() +{ + // do nothing +} + +XWindowsClipboardAnyBitmapConverter::~XWindowsClipboardAnyBitmapConverter() +{ + // do nothing +} + +IClipboard::EFormat +XWindowsClipboardAnyBitmapConverter::getFormat() const +{ + return IClipboard::kBitmap; +} + +int +XWindowsClipboardAnyBitmapConverter::getDataSize() const +{ + return 8; +} + +String +XWindowsClipboardAnyBitmapConverter::fromIClipboard(const String& bmp) const +{ + // fill BMP info header with native-endian data + CBMPInfoHeader infoHeader; + const UInt8* rawBMPInfoHeader = reinterpret_cast<const UInt8*>(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 String(); + } + + // 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); + } +} + +String +XWindowsClipboardAnyBitmapConverter::toIClipboard(const String& image) const +{ + // convert to raw BMP data + UInt32 w, h, depth; + String rawBMP = doToIClipboard(image, w, h, depth); + if (rawBMP.empty() || w == 0 || h == 0 || (depth != 24 && depth != 32)) { + return String(); + } + + // fill BMP info header with little-endian data + UInt8 infoHeader[40]; + UInt8* dst = infoHeader; + toLE(dst, static_cast<UInt32>(40)); + toLE(dst, static_cast<SInt32>(w)); + toLE(dst, static_cast<SInt32>(h)); + toLE(dst, static_cast<UInt16>(1)); + toLE(dst, static_cast<UInt16>(depth)); + toLE(dst, static_cast<UInt32>(0)); // BI_RGB + toLE(dst, static_cast<UInt32>(image.size())); + toLE(dst, static_cast<SInt32>(2834)); // 72 dpi + toLE(dst, static_cast<SInt32>(2834)); // 72 dpi + toLE(dst, static_cast<UInt32>(0)); + toLE(dst, static_cast<UInt32>(0)); + + // construct image + return String(reinterpret_cast<const char*>(infoHeader), + sizeof(infoHeader)) + rawBMP; +} |
