1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Generics backingstore operations
4 Copyright (C) Jay Sorg 2005-2006
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 static char * g_bs
= 0;
28 static int g_bs_size
= 0;
30 static int g_width1
= 800;
31 static int g_height1
= 600;
35 static int g_clip_left1
= 0;
36 static int g_clip_top1
= 0;
37 static int g_clip_right1
= 800;
38 static int g_clip_bottom1
= 600;
41 static char g_hatch_patterns
[] =
43 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
44 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
45 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
46 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
47 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
48 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
52 /*****************************************************************************/
55 bs_do_rop(int rop
, int src
, int dst
)
60 case 0x1: return ~(src
| dst
);
61 case 0x2: return (~src
) & dst
;
62 case 0x3: return ~src
;
63 case 0x4: return src
& (~dst
);
64 case 0x5: return ~(dst
);
65 case 0x6: return src
^ dst
;
66 case 0x7: return ~(src
& dst
);
67 case 0x8: return src
& dst
;
68 case 0x9: return ~(src
) ^ dst
;
70 case 0xb: return (~src
) | dst
;
72 case 0xd: return src
| (~dst
);
73 case 0xe: return src
| dst
;
79 /*****************************************************************************/
80 /* get a pixel from the in memory copy of whats on the screen */
82 bs_get_pixel(int x
, int y
)
86 if (x
>= 0 && x
< g_width1
&& y
>= 0 && y
< g_height1
)
88 p
= g_bs
+ (y
* g_width1
* g_Bpp
) + (x
* g_Bpp
);
91 return *((unsigned char *) p
);
95 return *((unsigned short *) p
);
99 return *((unsigned int *) p
);
108 /*****************************************************************************/
109 /* set a pixel on the screen using the clip */
111 bs_set_pixel(int x
, int y
, int pixel
, int rop
, int use_clip
)
116 (x
>= g_clip_left1
&& x
< g_clip_right1
&&
117 y
>= g_clip_top1
&& y
< g_clip_bottom1
))
119 if (x
>= 0 && x
< g_width1
&& y
>= 0 && y
< g_height1
)
121 p
= g_bs
+ (y
* g_width1
* g_Bpp
) + (x
* g_Bpp
);
124 pixel
= bs_do_rop(rop
, pixel
, bs_get_pixel(x
, y
));
128 *((unsigned char *) p
) = pixel
;
132 *((unsigned short *) p
) = pixel
;
136 *((unsigned int *) p
) = pixel
;
142 /*****************************************************************************/
144 get_bs_ptr(int x
, int y
)
148 if (x
>= 0 && x
< g_width1
&& y
>= 0 && y
< g_height1
)
150 p
= g_bs
+ (y
* g_width1
* g_Bpp
) + (x
* g_Bpp
);
159 /*****************************************************************************/
161 bs_init(int width
, int height
, int bpp
)
170 g_Bpp
= (bpp
+ 7) / 8;
171 g_bs_size
= width
* height
* g_Bpp
;
172 g_bs
= malloc(g_bs_size
);
173 memset(g_bs
, 0, g_bs_size
);
176 g_clip_right1
= width
;
177 g_clip_bottom1
= height
;
180 /*****************************************************************************/
190 /*****************************************************************************/
192 bs_set_clip(int x
, int y
, int cx
, int cy
)
196 g_clip_right1
= x
+ cx
;
197 g_clip_bottom1
= y
+ cy
;
200 /*****************************************************************************/
206 g_clip_right1
= g_width1
;
207 g_clip_bottom1
= g_height1
;
210 /*****************************************************************************/
211 /* check if a certain pixel is set in a bitmap */
213 bs_is_pixel_on(char * data
, int x
, int y
, int width
, int bpp
)
220 width
= (width
+ 7) / 8;
221 start
= (y
* width
) + x
/ 8;
223 return (data
[start
] & (0x80 >> shift
)) != 0;
227 return data
[y
* width
+ x
] != 0;
231 return data
[(y
* 3) * width
+ (x
* 3)] != 0 &&
232 data
[(y
* 3) * width
+ (x
* 3) + 1] != 0 &&
233 data
[(y
* 3) * width
+ (x
* 3) + 2] != 0;
241 /*****************************************************************************/
243 bs_set_pixel_on(char * data
, int x
, int y
, int width
, int bpp
,
251 width
= (width
+ 7) / 8;
252 start
= (y
* width
) + x
/ 8;
256 data
[start
] = data
[start
] | (0x80 >> shift
);
260 data
[start
] = data
[start
] & ~(0x80 >> shift
);
265 data
[y
* width
+ x
] = pixel
;
267 else if (bpp
== 15 || bpp
== 16)
269 ((unsigned short *) data
)[y
* width
+ x
] = pixel
;
273 /*****************************************************************************/
275 bs_copy_mem(char * d
, char * s
, int n
)
296 /*****************************************************************************/
298 bs_copy_memb(char * d
, char * s
, int n
)
321 /*****************************************************************************/
322 /* return true is the is something to draw */
324 bs_warp_coords(int * x
, int * y
, int * cx
, int * cy
,
325 int * srcx
, int * srcy
)
330 if (g_clip_left1
> *x
)
332 dx
= g_clip_left1
- *x
;
338 if (g_clip_top1
> *y
)
340 dy
= g_clip_top1
- *y
;
346 if (*x
+ *cx
> g_clip_right1
)
348 *cx
= (*cx
- ((*x
+ *cx
) - g_clip_right1
));
350 if (*y
+ *cy
> g_clip_bottom1
)
352 *cy
= (*cy
- ((*y
+ *cy
) - g_clip_bottom1
));
377 /*****************************************************************************/
379 bs_rect(int x
, int y
, int cx
, int cy
, int colour
, int rop
)
384 unsigned short * p16
;
387 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, 0, 0))
389 if (rop
== 0) /* black */
394 else if (rop
== 15) /* white */
399 if (rop
== 12) /* copy */
403 for (i
= 0; i
< cy
; i
++)
405 p8
= (unsigned char *) get_bs_ptr(x
, y
+ i
);
408 for (j
= 0; j
< cx
; j
++)
418 for (i
= 0; i
< cy
; i
++)
420 p16
= (unsigned short *) get_bs_ptr(x
, y
+ i
);
423 for (j
= 0; j
< cx
; j
++)
433 for (i
= 0; i
< cy
; i
++)
435 p32
= (unsigned int *) get_bs_ptr(x
, y
+ i
);
438 for (j
= 0; j
< cx
; j
++)
449 for (i
= 0; i
< cy
; i
++)
451 for (j
= 0; j
< cx
; j
++)
453 bs_set_pixel(j
+ x
, i
+ y
, colour
, rop
, 0);
460 /*****************************************************************************/
462 bs_screenblt(int rop
, int x
, int y
, int cx
, int cy
,
471 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
473 if (rop
== 12) /* copy */
475 if (srcy
< y
) /* copy down - bottom to top */
477 for (i
= cy
- 1; i
>= 0; i
--)
479 src
= get_bs_ptr(srcx
, srcy
+ i
);
480 dst
= get_bs_ptr(x
, y
+ i
);
481 if (src
!= 0 && dst
!= 0)
483 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
487 else if (srcy
> y
|| srcx
> x
) /* copy up or left - top to bottom */
489 for (i
= 0; i
< cy
; i
++)
491 src
= get_bs_ptr(srcx
, srcy
+ i
);
492 dst
= get_bs_ptr(x
, y
+ i
);
493 if (src
!= 0 && dst
!= 0)
495 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
499 else /* copy straight right */
501 for (i
= 0; i
< cy
; i
++)
503 src
= get_bs_ptr(srcx
, srcy
+ i
);
504 dst
= get_bs_ptr(x
, y
+ i
);
505 if (src
!= 0 && dst
!= 0)
507 bs_copy_memb(dst
, src
, cx
* g_Bpp
);
514 if (srcy
< y
) /* copy down - bottom to top */
516 for (i
= cy
- 1; i
>= 0; i
--)
518 for (j
= 0; j
< cx
; j
++)
520 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
521 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
525 else if (srcy
> y
|| srcx
> x
) /* copy up or left - top to bottom */
527 for (i
= 0; i
< cy
; i
++)
529 for (j
= 0; j
< cx
; j
++)
531 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
532 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
536 else /* copy straight right */
538 for (i
= 0; i
< cy
; i
++)
540 for (j
= cx
- 1; j
>= 0; j
--)
542 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
543 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
551 /*****************************************************************************/
553 bs_memblt(int opcode
, int x
, int y
, int cx
, int cy
,
554 void * srcdata
, int srcwidth
, int srcheight
,
563 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
565 if (opcode
== 12) /* copy */
569 src
= (char *) (((unsigned char *) srcdata
) + srcy
* srcwidth
+ srcx
);
573 src
= (char *) (((unsigned short *) srcdata
) + srcy
* srcwidth
+ srcx
);
577 src
= (char *) (((unsigned int *) srcdata
) + srcy
* srcwidth
+ srcx
);
579 for (i
= 0; i
< cy
; i
++)
581 dst
= get_bs_ptr(x
, y
+ i
);
584 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
585 src
+= srcwidth
* g_Bpp
;
593 for (i
= 0; i
< cy
; i
++)
595 for (j
= 0; j
< cx
; j
++)
597 p
= *(((unsigned char *) srcdata
) +
598 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
599 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
605 for (i
= 0; i
< cy
; i
++)
607 for (j
= 0; j
< cx
; j
++)
609 p
= *(((unsigned short *) srcdata
) +
610 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
611 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
617 for (i
= 0; i
< cy
; i
++)
619 for (j
= 0; j
< cx
; j
++)
621 p
= *(((unsigned int *) srcdata
) +
622 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
623 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
631 /*****************************************************************************/
633 bs_draw_glyph(int x
, int y
, char * glyph_data
, int glyph_width
,
634 int glyph_height
, int fgcolour
)
639 for (i
= 0; i
< glyph_height
; i
++)
641 for (j
= 0; j
< glyph_width
; j
++)
643 if (bs_is_pixel_on(glyph_data
, j
, i
, glyph_width
, 8))
645 bs_set_pixel(x
+ j
, y
+ i
, fgcolour
, 12, 1);
651 /*****************************************************************************/
652 /* Bresenham's line drawing algorithm */
654 bs_line(int opcode
, int startx
, int starty
, int endx
, int endy
,
655 int pen_width
, int pen_style
, int pen_colour
)
688 dpru
= dpr
- (dx
<< 1);
690 for (; dx
>= 0; dx
--)
692 if (startx
!= endx
|| starty
!= endy
)
694 bs_set_pixel(startx
, starty
, pen_colour
, opcode
, 1);
712 dpru
= dpr
- (dy
<< 1);
714 for (; dy
>= 0; dy
--)
716 if (startx
!= endx
|| starty
!= endy
)
718 bs_set_pixel(startx
, starty
, pen_colour
, opcode
, 1);
735 /*****************************************************************************/
737 bs_patblt(int opcode
, int x
, int y
, int cx
, int cy
,
738 int brush_style
, char * brush_pattern
,
739 int brush_x_org
, int brush_y_org
,
740 int bgcolour
, int fgcolour
)
751 bs_rect(x
, y
, cx
, cy
, fgcolour
, opcode
);
754 b
= g_hatch_patterns
+ brush_pattern
[0] * 8;
757 for (i
= 0; i
< 8; i
++)
759 ipattern
[i
] = ~brush_pattern
[7 - i
];
766 for (i
= 0; i
< cy
; i
++)
768 for (j
= 0; j
< cx
; j
++)
770 if (bs_is_pixel_on(b
, (x
+ j
+ brush_x_org
) % 8,
771 (y
+ i
+ brush_y_org
) % 8, 8, 1))
773 bs_set_pixel(x
+ j
, y
+ i
, fgcolour
, opcode
, 1);
777 bs_set_pixel(x
+ j
, y
+ i
, bgcolour
, opcode
, 1);
784 /*****************************************************************************/
786 bs_copy_box(char * dst
, int x
, int y
, int cx
, int cy
, int line_size
)
791 /* shouldn't happen */
792 if (cx
< 1 || cy
< 1)
796 /* nothing to draw, memset and leave */
797 if (x
+ cx
< 0 || y
+ cy
< 0 || x
>= g_width1
|| y
>= g_height1
)
799 memset(dst
, 0, cx
* cy
* g_Bpp
);
802 /* check if it goes over an edge */
803 if (x
< 0 || y
< 0 || x
+ cx
> g_width1
|| y
+ cy
> g_height1
)
805 memset(dst
, 0, cx
* cy
* g_Bpp
);
812 if (x
+ cx
> g_width1
)
816 for (i
= 0; i
< cy
; i
++)
818 src
= get_bs_ptr(x
, y
+ i
);
821 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
826 else /* whole box is within */
828 for (i
= 0; i
< cy
; i
++)
830 src
= get_bs_ptr(x
, y
+ i
);
833 bs_copy_mem(dst
, src
, cx
* g_Bpp
);