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 along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 static char * g_bs
= 0;
25 static int g_bs_size
= 0;
27 static int g_width1
= 800;
28 static int g_height1
= 600;
32 static int g_clip_left1
= 0;
33 static int g_clip_top1
= 0;
34 static int g_clip_right1
= 800;
35 static int g_clip_bottom1
= 600;
38 static char g_hatch_patterns
[] =
40 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, /* 0 - bsHorizontal */
41 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* 1 - bsVertical */
42 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, /* 2 - bsFDiagonal */
43 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, /* 3 - bsBDiagonal */
44 0x08, 0x08, 0x08, 0xff, 0x08, 0x08, 0x08, 0x08, /* 4 - bsCross */
45 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 /* 5 - bsDiagCross */
49 /*****************************************************************************/
52 bs_do_rop(int rop
, int src
, int dst
)
57 case 0x1: return ~(src
| dst
);
58 case 0x2: return (~src
) & dst
;
59 case 0x3: return ~src
;
60 case 0x4: return src
& (~dst
);
61 case 0x5: return ~(dst
);
62 case 0x6: return src
^ dst
;
63 case 0x7: return ~(src
& dst
);
64 case 0x8: return src
& dst
;
65 case 0x9: return ~(src
) ^ dst
;
67 case 0xb: return (~src
) | dst
;
69 case 0xd: return src
| (~dst
);
70 case 0xe: return src
| dst
;
76 /*****************************************************************************/
77 /* get a pixel from the in memory copy of whats on the screen */
79 bs_get_pixel(int x
, int y
)
83 if (x
>= 0 && x
< g_width1
&& y
>= 0 && y
< g_height1
)
85 p
= g_bs
+ (y
* g_width1
* g_Bpp
) + (x
* g_Bpp
);
88 return *((unsigned char *) p
);
92 return *((unsigned short *) p
);
96 return *((unsigned int *) p
);
105 /*****************************************************************************/
106 /* set a pixel on the screen using the clip */
108 bs_set_pixel(int x
, int y
, int pixel
, int rop
, int use_clip
)
113 (x
>= g_clip_left1
&& x
< g_clip_right1
&&
114 y
>= g_clip_top1
&& y
< g_clip_bottom1
))
116 if (x
>= 0 && x
< g_width1
&& y
>= 0 && y
< g_height1
)
118 p
= g_bs
+ (y
* g_width1
* g_Bpp
) + (x
* g_Bpp
);
121 pixel
= bs_do_rop(rop
, pixel
, bs_get_pixel(x
, y
));
125 *((unsigned char *) p
) = pixel
;
129 *((unsigned short *) p
) = pixel
;
133 *((unsigned int *) p
) = pixel
;
139 /*****************************************************************************/
141 get_bs_ptr(int x
, int y
)
145 if (x
>= 0 && x
< g_width1
&& y
>= 0 && y
< g_height1
)
147 p
= g_bs
+ (y
* g_width1
* g_Bpp
) + (x
* g_Bpp
);
156 /*****************************************************************************/
158 bs_init(int width
, int height
, int bpp
)
167 g_Bpp
= (bpp
+ 7) / 8;
168 g_bs_size
= width
* height
* g_Bpp
;
169 g_bs
= malloc(g_bs_size
);
170 memset(g_bs
, 0, g_bs_size
);
173 g_clip_right1
= width
;
174 g_clip_bottom1
= height
;
177 /*****************************************************************************/
187 /*****************************************************************************/
189 bs_set_clip(int x
, int y
, int cx
, int cy
)
193 g_clip_right1
= x
+ cx
;
194 g_clip_bottom1
= y
+ cy
;
197 /*****************************************************************************/
203 g_clip_right1
= g_width1
;
204 g_clip_bottom1
= g_height1
;
207 /*****************************************************************************/
208 /* check if a certain pixel is set in a bitmap */
210 bs_is_pixel_on(char * data
, int x
, int y
, int width
, int bpp
)
217 width
= (width
+ 7) / 8;
218 start
= (y
* width
) + x
/ 8;
220 return (data
[start
] & (0x80 >> shift
)) != 0;
224 return data
[y
* width
+ x
] != 0;
228 return data
[(y
* 3) * width
+ (x
* 3)] != 0 &&
229 data
[(y
* 3) * width
+ (x
* 3) + 1] != 0 &&
230 data
[(y
* 3) * width
+ (x
* 3) + 2] != 0;
238 /*****************************************************************************/
240 bs_set_pixel_on(char * data
, int x
, int y
, int width
, int bpp
,
248 width
= (width
+ 7) / 8;
249 start
= (y
* width
) + x
/ 8;
253 data
[start
] = data
[start
] | (0x80 >> shift
);
257 data
[start
] = data
[start
] & ~(0x80 >> shift
);
262 data
[y
* width
+ x
] = pixel
;
264 else if (bpp
== 15 || bpp
== 16)
266 ((unsigned short *) data
)[y
* width
+ x
] = pixel
;
270 /*****************************************************************************/
272 bs_copy_mem(char * d
, char * s
, int n
)
293 /*****************************************************************************/
295 bs_copy_memb(char * d
, char * s
, int n
)
318 /*****************************************************************************/
319 /* return true is the is something to draw */
321 bs_warp_coords(int * x
, int * y
, int * cx
, int * cy
,
322 int * srcx
, int * srcy
)
327 if (g_clip_left1
> *x
)
329 dx
= g_clip_left1
- *x
;
335 if (g_clip_top1
> *y
)
337 dy
= g_clip_top1
- *y
;
343 if (*x
+ *cx
> g_clip_right1
)
345 *cx
= (*cx
- ((*x
+ *cx
) - g_clip_right1
));
347 if (*y
+ *cy
> g_clip_bottom1
)
349 *cy
= (*cy
- ((*y
+ *cy
) - g_clip_bottom1
));
374 /*****************************************************************************/
376 bs_rect(int x
, int y
, int cx
, int cy
, int colour
, int rop
)
381 unsigned short * p16
;
384 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, 0, 0))
386 if (rop
== 0) /* black */
391 else if (rop
== 15) /* white */
396 if (rop
== 12) /* copy */
400 for (i
= 0; i
< cy
; i
++)
402 p8
= (unsigned char *) get_bs_ptr(x
, y
+ i
);
405 for (j
= 0; j
< cx
; j
++)
415 for (i
= 0; i
< cy
; i
++)
417 p16
= (unsigned short *) get_bs_ptr(x
, y
+ i
);
420 for (j
= 0; j
< cx
; j
++)
430 for (i
= 0; i
< cy
; i
++)
432 p32
= (unsigned int *) get_bs_ptr(x
, y
+ i
);
435 for (j
= 0; j
< cx
; j
++)
446 for (i
= 0; i
< cy
; i
++)
448 for (j
= 0; j
< cx
; j
++)
450 bs_set_pixel(j
+ x
, i
+ y
, colour
, rop
, 0);
457 /*****************************************************************************/
459 bs_screenblt(int rop
, int x
, int y
, int cx
, int cy
,
468 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
470 if (rop
== 12) /* copy */
472 if (srcy
< y
) /* copy down - bottom to top */
474 for (i
= cy
- 1; i
>= 0; i
--)
476 src
= get_bs_ptr(srcx
, srcy
+ i
);
477 dst
= get_bs_ptr(x
, y
+ i
);
478 if (src
!= 0 && dst
!= 0)
480 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
484 else if (srcy
> y
|| srcx
> x
) /* copy up or left - top to bottom */
486 for (i
= 0; i
< cy
; i
++)
488 src
= get_bs_ptr(srcx
, srcy
+ i
);
489 dst
= get_bs_ptr(x
, y
+ i
);
490 if (src
!= 0 && dst
!= 0)
492 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
496 else /* copy straight right */
498 for (i
= 0; i
< cy
; i
++)
500 src
= get_bs_ptr(srcx
, srcy
+ i
);
501 dst
= get_bs_ptr(x
, y
+ i
);
502 if (src
!= 0 && dst
!= 0)
504 bs_copy_memb(dst
, src
, cx
* g_Bpp
);
511 if (srcy
< y
) /* copy down - bottom to top */
513 for (i
= cy
- 1; i
>= 0; i
--)
515 for (j
= 0; j
< cx
; j
++)
517 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
518 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
522 else if (srcy
> y
|| srcx
> x
) /* copy up or left - top to bottom */
524 for (i
= 0; i
< cy
; i
++)
526 for (j
= 0; j
< cx
; j
++)
528 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
529 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
533 else /* copy straight right */
535 for (i
= 0; i
< cy
; i
++)
537 for (j
= cx
- 1; j
>= 0; j
--)
539 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
540 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
548 /*****************************************************************************/
550 bs_memblt(int opcode
, int x
, int y
, int cx
, int cy
,
551 void * srcdata
, int srcwidth
, int srcheight
,
560 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
562 if (opcode
== 12) /* copy */
566 src
= (char *) (((unsigned char *) srcdata
) + srcy
* srcwidth
+ srcx
);
570 src
= (char *) (((unsigned short *) srcdata
) + srcy
* srcwidth
+ srcx
);
574 src
= (char *) (((unsigned int *) srcdata
) + srcy
* srcwidth
+ srcx
);
576 for (i
= 0; i
< cy
; i
++)
578 dst
= get_bs_ptr(x
, y
+ i
);
581 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
582 src
+= srcwidth
* g_Bpp
;
590 for (i
= 0; i
< cy
; i
++)
592 for (j
= 0; j
< cx
; j
++)
594 p
= *(((unsigned char *) srcdata
) +
595 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
596 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
602 for (i
= 0; i
< cy
; i
++)
604 for (j
= 0; j
< cx
; j
++)
606 p
= *(((unsigned short *) srcdata
) +
607 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
608 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
614 for (i
= 0; i
< cy
; i
++)
616 for (j
= 0; j
< cx
; j
++)
618 p
= *(((unsigned int *) srcdata
) +
619 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
620 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
628 /*****************************************************************************/
630 bs_draw_glyph(int x
, int y
, char * glyph_data
, int glyph_width
,
631 int glyph_height
, int fgcolour
)
636 for (i
= 0; i
< glyph_height
; i
++)
638 for (j
= 0; j
< glyph_width
; j
++)
640 if (bs_is_pixel_on(glyph_data
, j
, i
, glyph_width
, 8))
642 bs_set_pixel(x
+ j
, y
+ i
, fgcolour
, 12, 1);
648 /*****************************************************************************/
649 /* Bresenham's line drawing algorithm */
651 bs_line(int opcode
, int startx
, int starty
, int endx
, int endy
,
652 int pen_width
, int pen_style
, int pen_colour
)
685 dpru
= dpr
- (dx
<< 1);
687 for (; dx
>= 0; dx
--)
689 if (startx
!= endx
|| starty
!= endy
)
691 bs_set_pixel(startx
, starty
, pen_colour
, opcode
, 1);
709 dpru
= dpr
- (dy
<< 1);
711 for (; dy
>= 0; dy
--)
713 if (startx
!= endx
|| starty
!= endy
)
715 bs_set_pixel(startx
, starty
, pen_colour
, opcode
, 1);
732 /*****************************************************************************/
734 bs_patblt(int opcode
, int x
, int y
, int cx
, int cy
,
735 int brush_style
, char * brush_pattern
,
736 int brush_x_org
, int brush_y_org
,
737 int bgcolour
, int fgcolour
)
748 bs_rect(x
, y
, cx
, cy
, fgcolour
, opcode
);
751 b
= g_hatch_patterns
+ brush_pattern
[0] * 8;
754 for (i
= 0; i
< 8; i
++)
756 ipattern
[i
] = ~brush_pattern
[7 - i
];
763 for (i
= 0; i
< cy
; i
++)
765 for (j
= 0; j
< cx
; j
++)
767 if (bs_is_pixel_on(b
, (x
+ j
+ brush_x_org
) % 8,
768 (y
+ i
+ brush_y_org
) % 8, 8, 1))
770 bs_set_pixel(x
+ j
, y
+ i
, fgcolour
, opcode
, 1);
774 bs_set_pixel(x
+ j
, y
+ i
, bgcolour
, opcode
, 1);
781 /*****************************************************************************/
783 bs_copy_box(char * dst
, int x
, int y
, int cx
, int cy
, int line_size
)
788 /* shouldn't happen */
789 if (cx
< 1 || cy
< 1)
793 /* nothing to draw, memset and leave */
794 if (x
+ cx
< 0 || y
+ cy
< 0 || x
>= g_width1
|| y
>= g_height1
)
796 memset(dst
, 0, cx
* cy
* g_Bpp
);
799 /* check if it goes over an edge */
800 if (x
< 0 || y
< 0 || x
+ cx
> g_width1
|| y
+ cy
> g_height1
)
802 memset(dst
, 0, cx
* cy
* g_Bpp
);
809 if (x
+ cx
> g_width1
)
813 for (i
= 0; i
< cy
; i
++)
815 src
= get_bs_ptr(x
, y
+ i
);
818 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
823 else /* whole box is within */
825 for (i
= 0; i
< cy
; i
++)
827 src
= get_bs_ptr(x
, y
+ i
);
830 bs_copy_mem(dst
, src
, cx
* g_Bpp
);