diff options
Diffstat (limited to 'rdp/rdp_bitmap.c')
| -rw-r--r-- | rdp/rdp_bitmap.c | 1743 |
1 files changed, 907 insertions, 836 deletions
diff --git a/rdp/rdp_bitmap.c b/rdp/rdp_bitmap.c index f2d31dae..adba5f6f 100644 --- a/rdp/rdp_bitmap.c +++ b/rdp/rdp_bitmap.c @@ -1,24 +1,22 @@ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp bitmap routines - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * 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. + * + * librdp bitmap routines + */ #include "rdp.h" @@ -35,891 +33,964 @@ /******************************************************************************/ #define REPEAT(statement) \ -{ \ - while ((count > 0) && (x < width)) \ - { \ - statement; \ - count--; \ - x++; \ - } \ -} + { \ + while ((count > 0) && (x < width)) \ + { \ + statement; \ + count--; \ + x++; \ + } \ + } /******************************************************************************/ #define MASK_UPDATE \ -{ \ - mixmask <<= 1; \ - if ((mixmask & 0xff) == 0) \ - { \ - mask = fom_mask ? fom_mask : CVAL(input); \ - mixmask = 1; \ - } \ -} + { \ + mixmask <<= 1; \ + if ((mixmask & 0xff) == 0) \ + { \ + mask = fom_mask ? fom_mask : CVAL(input); \ + mixmask = 1; \ + } \ + } /******************************************************************************/ /* 1 byte bitmap decompress */ /* returns boolean */ static int APP_CC -bitmap_decompress1(char* output, int width, int height, char* input, int size) +bitmap_decompress1(char *output, int width, int height, char *input, int size) { - char* prevline; - char* line; - char* end; - char color1; - char color2; - char mix; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1 = 0; - color2 = 0; - mix = 0xff; - mask = 0; - fom_mask = 0; - - while (input < end) - { + char *prevline; + char *line; + char *end; + char color1; + char color2; + char mix; + int code; + int mixmask; + int mask; + int opcode; + int count; + int offset; + int isfillormix; + int x; + int lastopcode; + int insertmix; + int bicolor; + int fom_mask; + + end = input + size; + prevline = 0; + line = 0; + x = width; + lastopcode = -1; + insertmix = 0; + bicolor = 0; + color1 = 0; + color2 = 0; + mix = 0xff; + mask = 0; fom_mask = 0; - code = CVAL(input); - opcode = code >> 4; - /* Handle different opcode forms */ - switch (opcode) - { - case 0xc: - case 0xd: - case 0xe: - opcode -= 6; - count = code & 0xf; - offset = 16; - break; - case 0xf: - opcode = code & 0xf; - if (opcode < 9) - { - count = CVAL(input); - count |= CVAL(input) << 8; - } - else - { - count = (opcode < 0xb) ? 8 : 1; - } - offset = 0; - break; - default: - opcode >>= 1; - count = code & 0x1f; - offset = 32; - break; - } - /* Handle strange cases for counts */ - if (offset != 0) - { - isfillormix = ((opcode == 2) || (opcode == 7)); - if (count == 0) - { - if (isfillormix) - { - count = CVAL(input) + 1; - } - else - { - count = CVAL(input) + offset; - } - } - else if (isfillormix) - { - count <<= 3; - } - } - /* Read preliminary data */ - switch (opcode) + + while (input < end) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + + /* Handle different opcode forms */ + switch (opcode) { - insertmix = 1; + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; } - break; - case 8: /* Bicolor */ - color1 = CVAL(input); - case 3: /* Color */ - color2 = CVAL(input); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - mix = CVAL(input); - opcode -= 5; - break; - case 9: /* FillOrMix_1 */ - mask = 0x03; - opcode = 0x02; - fom_mask = 3; - break; - case 0x0a: /* FillOrMix_2 */ - mask = 0x05; - opcode = 0x02; - fom_mask = 5; - break; - } - lastopcode = opcode; - mixmask = 0; - /* Output body */ - while (count > 0) - { - if (x >= width) - { - if (height <= 0) + + /* Handle strange cases for counts */ + if (offset != 0) { - return 0; - } - x = 0; - height--; - prevline = line; - line = output + height * width; - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) + isfillormix = ((opcode == 2) || (opcode == 7)); + + if (count == 0) { - line[x] = mix; + if (isfillormix) + { + count = CVAL(input) + 1; + } + else + { + count = CVAL(input) + offset; + } } - else + else if (isfillormix) { - line[x] = prevline[x] ^ mix; + count <<= 3; } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT(line[x] = 0) - } - else - { - REPEAT(line[x] = prevline[x]) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT(line[x] = mix) - } - else - { - REPEAT(line[x] = prevline[x] ^ mix) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x] = mix; - } - else - { - line[x] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x] = prevline[x] ^ mix; - } - else - { - line[x] = prevline[x]; - } - ) - } - break; - case 3: /* Color */ - REPEAT(line[x] = color2) - break; - case 4: /* Copy */ - REPEAT(line[x] = CVAL(input)) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + } + + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + + if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + { + insertmix = 1; + } + + break; + case 8: /* Bicolor */ + color1 = CVAL(input); + case 3: /* Color */ + color2 = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + + lastopcode = opcode; + mixmask = 0; + + /* Output body */ + while (count > 0) + { + if (x >= width) { - line[x] = color2; - bicolor = 0; + if (height <= 0) + { + return 0; + } + + x = 0; + height--; + prevline = line; + line = output + height * width; } - else + + switch (opcode) { - line[x] = color1; - bicolor = 1; - count++; + case 0: /* Fill */ + + if (insertmix) + { + if (prevline == 0) + { + line[x] = mix; + } + else + { + line[x] = prevline[x] ^ mix; + } + + insertmix = 0; + count--; + x++; + } + + if (prevline == 0) + { + REPEAT(line[x] = 0) + } + else + { + REPEAT(line[x] = prevline[x]) + } + + break; + case 1: /* Mix */ + + if (prevline == 0) + { + REPEAT(line[x] = mix) + } + else + { + REPEAT(line[x] = prevline[x] ^ mix) + } + + break; + case 2: /* Fill or Mix */ + + if (prevline == 0) + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x] = mix; + } + else + { + line[x] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x] = prevline[x] ^ mix; + } + else + { + line[x] = prevline[x]; + } + ) + } + + break; + case 3: /* Color */ + REPEAT(line[x] = color2) + break; + case 4: /* Copy */ + REPEAT(line[x] = CVAL(input)) + break; + case 8: /* Bicolor */ + REPEAT + ( + + if (bicolor) + { + line[x] = color2; + bicolor = 0; + } + else + { + line[x] = color1; + bicolor = 1; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT(line[x] = 0xff) + break; + case 0xe: /* Black */ + REPEAT(line[x] = 0) + break; + default: + return 0; + break; } - ) - break; - case 0xd: /* White */ - REPEAT(line[x] = 0xff) - break; - case 0xe: /* Black */ - REPEAT(line[x] = 0) - break; - default: - return 0; - break; - } + } } - } - return 1; + + return 1; } /******************************************************************************/ /* 2 byte bitmap decompress */ /* returns boolean */ static int APP_CC -bitmap_decompress2(char* output, int width, int height, char* input, int size) +bitmap_decompress2(char *output, int width, int height, char *input, int size) { - char* prevline; - char* line; - char* end; - char color1[2]; - char color2[2]; - char mix[2]; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1[0] = 0; - color1[1] = 0; - color2[0] = 0; - color2[1] = 0; - mix[0] = 0xff; - mix[1] = 0xff; - mask = 0; - fom_mask = 0; - - while (input < end) - { + char *prevline; + char *line; + char *end; + char color1[2]; + char color2[2]; + char mix[2]; + int code; + int mixmask; + int mask; + int opcode; + int count; + int offset; + int isfillormix; + int x; + int lastopcode; + int insertmix; + int bicolor; + int fom_mask; + + end = input + size; + prevline = 0; + line = 0; + x = width; + lastopcode = -1; + insertmix = 0; + bicolor = 0; + color1[0] = 0; + color1[1] = 0; + color2[0] = 0; + color2[1] = 0; + mix[0] = 0xff; + mix[1] = 0xff; + mask = 0; fom_mask = 0; - code = CVAL(input); - opcode = code >> 4; - /* Handle different opcode forms */ - switch (opcode) - { - case 0xc: - case 0xd: - case 0xe: - opcode -= 6; - count = code & 0xf; - offset = 16; - break; - case 0xf: - opcode = code & 0xf; - if (opcode < 9) - { - count = CVAL(input); - count |= CVAL(input) << 8; - } - else - { - count = (opcode < 0xb) ? 8 : 1; - } - offset = 0; - break; - default: - opcode >>= 1; - count = code & 0x1f; - offset = 32; - break; - } - /* Handle strange cases for counts */ - if (offset != 0) - { - isfillormix = ((opcode == 2) || (opcode == 7)); - if (count == 0) - { - if (isfillormix) - { - count = CVAL(input) + 1; - } - else - { - count = CVAL(input) + offset; - } - } - else if (isfillormix) - { - count <<= 3; - } - } - /* Read preliminary data */ - switch (opcode) + + while (input < end) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + + /* Handle different opcode forms */ + switch (opcode) { - insertmix = 1; + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; } - break; - case 8: /* Bicolor */ - color1[EIK0] = CVAL(input); - color1[EIK1] = CVAL(input); - case 3: /* Color */ - color2[EIK0] = CVAL(input); - color2[EIK1] = CVAL(input); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - mix[EIK0] = CVAL(input); - mix[EIK1] = CVAL(input); - opcode -= 5; - break; - case 9: /* FillOrMix_1 */ - mask = 0x03; - opcode = 0x02; - fom_mask = 3; - break; - case 0x0a: /* FillOrMix_2 */ - mask = 0x05; - opcode = 0x02; - fom_mask = 5; - break; - } - lastopcode = opcode; - mixmask = 0; - /* Output body */ - while (count > 0) - { - if (x >= width) - { - if (height <= 0) + + /* Handle strange cases for counts */ + if (offset != 0) { - return 0; - } - x = 0; - height--; - prevline = line; - line = output + height * (width * 2); - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) + isfillormix = ((opcode == 2) || (opcode == 7)); + + if (count == 0) { - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; + if (isfillormix) + { + count = CVAL(input) + 1; + } + else + { + count = CVAL(input) + offset; + } } - else + else if (isfillormix) { - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + count <<= 3; } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT - ( - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - ) - } - else - { - REPEAT - ( - line[x * 2 + 0] = prevline[x * 2 + 0]; - line[x * 2 + 1] = prevline[x * 2 + 1]; - ) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT - ( - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; - ) - } - else - { - REPEAT - ( - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; - ) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; - } - else - { - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; - } - else - { - line[x * 2 + 0] = prevline[x * 2 + 0]; - line[x * 2 + 1] = prevline[x * 2 + 1]; - } - ) - } - break; - case 3: /* Color */ - REPEAT - ( - line[x * 2 + 0] = color2[0]; - line[x * 2 + 1] = color2[1]; - ) - break; - case 4: /* Copy */ - REPEAT - ( - line[x * 2 + EIK0] = CVAL(input); - line[x * 2 + EIK1] = CVAL(input); - ) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + } + + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + + if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + { + insertmix = 1; + } + + break; + case 8: /* Bicolor */ + color1[EIK0] = CVAL(input); + color1[EIK1] = CVAL(input); + case 3: /* Color */ + color2[EIK0] = CVAL(input); + color2[EIK1] = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix[EIK0] = CVAL(input); + mix[EIK1] = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + + lastopcode = opcode; + mixmask = 0; + + /* Output body */ + while (count > 0) + { + if (x >= width) { - line[x * 2 + 0] = color2[0]; - line[x * 2 + 1] = color2[1]; - bicolor = 0; + if (height <= 0) + { + return 0; + } + + x = 0; + height--; + prevline = line; + line = output + height * (width * 2); } - else + + switch (opcode) { - line[x * 2 + 0] = color1[0]; - line[x * 2 + 1] = color1[1]; - bicolor = 1; - count++; + case 0: /* Fill */ + + if (insertmix) + { + if (prevline == 0) + { + line[x * 2 + 0] = mix[0]; + line[x * 2 + 1] = mix[1]; + } + else + { + line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; + line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + } + + insertmix = 0; + count--; + x++; + } + + if (prevline == 0) + { + REPEAT + ( + line[x * 2 + 0] = 0; + line[x * 2 + 1] = 0; + ) + } + else + { + REPEAT + ( + line[x * 2 + 0] = prevline[x * 2 + 0]; + line[x * 2 + 1] = prevline[x * 2 + 1]; + ) + } + + break; + case 1: /* Mix */ + + if (prevline == 0) + { + REPEAT + ( + line[x * 2 + 0] = mix[0]; + line[x * 2 + 1] = mix[1]; + ) + } + else + { + REPEAT + ( + line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; + line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + ) + } + + break; + case 2: /* Fill or Mix */ + + if (prevline == 0) + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 2 + 0] = mix[0]; + line[x * 2 + 1] = mix[1]; + } + else + { + line[x * 2 + 0] = 0; + line[x * 2 + 1] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; + line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + } + else + { + line[x * 2 + 0] = prevline[x * 2 + 0]; + line[x * 2 + 1] = prevline[x * 2 + 1]; + } + ) + } + + break; + case 3: /* Color */ + REPEAT + ( + line[x * 2 + 0] = color2[0]; + line[x * 2 + 1] = color2[1]; + ) + break; + case 4: /* Copy */ + REPEAT + ( + line[x * 2 + EIK0] = CVAL(input); + line[x * 2 + EIK1] = CVAL(input); + ) + break; + case 8: /* Bicolor */ + REPEAT + ( + + if (bicolor) + { + line[x * 2 + 0] = color2[0]; + line[x * 2 + 1] = color2[1]; + bicolor = 0; + } + else + { + line[x * 2 + 0] = color1[0]; + line[x * 2 + 1] = color1[1]; + bicolor = 1; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT + ( + line[x * 2 + 0] = 0xff; + line[x * 2 + 1] = 0xff; + ) + break; + case 0xe: /* Black */ + REPEAT + ( + line[x * 2 + 0] = 0; + line[x * 2 + 1] = 0; + ) + break; + default: + return 0; + break; } - ) - break; - case 0xd: /* White */ - REPEAT - ( - line[x * 2 + 0] = 0xff; - line[x * 2 + 1] = 0xff; - ) - break; - case 0xe: /* Black */ - REPEAT - ( - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - ) - break; - default: - return 0; - break; - } + } } - } - return 1; + + return 1; } /******************************************************************************/ /* 3 byte bitmap decompress */ /* returns boolean */ static int APP_CC -bitmap_decompress3(char* output, int width, int height, char* input, int size) +bitmap_decompress3(char *output, int width, int height, char *input, int size) { - char* prevline; - char* line; - char* end; - char color1[3]; - char color2[3]; - char mix[3]; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1[0] = 0; - color1[1] = 0; - color1[2] = 0; - color2[0] = 0; - color2[1] = 0; - color2[2] = 0; - mix[0] = 0xff; - mix[1] = 0xff; - mix[2] = 0xff; - mask = 0; - fom_mask = 0; - - while (input < end) - { + char *prevline; + char *line; + char *end; + char color1[3]; + char color2[3]; + char mix[3]; + int code; + int mixmask; + int mask; + int opcode; + int count; + int offset; + int isfillormix; + int x; + int lastopcode; + int insertmix; + int bicolor; + int fom_mask; + + end = input + size; + prevline = 0; + line = 0; + x = width; + lastopcode = -1; + insertmix = 0; + bicolor = 0; + color1[0] = 0; + color1[1] = 0; + color1[2] = 0; + color2[0] = 0; + color2[1] = 0; + color2[2] = 0; + mix[0] = 0xff; + mix[1] = 0xff; + mix[2] = 0xff; + mask = 0; fom_mask = 0; - code = CVAL(input); - opcode = code >> 4; - /* Handle different opcode forms */ - switch (opcode) - { - case 0xc: - case 0xd: - case 0xe: - opcode -= 6; - count = code & 0xf; - offset = 16; - break; - case 0xf: - opcode = code & 0xf; - if (opcode < 9) - { - count = CVAL(input); - count |= CVAL(input) << 8; - } - else - { - count = (opcode < 0xb) ? 8 : 1; - } - offset = 0; - break; - default: - opcode >>= 1; - count = code & 0x1f; - offset = 32; - break; - } - /* Handle strange cases for counts */ - if (offset != 0) - { - isfillormix = ((opcode == 2) || (opcode == 7)); - if (count == 0) - { - if (isfillormix) - { - count = CVAL(input) + 1; - } - else - { - count = CVAL(input) + offset; - } - } - else if (isfillormix) - { - count <<= 3; - } - } - /* Read preliminary data */ - switch (opcode) + + while (input < end) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + + /* Handle different opcode forms */ + switch (opcode) { - insertmix = 1; + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; } - break; - case 8: /* Bicolor */ - color1[0] = CVAL(input); - color1[1] = CVAL(input); - color1[2] = CVAL(input); - case 3: /* Color */ - color2[0] = CVAL(input); - color2[1] = CVAL(input); - color2[2] = CVAL(input); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - mix[0] = CVAL(input); - mix[1] = CVAL(input); - mix[2] = CVAL(input); - opcode -= 5; - break; - case 9: /* FillOrMix_1 */ - mask = 0x03; - opcode = 0x02; - fom_mask = 3; - break; - case 0x0a: /* FillOrMix_2 */ - mask = 0x05; - opcode = 0x02; - fom_mask = 5; - break; - } - lastopcode = opcode; - mixmask = 0; - /* Output body */ - while (count > 0) - { - if (x >= width) - { - if (height <= 0) + + /* Handle strange cases for counts */ + if (offset != 0) { - return 0; - } - x = 0; - height--; - prevline = line; - line = output + height * (width * 3); - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) + isfillormix = ((opcode == 2) || (opcode == 7)); + + if (count == 0) { - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; + if (isfillormix) + { + count = CVAL(input) + 1; + } + else + { + count = CVAL(input) + offset; + } } - else + else if (isfillormix) { - line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; - line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + count <<= 3; } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT - ( - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - } - else - { - REPEAT - ( - line[x * 3 + 0] = prevline[x * 3 + 0]; - line[x * 3 + 1] = prevline[x * 3 + 1]; - line[x * 3 + 2] = prevline[x * 3 + 2]; - ) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT - ( - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - ) - } - else - { - REPEAT - ( - line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; - line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; - ) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - } - else - { - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; - line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; - } - else - { - line[x * 3 + 0] = prevline[x * 3 + 0]; - line[x * 3 + 1] = prevline[x * 3 + 1]; - line[x * 3 + 2] = prevline[x * 3 + 2]; - } - ) - } - break; - case 3: /* Color */ - REPEAT - ( - line[x * 3 + 0] = color2[0]; - line[x * 3 + 1] = color2[1]; - line[x * 3 + 2] = color2[2]; - ) - break; - case 4: /* Copy */ - REPEAT - ( - line[x * 3 + 0] = CVAL(input); - line[x * 3 + 1] = CVAL(input); - line[x * 3 + 2] = CVAL(input); - ) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + } + + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + + if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + { + insertmix = 1; + } + + break; + case 8: /* Bicolor */ + color1[0] = CVAL(input); + color1[1] = CVAL(input); + color1[2] = CVAL(input); + case 3: /* Color */ + color2[0] = CVAL(input); + color2[1] = CVAL(input); + color2[2] = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix[0] = CVAL(input); + mix[1] = CVAL(input); + mix[2] = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + + lastopcode = opcode; + mixmask = 0; + + /* Output body */ + while (count > 0) + { + if (x >= width) { - line[x * 3 + 0] = color2[0]; - line[x * 3 + 1] = color2[1]; - line[x * 3 + 2] = color2[2]; - bicolor = 0; + if (height <= 0) + { + return 0; + } + + x = 0; + height--; + prevline = line; + line = output + height * (width * 3); } - else + + switch (opcode) { - line[x * 3 + 0] = color1[0]; - line[x * 3 + 1] = color1[1]; - line[x * 3 + 2] = color1[2]; - bicolor = 1; - count++; + case 0: /* Fill */ + + if (insertmix) + { + if (prevline == 0) + { + line[x * 3 + 0] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + } + else + { + line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; + line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + } + + insertmix = 0; + count--; + x++; + } + + if (prevline == 0) + { + REPEAT + ( + line[x * 3 + 0] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + ) + } + else + { + REPEAT + ( + line[x * 3 + 0] = prevline[x * 3 + 0]; + line[x * 3 + 1] = prevline[x * 3 + 1]; + line[x * 3 + 2] = prevline[x * 3 + 2]; + ) + } + + break; + case 1: /* Mix */ + + if (prevline == 0) + { + REPEAT + ( + line[x * 3 + 0] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + ) + } + else + { + REPEAT + ( + line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; + line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + ) + } + + break; + case 2: /* Fill or Mix */ + + if (prevline == 0) + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 3 + 0] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + } + else + { + line[x * 3 + 0] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; + line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + } + else + { + line[x * 3 + 0] = prevline[x * 3 + 0]; + line[x * 3 + 1] = prevline[x * 3 + 1]; + line[x * 3 + 2] = prevline[x * 3 + 2]; + } + ) + } + + break; + case 3: /* Color */ + REPEAT + ( + line[x * 3 + 0] = color2[0]; + line[x * 3 + 1] = color2[1]; + line[x * 3 + 2] = color2[2]; + ) + break; + case 4: /* Copy */ + REPEAT + ( + line[x * 3 + 0] = CVAL(input); + line[x * 3 + 1] = CVAL(input); + line[x * 3 + 2] = CVAL(input); + ) + break; + case 8: /* Bicolor */ + REPEAT + ( + + if (bicolor) + { + line[x * 3 + 0] = color2[0]; + line[x * 3 + 1] = color2[1]; + line[x * 3 + 2] = color2[2]; + bicolor = 0; + } + else + { + line[x * 3 + 0] = color1[0]; + line[x * 3 + 1] = color1[1]; + line[x * 3 + 2] = color1[2]; + bicolor = 1; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT + ( + line[x * 3 + 0] = 0xff; + line[x * 3 + 1] = 0xff; + line[x * 3 + 2] = 0xff; + ) + break; + case 0xe: /* Black */ + REPEAT + ( + line[x * 3 + 0] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + ) + break; + default: + return 0; + break; } - ) - break; - case 0xd: /* White */ - REPEAT - ( - line[x * 3 + 0] = 0xff; - line[x * 3 + 1] = 0xff; - line[x * 3 + 2] = 0xff; - ) - break; - case 0xe: /* Black */ - REPEAT - ( - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - break; - default: - return 0; - break; - } + } } - } - return 1; + + return 1; } /*****************************************************************************/ /* returns boolean */ int APP_CC -rdp_bitmap_decompress(char* output, int width, int height, char* input, +rdp_bitmap_decompress(char *output, int width, int height, char *input, int size, int Bpp) { - int rv; - - switch (Bpp) - { - case 1: - rv = bitmap_decompress1(output, width, height, input, size); - break; - case 2: - rv = bitmap_decompress2(output, width, height, input, size); - break; - case 3: - rv = bitmap_decompress3(output, width, height, input, size); - break; - default: - rv = 0; - break; - } - return rv; + int rv; + + switch (Bpp) + { + case 1: + rv = bitmap_decompress1(output, width, height, input, size); + break; + case 2: + rv = bitmap_decompress2(output, width, height, input, size); + break; + case 3: + rv = bitmap_decompress3(output, width, height, input, size); + break; + default: + rv = 0; + break; + } + + return rv; } |
