Diffstat (limited to 'noncore/net/opierdesktop/bitmap.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/net/opierdesktop/bitmap.cpp | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/noncore/net/opierdesktop/bitmap.cpp b/noncore/net/opierdesktop/bitmap.cpp new file mode 100644 index 0000000..378623f --- a/dev/null +++ b/noncore/net/opierdesktop/bitmap.cpp | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | rdesktop: A Remote Desktop Protocol client. | ||
3 | Bitmap decompression routines | ||
4 | Copyright (C) Matthew Chapman 1999-2002 | ||
5 | |||
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. | ||
10 | |||
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. | ||
15 | |||
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. | ||
19 | */ | ||
20 | |||
21 | #include "rdesktop.h" | ||
22 | |||
23 | #define CVAL(p) (*(p++)) | ||
24 | |||
25 | static uint32 | ||
26 | cvalx(unsigned char **input, int Bpp) | ||
27 | { | ||
28 | uint32 rv = 0; | ||
29 | memcpy(&rv, *input, Bpp); | ||
30 | *input += Bpp; | ||
31 | return rv; | ||
32 | } | ||
33 | |||
34 | static void | ||
35 | setli(unsigned char *input, int offset, uint32 value, int Bpp) | ||
36 | { | ||
37 | input += offset * Bpp; | ||
38 | memcpy(input, &value, Bpp); | ||
39 | } | ||
40 | |||
41 | static uint32 | ||
42 | getli(unsigned char *input, int offset, int Bpp) | ||
43 | { | ||
44 | uint32 rv = 0; | ||
45 | input += offset * Bpp; | ||
46 | memcpy(&rv, input, Bpp); | ||
47 | return rv; | ||
48 | } | ||
49 | |||
50 | #define UNROLL8(exp) { exp exp exp exp exp exp exp exp } | ||
51 | |||
52 | #define REPEAT(statement) \ | ||
53 | { \ | ||
54 | while((count & ~0x7) && ((x+8) < width)) \ | ||
55 | UNROLL8( statement; count--; x++; ); \ | ||
56 | \ | ||
57 | while((count > 0) && (x < width)) { statement; count--; x++; } \ | ||
58 | } | ||
59 | |||
60 | #define MASK_UPDATE() \ | ||
61 | { \ | ||
62 | mixmask <<= 1; \ | ||
63 | if (mixmask == 0) \ | ||
64 | { \ | ||
65 | mask = fom_mask ? fom_mask : CVAL(input); \ | ||
66 | mixmask = 1; \ | ||
67 | } \ | ||
68 | } | ||
69 | |||
70 | BOOL | ||
71 | bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, | ||
72 | int Bpp) | ||
73 | { | ||
74 | unsigned char *end = input + size; | ||
75 | unsigned char *prevline = NULL, *line = NULL; | ||
76 | int opcode, count, offset, isfillormix, x = width; | ||
77 | int lastopcode = -1, insertmix = False, bicolour = False; | ||
78 | uint8 code; | ||
79 | uint32 colour1 = 0, colour2 = 0; | ||
80 | uint8 mixmask, mask = 0; | ||
81 | uint32 mix = 0xffffffff; | ||
82 | int fom_mask = 0; | ||
83 | |||
84 | while (input < end) | ||
85 | { | ||
86 | fom_mask = 0; | ||
87 | code = CVAL(input); | ||
88 | opcode = code >> 4; | ||
89 | |||
90 | /* Handle different opcode forms */ | ||
91 | switch (opcode) | ||
92 | { | ||
93 | case 0xc: | ||
94 | case 0xd: | ||
95 | case 0xe: | ||
96 | opcode -= 6; | ||
97 | count = code & 0xf; | ||
98 | offset = 16; | ||
99 | break; | ||
100 | |||
101 | case 0xf: | ||
102 | opcode = code & 0xf; | ||
103 | if (opcode < 9) | ||
104 | { | ||
105 | count = CVAL(input); | ||
106 | count |= CVAL(input) << 8; | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | count = (opcode < 0xb) ? 8 : 1; | ||
111 | } | ||
112 | offset = 0; | ||
113 | break; | ||
114 | |||
115 | default: | ||
116 | opcode >>= 1; | ||
117 | count = code & 0x1f; | ||
118 | offset = 32; | ||
119 | break; | ||
120 | } | ||
121 | |||
122 | /* Handle strange cases for counts */ | ||
123 | if (offset != 0) | ||
124 | { | ||
125 | isfillormix = ((opcode == 2) || (opcode == 7)); | ||
126 | |||
127 | if (count == 0) | ||
128 | { | ||
129 | if (isfillormix) | ||
130 | count = CVAL(input) + 1; | ||
131 | else | ||
132 | count = CVAL(input) + offset; | ||
133 | } | ||
134 | else if (isfillormix) | ||
135 | { | ||
136 | count <<= 3; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | /* Read preliminary data */ | ||
141 | switch (opcode) | ||
142 | { | ||
143 | case 0:/* Fill */ | ||
144 | if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) | ||
145 | insertmix = True; | ||
146 | break; | ||
147 | case 8:/* Bicolour */ | ||
148 | colour1 = cvalx(&input, Bpp); | ||
149 | case 3:/* Colour */ | ||
150 | colour2 = cvalx(&input, Bpp); | ||
151 | break; | ||
152 | case 6:/* SetMix/Mix */ | ||
153 | case 7:/* SetMix/FillOrMix */ | ||
154 | mix = cvalx(&input, Bpp); | ||
155 | opcode -= 5; | ||
156 | break; | ||
157 | case 9:/* FillOrMix_1 */ | ||
158 | mask = 0x03; | ||
159 | opcode = 0x02; | ||
160 | fom_mask = 3; | ||
161 | break; | ||
162 | case 0x0a:/* FillOrMix_2 */ | ||
163 | mask = 0x05; | ||
164 | opcode = 0x02; | ||
165 | fom_mask = 5; | ||
166 | break; | ||
167 | |||
168 | } | ||
169 | |||
170 | lastopcode = opcode; | ||
171 | mixmask = 0; | ||
172 | |||
173 | /* Output body */ | ||
174 | while (count > 0) | ||
175 | { | ||
176 | if (x >= width) | ||
177 | { | ||
178 | if (height <= 0) | ||
179 | return False; | ||
180 | |||
181 | x = 0; | ||
182 | height--; | ||
183 | |||
184 | prevline = line; | ||
185 | line = output + height * width * Bpp; | ||
186 | } | ||
187 | |||
188 | switch (opcode) | ||
189 | { | ||
190 | case 0:/* Fill */ | ||
191 | if (insertmix) | ||
192 | { | ||
193 | if (prevline == NULL) | ||
194 | setli(line, x, mix, Bpp); | ||
195 | else | ||
196 | setli(line, x, | ||
197 | getli(prevline, x, Bpp) ^ mix, Bpp); | ||
198 | |||
199 | insertmix = False; | ||
200 | count--; | ||
201 | x++; | ||
202 | } | ||
203 | |||
204 | if (prevline == NULL) | ||
205 | { | ||
206 | REPEAT(setli(line, x, 0, Bpp))} | ||
207 | else | ||
208 | { | ||
209 | REPEAT(setli | ||
210 | (line, x, getli(prevline, x, Bpp), Bpp)); | ||
211 | } | ||
212 | break; | ||
213 | |||
214 | case 1:/* Mix */ | ||
215 | if (prevline == NULL) | ||
216 | { | ||
217 | REPEAT(setli(line, x, mix, Bpp)); | ||
218 | } | ||
219 | else | ||
220 | { | ||
221 | REPEAT(setli | ||
222 | (line, x, getli(prevline, x, Bpp) ^ mix, | ||
223 | Bpp)); | ||
224 | } | ||
225 | break; | ||
226 | |||
227 | case 2:/* Fill or Mix */ | ||
228 | if (prevline == NULL) | ||
229 | { | ||
230 | REPEAT(MASK_UPDATE(); | ||
231 | if (mask & mixmask) setli(line, x, mix, Bpp); | ||
232 | else | ||
233 | setli(line, x, 0, Bpp);); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | REPEAT(MASK_UPDATE(); | ||
238 | if (mask & mixmask) | ||
239 | setli(line, x, getli(prevline, x, Bpp) ^ mix, | ||
240 | Bpp); | ||
241 | else | ||
242 | setli(line, x, getli(prevline, x, Bpp), | ||
243 | Bpp);); | ||
244 | } | ||
245 | break; | ||
246 | |||
247 | case 3:/* Colour */ | ||
248 | REPEAT(setli(line, x, colour2, Bpp)); | ||
249 | break; | ||
250 | |||
251 | case 4:/* Copy */ | ||
252 | REPEAT(setli(line, x, cvalx(&input, Bpp), Bpp)); | ||
253 | break; | ||
254 | |||
255 | case 8:/* Bicolour */ | ||
256 | REPEAT(if (bicolour) | ||
257 | { | ||
258 | setli(line, x, colour2, Bpp); bicolour = False;} | ||
259 | else | ||
260 | { | ||
261 | setli(line, x, colour1, Bpp); bicolour = True; | ||
262 | count++;} | ||
263 | ); | ||
264 | break; | ||
265 | |||
266 | case 0xd:/* White */ | ||
267 | REPEAT(setli(line, x, 0xffffffff, Bpp)); | ||
268 | break; | ||
269 | |||
270 | case 0xe:/* Black */ | ||
271 | REPEAT(setli(line, x, 0, Bpp)); | ||
272 | break; | ||
273 | |||
274 | default: | ||
275 | unimpl("bitmap opcode 0x%x\n", opcode); | ||
276 | return False; | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | return True; | ||
282 | } | ||