Hi François,

Our OS-X expert has tested and integrated this patch. Thank you for the 
patch.

Regards,
Ram.


On 03/ 6/11 06:03 PM, François Revol wrote:
> I managed to get darwin to handle the bitmap clipboard format.
> I had to write some helpers to generate real BMP "files" since the passed DIB 
> miss the BM header... added them to clipboard-helpers.* for use by other OSes.
> I didn't bother supporting all DIB header types though, only the 40bytes one, 
> but it WorksForMe™ (XP guest) :
> http://revolf.free.fr/osx/shots/shot_osx_vbox_bitmap_clipboard.png
> Really using raw DIB data as exchange format wasn't really the best choice... 
> another option would be to change vbox to pass full BMP data around so only 
> win32 code would have to handle DIB-BMP conversion (for which it likely has a 
> native and more complete API than the helpers I wrote).
>
> Also tested with the Haiku guest additions I'm writing, and it works fine 
> except for a bug in Haiku's BMP translator which puts the image up-side-down 
> when the height field is negative, but that's not of vbox concern.
>
> This patch is under MIT license.
>
> François.
>
>
> Index: include/VBox/GuestHost/clipboard-helper.h
> ===================================================================
> --- include/VBox/GuestHost/clipboard-helper.h (revision 36094)
> +++ include/VBox/GuestHost/clipboard-helper.h (working copy)
> @@ -27,6 +27,7 @@
>   #ifndef ___CLIPBOARD_HELPER_H
>   #define ___CLIPBOARD_HELPER_H
>
> +#include<iprt/cdefs.h>
>   #include<iprt/string.h>
>
>   /** Constants needed for string conversions done by the Linux/Mac clipboard 
> code. */
> @@ -91,5 +92,71 @@
>    */
>   int vboxClipboardUtf16WinToLin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 
> pu16Dest, size_t cwDest);
>
> +#pragma pack(1)
> +/**
> + * Bitmap File Header. Official win32 name is BITMAPFILEHEADER
> + * Always Little Endian.
> + */
> +typedef struct BMFILEHEADER
> +{
> +    uint16_t    u16Type;
> +    uint32_t    u32Size;
> +    uint16_t    u16Reserved1;
> +    uint16_t    u16Reserved2;
> +    uint32_t    u32OffBits;
> +} BMFILEHEADER;
> +/** Pointer to a BMFILEHEADER structure. */
> +typedef BMFILEHEADER *PBMFILEHEADER;
> +/** BMP file magic number */
> +#define BITMAPHEADERMAGIC (RT_H2LE_U16_C(0x4d42))
> +
> +/**
> + * Bitmap Info Header. Official win32 name is BITMAPINFOHEADER
> + * Always Little Endian.
> + */
> +typedef struct BMINFOHEADER
> +{
> +    uint32_t    u32Size;
> +    uint32_t    u32Width;
> +    uint32_t    u32Height;
> +    uint16_t    u16Planes;
> +    uint16_t    u16BitCount;
> +    uint32_t    u32Compression;
> +    uint32_t    u32SizeImage;
> +    uint32_t    u32XBitsPerMeter;
> +    uint32_t    u32YBitsPerMeter;
> +    uint32_t    u32ClrUsed;
> +    uint32_t    u32ClrImportant;
> +} BMINFOHEADER;
> +/** Pointer to a BMINFOHEADER structure. */
> +typedef BMINFOHEADER *PBMINFOHEADER;
> +#pragma pack()
> +
> +/**
> + * Convert CF_DIB data to full BMP data by prepending the BM header.
> + * Allocates with RTMemAlloc.
> + *
> + * @returns VBox status code
> + *
> + * @param   pSrc          DIB data to convert
> + * @param   cbSrc         Size of the DIB data to convert in bytes
> + * @param   ppDest        Where to store the pointer to the buffer for the 
> destination data
> + * @param   pcbDest       Pointer to the size of the buffer for the 
> destination data in bytes
> + */
> +int vboxClipboardDibToBmp(const void *pSrc, size_t cbSrc, void **ppDest, 
> size_t *pcbDest);
> +
> +/**
> + * Get the address and size of CF_DIB data in a full BMP data in the input 
> buffer.
> + * Does not do any allocation.
> + *
> + * @returns VBox status code
> + *
> + * @param   pSrc          BMP data to convert
> + * @param   cbSrc         Size of the BMP data to convert in bytes
> + * @param   ppDest        Where to store the pointer to the destination data
> + * @param   pcbDest       Pointer to the size of the destination data in 
> bytes
> + */
> +int vboxClipboardBmpGetDib(const void *pSrc, size_t cbSrc, const void 
> **ppDest, size_t *pcbDest);
> +
>   #endif
>
> Index: src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp
> ===================================================================
> --- src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp   (revision 36094)
> +++ src/VBox/GuestHost/SharedClipboard/clipboard-helper.cpp   (working copy)
> @@ -15,6 +15,7 @@
>    * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
>    */
>
> +#include<iprt/alloc.h>
>   #include<iprt/assert.h>
>   #include<VBox/log.h>
>   #include<VBox/GuestHost/clipboard-helper.h>
> @@ -263,3 +264,62 @@
>       return VINF_SUCCESS;
>   }
>
> +int vboxClipboardDibToBmp(const void *pSrc, size_t cbSrc, void **ppDest, 
> size_t *pcbDest)
> +{
> +    size_t cb = sizeof(BMFILEHEADER) + cbSrc;
> +    PBMFILEHEADER pFileHeader;
> +    void *dest;
> +    size_t pixelOffset;
> +
> +    PBMINFOHEADER pBitmapInfoHeader = (PBMINFOHEADER)pSrc;
> +    if (cbSrc<  sizeof(BMINFOHEADER) ||
> +        RT_LE2H_U32(pBitmapInfoHeader->u32Size)<  sizeof(BMINFOHEADER) ||
> +    /** @todo Support all the many versions of the DIB headers. */
> +        RT_LE2H_U32(pBitmapInfoHeader->u32Size) != sizeof(BMINFOHEADER))
> +    {
> +        Log (("vboxClipboardDibToBmp: invalid or unsupported bitmap 
> data.\n"));
> +        return VERR_INVALID_PARAMETER;
> +    }
> +    pixelOffset = sizeof(BMFILEHEADER)
> +        + RT_LE2H_U32(pBitmapInfoHeader->u32Size)
> +        + RT_LE2H_U32(pBitmapInfoHeader->u32ClrUsed) * sizeof(uint32_t);
> +    if (cbSrc<  pixelOffset)
> +    {
> +        Log (("vboxClipboardDibToBmp: invalid bitmap data.\n"));
> +        return VERR_INVALID_PARAMETER;
> +    }
> +
> +    dest = RTMemAlloc(cb);
> +    if (dest == NULL)
> +    {
> +        Log (("writeToPasteboard: cannot allocate memory for bitmap.\n"));
> +        return VERR_NO_MEMORY;
> +    }
> +
> +    pFileHeader = (PBMFILEHEADER)dest;
> +    pFileHeader->u16Type = BITMAPHEADERMAGIC;
> +    pFileHeader->u32Size = RT_H2LE_U32(cb);
> +    pFileHeader->u16Reserved1 = pFileHeader->u16Reserved2 = 0;
> +    pFileHeader->u32OffBits = RT_H2LE_U32(pixelOffset);
> +    memcpy((uint8_t *)dest + sizeof(BMFILEHEADER), pSrc, cbSrc);
> +    *ppDest = dest;
> +    *pcbDest = cb;
> +    return VINF_SUCCESS;
> +}
> +
> +int vboxClipboardBmpGetDib(const void *pSrc, size_t cbSrc, const void 
> **pDest, size_t *pcbDest)
> +{
> +    PBMFILEHEADER pFileHeader = (PBMFILEHEADER)pSrc;
> +
> +    if (pFileHeader == NULL || cbSrc<  sizeof(BMFILEHEADER) ||
> +        pFileHeader->u16Type != BITMAPHEADERMAGIC ||
> +        RT_LE2H_U32(pFileHeader->u32Size) != cbSrc)
> +    {
> +        Log (("vboxClipboardBmpGetDib: invalid bitmap data.\n"));
> +        return VERR_INVALID_PARAMETER;
> +    }
> +    *pDest = ((uint8_t *)pSrc) + sizeof(BMFILEHEADER);
> +    *pcbDest = cbSrc - sizeof(BMFILEHEADER);
> +    return VINF_SUCCESS;
> +}
> +
> Index: src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp
> ===================================================================
> --- src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp       
> (revision 36094)
> +++ src/VBox/HostServices/SharedClipboard/darwin-pasteboard.cpp       
> (working copy)
> @@ -116,6 +116,11 @@
>                       Log (("Unicode flavor detected.\n"));
>                       *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
>                   }
> +                if (UTTypeConformsTo (flavorType, kUTTypeBMP))
> +                {
> +                    Log (("BMP flavor detected.\n"));
> +                    *pfFormats |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
> +                }
>               }
>               CFRelease (flavorTypeArray);
>           }
> @@ -209,6 +214,44 @@
>                   RTUtf16Free (pwszTmp);
>               }
>           }
> +        /* The guest request BITMAP */
> +        else if (fFormat&  VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
> +        {
> +            CFDataRef outData;
> +            const void *pTmp = NULL;
> +            size_t cbTmpSize;
> +            /* Get the data from the pasteboard */
> +            if (!(err = PasteboardCopyItemFlavorData (pPasteboard, itemID, 
> kUTTypeBMP,&outData)))
> +            {
> +                Log (("Clipboard content is BMP\n"));
> +                pTmp = CFDataGetBytePtr (outData);
> +                cbTmpSize = CFDataGetLength (outData);
> +            }
> +            if (pTmp)
> +            {
> +                const void *pDib;
> +                size_t cbDibSize;
> +                rc = vboxClipboardBmpGetDib (pTmp, 
> cbTmpSize,&pDib,&cbDibSize);
> +                if (RT_FAILURE (rc))
> +                {
> +                    rc = VERR_NOT_SUPPORTED;
> +                    Log (("readFromPasteboard: unknown bitmap format.  
> vboxClipboardBmpGetDib returned %Rrc.  Abandoning.\n", rc));
> +                    AssertRCReturn (rc, rc);
> +                }
> +
> +                *pcbActual = cbDibSize;
> +                /* Return success state */
> +                rc = VINF_SUCCESS;
> +                /* Do not copy data if the dst buffer is not big enough. */
> +                if (*pcbActual<= cb)
> +                {
> +                    memcpy (pv, pDib, cbDibSize);
> +#ifdef SHOW_CLIPBOARD_CONTENT
> +                    Log (("readFromPasteboard: clipboard content bitmap %d 
> bytes\n", cbDibSize));
> +#endif
> +                }
> +            }
> +        }
>       }
>
>       Log (("readFromPasteboard: rc = %02X\n", rc));
> @@ -305,6 +348,33 @@
>           RTMemFree (pwszDestText);
>           rc = VINF_SUCCESS;
>       }
> +    /* Handle the bitmap */
> +    else if (fFormat&  VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
> +    {
> +        /* Create a full BMP from it */
> +        void *pBmp;
> +        size_t cbBmpSize;
> +        CFDataRef bmpData = NULL;
> +        /* Item id is 1. Nothing special here. */
> +        PasteboardItemID itemId = (PasteboardItemID)1;
> +
> +        rc = vboxClipboardDibToBmp (pv, cb,&pBmp,&cbBmpSize);
> +        if (RT_SUCCESS (rc))
> +        {
> +            /* Create a CData object which we could pass to the pasteboard */
> +            if ((bmpData = CFDataCreate (kCFAllocatorDefault,
> +                                          reinterpret_cast<UInt8*>  (pBmp), 
> cbBmpSize)))
> +            {
> +                /* Put the Utf-8 version to the pasteboard */
> +                PasteboardPutItemFlavor (pPasteboard, itemId,
> +                                         kUTTypeBMP,
> +                                         bmpData, 0);
> +            }
> +            RTMemFree (pBmp);
> +        }
> +
> +        rc = VINF_SUCCESS;
> +    }
>       else
>           rc = VERR_NOT_IMPLEMENTED;
>
>
>
> _______________________________________________
> vbox-dev mailing list
> [email protected]
> http://vbox.innotek.de/mailman/listinfo/vbox-dev


_______________________________________________
vbox-dev mailing list
[email protected]
https://www.virtualbox.org/mailman/listinfo/vbox-dev

Reply via email to