}
/*
- * DIB color palettes are arrays of RGBQUAD structs with colors in BGRX format.
- * They are used only by 1, 2, 4, and 8-bit bitmaps.
- */
-static void fill_gdi_palette_for_icon(ICON_INFO* iconInfo, gdiPalette* palette)
-{
- UINT32 i;
- palette->format = PIXEL_FORMAT_BGRX32;
- ZeroMemory(palette->palette, sizeof(palette->palette));
-
- if (!iconInfo->cbColorTable)
- return;
-
- if ((iconInfo->cbColorTable % 4 != 0) || (iconInfo->cbColorTable / 4 > 256))
- {
- WLog_WARN(TAG, "weird palette size: %u", iconInfo->cbColorTable);
- return;
- }
-
- for (i = 0; i < iconInfo->cbColorTable / 4; i++)
- {
- palette->palette[i] = ReadColor(&iconInfo->colorTable[4 * i], palette->format);
- }
-}
-
-static BOOL convert_icon_color_to_argb(ICON_INFO* iconInfo, BYTE* argbPixels)
-{
- DWORD format;
- gdiPalette palette;
-
- /*
- * Color formats used by icons are DIB bitmap formats (2-bit format
- * is not used by MS-RDPERP). Note that 16-bit is RGB555, not RGB565,
- * and that 32-bit format uses BGRA order.
- */
- switch (iconInfo->bpp)
- {
- case 1:
- case 4:
- /*
- * These formats are not supported by freerdp_image_copy().
- * PIXEL_FORMAT_MONO and PIXEL_FORMAT_A4 are *not* correct
- * color formats for this. Please fix freerdp_image_copy()
- * if you came here to fix a broken icon of some weird app
- * that still uses 1 or 4bpp format in the 21st century.
- */
- WLog_WARN(TAG, "1bpp and 4bpp icons are not supported");
- return FALSE;
-
- case 8:
- format = PIXEL_FORMAT_RGB8;
- break;
-
- case 16:
- format = PIXEL_FORMAT_RGB15;
- break;
-
- case 24:
- format = PIXEL_FORMAT_RGB24;
- break;
-
- case 32:
- format = PIXEL_FORMAT_BGRA32;
- break;
-
- default:
- WLog_WARN(TAG, "invalid icon bpp: %d", iconInfo->bpp);
- return FALSE;
- }
-
- fill_gdi_palette_for_icon(iconInfo, &palette);
- return freerdp_image_copy(
- argbPixels,
- PIXEL_FORMAT_ARGB32,
- 0, 0, 0,
- iconInfo->width,
- iconInfo->height,
- iconInfo->bitsColor,
- format,
- 0, 0, 0,
- &palette,
- FREERDP_FLIP_VERTICAL
- );
-}
-
-static inline UINT32 div_ceil(UINT32 a, UINT32 b)
-{
- return (a + (b - 1)) / b;
-}
-
-static inline UINT32 round_up(UINT32 a, UINT32 b)
-{
- return b * div_ceil(a, b);
-}
-
-static void apply_icon_alpha_mask(ICON_INFO* iconInfo, BYTE* argbPixels)
-{
- BYTE nextBit;
- BYTE* maskByte;
- UINT32 x, y;
- UINT32 stride;
-
- if (!iconInfo->cbBitsMask)
- return;
-
- /*
- * Each byte encodes 8 adjacent pixels (with LSB padding as needed).
- * And due to hysterical raisins, stride of DIB bitmaps must be
- * a multiple of 4 bytes.
- */
- stride = round_up(div_ceil(iconInfo->width, 8), 4);
-
- for (y = 0; y < iconInfo->height; y++)
- {
- /* ɐᴉlɐɹʇsn∀ uᴉ ǝɹ,ǝʍ ʇɐɥʇ ʇǝƃɹoɟ ʇ,uop */
- maskByte = &iconInfo->bitsMask[stride * (iconInfo->height - 1 - y)];
- nextBit = 0x80;
-
- for (x = 0; x < iconInfo->width; x++)
- {
- BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
- argbPixels[4 * (x + y * iconInfo->width)] &= alpha;
- nextBit >>= 1;
-
- if (!nextBit)
- {
- nextBit = 0x80;
- maskByte++;
- }
- }
- }
-}
-
-/*
* _NET_WM_ICON format is defined as "array of CARDINAL" values which for
* Xlib must be represented with an array of C's "long" values. Note that
* "long" != "INT32" on 64-bit systems. Therefore we can't simply cast
*/
static BOOL convert_rail_icon(ICON_INFO* iconInfo, xfRailIcon* railIcon)
{
- BYTE* argbPixels;
+ BYTE* argbPixels = NULL;
BYTE* nextPixel;
long* pixels;
int i;
if (!argbPixels)
goto error;
- if (!convert_icon_color_to_argb(iconInfo, argbPixels))
+ if (!freerdp_image_copy_from_icon_data(argbPixels,
+ PIXEL_FORMAT_ARGB32, 0, 0, 0,
+ iconInfo->width, iconInfo->height,
+ iconInfo->bitsColor, iconInfo->cbBitsColor,
+ iconInfo->bitsMask, iconInfo->cbBitsMask,
+ iconInfo->colorTable, iconInfo->cbColorTable, iconInfo->bpp))
goto error;
- apply_icon_alpha_mask(iconInfo, argbPixels);
nelements = 2 + iconInfo->width * iconInfo->height;
pixels = realloc(railIcon->data, nelements * sizeof(long));
* @param nYDst destination buffer offset y
* @param nWidth width to copy in pixels
* @param nHeight height to copy in pixels
+ * @param bitsColor icon's image data buffer
+ * @param cbBitsColor length of the image data buffer in bytes
+ * @param bitsMask icon's 1bpp image mask buffer
+ * @param cbBitsMask length of the image mask buffer in bytes
+ * @param colorTable icon's image color table
+ * @param cbBitsColor length of the image color table buffer in bytes
+ * @param bpp color image data bits per pixel
+ *
+ * @return TRUE if success, FALSE otherwise
+ */
+FREERDP_API BOOL freerdp_image_copy_from_icon_data(
+ BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
+ UINT32 nXDst, UINT32 nYDst, UINT16 nWidth, UINT16 nHeight,
+ const BYTE* bitsColor, UINT16 cbBitsColor,
+ const BYTE* bitsMask, UINT16 cbBitsMask,
+ const BYTE* colorTable, UINT16 cbColorTable,
+ UINT32 bpp);
+
+/***
+ *
+ * @param pDstData destination buffer
+ * @param DstFormat destination buffer format
+ * @param nDstStep destination buffer stride (line in bytes) 0 for default
+ * @param nXDst destination buffer offset x
+ * @param nYDst destination buffer offset y
+ * @param nWidth width to copy in pixels
+ * @param nHeight height to copy in pixels
* @param xorMask XOR mask buffer
* @param xorMaskLength XOR mask length in bytes
* @param andMask AND mask buffer
return FreeRDPGetColor(format, fill, fill, fill, 0xFF);
}
+
+/*
+ * DIB color palettes are arrays of RGBQUAD structs with colors in BGRX format.
+ * They are used only by 1, 2, 4, and 8-bit bitmaps.
+ */
+static void fill_gdi_palette_for_icon(const BYTE* colorTable, UINT16 cbColorTable, gdiPalette* palette)
+{
+ UINT16 i;
+ palette->format = PIXEL_FORMAT_BGRX32;
+ ZeroMemory(palette->palette, sizeof(palette->palette));
+
+ if (!cbColorTable)
+ return;
+
+ if ((cbColorTable % 4 != 0) || (cbColorTable / 4 > 256))
+ {
+ WLog_WARN(TAG, "weird palette size: %u", cbColorTable);
+ return;
+ }
+
+ for (i = 0; i < cbColorTable / 4; i++)
+ {
+ palette->palette[i] = ReadColor(&colorTable[4 * i], palette->format);
+ }
+}
+
+static INLINE UINT32 div_ceil(UINT32 a, UINT32 b)
+{
+ return (a + (b - 1)) / b;
+}
+
+static INLINE UINT32 round_up(UINT32 a, UINT32 b)
+{
+ return b * div_ceil(a, b);
+}
+
+BOOL freerdp_image_copy_from_icon_data(
+ BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
+ UINT32 nXDst, UINT32 nYDst, UINT16 nWidth, UINT16 nHeight,
+ const BYTE* bitsColor, UINT16 cbBitsColor,
+ const BYTE* bitsMask, UINT16 cbBitsMask,
+ const BYTE* colorTable, UINT16 cbColorTable,
+ UINT32 bpp)
+{
+ DWORD format;
+ gdiPalette palette;
+
+ if (!pDstData || !bitsColor)
+ return FALSE;
+
+ /*
+ * Color formats used by icons are DIB bitmap formats (2-bit format
+ * is not used by MS-RDPERP). Note that 16-bit is RGB555, not RGB565,
+ * and that 32-bit format uses BGRA order.
+ */
+ switch (bpp)
+ {
+ case 1:
+ case 4:
+ /*
+ * These formats are not supported by freerdp_image_copy().
+ * PIXEL_FORMAT_MONO and PIXEL_FORMAT_A4 are *not* correct
+ * color formats for this. Please fix freerdp_image_copy()
+ * if you came here to fix a broken icon of some weird app
+ * that still uses 1 or 4bpp format in the 21st century.
+ */
+ WLog_WARN(TAG, "1bpp and 4bpp icons are not supported");
+ return FALSE;
+
+ case 8:
+ format = PIXEL_FORMAT_RGB8;
+ break;
+
+ case 16:
+ format = PIXEL_FORMAT_RGB15;
+ break;
+
+ case 24:
+ format = PIXEL_FORMAT_RGB24;
+ break;
+
+ case 32:
+ format = PIXEL_FORMAT_BGRA32;
+ break;
+
+ default:
+ WLog_WARN(TAG, "invalid icon bpp: %d", bpp);
+ return FALSE;
+ }
+
+ fill_gdi_palette_for_icon(colorTable, cbColorTable, &palette);
+ if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
+ nWidth, nHeight, bitsColor, format, 0, 0, 0, &palette,
+ FREERDP_FLIP_VERTICAL))
+ return FALSE;
+
+ /* apply alpha mask */
+ if (ColorHasAlpha(DstFormat) && cbBitsMask)
+ {
+ BYTE nextBit;
+ const BYTE* maskByte;
+ UINT32 x, y;
+ UINT32 stride;
+ BYTE r, g, b;
+ BYTE* dstBuf = pDstData;
+ UINT32 dstBpp = GetBytesPerPixel(DstFormat);
+
+ /*
+ * Each byte encodes 8 adjacent pixels (with LSB padding as needed).
+ * And due to hysterical raisins, stride of DIB bitmaps must be
+ * a multiple of 4 bytes.
+ */
+ stride = round_up(div_ceil(nWidth, 8), 4);
+
+ for (y = 0; y < nHeight; y++)
+ {
+ maskByte = &bitsMask[stride * (nHeight - 1 - y)];
+ nextBit = 0x80;
+
+ for (x = 0; x < nWidth; x++)
+ {
+ UINT32 color;
+ BYTE alpha = (*maskByte & nextBit) ? 0x00 : 0xFF;
+
+ /* read color back, add alpha and write it back */
+ color = ReadColor(dstBuf, DstFormat);
+ SplitColor(color, DstFormat, &r, &g, &b, NULL, &palette);
+ color = FreeRDPGetColor(DstFormat, r, g, b, alpha);
+ WriteColor(dstBuf, DstFormat, color);
+
+ nextBit >>= 1;
+ dstBuf += dstBpp;
+ if (!nextBit)
+ {
+ nextBit = 0x80;
+ maskByte++;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
/**
* Drawing Monochrome Pointers:
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff556143/