diff --git a/libfreerdp-gdi/gdi.h b/libfreerdp-gdi/gdi.h new file mode 100644 index 000000000..472077ed1 --- /dev/null +++ b/libfreerdp-gdi/gdi.h @@ -0,0 +1,273 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Library + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef __GDI_H +#define __GDI_H + +#include "color.h" +#include +#include +#include + +/* For more information, see [MS-RDPEGDI] */ + +/* Binary Raster Operations (ROP2) */ +#define GDI_R2_BLACK 0x01 /* D = 0 */ +#define GDI_R2_NOTMERGEPEN 0x02 /* D = ~(D | P) */ +#define GDI_R2_MASKNOTPEN 0x03 /* D = D & ~P */ +#define GDI_R2_NOTCOPYPEN 0x04 /* D = ~P */ +#define GDI_R2_MASKPENNOT 0x05 /* D = P & ~D */ +#define GDI_R2_NOT 0x06 /* D = ~D */ +#define GDI_R2_XORPEN 0x07 /* D = D ^ P */ +#define GDI_R2_NOTMASKPEN 0x08 /* D = ~(D & P) */ +#define GDI_R2_MASKPEN 0x09 /* D = D & P */ +#define GDI_R2_NOTXORPEN 0x0A /* D = ~(D ^ P) */ +#define GDI_R2_NOP 0x0B /* D = D */ +#define GDI_R2_MERGENOTPEN 0x0C /* D = D | ~P */ +#define GDI_R2_COPYPEN 0x0D /* D = P */ +#define GDI_R2_MERGEPENNOT 0x0E /* D = P | ~D */ +#define GDI_R2_MERGEPEN 0x0F /* D = P | D */ +#define GDI_R2_WHITE 0x10 /* D = 1 */ + +/* Ternary Raster Operations (ROP3) */ +#define GDI_SRCCOPY 0x00CC0020 /* D = S */ +#define GDI_SRCPAINT 0x00EE0086 /* D = S | D */ +#define GDI_SRCAND 0x008800C6 /* D = S & D */ +#define GDI_SRCINVERT 0x00660046 /* D = S ^ D */ +#define GDI_SRCERASE 0x00440328 /* D = S & ~D */ +#define GDI_NOTSRCCOPY 0x00330008 /* D = ~S */ +#define GDI_NOTSRCERASE 0x001100A6 /* D = ~S & ~D */ +#define GDI_MERGECOPY 0x00C000CA /* D = S & P */ +#define GDI_MERGEPAINT 0x00BB0226 /* D = ~S | D */ +#define GDI_PATCOPY 0x00F00021 /* D = P */ +#define GDI_PATPAINT 0x00FB0A09 /* D = D | (P | ~S) */ +#define GDI_PATINVERT 0x005A0049 /* D = P ^ D */ +#define GDI_DSTINVERT 0x00550009 /* D = ~D */ +#define GDI_BLACKNESS 0x00000042 /* D = 0 */ +#define GDI_WHITENESS 0x00FF0062 /* D = 1 */ +#define GDI_DSPDxax 0x00E20746 /* D = (S & P) | (~S & D) */ +#define GDI_SPna 0x000C0324 /* D = S & ~P */ +#define GDI_DSna 0x00220326 /* D = D & ~S */ + +/* Brush Styles */ +#define GDI_BS_SOLID 0x00 +#define GDI_BS_NULL 0x01 +#define GDI_BS_HATCHED 0x02 +#define GDI_BS_PATTERN 0x03 + +/* Hatch Patterns */ +#define GDI_HS_HORIZONTAL 0x00 +#define GDI_HS_VERTICAL 0x01 +#define GDI_HS_FDIAGONAL 0x02 +#define GDI_HS_BDIAGONAL 0x03 +#define GDI_HS_CROSS 0x04 +#define GDI_HS_DIAGCROSS 0x05 + +/* Pen Styles */ +#define GDI_PS_SOLID 0x00 +#define GDI_PS_DASH 0x01 +#define GDI_PS_NULL 0x05 + +/* Background Modes */ +#define GDI_OPAQUE 0x00000001 +#define GDI_TRANSPARENT 0x00000002 + +/* GDI Object Types */ +#define GDIOBJECT_BITMAP 0x00 +#define GDIOBJECT_PEN 0x01 +#define GDIOBJECT_PALETTE 0x02 +#define GDIOBJECT_BRUSH 0x03 +#define GDIOBJECT_RECT 0x04 +#define GDIOBJECT_REGION 0x04 + +struct _GDIOBJECT +{ + uint8 objectType; +}; +typedef struct _GDIOBJECT GDIOBJECT; +typedef GDIOBJECT* HGDIOBJECT; + +/* RGB encoded as 0x00BBGGRR */ +typedef unsigned int GDI_COLOR; +typedef GDI_COLOR* LPGDI_COLOR; + +struct _GDI_RECT +{ + uint8 objectType; + int left; + int top; + int right; + int bottom; +}; +typedef struct _GDI_RECT GDI_RECT; +typedef GDI_RECT* HGDI_RECT; + +struct _GDI_RGN +{ + uint8 objectType; + int x; /* left */ + int y; /* top */ + int w; /* width */ + int h; /* height */ + int null; /* null region */ +}; +typedef struct _GDI_RGN GDI_RGN; +typedef GDI_RGN* HGDI_RGN; + +struct _GDI_BITMAP +{ + uint8 objectType; + int bytesPerPixel; + int bitsPerPixel; + int width; + int height; + int scanline; + uint8* data; +}; +typedef struct _GDI_BITMAP GDI_BITMAP; +typedef GDI_BITMAP* HGDI_BITMAP; + +struct _GDI_PEN +{ + uint8 objectType; + int style; + int width; + int posX; + int posY; + GDI_COLOR color; +}; +typedef struct _GDI_PEN GDI_PEN; +typedef GDI_PEN* HGDI_PEN; + +struct _GDI_PALETTEENTRY +{ + uint8 red; + uint8 green; + uint8 blue; +}; +typedef struct _GDI_PALETTEENTRY GDI_PALETTEENTRY; + +struct _GDI_PALETTE +{ + uint16 count; + GDI_PALETTEENTRY *entries; +}; +typedef struct _GDI_PALETTE GDI_PALETTE; +typedef GDI_PALETTE* HGDI_PALETTE; + +struct _GDI_POINT +{ + int x; + int y; +}; +typedef struct _GDI_POINT GDI_POINT; +typedef GDI_POINT* HGDI_POINT; + +struct _GDI_BRUSH +{ + uint8 objectType; + int style; + HGDI_BITMAP pattern; + GDI_COLOR color; +}; +typedef struct _GDI_BRUSH GDI_BRUSH; +typedef GDI_BRUSH* HGDI_BRUSH; + +struct _GDI_WND +{ + HGDI_RGN invalid; +}; +typedef struct _GDI_WND GDI_WND; +typedef GDI_WND* HGDI_WND; + +struct _GDI_DC +{ + HGDIOBJECT selectedObject; + int bytesPerPixel; + int bitsPerPixel; + GDI_COLOR bkColor; + GDI_COLOR textColor; + HGDI_BRUSH brush; + HGDI_RGN clip; + HGDI_PEN pen; + HGDI_WND hwnd; + int drawMode; + int bkMode; + int alpha; + int invert; + int rgb555; +}; +typedef struct _GDI_DC GDI_DC; +typedef GDI_DC* HGDI_DC; + +struct _GDI_IMAGE +{ + HGDI_DC hdc; + HGDI_BITMAP bitmap; + HGDI_BITMAP org_bitmap; +}; +typedef struct _GDI_IMAGE GDI_IMAGE; +typedef GDI_IMAGE* HGDI_IMAGE; + +struct _GDI +{ + int width; + int height; + int dstBpp; + int srcBpp; + int cursor_x; + int cursor_y; + int bytesPerPixel; + + HGDI_DC hdc; + HCLRCONV clrconv; + GDI_IMAGE *primary; + GDI_IMAGE *drawing; + uint8* primary_buffer; + GDI_COLOR textColor; + void * rfx_context; + GDI_IMAGE *tile; +}; +typedef struct _GDI GDI; + +uint32 gdi_rop3_code(uint8 code); +void gdi_copy_mem(uint8 *d, uint8 *s, int n); +void gdi_copy_memb(uint8 *d, uint8 *s, int n); +uint8* gdi_get_bitmap_pointer(HGDI_DC hdcBmp, int x, int y); +uint8* gdi_get_brush_pointer(HGDI_DC hdcBrush, int x, int y); +int gdi_is_mono_pixel_set(uint8* data, int x, int y, int width); +int gdi_init(rdpInst * inst, uint32 flags); +GDI_IMAGE* gdi_bitmap_new(GDI *gdi, int width, int height, int bpp, uint8* data); +void gdi_bitmap_free(GDI_IMAGE *gdi_bmp); +void gdi_free(rdpInst* inst); + +#define SET_GDI(_inst, _gdi) (_inst)->param2 = _gdi +#define GET_GDI(_inst) ((GDI*) ((_inst)->param2)) + +#ifdef WITH_DEBUG_GDI +#define DEBUG_GDI(fmt, ...) DEBUG_CLASS(GDI, fmt, ## __VA_ARGS__) +#else +#define DEBUG_GDI(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) +#endif + +#endif /* __GDI_H */ diff --git a/libfreerdp-gdi/gdi_16bpp.c b/libfreerdp-gdi/gdi_16bpp.c new file mode 100644 index 000000000..b4d07b530 --- /dev/null +++ b/libfreerdp-gdi/gdi_16bpp.c @@ -0,0 +1,1044 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI 16bpp Internal Buffer Routines + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "gdi.h" +#include "color.h" +#include "gdi_pen.h" +#include "gdi_bitmap.h" +#include "gdi_region.h" +#include "gdi_clipping.h" +#include "gdi_drawing.h" + +#include "gdi_16bpp.h" + +uint16 gdi_get_color_16bpp(HGDI_DC hdc, GDI_COLOR color) +{ + uint8 r, g, b; + uint16 color16; + + GetRGB32(r, g, b, color); + + if(hdc->rgb555) + { + if (hdc->invert) + { + color16 = BGR15(r, g, b); + } + else + { + color16 = RGB15(r, g, b); + } + } + else + { + if (hdc->invert) + { + color16 = BGR16(r, g, b); + } + else + { + color16 = RGB16(r, g, b); + } + } + + return color16; +} + +int FillRect_16bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) +{ + int x, y; + uint16 *dstp; + int nXDest, nYDest; + int nWidth, nHeight; + + uint16 color16; + + gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight); + + if (gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + + color16 = gdi_get_color_16bpp(hdc, hbr->color); + + for (y = 0; y < nHeight; y++) + { + dstp = (uint16*) gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = color16; + dstp++; + } + } + } + + gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight); + return 0; +} + +static int BitBlt_BLACKNESS_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + memset(dstp, 0, nWidth * hdcDest->bytesPerPixel); + } + + return 0; +} + +static int BitBlt_WHITENESS_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + memset(dstp, 0xFF, nWidth * hdcDest->bytesPerPixel); + } + + return 0; +} + +static int BitBlt_SRCCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int y; + uint8 *srcp; + uint8 *dstp; + + if ((hdcDest->selectedObject != hdcSrc->selectedObject) || + gdi_CopyOverlap(nXDest, nYDest, nWidth, nHeight, nXSrc, nYSrc) == 0) + { + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + + return 0; + } + + if (nYSrc < nYDest) + { + /* copy down (bottom to top) */ + for (y = nHeight - 1; y >= 0; y--) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + else if (nYSrc > nYDest || nXSrc > nXDest) + { + /* copy up or left (top top bottom) */ + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + else + { + /* copy straight right */ + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_memb(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + + return 0; +} + +static int BitBlt_NOTSRCCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp); + srcp++; + dstp++; + + *dstp = ~(*srcp); + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_DSTINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*dstp); + dstp++; + + *dstp = ~(*dstp); + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCERASE_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = *srcp & ~(*dstp); + srcp++; + dstp++; + + *dstp = *srcp & ~(*dstp); + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_NOTSRCERASE_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) & ~(*dstp); + srcp++; + dstp++; + + *dstp = ~(*srcp) & ~(*dstp); + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp ^= *srcp; + srcp++; + dstp++; + + *dstp ^= *srcp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCAND_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp &= *srcp; + srcp++; + dstp++; + + *dstp &= *srcp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp |= *srcp; + srcp++; + dstp++; + + *dstp |= *srcp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_DSPDxax_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + uint16 color16; + HGDI_BITMAP hSrcBmp; + + /* D = (S & P) | (~S & D) */ + /* DSPDxax, used to draw glyphs */ + + color16 = gdi_get_color_16bpp(hdcDest, hdcDest->textColor); + + hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; + srcp = hSrcBmp->data; + + if (hdcSrc->bytesPerPixel != 1) + { + printf("BitBlt_DSPDxax expects 1 bpp, unimplemented for %d\n", hdcSrc->bytesPerPixel); + return 0; + } + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = (uint8*) &color16; + + *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); + dstp++; + patp++; + + *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); + dstp++; + patp++; + srcp++; + } + } + } + + return 0; +} + +static int BitBlt_SPna_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *srcp & ~(*patp); + patp++; + srcp++; + dstp++; + + *dstp = *srcp & ~(*patp); + patp++; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_DSna_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) & (*dstp); + srcp++; + dstp++; + + *dstp = ~(*srcp) & (*dstp); + srcp++; + dstp++; + } + } + } + + return 0; +} + + +static int BitBlt_MERGECOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *srcp & *patp; + patp++; + srcp++; + dstp++; + + *dstp = *srcp & *patp; + patp++; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_MERGEPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) | *dstp; + srcp++; + dstp++; + + *dstp = ~(*srcp) | *dstp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_PATCOPY_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + uint8 *patp; + uint16 color16; + uint16 *dstp16; + + if(hdcDest->brush->style == GDI_BS_SOLID) + { + color16 = gdi_get_color_16bpp(hdcDest, hdcDest->brush->color); + + for (y = 0; y < nHeight; y++) + { + dstp16 = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp16 != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp16 = color16; + dstp16++; + } + } + } + } + else + { + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *patp; + patp++; + dstp++; + + *dstp = *patp; + patp++; + dstp++; + } + } + } + } + + return 0; +} + +static int BitBlt_PATINVERT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + uint8 *patp; + uint16 color16; + uint16 *dstp16; + + if(hdcDest->brush->style == GDI_BS_SOLID) + { + color16 = gdi_get_color_16bpp(hdcDest, hdcDest->brush->color); + + for (y = 0; y < nHeight; y++) + { + dstp16 = (uint16*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp16 != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp16 ^= color16; + dstp16++; + } + } + } + } + else + { + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *patp ^ *dstp; + patp++; + dstp++; + + *dstp = *patp ^ *dstp; + patp++; + dstp++; + } + } + } + } + + return 0; +} + +static int BitBlt_PATPAINT_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *dstp | (*patp | ~(*srcp)); + patp++; + srcp++; + dstp++; + + *dstp = *dstp | (*patp | ~(*srcp)); + patp++; + srcp++; + dstp++; + } + } + } + + return 0; +} + +int BitBlt_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) +{ + if (hdcSrc != NULL) + { + if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc) == 0) + return 0; + } + else + { + if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + } + + gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight); + + switch (rop) + { + case GDI_BLACKNESS: + return BitBlt_BLACKNESS_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_WHITENESS: + return BitBlt_WHITENESS_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_SRCCOPY: + return BitBlt_SRCCOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SPna: + return BitBlt_SPna_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSna: + return BitBlt_DSna_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSPDxax: + return BitBlt_DSPDxax_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_NOTSRCCOPY: + return BitBlt_NOTSRCCOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSTINVERT: + return BitBlt_DSTINVERT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_SRCERASE: + return BitBlt_SRCERASE_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_NOTSRCERASE: + return BitBlt_NOTSRCERASE_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCINVERT: + return BitBlt_SRCINVERT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCAND: + return BitBlt_SRCAND_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCPAINT: + return BitBlt_SRCPAINT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_MERGECOPY: + return BitBlt_MERGECOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_MERGEPAINT: + return BitBlt_MERGEPAINT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_PATCOPY: + return BitBlt_PATCOPY_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_PATINVERT: + return BitBlt_PATINVERT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_PATPAINT: + return BitBlt_PATPAINT_16bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + } + + printf("BitBlt: unknown rop: 0x%08X\n", rop); + return 1; +} + +int PatBlt_16bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) +{ + if (gdi_ClipCoords(hdc, &nXLeft, &nYLeft, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + + gdi_InvalidateRegion(hdc, nXLeft, nYLeft, nWidth, nHeight); + + switch (rop) + { + case GDI_PATCOPY: + return BitBlt_PATCOPY_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_PATINVERT: + return BitBlt_PATINVERT_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_DSTINVERT: + return BitBlt_DSTINVERT_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_BLACKNESS: + return BitBlt_BLACKNESS_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_WHITENESS: + return BitBlt_WHITENESS_16bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + } + + printf("PatBlt: unknown rop: 0x%08X", rop); + return 1; +} + +void SetPixel_BLACK_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = 0 */ + *pixel = 0; +} + +void SetPixel_NOTMERGEPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = ~(D | P) */ + *pixel = ~(*pixel | *pen); +} + +void SetPixel_MASKNOTPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = D & ~P */ + *pixel &= ~(*pen); +} + +void SetPixel_NOTCOPYPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = ~P */ + *pixel = ~(*pen); +} + +void SetPixel_MASKPENNOT_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = P & ~D */ + *pixel = *pen & ~*pixel; +} + +void SetPixel_NOT_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = ~D */ + *pixel = ~(*pixel); +} + +void SetPixel_XORPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = D ^ P */ + *pixel = *pixel ^ *pen; +} + +void SetPixel_NOTMASKPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = ~(D & P) */ + *pixel = ~(*pixel & *pen); +} + +void SetPixel_MASKPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = D & P */ + *pixel &= *pen; +} + +void SetPixel_NOTXORPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = ~(D ^ P) */ + *pixel = ~(*pixel ^ *pen); +} + +void SetPixel_NOP_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = D */ +} + +void SetPixel_MERGENOTPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = D | ~P */ + *pixel |= ~(*pen); +} + +void SetPixel_COPYPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = P */ + *pixel = *pen; +} + +void SetPixel_MERGEPENNOT_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = P | ~D */ + *pixel = *pen | ~(*pixel); +} + +void SetPixel_MERGEPEN_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = P | D */ + *pixel |= *pen; +} + +void SetPixel_WHITE_16bpp(uint16 *pixel, uint16 *pen) +{ + /* D = 1 */ + *pixel = 0xFFFF; +} + +pSetPixel16_ROP2 SetPixel16_ROP2_[16] = +{ + SetPixel_BLACK_16bpp, + SetPixel_NOTMERGEPEN_16bpp, + SetPixel_MASKNOTPEN_16bpp, + SetPixel_NOTCOPYPEN_16bpp, + SetPixel_MASKPENNOT_16bpp, + SetPixel_NOT_16bpp, + SetPixel_XORPEN_16bpp, + SetPixel_NOTMASKPEN_16bpp, + SetPixel_MASKPEN_16bpp, + SetPixel_NOTXORPEN_16bpp, + SetPixel_NOP_16bpp, + SetPixel_MERGENOTPEN_16bpp, + SetPixel_COPYPEN_16bpp, + SetPixel_MERGEPENNOT_16bpp, + SetPixel_MERGEPEN_16bpp, + SetPixel_WHITE_16bpp +}; + +int LineTo_16bpp(HGDI_DC hdc, int nXEnd, int nYEnd) +{ + int x, y; + int x1, y1; + int x2, y2; + int e, e2; + int dx, dy; + int sx, sy; + HGDI_BITMAP bmp; + int bx1, by1; + int bx2, by2; + + int irop2; + uint16 pen; + uint16 *pixel; + + x1 = hdc->pen->posX; + y1 = hdc->pen->posY; + x2 = nXEnd; + y2 = nYEnd; + + dx = (x1 > x2) ? x1 - x2 : x2 - x1; + dy = (y1 > y2) ? y1 - y2 : y2 - y1; + + sx = (x1 < x2) ? 1 : -1; + sy = (y1 < y2) ? 1 : -1; + + e = dx - dy; + + x = x1; + y = y1; + + irop2 = gdi_GetROP2(hdc) - 1; + bmp = (HGDI_BITMAP) hdc->selectedObject; + + if (hdc->clip->null) + { + bx1 = (x1 < x2) ? x1 : x2; + by1 = (y1 < y2) ? y1 : y2; + bx2 = (x1 > x2) ? x1 : x2; + by2 = (y1 > y2) ? y1 : y2; + } + else + { + bx1 = hdc->clip->x; + by1 = hdc->clip->y; + bx2 = bx1 + hdc->clip->w - 1; + by2 = by1 + hdc->clip->h - 1; + } + + pen = gdi_GetPenColor_16bpp(hdc->pen); + + while (1) + { + if (!(x == x2 && y == y2)) + { + if ((x >= bx1 && x <= bx2) && (y >= by1 && y <= by2)) + { + pixel = gdi_GetPointer_16bpp(bmp, x, y); + SetPixel16_ROP2_[irop2](pixel, &pen); + } + } + else + { + break; + } + + e2 = 2 * e; + + if (e2 > -dy) + { + e -= dy; + x += sx; + } + + if (e2 < dx) + { + e += dx; + y += sy; + } + } + + return 1; +} diff --git a/libfreerdp-gdi/gdi_16bpp.h b/libfreerdp-gdi/gdi_16bpp.h new file mode 100644 index 000000000..5f51f1c91 --- /dev/null +++ b/libfreerdp-gdi/gdi_16bpp.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI 16bpp Internal Buffer Routines + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "gdi.h" + +typedef void (*pSetPixel16_ROP2)(uint16 *pixel, uint16 *pen); + +int FillRect_16bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); +int BitBlt_16bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); +int PatBlt_16bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); +int LineTo_16bpp(HGDI_DC hdc, int nXEnd, int nYEnd); diff --git a/libfreerdp-gdi/gdi_32bpp.c b/libfreerdp-gdi/gdi_32bpp.c new file mode 100644 index 000000000..0888386ae --- /dev/null +++ b/libfreerdp-gdi/gdi_32bpp.c @@ -0,0 +1,1117 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI 32bpp Internal Buffer Routines + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "gdi.h" +#include "color.h" +#include "gdi_pen.h" +#include "gdi_bitmap.h" +#include "gdi_region.h" +#include "gdi_clipping.h" +#include "gdi_drawing.h" + +#include "gdi_32bpp.h" + +uint32 gdi_get_color_32bpp(HGDI_DC hdc, GDI_COLOR color) +{ + uint32 color32; + uint8 a, r, g, b; + + a = 0xFF; + GetRGB32(r, g, b, color); + + if (hdc->invert) + { + color32 = ABGR32(a, r, g, b); + } + else + { + color32 = ARGB32(a, r, g, b); + } + + return color32; +} + +int FillRect_32bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) +{ + int x, y; + uint32 *dstp; + uint32 color32; + int nXDest, nYDest; + int nWidth, nHeight; + + gdi_RectToCRgn(rect, &nXDest, &nYDest, &nWidth, &nHeight); + + if (gdi_ClipCoords(hdc, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + + color32 = gdi_get_color_32bpp(hdc, hbr->color); + + for (y = 0; y < nHeight; y++) + { + dstp = (uint32*) gdi_get_bitmap_pointer(hdc, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = color32; + dstp++; + } + } + } + + gdi_InvalidateRegion(hdc, nXDest, nYDest, nWidth, nHeight); + return 0; +} + +static int BitBlt_BLACKNESS_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + if (hdcDest->alpha) + { + int x, y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = 0; + dstp++; + + *dstp = 0; + dstp++; + + *dstp = 0; + dstp++; + + *dstp = 0xFF; + dstp++; + } + } + } + } + else + { + int y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + memset(dstp, 0, nWidth * hdcDest->bytesPerPixel); + } + } + + return 0; +} + +static int BitBlt_WHITENESS_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + memset(dstp, 0xFF, nWidth * hdcDest->bytesPerPixel); + } + + return 0; +} + +static int BitBlt_SRCCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int y; + uint8 *srcp; + uint8 *dstp; + + if ((hdcDest->selectedObject != hdcSrc->selectedObject) || + gdi_CopyOverlap(nXDest, nYDest, nWidth, nHeight, nXSrc, nYSrc) == 0) + { + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + + return 0; + } + + if (nYSrc < nYDest) + { + /* copy down (bottom to top) */ + for (y = nHeight - 1; y >= 0; y--) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + else if (nYSrc > nYDest || nXSrc > nXDest) + { + /* copy up or left (top top bottom) */ + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + else + { + /* copy straight right */ + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_memb(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + + return 0; +} + +static int BitBlt_NOTSRCCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp); + srcp++; + dstp++; + + *dstp = ~(*srcp); + srcp++; + dstp++; + + *dstp = ~(*srcp); + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_DSTINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*dstp); + dstp++; + + *dstp = ~(*dstp); + dstp++; + + *dstp = ~(*dstp); + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_SRCERASE_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = *srcp & ~(*dstp); + srcp++; + dstp++; + + *dstp = *srcp & ~(*dstp); + srcp++; + dstp++; + + *dstp = *srcp & ~(*dstp); + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_NOTSRCERASE_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) & ~(*dstp); + srcp++; + dstp++; + + *dstp = ~(*srcp) & ~(*dstp); + srcp++; + dstp++; + + *dstp = ~(*srcp) & ~(*dstp); + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_SRCINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp ^= *srcp; + srcp++; + dstp++; + + *dstp ^= *srcp; + srcp++; + dstp++; + + *dstp ^= *srcp; + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_SRCAND_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp &= *srcp; + srcp++; + dstp++; + + *dstp &= *srcp; + srcp++; + dstp++; + + *dstp &= *srcp; + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_SRCPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp |= *srcp; + srcp++; + dstp++; + + *dstp |= *srcp; + srcp++; + dstp++; + + *dstp |= *srcp; + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_DSPDxax_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + uint32 color32; + HGDI_BITMAP hSrcBmp; + + /* D = (S & P) | (~S & D) */ + /* DSPDxax, used to draw glyphs */ + + color32 = gdi_get_color_32bpp(hdcDest, hdcDest->textColor); + + hSrcBmp = (HGDI_BITMAP) hdcSrc->selectedObject; + srcp = hSrcBmp->data; + + if (hdcSrc->bytesPerPixel != 1) + { + printf("BitBlt_DSPDxax expects 1 bpp, unimplemented for %d\n", hdcSrc->bytesPerPixel); + return 0; + } + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = (uint8*) &color32; + + *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); + dstp++; + patp++; + + *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); + dstp++; + patp++; + + *dstp = (*srcp & *patp) | (~(*srcp) & *dstp); + dstp += 2; + srcp++; + } + } + } + + return 0; +} + +static int BitBlt_SPna_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *srcp & ~(*patp); + patp++; + srcp++; + dstp++; + + *dstp = *srcp & ~(*patp); + patp++; + srcp++; + dstp++; + + *dstp = *srcp & ~(*patp); + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + +static int BitBlt_DSna_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) & (*dstp); + srcp++; + dstp++; + + *dstp = ~(*srcp) & (*dstp); + srcp++; + dstp++; + + *dstp = ~(*srcp) & (*dstp); + srcp += 2; + dstp += 2; + } + } + } + + return 0; +} + + +static int BitBlt_MERGECOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *srcp & *patp; + patp++; + srcp++; + dstp++; + + *dstp = *srcp & *patp; + patp++; + srcp++; + dstp++; + + *dstp = *srcp & *patp; + dstp += 2; + srcp += 2; + } + } + } + + return 0; +} + +static int BitBlt_MERGEPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) | *dstp; + srcp++; + dstp++; + + *dstp = ~(*srcp) | *dstp; + srcp++; + dstp++; + + *dstp = ~(*srcp) | *dstp; + dstp += 2; + srcp += 2; + } + } + } + + return 0; +} + +static int BitBlt_PATCOPY_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + uint8 *patp; + uint32 color32; + uint32 *dstp32; + + if(hdcDest->brush->style == GDI_BS_SOLID) + { + color32 = gdi_get_color_32bpp(hdcDest, hdcDest->brush->color); + + for (y = 0; y < nHeight; y++) + { + dstp32 = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp32 != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp32 = color32; + dstp32++; + } + } + } + } + else + { + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *patp; + patp++; + dstp++; + + *dstp = *patp; + patp++; + dstp++; + + *dstp = *patp; + dstp += 2; + } + } + } + } + + return 0; +} + +static int BitBlt_PATINVERT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + uint8 *patp; + uint32 color32; + uint32 *dstp32; + + if(hdcDest->brush->style == GDI_BS_SOLID) + { + color32 = gdi_get_color_32bpp(hdcDest, hdcDest->brush->color); + + for (y = 0; y < nHeight; y++) + { + dstp32 = (uint32*) gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp32 != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp32 ^= color32; + dstp32++; + } + } + } + } + else + { + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *patp ^ *dstp; + patp++; + dstp++; + + *dstp = *patp ^ *dstp; + patp++; + dstp++; + + *dstp = *patp ^ *dstp; + dstp += 2; + } + } + } + } + + return 0; +} + +static int BitBlt_PATPAINT_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *dstp | (*patp | ~(*srcp)); + patp++; + srcp++; + dstp++; + + *dstp = *dstp | (*patp | ~(*srcp)); + patp++; + srcp++; + dstp++; + + *dstp = *dstp | (*patp | ~(*srcp)); + dstp += 2; + srcp += 2; + } + } + } + + return 0; +} + +int BitBlt_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) +{ + if (hdcSrc != NULL) + { + if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc) == 0) + return 0; + } + else + { + if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + } + + gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight); + + switch (rop) + { + case GDI_BLACKNESS: + return BitBlt_BLACKNESS_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_WHITENESS: + return BitBlt_WHITENESS_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_SRCCOPY: + return BitBlt_SRCCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SPna: + return BitBlt_SPna_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSna: + return BitBlt_DSna_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSPDxax: + return BitBlt_DSPDxax_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_NOTSRCCOPY: + return BitBlt_NOTSRCCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSTINVERT: + return BitBlt_DSTINVERT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_SRCERASE: + return BitBlt_SRCERASE_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_NOTSRCERASE: + return BitBlt_NOTSRCERASE_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCINVERT: + return BitBlt_SRCINVERT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCAND: + return BitBlt_SRCAND_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCPAINT: + return BitBlt_SRCPAINT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_MERGECOPY: + return BitBlt_MERGECOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_MERGEPAINT: + return BitBlt_MERGEPAINT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_PATCOPY: + return BitBlt_PATCOPY_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_PATINVERT: + return BitBlt_PATINVERT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_PATPAINT: + return BitBlt_PATPAINT_32bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + } + + printf("BitBlt: unknown rop: 0x%08X\n", rop); + return 1; +} + +int PatBlt_32bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) +{ + if (gdi_ClipCoords(hdc, &nXLeft, &nYLeft, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + + gdi_InvalidateRegion(hdc, nXLeft, nYLeft, nWidth, nHeight); + + switch (rop) + { + case GDI_PATCOPY: + return BitBlt_PATCOPY_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_PATINVERT: + return BitBlt_PATINVERT_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_DSTINVERT: + return BitBlt_DSTINVERT_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_BLACKNESS: + return BitBlt_BLACKNESS_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_WHITENESS: + return BitBlt_WHITENESS_32bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + } + + printf("PatBlt: unknown rop: 0x%08X", rop); + return 1; +} + +void SetPixel_BLACK_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = 0 */ + *pixel = 0; +} + +void SetPixel_NOTMERGEPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = ~(D | P) */ + *pixel = ~(*pixel | *pen); +} + +void SetPixel_MASKNOTPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = D & ~P */ + *pixel &= ~(*pen); +} + +void SetPixel_NOTCOPYPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = ~P */ + *pixel = ~(*pen); +} + +void SetPixel_MASKPENNOT_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = P & ~D */ + *pixel = *pen & ~*pixel; +} + +void SetPixel_NOT_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = ~D */ + *pixel = ~(*pixel); +} + +void SetPixel_XORPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = D ^ P */ + *pixel = *pixel ^ *pen; +} + +void SetPixel_NOTMASKPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = ~(D & P) */ + *pixel = ~(*pixel & *pen); +} + +void SetPixel_MASKPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = D & P */ + *pixel &= *pen; +} + +void SetPixel_NOTXORPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = ~(D ^ P) */ + *pixel = ~(*pixel ^ *pen); +} + +void SetPixel_NOP_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = D */ +} + +void SetPixel_MERGENOTPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = D | ~P */ + *pixel |= ~(*pen); +} + +void SetPixel_COPYPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = P */ + *pixel = *pen; +} + +void SetPixel_MERGEPENNOT_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = P | ~D */ + *pixel = *pen | ~(*pixel); +} + +void SetPixel_MERGEPEN_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = P | D */ + *pixel |= *pen; +} + +void SetPixel_WHITE_32bpp(uint32 *pixel, uint32 *pen) +{ + /* D = 1 */ + *pixel = 0xFFFFFF; +} + +pSetPixel32_ROP2 SetPixel32_ROP2_[32] = +{ + SetPixel_BLACK_32bpp, + SetPixel_NOTMERGEPEN_32bpp, + SetPixel_MASKNOTPEN_32bpp, + SetPixel_NOTCOPYPEN_32bpp, + SetPixel_MASKPENNOT_32bpp, + SetPixel_NOT_32bpp, + SetPixel_XORPEN_32bpp, + SetPixel_NOTMASKPEN_32bpp, + SetPixel_MASKPEN_32bpp, + SetPixel_NOTXORPEN_32bpp, + SetPixel_NOP_32bpp, + SetPixel_MERGENOTPEN_32bpp, + SetPixel_COPYPEN_32bpp, + SetPixel_MERGEPENNOT_32bpp, + SetPixel_MERGEPEN_32bpp, + SetPixel_WHITE_32bpp +}; + +int LineTo_32bpp(HGDI_DC hdc, int nXEnd, int nYEnd) +{ + int x, y; + int x1, y1; + int x2, y2; + int e, e2; + int dx, dy; + int sx, sy; + HGDI_BITMAP bmp; + int bx1, by1; + int bx2, by2; + + int irop2; + uint32 pen; + uint32 *pixel; + + x1 = hdc->pen->posX; + y1 = hdc->pen->posY; + x2 = nXEnd; + y2 = nYEnd; + + dx = (x1 > x2) ? x1 - x2 : x2 - x1; + dy = (y1 > y2) ? y1 - y2 : y2 - y1; + + sx = (x1 < x2) ? 1 : -1; + sy = (y1 < y2) ? 1 : -1; + + e = dx - dy; + + x = x1; + y = y1; + + irop2 = gdi_GetROP2(hdc) - 1; + bmp = (HGDI_BITMAP) hdc->selectedObject; + + if (hdc->clip->null) + { + bx1 = (x1 < x2) ? x1 : x2; + by1 = (y1 < y2) ? y1 : y2; + bx2 = (x1 > x2) ? x1 : x2; + by2 = (y1 > y2) ? y1 : y2; + } + else + { + bx1 = hdc->clip->x; + by1 = hdc->clip->y; + bx2 = bx1 + hdc->clip->w - 1; + by2 = by1 + hdc->clip->h - 1; + } + + pen = gdi_GetPenColor_32bpp(hdc->pen); + + while (1) + { + if (!(x == x2 && y == y2)) + { + if ((x >= bx1 && x <= bx2) && (y >= by1 && y <= by2)) + { + pixel = gdi_GetPointer_32bpp(bmp, x, y); + SetPixel32_ROP2_[irop2](pixel, &pen); + } + } + else + { + break; + } + + e2 = 2 * e; + + if (e2 > -dy) + { + e -= dy; + x += sx; + } + + if (e2 < dx) + { + e += dx; + y += sy; + } + } + + return 1; +} diff --git a/libfreerdp-gdi/gdi_32bpp.h b/libfreerdp-gdi/gdi_32bpp.h new file mode 100644 index 000000000..3923a9f32 --- /dev/null +++ b/libfreerdp-gdi/gdi_32bpp.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI 32bpp Internal Buffer Routines + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "gdi.h" + +typedef void (*pSetPixel32_ROP2)(uint32 *pixel, uint32 *pen); + +int FillRect_32bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); +int BitBlt_32bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); +int PatBlt_32bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); +int LineTo_32bpp(HGDI_DC hdc, int nXEnd, int nYEnd); diff --git a/libfreerdp-gdi/gdi_8bpp.c b/libfreerdp-gdi/gdi_8bpp.c new file mode 100644 index 000000000..704dbaf6a --- /dev/null +++ b/libfreerdp-gdi/gdi_8bpp.c @@ -0,0 +1,875 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI 8bpp Internal Buffer Routines + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "gdi.h" +#include "color.h" +#include "gdi_pen.h" +#include "gdi_bitmap.h" +#include "gdi_region.h" +#include "gdi_clipping.h" +#include "gdi_drawing.h" + +#include "gdi_8bpp.h" + +int FillRect_8bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) +{ + /* TODO: Implement 8bpp FillRect() */ + return 0; +} + +static int BitBlt_BLACKNESS_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + memset(dstp, 0, nWidth * hdcDest->bytesPerPixel); + } + + return 0; +} + +static int BitBlt_WHITENESS_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + memset(dstp, 0xFF, nWidth * hdcDest->bytesPerPixel); + } + + return 0; +} + +static int BitBlt_SRCCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int y; + uint8 *srcp; + uint8 *dstp; + + if ((hdcDest->selectedObject != hdcSrc->selectedObject) || + gdi_CopyOverlap(nXDest, nYDest, nWidth, nHeight, nXSrc, nYSrc) == 0) + { + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + + return 0; + } + + if (nYSrc < nYDest) + { + /* copy down (bottom to top) */ + for (y = nHeight - 1; y >= 0; y--) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + else if (nYSrc > nYDest || nXSrc > nXDest) + { + /* copy up or left (top top bottom) */ + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_mem(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + else + { + /* copy straight right */ + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (srcp != 0 && dstp != 0) + { + gdi_copy_memb(dstp, srcp, nWidth * hdcDest->bytesPerPixel); + } + } + } + + return 0; +} + +static int BitBlt_NOTSRCCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp); + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_DSTINVERT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*dstp); + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCERASE_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = *srcp & ~(*dstp); + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_NOTSRCERASE_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) & ~(*dstp); + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCINVERT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp ^= *srcp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCAND_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp &= *srcp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_SRCPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp |= *srcp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_DSPDxax_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + /* TODO: Implement 8bpp DSPDxax BitBlt */ + return 0; +} + +static int BitBlt_SPna_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *srcp & ~(*patp); + patp++; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_DSna_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) & (*dstp); + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_MERGECOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *srcp & *patp; + patp++; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_MERGEPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = ~(*srcp) | *dstp; + srcp++; + dstp++; + } + } + } + + return 0; +} + +static int BitBlt_PATCOPY_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + uint8 *patp; + uint8 palIndex; + + if(hdcDest->brush->style == GDI_BS_SOLID) + { + palIndex = ((hdcDest->brush->color >> 16) & 0xFF); + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp = palIndex; + dstp++; + } + } + } + } + else + { + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *patp; + patp++; + dstp++; + } + } + } + } + + return 0; +} + +static int BitBlt_PATINVERT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight) +{ + int x, y; + uint8 *dstp; + uint8 *patp; + uint8 palIndex; + + if(hdcDest->brush->style == GDI_BS_SOLID) + { + palIndex = ((hdcDest->brush->color >> 16) & 0xFF); + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + *dstp ^= palIndex; + dstp++; + } + } + } + } + else + { + for (y = 0; y < nHeight; y++) + { + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *patp ^ *dstp; + patp++; + dstp++; + } + } + } + } + + return 0; +} + +static int BitBlt_PATPAINT_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc) +{ + int x, y; + uint8 *srcp; + uint8 *dstp; + uint8 *patp; + + for (y = 0; y < nHeight; y++) + { + srcp = gdi_get_bitmap_pointer(hdcSrc, nXSrc, nYSrc + y); + dstp = gdi_get_bitmap_pointer(hdcDest, nXDest, nYDest + y); + + if (dstp != 0) + { + for (x = 0; x < nWidth; x++) + { + patp = gdi_get_brush_pointer(hdcDest, x, y); + + *dstp = *dstp | (*patp | ~(*srcp)); + patp++; + srcp++; + dstp++; + } + } + } + + return 0; +} + +int BitBlt_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) +{ + if (hdcSrc != NULL) + { + if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, &nXSrc, &nYSrc) == 0) + return 0; + } + else + { + if (gdi_ClipCoords(hdcDest, &nXDest, &nYDest, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + } + + gdi_InvalidateRegion(hdcDest, nXDest, nYDest, nWidth, nHeight); + + switch (rop) + { + case GDI_BLACKNESS: + return BitBlt_BLACKNESS_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_WHITENESS: + return BitBlt_WHITENESS_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_SRCCOPY: + return BitBlt_SRCCOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SPna: + return BitBlt_SPna_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSna: + return BitBlt_DSna_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSPDxax: + return BitBlt_DSPDxax_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_NOTSRCCOPY: + return BitBlt_NOTSRCCOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_DSTINVERT: + return BitBlt_DSTINVERT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_SRCERASE: + return BitBlt_SRCERASE_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_NOTSRCERASE: + return BitBlt_NOTSRCERASE_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCINVERT: + return BitBlt_SRCINVERT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCAND: + return BitBlt_SRCAND_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_SRCPAINT: + return BitBlt_SRCPAINT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_MERGECOPY: + return BitBlt_MERGECOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_MERGEPAINT: + return BitBlt_MERGEPAINT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + + case GDI_PATCOPY: + return BitBlt_PATCOPY_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_PATINVERT: + return BitBlt_PATINVERT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight); + break; + + case GDI_PATPAINT: + return BitBlt_PATPAINT_8bpp(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc); + break; + } + + printf("BitBlt: unknown rop: 0x%08X\n", rop); + return 1; +} + +int PatBlt_8bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) +{ + if (gdi_ClipCoords(hdc, &nXLeft, &nYLeft, &nWidth, &nHeight, NULL, NULL) == 0) + return 0; + + gdi_InvalidateRegion(hdc, nXLeft, nYLeft, nWidth, nHeight); + + switch (rop) + { + case GDI_PATCOPY: + return BitBlt_PATCOPY_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_PATINVERT: + return BitBlt_PATINVERT_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_DSTINVERT: + return BitBlt_DSTINVERT_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_BLACKNESS: + return BitBlt_BLACKNESS_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + + case GDI_WHITENESS: + return BitBlt_WHITENESS_8bpp(hdc, nXLeft, nYLeft, nWidth, nHeight); + break; + } + + printf("PatBlt: unknown rop: 0x%08X", rop); + return 1; +} + +void SetPixel_BLACK_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = 0 */ + *pixel = 0; +} + +void SetPixel_NOTMERGEPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = ~(D | P) */ + *pixel = ~(*pixel | *pen); +} + +void SetPixel_MASKNOTPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = D & ~P */ + *pixel &= ~(*pen); +} + +void SetPixel_NOTCOPYPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = ~P */ + *pixel = ~(*pen); +} + +void SetPixel_MASKPENNOT_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = P & ~D */ + *pixel = *pen & ~*pixel; +} + +void SetPixel_NOT_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = ~D */ + *pixel = ~(*pixel); +} + +void SetPixel_XORPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = D ^ P */ + *pixel = *pixel ^ *pen; +} + +void SetPixel_NOTMASKPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = ~(D & P) */ + *pixel = ~(*pixel & *pen); +} + +void SetPixel_MASKPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = D & P */ + *pixel &= *pen; +} + +void SetPixel_NOTXORPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = ~(D ^ P) */ + *pixel = ~(*pixel ^ *pen); +} + +void SetPixel_NOP_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = D */ +} + +void SetPixel_MERGENOTPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = D | ~P */ + *pixel |= ~(*pen); +} + +void SetPixel_COPYPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = P */ + *pixel = *pen; +} + +void SetPixel_MERGEPENNOT_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = P | ~D */ + *pixel = *pen | ~(*pixel); +} + +void SetPixel_MERGEPEN_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = P | D */ + *pixel |= *pen; +} + +void SetPixel_WHITE_8bpp(uint8 *pixel, uint8 *pen) +{ + /* D = 1 */ + *pixel = 0xFF; +} + +pSetPixel8_ROP2 SetPixel8_ROP2_[16] = +{ + SetPixel_BLACK_8bpp, + SetPixel_NOTMERGEPEN_8bpp, + SetPixel_MASKNOTPEN_8bpp, + SetPixel_NOTCOPYPEN_8bpp, + SetPixel_MASKPENNOT_8bpp, + SetPixel_NOT_8bpp, + SetPixel_XORPEN_8bpp, + SetPixel_NOTMASKPEN_8bpp, + SetPixel_MASKPEN_8bpp, + SetPixel_NOTXORPEN_8bpp, + SetPixel_NOP_8bpp, + SetPixel_MERGENOTPEN_8bpp, + SetPixel_COPYPEN_8bpp, + SetPixel_MERGEPENNOT_8bpp, + SetPixel_MERGEPEN_8bpp, + SetPixel_WHITE_8bpp +}; + +int LineTo_8bpp(HGDI_DC hdc, int nXEnd, int nYEnd) +{ + int x, y; + int x1, y1; + int x2, y2; + int e, e2; + int dx, dy; + int sx, sy; + HGDI_BITMAP bmp; + int bx1, by1; + int bx2, by2; + + int irop2; + uint8 pen; + uint8 *pixel; + + x1 = hdc->pen->posX; + y1 = hdc->pen->posY; + x2 = nXEnd; + y2 = nYEnd; + + dx = (x1 > x2) ? x1 - x2 : x2 - x1; + dy = (y1 > y2) ? y1 - y2 : y2 - y1; + + sx = (x1 < x2) ? 1 : -1; + sy = (y1 < y2) ? 1 : -1; + + e = dx - dy; + + x = x1; + y = y1; + + irop2 = gdi_GetROP2(hdc) - 1; + bmp = (HGDI_BITMAP) hdc->selectedObject; + + if (hdc->clip->null) + { + bx1 = (x1 < x2) ? x1 : x2; + by1 = (y1 < y2) ? y1 : y2; + bx2 = (x1 > x2) ? x1 : x2; + by2 = (y1 > y2) ? y1 : y2; + } + else + { + bx1 = hdc->clip->x; + by1 = hdc->clip->y; + bx2 = bx1 + hdc->clip->w - 1; + by2 = by1 + hdc->clip->h - 1; + } + + pen = gdi_GetPenColor_8bpp(hdc->pen); + + while (1) + { + if (!(x == x2 && y == y2)) + { + if ((x >= bx1 && x <= bx2) && (y >= by1 && y <= by2)) + { + pixel = gdi_GetPointer_8bpp(bmp, x, y); + SetPixel8_ROP2_[irop2](pixel, &pen); + } + } + else + { + break; + } + + e2 = 2 * e; + + if (e2 > -dy) + { + e -= dy; + x += sx; + } + + if (e2 < dx) + { + e += dx; + y += sy; + } + } + + return 1; +} diff --git a/libfreerdp-gdi/gdi_8bpp.h b/libfreerdp-gdi/gdi_8bpp.h new file mode 100644 index 000000000..6ee6e4d09 --- /dev/null +++ b/libfreerdp-gdi/gdi_8bpp.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI 8bpp Internal Buffer Routines + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "gdi.h" + +typedef void (*pSetPixel8_ROP2)(uint8 *pixel, uint8 *pen); + +int FillRect_8bpp(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); +int BitBlt_8bpp(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); +int PatBlt_8bpp(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); +int LineTo_8bpp(HGDI_DC hdc, int nXEnd, int nYEnd); diff --git a/libfreerdp-gdi/gdi_bitmap.c b/libfreerdp-gdi/gdi_bitmap.c new file mode 100644 index 000000000..831c9a5f8 --- /dev/null +++ b/libfreerdp-gdi/gdi_bitmap.c @@ -0,0 +1,189 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Bitmap Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include "gdi.h" + +#include "color.h" +#include "gdi_32bpp.h" +#include "gdi_16bpp.h" +#include "gdi_8bpp.h" + +#include "gdi_bitmap.h" + +pBitBlt BitBlt_[5] = +{ + NULL, + BitBlt_8bpp, + BitBlt_16bpp, + NULL, + BitBlt_32bpp +}; + +/** + * Get pixel at the given coordinates.\n + * @msdn{dd144909} + * @param hdc device context + * @param nXPos pixel x position + * @param nYPos pixel y position + * @return pixel color + */ + +GDI_COLOR gdi_GetPixel(HGDI_DC hdc, int nXPos, int nYPos) +{ + HGDI_BITMAP hBmp = (HGDI_BITMAP) hdc->selectedObject; + GDI_COLOR* colorp = (GDI_COLOR*)&(hBmp->data[(nYPos * hBmp->width * hdc->bytesPerPixel) + nXPos * hdc->bytesPerPixel]); + return (GDI_COLOR) *colorp; +} + +uint8 gdi_GetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y) +{ + return *((uint8*)&(hBmp->data[(Y * hBmp->width) + X])); +} + +uint16 gdi_GetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y) +{ + return *((uint16*)&(hBmp->data[(Y * hBmp->width * 2) + X * 2])); +} + +uint32 gdi_GetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y) +{ + return *((uint32*)&(hBmp->data[(Y * hBmp->width * 4) + X * 4])); +} + +uint8* gdi_GetPointer_8bpp(HGDI_BITMAP hBmp, int X, int Y) +{ + return ((uint8*)&(hBmp->data[(Y * hBmp->width) + X])); +} + +uint16* gdi_GetPointer_16bpp(HGDI_BITMAP hBmp, int X, int Y) +{ + return ((uint16*)&(hBmp->data[(Y * hBmp->width * 2) + X * 2])); +} + +uint32* gdi_GetPointer_32bpp(HGDI_BITMAP hBmp, int X, int Y) +{ + return ((uint32*)&(hBmp->data[(Y * hBmp->width * 4) + X * 4])); +} + +/** + * Set pixel at the given coordinates.\n + * @msdn{dd145078} + * @param hdc device context + * @param X pixel x position + * @param Y pixel y position + * @param crColor new pixel color + * @return + */ + +GDI_COLOR gdi_SetPixel(HGDI_DC hdc, int X, int Y, GDI_COLOR crColor) +{ + HGDI_BITMAP hBmp = (HGDI_BITMAP) hdc->selectedObject; + *((GDI_COLOR*)&(hBmp->data[(Y * hBmp->width * hdc->bytesPerPixel) + X * hdc->bytesPerPixel])) = crColor; + return 0; +} + +void gdi_SetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y, uint8 pixel) +{ + *((uint8*)&(hBmp->data[(Y * hBmp->width) + X])) = pixel; +} + +void gdi_SetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y, uint16 pixel) +{ + *((uint16*)&(hBmp->data[(Y * hBmp->width * 2) + X * 2])) = pixel; +} + +void gdi_SetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y, uint32 pixel) +{ + *((uint32*)&(hBmp->data[(Y * hBmp->width * 4) + X * 4])) = pixel; +} + +/** + * Create a new bitmap with the given width, height, color format and pixel buffer.\n + * @msdn{dd183485} + * @param nWidth width + * @param nHeight height + * @param cBitsPerPixel bits per pixel + * @param data pixel buffer + * @return new bitmap + */ + +HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, uint8* data) +{ + HGDI_BITMAP hBitmap = (HGDI_BITMAP) malloc(sizeof(GDI_BITMAP)); + hBitmap->objectType = GDIOBJECT_BITMAP; + hBitmap->bitsPerPixel = cBitsPerPixel; + hBitmap->bytesPerPixel = (cBitsPerPixel + 1) / 8; + hBitmap->scanline = nWidth * hBitmap->bytesPerPixel; + hBitmap->width = nWidth; + hBitmap->height = nHeight; + hBitmap->data = data; + return hBitmap; +} + +/** + * Create a new bitmap of the given width and height compatible with the current device context.\n + * @msdn{dd183488} + * @param hdc device context + * @param nWidth width + * @param nHeight height + * @return new bitmap + */ + +HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, int nWidth, int nHeight) +{ + HGDI_BITMAP hBitmap = (HGDI_BITMAP) malloc(sizeof(GDI_BITMAP)); + hBitmap->objectType = GDIOBJECT_BITMAP; + hBitmap->bytesPerPixel = hdc->bytesPerPixel; + hBitmap->bitsPerPixel = hdc->bitsPerPixel; + hBitmap->width = nWidth; + hBitmap->height = nHeight; + hBitmap->data = malloc(nWidth * nHeight * hBitmap->bytesPerPixel); + hBitmap->scanline = nWidth * hBitmap->bytesPerPixel; + return hBitmap; +} + +/** + * Perform a bit blit operation on the given pixel buffers.\n + * @msdn{dd183370} + * @param hdcDest destination device context + * @param nXDest destination x1 + * @param nYDest destination y1 + * @param nWidth width + * @param nHeight height + * @param hdcSrc source device context + * @param nXSrc source x1 + * @param nYSrc source y1 + * @param rop raster operation code + * @return 1 if successful, 0 otherwise + */ + +int gdi_BitBlt(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop) +{ + pBitBlt _BitBlt = BitBlt_[IBPP(hdcDest->bitsPerPixel)]; + + if (_BitBlt != NULL) + return _BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, rop); + else + return 0; +} diff --git a/libfreerdp-gdi/gdi_bitmap.h b/libfreerdp-gdi/gdi_bitmap.h new file mode 100644 index 000000000..ba9272b34 --- /dev/null +++ b/libfreerdp-gdi/gdi_bitmap.h @@ -0,0 +1,42 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Bitmap Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_BITMAP_H +#define __GDI_BITMAP_H + +#include "gdi.h" + +GDI_COLOR gdi_GetPixel(HGDI_DC hdc, int nXPos, int nYPos); +GDI_COLOR gdi_SetPixel(HGDI_DC hdc, int X, int Y, GDI_COLOR crColor); +uint8 gdi_GetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y); +uint16 gdi_GetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y); +uint32 gdi_GetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y); +uint8* gdi_GetPointer_8bpp(HGDI_BITMAP hBmp, int X, int Y); +uint16* gdi_GetPointer_16bpp(HGDI_BITMAP hBmp, int X, int Y); +uint32* gdi_GetPointer_32bpp(HGDI_BITMAP hBmp, int X, int Y); +void gdi_SetPixel_8bpp(HGDI_BITMAP hBmp, int X, int Y, uint8 pixel); +void gdi_SetPixel_16bpp(HGDI_BITMAP hBmp, int X, int Y, uint16 pixel); +void gdi_SetPixel_32bpp(HGDI_BITMAP hBmp, int X, int Y, uint32 pixel); +HGDI_BITMAP gdi_CreateBitmap(int nWidth, int nHeight, int cBitsPerPixel, uint8* data); +HGDI_BITMAP gdi_CreateCompatibleBitmap(HGDI_DC hdc, int nWidth, int nHeight); +int gdi_BitBlt(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); + +typedef int (*pBitBlt)(HGDI_DC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HGDI_DC hdcSrc, int nXSrc, int nYSrc, int rop); + +#endif /* __GDI_BITMAP_H */ diff --git a/libfreerdp-gdi/gdi_brush.c b/libfreerdp-gdi/gdi_brush.c new file mode 100644 index 000000000..23fe99c1f --- /dev/null +++ b/libfreerdp-gdi/gdi_brush.c @@ -0,0 +1,96 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Brush Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* GDI Brush Functions: http://msdn.microsoft.com/en-us/library/dd183395/ */ + +#include +#include +#include + +#include +#include "gdi.h" + +#include "gdi_32bpp.h" +#include "gdi_16bpp.h" +#include "gdi_8bpp.h" + +#include "gdi_brush.h" + +pPatBlt PatBlt_[5] = +{ + NULL, + PatBlt_8bpp, + PatBlt_16bpp, + NULL, + PatBlt_32bpp +}; + +/** + * Create a new solid brush.\n + * @msdn{dd183518} + * @param crColor brush color + * @return new brush + */ + +HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor) +{ + HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); + hBrush->objectType = GDIOBJECT_BRUSH; + hBrush->style = GDI_BS_SOLID; + hBrush->color = crColor; + return hBrush; +} + +/** + * Create a new pattern brush.\n + * @msdn{dd183508} + * @param hbmp pattern bitmap + * @return new brush + */ + +HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp) +{ + HGDI_BRUSH hBrush = (HGDI_BRUSH) malloc(sizeof(GDI_BRUSH)); + hBrush->objectType = GDIOBJECT_BRUSH; + hBrush->style = GDI_BS_PATTERN; + hBrush->pattern = hbmp; + return hBrush; +} + +/** + * Perform a pattern blit operation on the given pixel buffer.\n + * @msdn{dd162778} + * @param hdc device context + * @param nXLeft x1 + * @param nYLeft y1 + * @param nWidth width + * @param nHeight height + * @param rop raster operation code + * @return 1 if successful, 0 otherwise + */ + +int gdi_PatBlt(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop) +{ + pPatBlt _PatBlt = PatBlt_[IBPP(hdc->bitsPerPixel)]; + + if (_PatBlt != NULL) + return _PatBlt(hdc, nXLeft, nYLeft, nWidth, nHeight, rop); + else + return 0; +} diff --git a/libfreerdp-gdi/gdi_brush.h b/libfreerdp-gdi/gdi_brush.h new file mode 100644 index 000000000..26d8d7df9 --- /dev/null +++ b/libfreerdp-gdi/gdi_brush.h @@ -0,0 +1,31 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Brush Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_BRUSH_H +#define __GDI_BRUSH_H + +#include "gdi.h" + +HGDI_BRUSH gdi_CreateSolidBrush(GDI_COLOR crColor); +HGDI_BRUSH gdi_CreatePatternBrush(HGDI_BITMAP hbmp); +int gdi_PatBlt(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); + +typedef int (*pPatBlt)(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight, int rop); + +#endif /* __GDI_BRUSH_H */ diff --git a/libfreerdp-gdi/gdi_clipping.c b/libfreerdp-gdi/gdi_clipping.c new file mode 100644 index 000000000..669168052 --- /dev/null +++ b/libfreerdp-gdi/gdi_clipping.c @@ -0,0 +1,172 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Clipping Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "gdi.h" +#include "gdi_region.h" + +#include "gdi_clipping.h" + +int gdi_SetClipRgn(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight) +{ + return gdi_SetRgn(hdc->clip, nXLeft, nYLeft, nWidth, nHeight); +} + +/** + * Get the current clipping region.\n + * @msdn{dd144866} + * @param hdc device context + * @return clipping region + */ + +HGDI_RGN gdi_GetClipRgn(HGDI_DC hdc) +{ + return hdc->clip; +} + +/** + * Set the current clipping region to null. + * @param hdc device context + * @return + */ + +int gdi_SetNullClipRgn(HGDI_DC hdc) +{ + gdi_SetClipRgn(hdc, 0, 0, 0, 0); + hdc->clip->null = 1; + return 0; +} + +/** + * Clip coordinates according to clipping region + * @param hdc device context + * @param x x1 + * @param y y1 + * @param w width + * @param h height + * @param srcx source x1 + * @param srcy source y1 + * @return 1 if there is something to draw, 0 otherwise + */ + +int gdi_ClipCoords(HGDI_DC hdc, int *x, int *y, int *w, int *h, int *srcx, int *srcy) +{ + GDI_RECT bmp; + GDI_RECT clip; + GDI_RECT coords; + HGDI_BITMAP hBmp; + + int dx = 0; + int dy = 0; + int draw = 1; + + if (hdc == NULL) + return 0; + + hBmp = (HGDI_BITMAP) hdc->selectedObject; + + if (hBmp != NULL) + { + if (hdc->clip->null) + { + gdi_CRgnToRect(0, 0, hBmp->width, hBmp->height, &clip); + } + else + { + gdi_RgnToRect(hdc->clip, &clip); + gdi_CRgnToRect(0, 0, hBmp->width, hBmp->height, &bmp); + + if (clip.left < bmp.left) + clip.left = bmp.left; + + if (clip.right > bmp.right) + clip.right = bmp.right; + + if (clip.top < bmp.top) + clip.top = bmp.top; + + if (clip.bottom > bmp.bottom) + clip.bottom = bmp.bottom; + } + } + else + { + gdi_RgnToRect(hdc->clip, &clip); + } + + gdi_CRgnToRect(*x, *y, *w, *h, &coords); + + if (coords.right >= clip.left && coords.left <= clip.right && + coords.bottom >= clip.top && coords.top <= clip.bottom) + { + /* coordinates overlap with clipping region */ + + if (coords.left < clip.left) + { + dx = (clip.left - coords.left) + 1; + coords.left = clip.left; + } + + if (coords.right > clip.right) + coords.right = clip.right; + + if (coords.top < clip.top) + { + dy = (clip.top - coords.top) + 1; + coords.top = clip.top; + } + + if (coords.bottom > clip.bottom) + coords.bottom = clip.bottom; + } + else + { + /* coordinates do not overlap with clipping region */ + + coords.left = 0; + coords.right = 0; + coords.top = 0; + coords.bottom = 0; + draw = 0; + } + + if (srcx != NULL) + { + if (dx > 0) + { + *srcx += dx - 1; + } + } + + if (srcy != NULL) + { + if (dy > 0) + { + *srcy += dy - 1; + } + } + + gdi_RectToCRgn(&coords, x, y, w, h); + + return draw; +} diff --git a/libfreerdp-gdi/gdi_clipping.h b/libfreerdp-gdi/gdi_clipping.h new file mode 100644 index 000000000..fc44771da --- /dev/null +++ b/libfreerdp-gdi/gdi_clipping.h @@ -0,0 +1,30 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Clipping Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_CLIPPING_H +#define __GDI_CLIPPING_H + +#include "gdi.h" + +int gdi_SetClipRgn(HGDI_DC hdc, int nXLeft, int nYLeft, int nWidth, int nHeight); +HGDI_RGN gdi_GetClipRgn(HGDI_DC hdc); +int gdi_SetNullClipRgn(HGDI_DC hdc); +int gdi_ClipCoords(HGDI_DC hdc, int *x, int *y, int *w, int *h, int *srcx, int *srcy); + +#endif /* __GDI_CLIPPING_H */ diff --git a/libfreerdp-gdi/gdi_dc.c b/libfreerdp-gdi/gdi_dc.c new file mode 100644 index 000000000..a205f8d50 --- /dev/null +++ b/libfreerdp-gdi/gdi_dc.c @@ -0,0 +1,190 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Device Context Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Device Context Functions: http://msdn.microsoft.com/en-us/library/dd183554 */ + +#include +#include +#include +#include + +#include "gdi.h" +#include "gdi_region.h" + +#include "gdi_dc.h" + +/** + * Get the current device context (a new one is created each time).\n + * @msdn{dd144871} + * @return current device context + */ + +HGDI_DC gdi_GetDC() +{ + HGDI_DC hDC = (HGDI_DC) malloc(sizeof(GDI_DC)); + hDC->bytesPerPixel = 4; + hDC->bitsPerPixel = 32; + hDC->drawMode = GDI_R2_BLACK; + hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0); + hDC->clip->null = 1; + hDC->hwnd = NULL; + return hDC; +} + +/** + * Create a new device context compatible with the given device context.\n + * @msdn{dd183489} + * @param hdc device context + * @return new compatible device context + */ + +HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc) +{ + HGDI_DC hDC = (HGDI_DC) malloc(sizeof(GDI_DC)); + hDC->bytesPerPixel = hdc->bytesPerPixel; + hDC->bitsPerPixel = hdc->bitsPerPixel; + hDC->drawMode = hdc->drawMode; + hDC->clip = gdi_CreateRectRgn(0, 0, 0, 0); + hDC->clip->null = 1; + hDC->hwnd = NULL; + hDC->alpha = hdc->alpha; + hDC->invert = hdc->invert; + hDC->rgb555 = hdc->rgb555; + return hDC; +} + +/** + * Select a GDI object in the current device context.\n + * @msdn{dd162957} + * @param hdc device context + * @param hgdiobject new selected GDI object + * @return previous selected GDI object + */ + +HGDIOBJECT gdi_SelectObject(HGDI_DC hdc, HGDIOBJECT hgdiobject) +{ + HGDIOBJECT previousSelectedObject = hdc->selectedObject; + + if (hgdiobject == NULL) + return NULL; + + if (hgdiobject->objectType == GDIOBJECT_BITMAP) + { + hdc->selectedObject = hgdiobject; + } + else if (hgdiobject->objectType == GDIOBJECT_PEN) + { + previousSelectedObject = (HGDIOBJECT) hdc->pen; + hdc->pen = (HGDI_PEN) hgdiobject; + } + else if (hgdiobject->objectType == GDIOBJECT_BRUSH) + { + previousSelectedObject = (HGDIOBJECT) hdc->brush; + hdc->brush = (HGDI_BRUSH) hgdiobject; + } + else if (hgdiobject->objectType == GDIOBJECT_REGION) + { + hdc->selectedObject = hgdiobject; + } + else if (hgdiobject->objectType == GDIOBJECT_RECT) + { + hdc->selectedObject = hgdiobject; + } + else + { + /* Unknown GDI Object Type */ + return 0; + } + + return previousSelectedObject; +} + +/** + * Delete a GDI object.\n + * @msdn{dd183539} + * @param hgdiobject GDI object + * @return 1 if successful, 0 otherwise + */ + +int gdi_DeleteObject(HGDIOBJECT hgdiobject) +{ + if (hgdiobject == NULL) + return 0; + + if (hgdiobject->objectType == GDIOBJECT_BITMAP) + { + HGDI_BITMAP hBitmap = (HGDI_BITMAP) hgdiobject; + + if (hBitmap->data != NULL) + free(hBitmap->data); + + free(hBitmap); + } + else if (hgdiobject->objectType == GDIOBJECT_PEN) + { + HGDI_PEN hPen = (HGDI_PEN) hgdiobject; + free(hPen); + } + else if (hgdiobject->objectType == GDIOBJECT_BRUSH) + { + HGDI_BRUSH hBrush = (HGDI_BRUSH) hgdiobject; + + if(hBrush->style == GDI_BS_PATTERN) + gdi_DeleteObject((HGDIOBJECT) hBrush->pattern); + + free(hBrush); + } + else if (hgdiobject->objectType == GDIOBJECT_REGION) + { + free(hgdiobject); + } + else if (hgdiobject->objectType == GDIOBJECT_RECT) + { + free(hgdiobject); + } + else + { + /* Unknown GDI Object Type */ + free(hgdiobject); + return 0; + } + + return 1; +} + +/** + * Delete device context.\n + * @msdn{dd183533} + * @param hdc device context + * @return 1 if successful, 0 otherwise + */ + +int gdi_DeleteDC(HGDI_DC hdc) +{ + if (hdc->hwnd) + { + free(hdc->hwnd->invalid); + free(hdc->hwnd); + } + + free(hdc->clip); + free(hdc); + + return 1; +} diff --git a/libfreerdp-gdi/gdi_dc.h b/libfreerdp-gdi/gdi_dc.h new file mode 100644 index 000000000..b45730501 --- /dev/null +++ b/libfreerdp-gdi/gdi_dc.h @@ -0,0 +1,31 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Device Context Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_DC_H +#define __GDI_DC_H + +#include "gdi.h" + +HGDI_DC gdi_GetDC(); +HGDI_DC gdi_CreateCompatibleDC(HGDI_DC hdc); +HGDIOBJECT gdi_SelectObject(HGDI_DC hdc, HGDIOBJECT hgdiobject); +int gdi_DeleteObject(HGDIOBJECT hgdiobject); +int gdi_DeleteDC(HGDI_DC hdc); + +#endif /* __GDI_DC_H */ diff --git a/libfreerdp-gdi/gdi_drawing.c b/libfreerdp-gdi/gdi_drawing.c new file mode 100644 index 000000000..56b71f773 --- /dev/null +++ b/libfreerdp-gdi/gdi_drawing.c @@ -0,0 +1,131 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Drawing Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* GDI Drawing Functions: http://msdn.microsoft.com/en-us/library/dd162760/ */ + +#include +#include +#include + +#include +#include "gdi.h" + +#include "gdi_dc.h" + +/** + * Set current foreground draw mode.\n + * @msdn{dd144922} + * @param hdc device context + * @return draw mode + */ + +int gdi_GetROP2(HGDI_DC hdc) +{ + return hdc->drawMode; +} + +/** + * Set current foreground draw mode.\n + * @msdn{dd145088} + * @param hdc device context + * @param fnDrawMode draw mode + * @return previous draw mode + */ + +int gdi_SetROP2(HGDI_DC hdc, int fnDrawMode) +{ + int prevDrawMode = hdc->drawMode; + + if (fnDrawMode > 0 && fnDrawMode <= 16) + hdc->drawMode = fnDrawMode; + + return prevDrawMode; +} + +/** + * Get the current background color.\n + * @msdn{dd144852} + * @param hdc device context + * @return background color + */ + +GDI_COLOR gdi_GetBkColor(HGDI_DC hdc) +{ + return hdc->bkColor; +} + +/** + * Set the current background color.\n + * @msdn{dd162964} + * @param hdc device color + * @param crColor new background color + * @return previous background color + */ + +GDI_COLOR gdi_SetBkColor(HGDI_DC hdc, GDI_COLOR crColor) +{ + GDI_COLOR previousBkColor = hdc->bkColor; + hdc->bkColor = crColor; + return previousBkColor; +} + +/** + * Get the current background mode.\n + * @msdn{dd144853} + * @param hdc device context + * @return background mode + */ + +int gdi_GetBkMode(HGDI_DC hdc) +{ + return hdc->bkMode; +} + +/** + * Set the current background mode.\n + * @msdn{dd162965} + * @param hdc device context + * @param iBkMode background mode + * @return + */ + +int gdi_SetBkMode(HGDI_DC hdc, int iBkMode) +{ + if (iBkMode == GDI_OPAQUE || iBkMode == GDI_TRANSPARENT) + hdc->bkMode = iBkMode; + else + hdc->bkMode = GDI_OPAQUE; + + return 0; +} + +/** + * Set the current text color.\n + * @msdn{dd145093} + * @param hdc device context + * @param crColor new text color + * @return previous text color + */ + +GDI_COLOR gdi_SetTextColor(HGDI_DC hdc, GDI_COLOR crColor) +{ + GDI_COLOR previousTextColor = hdc->textColor; + hdc->textColor = crColor; + return previousTextColor; +} diff --git a/libfreerdp-gdi/gdi_drawing.h b/libfreerdp-gdi/gdi_drawing.h new file mode 100644 index 000000000..cc58ccec9 --- /dev/null +++ b/libfreerdp-gdi/gdi_drawing.h @@ -0,0 +1,33 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Drawing Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_DRAWING_H +#define __GDI_DRAWING_H + +#include "gdi.h" + +int gdi_GetROP2(HGDI_DC hdc); +int gdi_SetROP2(HGDI_DC hdc, int fnDrawMode); +GDI_COLOR gdi_GetBkColor(HGDI_DC hdc); +GDI_COLOR gdi_SetBkColor(HGDI_DC hdc, GDI_COLOR crColor); +int gdi_GetBkMode(HGDI_DC hdc); +int gdi_SetBkMode(HGDI_DC hdc, int iBkMode); +GDI_COLOR gdi_SetTextColor(HGDI_DC hdc, GDI_COLOR crColor); + +#endif /* __GDI_DRAWING_H */ diff --git a/libfreerdp-gdi/gdi_line.c b/libfreerdp-gdi/gdi_line.c new file mode 100644 index 000000000..1eb79eedd --- /dev/null +++ b/libfreerdp-gdi/gdi_line.c @@ -0,0 +1,151 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Line Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include "gdi.h" + +#include "gdi_32bpp.h" +#include "gdi_16bpp.h" +#include "gdi_8bpp.h" + +#include "gdi_line.h" + +pLineTo LineTo_[5] = +{ + NULL, + LineTo_8bpp, + LineTo_16bpp, + NULL, + LineTo_32bpp +}; + +/** + * Draw a line from the current position to the given position.\n + * @msdn{dd145029} + * @param hdc device context + * @param nXEnd ending x position + * @param nYEnd ending y position + * @return 1 if successful, 0 otherwise + */ + +int gdi_LineTo(HGDI_DC hdc, int nXEnd, int nYEnd) +{ + pLineTo _LineTo = LineTo_[IBPP(hdc->bitsPerPixel)]; + + if (_LineTo != NULL) + return _LineTo(hdc, nXEnd, nYEnd); + else + return 0; +} + +/** + * Draw one or more straight lines + * @param hdc device context + * @param lppt array of points + * @param cCount number of points + * @return + */ +int gdi_PolylineTo(HGDI_DC hdc, GDI_POINT *lppt, int cCount) +{ + int i; + for (i = 0; i < cCount; i++) + { + gdi_LineTo(hdc, lppt[i].x, lppt[i].y); + gdi_MoveToEx(hdc, lppt[i].x, lppt[i].y, NULL); + } + + return 1; +} + +/** + * Draw one or more straight lines + * @param hdc device context + * @param lppt array of points + * @param cPoints number of points + * @return + */ +int gdi_Polyline(HGDI_DC hdc, GDI_POINT *lppt, int cPoints) +{ + if (cPoints > 0) + { + int i; + GDI_POINT pt; + + gdi_MoveToEx(hdc, lppt[0].x, lppt[0].y, &pt); + + for (i = 0; i < cPoints; i++) + { + gdi_LineTo(hdc, lppt[i].x, lppt[i].y); + gdi_MoveToEx(hdc, lppt[i].x, lppt[i].y, NULL); + } + + gdi_MoveToEx(hdc, pt.x, pt.y, NULL); + } + + return 1; +} + +/** + * Draw multiple series of connected line segments + * @param hdc device context + * @param lppt array of points + * @param lpdwPolyPoints array of numbers of points per series + * @param cCount count of entries in lpdwPolyPoints + * @return + */ +int gdi_PolyPolyline(HGDI_DC hdc, GDI_POINT *lppt, int *lpdwPolyPoints, int cCount) +{ + int cPoints; + int i, j = 0; + + for (i = 0; i < cCount; i++) + { + cPoints = lpdwPolyPoints[i]; + gdi_Polyline(hdc, &lppt[j], cPoints); + j += cPoints; + } + + return 1; +} + +/** + * Move pen from the current device context to a new position. + * @param hdc device context + * @param X x position + * @param Y y position + * @return 1 if successful, 0 otherwise + */ + +int gdi_MoveToEx(HGDI_DC hdc, int X, int Y, HGDI_POINT lpPoint) +{ + if (lpPoint != NULL) + { + lpPoint->x = hdc->pen->posX; + lpPoint->y = hdc->pen->posY; + } + + hdc->pen->posX = X; + hdc->pen->posY = Y; + + return 1; +} diff --git a/libfreerdp-gdi/gdi_line.h b/libfreerdp-gdi/gdi_line.h new file mode 100644 index 000000000..51e46910a --- /dev/null +++ b/libfreerdp-gdi/gdi_line.h @@ -0,0 +1,33 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Line Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_LINE_H +#define __GDI_LINE_H + +#include "gdi.h" + +int gdi_LineTo(HGDI_DC hdc, int nXEnd, int nYEnd); +int gdi_PolylineTo(HGDI_DC hdc, GDI_POINT *lppt, int cCount); +int gdi_Polyline(HGDI_DC hdc, GDI_POINT *lppt, int cPoints); +int gdi_PolyPolyline(HGDI_DC hdc, GDI_POINT *lppt, int *lpdwPolyPoints, int cCount); +int gdi_MoveToEx(HGDI_DC hdc, int X, int Y, HGDI_POINT lpPoint); + +typedef int (*pLineTo)(HGDI_DC hdc, int nXEnd, int nYEnd); + +#endif /* __GDI_LINE_H */ diff --git a/libfreerdp-gdi/gdi_palette.c b/libfreerdp-gdi/gdi_palette.c new file mode 100644 index 000000000..032b2efc9 --- /dev/null +++ b/libfreerdp-gdi/gdi_palette.c @@ -0,0 +1,106 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Palette Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* GDI Palette Functions: http://msdn.microsoft.com/en-us/library/dd183454/ */ + +#include +#include +#include + +#include +#include "gdi.h" + +#include "gdi_palette.h" + +static HGDI_PALETTE hSystemPalette = NULL; + +static const GDI_PALETTEENTRY default_system_palette[20] = +{ + /* First 10 entries */ + { 0x00, 0x00, 0x00 }, + { 0x80, 0x00, 0x00 }, + { 0x00, 0x80, 0x00 }, + { 0x80, 0x80, 0x00 }, + { 0x00, 0x00, 0x80 }, + { 0x80, 0x00, 0x80 }, + { 0x00, 0x80, 0x80 }, + { 0xC0, 0xC0, 0xC0 }, + { 0xC0, 0xDC, 0xC0 }, + { 0xA6, 0xCA, 0xF0 }, + + /* Last 10 entries */ + { 0xFF, 0xFB, 0xF0 }, + { 0xA0, 0xA0, 0xA4 }, + { 0x80, 0x80, 0x80 }, + { 0xFF, 0x00, 0x00 }, + { 0x00, 0xFF, 0x00 }, + { 0xFF, 0xFF, 0x00 }, + { 0x00, 0x00, 0xFF }, + { 0xFF, 0x00, 0xFF }, + { 0x00, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF } +}; + +/** + * Create a new palette.\n + * @msdn{dd183507} + * @param original palette + * @return new palette + */ + +HGDI_PALETTE gdi_CreatePalette(HGDI_PALETTE palette) +{ + HGDI_PALETTE hPalette = (HGDI_PALETTE) malloc(sizeof(GDI_PALETTE)); + hPalette->count = palette->count; + hPalette->entries = (GDI_PALETTEENTRY*) malloc(sizeof(GDI_PALETTEENTRY) * hPalette->count); + memcpy(hPalette->entries, palette->entries, sizeof(GDI_PALETTEENTRY) * hPalette->count); + return hPalette; +} + +/** + * Create system palette\n + * @return system palette + */ + +HGDI_PALETTE CreateSystemPalette() +{ + HGDI_PALETTE palette = (HGDI_PALETTE) malloc(sizeof(GDI_PALETTE)); + + palette->count = 256; + palette->entries = (GDI_PALETTEENTRY*) malloc(sizeof(GDI_PALETTEENTRY) * 256); + memset(palette->entries, 0, sizeof(GDI_PALETTEENTRY) * 256); + + memcpy(&palette->entries[0], &default_system_palette[0], 10 * sizeof(GDI_PALETTEENTRY)); + memcpy(&palette->entries[256 - 10], &default_system_palette[10], 10 * sizeof(GDI_PALETTEENTRY)); + + return palette; +} + +/** + * Get system palette\n + * @return system palette + */ + +HGDI_PALETTE gdi_GetSystemPalette() +{ + if (hSystemPalette == NULL) + hSystemPalette = CreateSystemPalette(); + + return hSystemPalette; +} diff --git a/libfreerdp-gdi/gdi_palette.h b/libfreerdp-gdi/gdi_palette.h new file mode 100644 index 000000000..0bfba4442 --- /dev/null +++ b/libfreerdp-gdi/gdi_palette.h @@ -0,0 +1,28 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Palette Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_PALETTE_H +#define __GDI_PALETTE_H + +#include "gdi.h" + +HGDI_PALETTE gdi_CreatePalette(HGDI_PALETTE palette); +HGDI_PALETTE gdi_GetSystemPalette(); + +#endif /* __GDI_PALETTE_H */ diff --git a/libfreerdp-gdi/gdi_pen.c b/libfreerdp-gdi/gdi_pen.c new file mode 100644 index 000000000..01a7b732e --- /dev/null +++ b/libfreerdp-gdi/gdi_pen.c @@ -0,0 +1,69 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Pen Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* GDI Pen Functions: http://msdn.microsoft.com/en-us/library/dd162790 */ + +#include +#include +#include + +#include +#include "gdi.h" + +#include "gdi_pen.h" + +/** + * Create a new pen.\n + * @msdn{dd183509} + * @param fnPenStyle pen style + * @param nWidth pen width + * @param crColor pen color + * @return new pen + */ + +HGDI_PEN gdi_CreatePen(int fnPenStyle, int nWidth, int crColor) +{ + HGDI_PEN hPen = (HGDI_PEN) malloc(sizeof(GDI_PEN)); + hPen->objectType = GDIOBJECT_PEN; + hPen->style = fnPenStyle; + hPen->color = crColor; + hPen->width = nWidth; + return hPen; +} + +uint8 gdi_GetPenColor_8bpp(HGDI_PEN pen) +{ + /* TODO: implement conversion using palette */ + return 0xFF; +} + +uint16 gdi_GetPenColor_16bpp(HGDI_PEN pen) +{ + uint16 p; + int r, g, b; + GetRGB32(r, g, b, pen->color); + RGB_888_565(r, g, b); + p = RGB16(r, g, b); + return p; +} + +uint32 gdi_GetPenColor_32bpp(HGDI_PEN pen) +{ + return pen->color; +} diff --git a/libfreerdp-gdi/gdi_pen.h b/libfreerdp-gdi/gdi_pen.h new file mode 100644 index 000000000..3978d2bd3 --- /dev/null +++ b/libfreerdp-gdi/gdi_pen.h @@ -0,0 +1,30 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Pen Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_PEN_H +#define __GDI_PEN_H + +#include "gdi.h" + +HGDI_PEN gdi_CreatePen(int fnPenStyle, int nWidth, int crColor); +uint8 gdi_GetPenColor_8bpp(HGDI_PEN pen); +uint16 gdi_GetPenColor_16bpp(HGDI_PEN pen); +uint32 gdi_GetPenColor_32bpp(HGDI_PEN pen); + +#endif /* __GDI_PEN_H */ diff --git a/libfreerdp-gdi/gdi_region.c b/libfreerdp-gdi/gdi_region.c new file mode 100644 index 000000000..191b169aa --- /dev/null +++ b/libfreerdp-gdi/gdi_region.c @@ -0,0 +1,422 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Region Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include "gdi.h" + +#include "gdi_region.h" + +/** + * Create a region from rectangular coordinates.\n + * @msdn{dd183514} + * @param nLeftRect x1 + * @param nTopRect y1 + * @param nRightRect x2 + * @param nBottomRect y2 + * @return new region + */ + +HGDI_RGN gdi_CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) +{ + HGDI_RGN hRgn = (HGDI_RGN) malloc(sizeof(GDI_RGN)); + hRgn->objectType = GDIOBJECT_REGION; + hRgn->x = nLeftRect; + hRgn->y = nTopRect; + hRgn->w = nRightRect - nLeftRect + 1; + hRgn->h = nBottomRect - nTopRect + 1; + hRgn->null = 0; + return hRgn; +} + +/** + * Create a new rectangle. + * @param xLeft x1 + * @param yTop y1 + * @param xRight x2 + * @param yBottom y2 + * @return new rectangle + */ + +HGDI_RECT gdi_CreateRect(int xLeft, int yTop, int xRight, int yBottom) +{ + HGDI_RECT hRect = (HGDI_RECT) malloc(sizeof(GDI_RECT)); + hRect->objectType = GDIOBJECT_RECT; + hRect->left = xLeft; + hRect->top = yTop; + hRect->right = xRight; + hRect->bottom = yBottom; + return hRect; +} + +/** + * Convert a rectangle to a region. + * @param rect source rectangle + * @param rgn destination region + */ + +void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn) +{ + rgn->x = rect->left; + rgn->y = rect->top; + rgn->w = rect->right - rect->left + 1; + rgn->h = rect->bottom - rect->top + 1; +} + +/** + * Convert rectangular coordinates to a region. + * @param left x1 + * @param top y1 + * @param right x2 + * @param bottom y2 + * @param rgn destination region + */ + +void gdi_CRectToRgn(int left, int top, int right, int bottom, HGDI_RGN rgn) +{ + rgn->x = left; + rgn->y = top; + rgn->w = right - left + 1; + rgn->h = bottom - top + 1; +} + +/** + * Convert a rectangle to region coordinates. + * @param rect source rectangle + * @param x x1 + * @param y y1 + * @param w width + * @param h height + */ + +void gdi_RectToCRgn(HGDI_RECT rect, int *x, int *y, int *w, int *h) +{ + *x = rect->left; + *y = rect->top; + *w = rect->right - rect->left + 1; + *h = rect->bottom - rect->top + 1; +} + +/** + * Convert rectangular coordinates to region coordinates. + * @param left x1 + * @param top y1 + * @param right x2 + * @param bottom y2 + * @param x x1 + * @param y y1 + * @param w width + * @param h height + */ + +void gdi_CRectToCRgn(int left, int top, int right, int bottom, int *x, int *y, int *w, int *h) +{ + *x = left; + *y = top; + *w = right - left + 1; + *h = bottom - top + 1; +} + +/** + * Convert a region to a rectangle. + * @param rgn source region + * @param rect destination rectangle + */ + +void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect) +{ + rect->left = rgn->x; + rect->top = rgn->y; + rect->right = rgn->x + rgn->w - 1; + rect->bottom = rgn->y + rgn->h - 1; +} + +/** + * Convert region coordinates to a rectangle. + * @param x x1 + * @param y y1 + * @param w width + * @param h height + * @param rect destination rectangle + */ + +void gdi_CRgnToRect(int x, int y, int w, int h, HGDI_RECT rect) +{ + rect->left = x; + rect->top = y; + rect->right = x + w - 1; + rect->bottom = y + h - 1; +} + +/** + * Convert a region to rectangular coordinates. + * @param rgn source region + * @param left x1 + * @param top y1 + * @param right x2 + * @param bottom y2 + */ + +void gdi_RgnToCRect(HGDI_RGN rgn, int *left, int *top, int *right, int *bottom) +{ + *left = rgn->x; + *top = rgn->y; + *right = rgn->x + rgn->w - 1; + *bottom = rgn->y + rgn->h - 1; +} + +/** + * Convert region coordinates to rectangular coordinates. + * @param x x1 + * @param y y1 + * @param w width + * @param h height + * @param left x1 + * @param top y1 + * @param right x2 + * @param bottom y2 + */ + +void gdi_CRgnToCRect(int x, int y, int w, int h, int *left, int *top, int *right, int *bottom) +{ + *left = x; + *top = y; + *right = x + w - 1; + *bottom = y + h - 1; +} + +/** + * Check if copying would involve overlapping regions + * @param x x1 + * @param y y1 + * @param width width + * @param height height + * @param srcx source x1 + * @param srcy source y1 + * @return 1 if there is an overlap, 0 otherwise + */ + +int gdi_CopyOverlap(int x, int y, int width, int height, int srcx, int srcy) +{ + GDI_RECT dst; + GDI_RECT src; + + gdi_CRgnToRect(x, y, width, height, &dst); + gdi_CRgnToRect(srcx, srcy, width, height, &src); + + return (dst.right > src.left && dst.left < src.right && + dst.bottom > src.top && dst.top < src.bottom) ? 1 : 0; +} + +/** + * Set the coordinates of a given rectangle.\n + * @msdn{dd145085} + * @param rc rectangle + * @param xLeft x1 + * @param yTop y1 + * @param xRight x2 + * @param yBottom y2 + * @return 1 if successful, 0 otherwise + */ + +int gdi_SetRect(HGDI_RECT rc, int xLeft, int yTop, int xRight, int yBottom) +{ + rc->left = xLeft; + rc->top = yTop; + rc->right = xRight; + rc->bottom = yBottom; + return 1; +} + +/** + * Set the coordinates of a given region. + * @param hRgn region + * @param nXLeft x1 + * @param nYLeft y1 + * @param nWidth width + * @param nHeight height + * @return + */ + +int gdi_SetRgn(HGDI_RGN hRgn, int nXLeft, int nYLeft, int nWidth, int nHeight) +{ + hRgn->x = nXLeft; + hRgn->y = nYLeft; + hRgn->w = nWidth; + hRgn->h = nHeight; + hRgn->null = 0; + return 0; +} + +/** + * Convert rectangular coordinates to a region + * @param hRgn destination region + * @param nLeftRect x1 + * @param nTopRect y1 + * @param nRightRect x2 + * @param nBottomRect y2 + * @return + */ + +int gdi_SetRectRgn(HGDI_RGN hRgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) +{ + gdi_CRectToRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, hRgn); + hRgn->null = 0; + return 0; +} + +/** + * Set the current clipping region coordinates. + * @param hdc device context + * @param nXLeft x1 + * @param nYLeft y1 + * @param nWidth width + * @param nHeight height + * @return + */ + +/** + * Compare two regions for equality.\n + * @msdn{dd162700} + * @param hSrcRgn1 first region + * @param hSrcRgn2 second region + * @return 1 if both regions are equal, 0 otherwise + */ + +int gdi_EqualRgn(HGDI_RGN hSrcRgn1, HGDI_RGN hSrcRgn2) +{ + if ((hSrcRgn1->x == hSrcRgn2->x) && + (hSrcRgn1->y == hSrcRgn2->y) && + (hSrcRgn1->w == hSrcRgn2->w) && + (hSrcRgn1->h == hSrcRgn2->h)) + { + return 1; + } + + return 0; +} + +/** + * Copy coordinates from a rectangle to another rectangle + * @param dst destination rectangle + * @param src source rectangle + * @return 1 if successful, 0 otherwise + */ + +int gdi_CopyRect(HGDI_RECT dst, HGDI_RECT src) +{ + dst->left = src->left; + dst->top = src->top; + dst->right = src->right; + dst->bottom = src->bottom; + return 1; +} + +/** + * Check if a point is inside a rectangle.\n + * @msdn{dd162882} + * @param rc rectangle + * @param x point x position + * @param y point y position + * @return 1 if the point is inside, 0 otherwise + */ + +int gdi_PtInRect(HGDI_RECT rc, int x, int y) +{ + /* + * points on the left and top sides are considered in, + * while points on the right and bottom sides are considered out + */ + + if (x >= rc->left && x <= rc->right) + { + if (y >= rc->top && y <= rc->bottom) + { + return 1; + } + } + + return 0; +} + +/** + * Invalidate a given region, such that it is redrawn on the next region update.\n + * @msdn{dd145003} + * @param hdc device context + * @param x x1 + * @param y y1 + * @param w width + * @param h height + * @return + */ + +int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h) +{ + GDI_RECT inv; + GDI_RECT rgn; + HGDI_RGN invalid; + HGDI_BITMAP bmp; + + if (hdc->hwnd == NULL) + return 0; + + if (hdc->hwnd->invalid == NULL) + return 0; + + invalid = hdc->hwnd->invalid; + bmp = (HGDI_BITMAP) hdc->selectedObject; + + if (invalid->null) + { + invalid->x = x; + invalid->y = y; + invalid->w = w; + invalid->h = h; + invalid->null = 0; + return 0; + } + + gdi_CRgnToRect(x, y, w, h, &rgn); + gdi_RgnToRect(invalid, &inv); + + if (rgn.left < 0) + rgn.left = 0; + + if (rgn.top < 0) + rgn.top = 0; + + if (rgn.left < inv.left) + inv.left = rgn.left; + + if (rgn.top < inv.top) + inv.top = rgn.top; + + if (rgn.right > inv.right) + inv.right = rgn.right; + + if (rgn.bottom > inv.bottom) + inv.bottom = rgn.bottom; + + gdi_RectToRgn(&inv, invalid); + + return 0; +} diff --git a/libfreerdp-gdi/gdi_region.h b/libfreerdp-gdi/gdi_region.h new file mode 100644 index 000000000..61f8ed47d --- /dev/null +++ b/libfreerdp-gdi/gdi_region.h @@ -0,0 +1,44 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Region Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_REGION_H +#define __GDI_REGION_H + +#include "gdi.h" + +HGDI_RGN gdi_CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); +HGDI_RECT gdi_CreateRect(int xLeft, int yTop, int xRight, int yBottom); +void gdi_RectToRgn(HGDI_RECT rect, HGDI_RGN rgn); +void gdi_CRectToRgn(int left, int top, int right, int bottom, HGDI_RGN rgn); +void gdi_RectToCRgn(HGDI_RECT rect, int *x, int *y, int *w, int *h); +void gdi_CRectToCRgn(int left, int top, int right, int bottom, int *x, int *y, int *w, int *h); +void gdi_RgnToRect(HGDI_RGN rgn, HGDI_RECT rect); +void gdi_CRgnToRect(int x, int y, int w, int h, HGDI_RECT rect); +void gdi_RgnToCRect(HGDI_RGN rgn, int *left, int *top, int *right, int *bottom); +void gdi_CRgnToCRect(int x, int y, int w, int h, int *left, int *top, int *right, int *bottom); +int gdi_CopyOverlap(int x, int y, int width, int height, int srcx, int srcy); +int gdi_SetRect(HGDI_RECT rc, int xLeft, int yTop, int xRight, int yBottom); +int gdi_SetRgn(HGDI_RGN hRgn, int nXLeft, int nYLeft, int nWidth, int nHeight); +int gdi_SetRectRgn(HGDI_RGN hRgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); +int gdi_EqualRgn(HGDI_RGN hSrcRgn1, HGDI_RGN hSrcRgn2); +int gdi_CopyRect(HGDI_RECT dst, HGDI_RECT src); +int gdi_PtInRect(HGDI_RECT rc, int x, int y); +int gdi_InvalidateRegion(HGDI_DC hdc, int x, int y, int w, int h); + +#endif /* __GDI_REGION_H */ diff --git a/libfreerdp-gdi/gdi_shape.c b/libfreerdp-gdi/gdi_shape.c new file mode 100644 index 000000000..54563123b --- /dev/null +++ b/libfreerdp-gdi/gdi_shape.c @@ -0,0 +1,240 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Shape Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "gdi.h" +#include "gdi_8bpp.h" +#include "gdi_16bpp.h" +#include "gdi_32bpp.h" +#include "gdi_bitmap.h" + +#include "gdi_shape.h" + +pFillRect FillRect_[5] = +{ + NULL, + FillRect_8bpp, + FillRect_16bpp, + NULL, + FillRect_32bpp +}; + +static void Ellipse_Bresenham(HGDI_DC hdc, int x1, int y1, int x2, int y2) +{ + int i; + long e, e2; + long dx, dy; + int a, b, c; + int bx1, by1; + int bx2, by2; + + HGDI_BITMAP bmp; + uint8 pixel8; + uint16 pixel16; + uint32 pixel32; + int bpp = hdc->bitsPerPixel; + + a = (x1 < x2) ? x2 - x1 : x1 - x2; + b = (y1 < y2) ? y2 - y1 : y1 - y2; + c = b & 1; + + dx = 4 * (1 - a) * b * b; + dy = 4 * (c + 1) * a * a; + e = dx + dy + c * a * a; + + if (x1 > x2) + { + x1 = x2; + x2 += a; + } + + if (y1 > y2) + y1 = y2; + + y1 += (b + 1) / 2; + y2 = y1 - c; + + a *= 8 * a; + c = 8 * b * b; + + pixel8 = 0; + pixel16 = 0; + pixel32 = 0; + bmp = (HGDI_BITMAP) hdc->selectedObject; + + if (hdc->clip->null) + { + bx1 = (x1 < x2) ? x1 : x2; + by1 = (y1 < y2) ? y1 : y2; + bx2 = (x1 > x2) ? x1 : x2; + by2 = (y1 > y2) ? y1 : y2; + } + else + { + bx1 = hdc->clip->x; + by1 = hdc->clip->y; + bx2 = bx1 + hdc->clip->w - 1; + by2 = by1 + hdc->clip->h - 1; + } + + do + { + if (bpp == 32) + { + gdi_SetPixel_32bpp(bmp, x2, y1, pixel32); + gdi_SetPixel_32bpp(bmp, x1, y1, pixel32); + gdi_SetPixel_32bpp(bmp, x1, y2, pixel32); + gdi_SetPixel_32bpp(bmp, x2, y2, pixel32); + } + else if (bpp == 16) + { + gdi_SetPixel_16bpp(bmp, x2, y1, pixel16); + gdi_SetPixel_16bpp(bmp, x1, y1, pixel16); + gdi_SetPixel_16bpp(bmp, x1, y2, pixel16); + gdi_SetPixel_16bpp(bmp, x2, y2, pixel16); + } + else if (bpp == 8) + { + for (i = x1; i < x2; i++) + { + gdi_SetPixel_8bpp(bmp, i, y1, pixel8); + gdi_SetPixel_8bpp(bmp, i, y2, pixel8); + } + + for (i = y1; i < y2; i++) + { + gdi_SetPixel_8bpp(bmp, x1, i, pixel8); + gdi_SetPixel_8bpp(bmp, x2, i, pixel8); + } + } + + e2 = 2 * e; + + if (e2 >= dx) + { + x1++; + x2--; + e += dx += c; + } + + if (e2 <= dy) + { + y1++; + y2--; + e += dy += a; + } + } + while (x1 <= x2); + + while (y1 - y2 < b) + { + if (bpp == 32) + { + gdi_SetPixel_32bpp(bmp, x1 - 1, ++y1, pixel32); + gdi_SetPixel_32bpp(bmp, x1 - 1, --y2, pixel32); + } + else if (bpp == 16) + { + gdi_SetPixel_16bpp(bmp, x1 - 1, ++y1, pixel16); + gdi_SetPixel_16bpp(bmp, x1 - 1, --y2, pixel16); + } + else if (bpp == 8) + { + gdi_SetPixel_8bpp(bmp, x1 - 1, ++y1, pixel8); + gdi_SetPixel_8bpp(bmp, x1 - 1, --y2, pixel8); + } + } +} + +/** + * Draw an ellipse + * @param hdc device context + * @param nLeftRect x1 + * @param nTopRect y1 + * @param nRightRect x2 + * @param nBottomRect y2 + * @return + */ +int gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) +{ + Ellipse_Bresenham(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); + return 1; +} + +/** + * Fill a rectangle with the given brush.\n + * @msdn{dd162719} + * @param hdc device context + * @param rect rectangle + * @param hbr brush + * @return 1 if successful, 0 otherwise + */ + +int gdi_FillRect(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr) +{ + pFillRect _FillRect = FillRect_[IBPP(hdc->bitsPerPixel)]; + + if (_FillRect != NULL) + return _FillRect(hdc, rect, hbr); + else + return 0; +} + +/** + * + * @param hdc device context + * @param lpPoints array of points + * @param nCount number of points + * @return + */ +int gdi_Polygon(HGDI_DC hdc, GDI_POINT *lpPoints, int nCount) +{ + return 1; +} + +/** + * Draw a series of closed polygons + * @param hdc device context + * @param lpPoints array of series of points + * @param lpPolyCounts array of number of points in each series + * @param nCount count of number of points in lpPolyCounts + * @return + */ +int gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT *lpPoints, int *lpPolyCounts, int nCount) +{ + return 1; +} + +/** + * Draw a rectangle + * @param hdc device context + * @param nLeftRect x1 + * @param nTopRect y1 + * @param nRightRect x2 + * @param nBottomRect y2 + * @return + */ +int gdi_Rectangle(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) +{ + return 1; +} diff --git a/libfreerdp-gdi/gdi_shape.h b/libfreerdp-gdi/gdi_shape.h new file mode 100644 index 000000000..732973448 --- /dev/null +++ b/libfreerdp-gdi/gdi_shape.h @@ -0,0 +1,33 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * GDI Shape Functions + * + * Copyright 2010-2011 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __GDI_SHAPE_H +#define __GDI_SHAPE_H + +#include "gdi.h" + +int gdi_Ellipse(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); +int gdi_FillRect(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); +int gdi_Polygon(HGDI_DC hdc, GDI_POINT *lpPoints, int nCount); +int gdi_PolyPolygon(HGDI_DC hdc, GDI_POINT *lpPoints, int *lpPolyCounts, int nCount); +int gdi_Rectangle(HGDI_DC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); + +typedef int (*pFillRect)(HGDI_DC hdc, HGDI_RECT rect, HGDI_BRUSH hbr); + +#endif /* __GDI_SHAPE_H */