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;
226 else if (bpp
== 15 || bpp
== 16)
228 return data
[(y
* 2) * width
+ (x
* 2)] != 0 ||
229 data
[(y
* 2) * width
+ (x
* 2) + 1] != 0;
231 else if (bpp
== 24 || bpp
== 32)
233 return data
[(y
* 4) * width
+ (x
* 4)] != 0 ||
234 data
[(y
* 4) * width
+ (x
* 4) + 1] != 0 ||
235 data
[(y
* 4) * width
+ (x
* 4) + 2] != 0 ||
236 data
[(y
* 4) * width
+ (x
* 4) + 3] != 0;
244 /*****************************************************************************/
246 bs_set_pixel_on(char * data
, int x
, int y
, int width
, int bpp
,
254 width
= (width
+ 7) / 8;
255 start
= (y
* width
) + x
/ 8;
259 data
[start
] = data
[start
] | (0x80 >> shift
);
263 data
[start
] = data
[start
] & ~(0x80 >> shift
);
268 data
[y
* width
+ x
] = pixel
;
270 else if (bpp
== 15 || bpp
== 16)
272 ((unsigned short *) data
)[y
* width
+ x
] = pixel
;
274 else if (bpp
== 24 || bpp
== 32)
276 ((unsigned int *) data
)[y
* width
+ x
] = (unsigned int) pixel
;
280 /*****************************************************************************/
282 bs_copy_mem(char * d
, char * s
, int n
)
303 /*****************************************************************************/
305 bs_copy_memb(char * d
, char * s
, int n
)
328 /*****************************************************************************/
329 /* return true is the is something to draw */
331 bs_warp_coords(int * x
, int * y
, int * cx
, int * cy
,
332 int * srcx
, int * srcy
)
337 if (g_clip_left1
> *x
)
339 dx
= g_clip_left1
- *x
;
345 if (g_clip_top1
> *y
)
347 dy
= g_clip_top1
- *y
;
353 if (*x
+ *cx
> g_clip_right1
)
355 *cx
= (*cx
- ((*x
+ *cx
) - g_clip_right1
));
357 if (*y
+ *cy
> g_clip_bottom1
)
359 *cy
= (*cy
- ((*y
+ *cy
) - g_clip_bottom1
));
384 /*****************************************************************************/
386 bs_rect(int x
, int y
, int cx
, int cy
, int colour
, int rop
)
391 unsigned short * p16
;
394 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, 0, 0))
396 if (rop
== 0) /* black */
401 else if (rop
== 15) /* white */
406 if (rop
== 12) /* copy */
410 for (i
= 0; i
< cy
; i
++)
412 p8
= (unsigned char *) get_bs_ptr(x
, y
+ i
);
415 for (j
= 0; j
< cx
; j
++)
425 for (i
= 0; i
< cy
; i
++)
427 p16
= (unsigned short *) get_bs_ptr(x
, y
+ i
);
430 for (j
= 0; j
< cx
; j
++)
440 for (i
= 0; i
< cy
; i
++)
442 p32
= (unsigned int *) get_bs_ptr(x
, y
+ i
);
445 for (j
= 0; j
< cx
; j
++)
456 for (i
= 0; i
< cy
; i
++)
458 for (j
= 0; j
< cx
; j
++)
460 bs_set_pixel(j
+ x
, i
+ y
, colour
, rop
, 0);
467 /*****************************************************************************/
469 bs_screenblt(int rop
, int x
, int y
, int cx
, int cy
,
478 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
480 if (rop
== 12) /* copy */
482 if (srcy
< y
) /* copy down - bottom to top */
484 for (i
= cy
- 1; i
>= 0; i
--)
486 src
= get_bs_ptr(srcx
, srcy
+ i
);
487 dst
= get_bs_ptr(x
, y
+ i
);
488 if (src
!= 0 && dst
!= 0)
490 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
494 else if (srcy
> y
|| srcx
> x
) /* copy up or left - top to bottom */
496 for (i
= 0; i
< cy
; i
++)
498 src
= get_bs_ptr(srcx
, srcy
+ i
);
499 dst
= get_bs_ptr(x
, y
+ i
);
500 if (src
!= 0 && dst
!= 0)
502 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
506 else /* copy straight right */
508 for (i
= 0; i
< cy
; i
++)
510 src
= get_bs_ptr(srcx
, srcy
+ i
);
511 dst
= get_bs_ptr(x
, y
+ i
);
512 if (src
!= 0 && dst
!= 0)
514 bs_copy_memb(dst
, src
, cx
* g_Bpp
);
521 if (srcy
< y
) /* copy down - bottom to top */
523 for (i
= cy
- 1; i
>= 0; i
--)
525 for (j
= 0; j
< cx
; j
++)
527 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
528 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
532 else if (srcy
> y
|| srcx
> x
) /* copy up or left - top to bottom */
534 for (i
= 0; i
< cy
; i
++)
536 for (j
= 0; j
< cx
; j
++)
538 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
539 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
543 else /* copy straight right */
545 for (i
= 0; i
< cy
; i
++)
547 for (j
= cx
- 1; j
>= 0; j
--)
549 p
= bs_get_pixel(srcx
+ j
, srcy
+ i
);
550 bs_set_pixel(x
+ j
, y
+ i
, p
, rop
, 0);
558 /*****************************************************************************/
560 bs_memblt(int opcode
, int x
, int y
, int cx
, int cy
,
561 void * srcdata
, int srcwidth
, int srcheight
,
570 if (bs_warp_coords(&x
, &y
, &cx
, &cy
, &srcx
, &srcy
))
572 if (opcode
== 12) /* copy */
576 src
= (char *) (((unsigned char *) srcdata
) + srcy
* srcwidth
+ srcx
);
580 src
= (char *) (((unsigned short *) srcdata
) + srcy
* srcwidth
+ srcx
);
584 src
= (char *) (((unsigned int *) srcdata
) + srcy
* srcwidth
+ srcx
);
586 for (i
= 0; i
< cy
; i
++)
588 dst
= get_bs_ptr(x
, y
+ i
);
591 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
592 src
+= srcwidth
* g_Bpp
;
600 for (i
= 0; i
< cy
; i
++)
602 for (j
= 0; j
< cx
; j
++)
604 p
= *(((unsigned char *) srcdata
) +
605 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
606 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
612 for (i
= 0; i
< cy
; i
++)
614 for (j
= 0; j
< cx
; j
++)
616 p
= *(((unsigned short *) srcdata
) +
617 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
618 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
624 for (i
= 0; i
< cy
; i
++)
626 for (j
= 0; j
< cx
; j
++)
628 p
= *(((unsigned int *) srcdata
) +
629 ((i
+ srcy
) * srcwidth
+ (j
+ srcx
)));
630 bs_set_pixel(x
+ j
, y
+ i
, p
, opcode
, 0);
638 /*****************************************************************************/
640 bs_draw_glyph(int x
, int y
, char * glyph_data
, int glyph_width
,
641 int glyph_height
, int fgcolour
)
646 for (i
= 0; i
< glyph_height
; i
++)
648 for (j
= 0; j
< glyph_width
; j
++)
650 if (bs_is_pixel_on(glyph_data
, j
, i
, glyph_width
, 8))
652 bs_set_pixel(x
+ j
, y
+ i
, fgcolour
, 12, 1);
658 /*****************************************************************************/
659 /* Bresenham's line drawing algorithm */
661 bs_line(int opcode
, int startx
, int starty
, int endx
, int endy
,
662 int pen_width
, int pen_style
, int pen_colour
)
695 dpru
= dpr
- (dx
<< 1);
697 for (; dx
>= 0; dx
--)
699 if (startx
!= endx
|| starty
!= endy
)
701 bs_set_pixel(startx
, starty
, pen_colour
, opcode
, 1);
719 dpru
= dpr
- (dy
<< 1);
721 for (; dy
>= 0; dy
--)
723 if (startx
!= endx
|| starty
!= endy
)
725 bs_set_pixel(startx
, starty
, pen_colour
, opcode
, 1);
742 /*****************************************************************************/
744 bs_patblt(int opcode
, int x
, int y
, int cx
, int cy
,
745 int brush_style
, char * brush_pattern
,
746 int brush_x_org
, int brush_y_org
,
747 int bgcolour
, int fgcolour
)
758 bs_rect(x
, y
, cx
, cy
, fgcolour
, opcode
);
761 b
= g_hatch_patterns
+ brush_pattern
[0] * 8;
764 for (i
= 0; i
< 8; i
++)
766 ipattern
[i
] = ~brush_pattern
[7 - i
];
773 for (i
= 0; i
< cy
; i
++)
775 for (j
= 0; j
< cx
; j
++)
777 if (bs_is_pixel_on(b
, (x
+ j
+ brush_x_org
) % 8,
778 (y
+ i
+ brush_y_org
) % 8, 8, 1))
780 bs_set_pixel(x
+ j
, y
+ i
, fgcolour
, opcode
, 1);
784 bs_set_pixel(x
+ j
, y
+ i
, bgcolour
, opcode
, 1);
791 /*****************************************************************************/
793 bs_copy_box(char * dst
, int x
, int y
, int cx
, int cy
, int line_size
)
798 /* shouldn't happen */
799 if (cx
< 1 || cy
< 1)
803 /* nothing to draw, memset and leave */
804 if (x
+ cx
< 0 || y
+ cy
< 0 || x
>= g_width1
|| y
>= g_height1
)
806 memset(dst
, 0, cx
* cy
* g_Bpp
);
809 /* check if it goes over an edge */
810 if (x
< 0 || y
< 0 || x
+ cx
> g_width1
|| y
+ cy
> g_height1
)
812 memset(dst
, 0, cx
* cy
* g_Bpp
);
819 if (x
+ cx
> g_width1
)
823 for (i
= 0; i
< cy
; i
++)
825 src
= get_bs_ptr(x
, y
+ i
);
828 bs_copy_mem(dst
, src
, cx
* g_Bpp
);
833 else /* whole box is within */
835 for (i
= 0; i
< cy
; i
++)
837 src
= get_bs_ptr(x
, y
+ i
);
840 bs_copy_mem(dst
, src
, cx
* g_Bpp
);