diff --git a/asn.c b/asn.c index 6c591c8..2c9fd4d 100644 --- a/asn.c +++ b/asn.c @@ -30,314 +30,286 @@ static asn1_node *asn_defs = NULL; -#define MAX_ERROR_DESCRIPTION_SIZE 1024 -char errstr[MAX_ERROR_DESCRIPTION_SIZE]; +#define MAX_ERROR_DESCRIPTION_SIZE 1024 +static char errstr[MAX_ERROR_DESCRIPTION_SIZE]; /* Parse an ASN.1 BER header */ -RD_BOOL -ber_parse_header(STREAM s, int tagval, uint32 *length) +static int ber_parse_header(STREAM s, int tagval, uint32 *length) { - int tag, len; + int tag, len; - if (tagval > 0xff) - { - if (!s_check_rem(s, 2)) { - return False; - } - in_uint16_be(s, tag); - } - else - { - if (!s_check_rem(s, 1)) { - return False; - } - in_uint8(s, tag); - } + if (tagval > 0xff) { + if (!s_check_rem(s, 2)) { + return ASN_PARSE_ERROR; + } + in_uint16_be(s, tag); + } else { + if (!s_check_rem(s, 1)) { + return ASN_PARSE_ERROR; + } + in_uint8(s, tag); + } - if (tag != tagval) - { - logger(Core, Error, "ber_parse_header(), expected tag %d, got %d", tagval, tag); - return False; - } + if (tag != tagval) { + logger(Core, Error, "ber_parse_header(), expected tag %d, got %d", tagval, tag); + return ASN_TAG_ERROR; + } - if (!s_check_rem(s, 1)) { - return False; - } - in_uint8(s, len); + if (!s_check_rem(s, 1)) { + return ASN_PARSE_ERROR; + } + in_uint8(s, len); - if (len & 0x80) - { - len &= ~0x80; - if (!s_check_rem(s, len)) { - return False; - } - *length = 0; - while (len--) - next_be(s, *length); - } - else - *length = len; + if (len & 0x80) { + len &= ~0x80; + if (!s_check_rem(s, len)) { + return ASN_PARSE_ERROR; + } + *length = 0; + while (len--) { + next_be(s, *length); + } + } else { + *length = len; + } - return True; + return ASN_SUCCESS; } -void -ber_out_sequence(STREAM out, STREAM content) +static void ber_out_sequence(STREAM out, STREAM content) { - size_t length; - length = (content ? s_length(content) : 0); - ber_out_header(out, BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, length); - if (content) - out_stream(out, content); + size_t length; + length = (content ? s_length(content) : 0); + ber_out_header(out, BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, length); + if (content) { + out_stream(out, content); + } } - /* Output an ASN.1 BER header */ -void -ber_out_header(STREAM s, int tagval, int length) +static void ber_out_header(STREAM s, int tagval, int length) { - if (tagval > 0xff) - { - out_uint16_be(s, tagval); - } - else - { - out_uint8(s, tagval); - } + if (tagval > 0xff) { + out_uint16_be(s, tagval); + } else { + out_uint8(s, tagval); + } - if (length >= 0x80) - { - out_uint8(s, 0x82); - out_uint16_be(s, length); - } - else - out_uint8(s, length); + if (length >= 0x80) { + out_uint8(s, 0x82); + out_uint16_be(s, length); + } else { + out_uint8(s, length); + } } /* Output an ASN.1 BER integer */ -void -ber_out_integer(STREAM s, int value) +static void ber_out_integer(STREAM s, int value) { - ber_out_header(s, BER_TAG_INTEGER, 2); - out_uint16_be(s, value); + ber_out_header(s, BER_TAG_INTEGER, 2); + out_uint16_be(s, value); } -RD_BOOL -ber_in_header(STREAM s, int *tagval, int *decoded_len) +static int ber_in_header(STREAM s, int *tagval, int *decoded_len) { - in_uint8(s, *tagval); - in_uint8(s, *decoded_len); + in_uint8(s, *tagval); + in_uint8(s, *decoded_len); - if (*decoded_len < 0x80) - return True; - else if (*decoded_len == 0x81) - { - in_uint8(s, *decoded_len); - return True; - } - else if (*decoded_len == 0x82) - { - in_uint16_be(s, *decoded_len); - return True; - } + if (*decoded_len < 0x80) { + return ASN_SUCCESS; + } else if (*decoded_len == 0x81) { + in_uint8(s, *decoded_len); + return ASN_SUCCESS; + } else if (*decoded_len == 0x82) { + in_uint16_be(s, *decoded_len); + return ASN_SUCCESS; + } - return False; + return ASN_PARSE_ERROR; } - -int init_asn1_lib(void) +static int init_asn1_lib(void) { - int asn1_rv; + int asn1_rv; - if (asn_defs) { - return 0; - } + if (asn_defs) { + return ASN_SUCCESS; + } - asn_defs = malloc(sizeof(*asn_defs)); + asn_defs = malloc(sizeof(*asn_defs)); - if (!asn_defs) { - logger(Core, Error, "%s:%s:%d Failed to allocate memory for ASN.1 parser\n", - __FILE__, __func__, __LINE__); - return 1; - } + if (!asn_defs) { + logger(Core, Error, "%s:%s:%d Failed to allocate memory for ASN.1 parser\n", + __FILE__, __func__, __LINE__); + return ASN_MEM_ERROR; + } - *asn_defs = NULL; + *asn_defs = NULL; - if (ASN1_SUCCESS != (asn1_rv = asn1_array2tree(pkix_asn1_tab, asn_defs, errstr))) { - logger(Core, Error, "%s:%s:%d Failed to init ASN.1 parser. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + if (ASN1_SUCCESS != (asn1_rv = asn1_array2tree(pkix_asn1_tab, asn_defs, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to init ASN.1 parser. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } + free(asn_defs); + asn_defs = NULL; + return asn1_rv; + } - return 0; + return ASN_SUCCESS; } /* Encode RSA public key into DER PKCS#1 */ -/* Returns; 0 - success, 1 - fatal error, 2 - insufficient space in buffer */ -int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len) +static int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len) { - int asn1_rv; - asn1_node asn_cert; + int asn1_rv; + asn1_node asn_cert; - if (!asn_defs) { - if (init_asn1_lib() != 0) { - return 1; - } - } + if (!asn_defs) { + if (init_asn1_lib() != ASN_SUCCESS) { + return ASN_INIT_ERROR; + } + } - if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_cert))) { - logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element for RSAPublicKey. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } + if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_cert))) { + logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element for RSAPublicKey. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_CREATE_ERROR; + } - if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "modulus", m->data, m->size))) { - logger(Core, Error, "%s:%s:%d Failed to write modulus. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "modulus", m->data, m->size))) { + logger(Core, Error, "%s:%s:%d Failed to write modulus. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } + return ASN_WRITE_ERROR; + } - if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "publicExponent", e->data, e->size))) { - logger(Core, Error, "%s:%s:%d Failed to write publicExponent. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } + if (ASN1_SUCCESS != (asn1_rv = asn1_write_value(asn_cert, "publicExponent", e->data, e->size))) { + logger(Core, Error, "%s:%s:%d Failed to write publicExponent. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_WRITE_ERROR; + } - if (ASN1_SUCCESS != (asn1_rv = asn1_der_coding(asn_cert, "", out, out_len, errstr))) { - logger(Core, Error, "%s:%s:%d Failed to encode PKIX1Implicit88.RSAPublicKey. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + if (ASN1_SUCCESS != (asn1_rv = asn1_der_coding(asn_cert, "", out, out_len, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to encode PKIX1Implicit88.RSAPublicKey. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - if (asn1_rv == ASN1_MEM_ERROR) { - return 2; - } + return ASN_ENCODE_ERROR; + } - return 1; - } + return ASN_SUCCESS; +} - return 0; +static int libtasn_read_cert_pk(uint8_t *data, size_t len, char *oid, size_t *oid_size, gnutls_datum_t *m, gnutls_datum_t *e) +{ + int asn1_rv; + asn1_node asn_cert; + + /* Parse DER encoded x.509 certificate */ + if (!asn_defs) { + if (init_asn1_lib() != ASN_SUCCESS) { + return ASN_INIT_ERROR; + } + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) { + logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_CREATE_ERROR; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_DECODE_ERROR; + } + + if (oid && oid_size) { + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm", + oid, (int *)oid_size))) + { + logger(Core, Error, "%s:%s:%d Failed to get cert's public key algorithm. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_READ_ERROR; + } + } + + if (m && e) { + int buflen; + uint8_t buf[16384]; + + asn1_node asn_key; + int nblen; + uint8_t newbuf[16384]; + + buflen = sizeof(buf) - 1; + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", buf, &buflen))) { + logger(Core, Error, "%s:%s:%d Failed to get cert's public key. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_READ_ERROR; + } + + if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_key))) { + logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_CREATE_ERROR; + } + + // As it' a BIT STRING the len constitutes the number of BITS, not BYTES + if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_key, buf, buflen / 8, errstr))) { + logger(Core, Error, "%s:%s:%d Failed to decode public key object. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_DECODE_ERROR; + } + + /* Get RSA public key's modulus and exponent */ + nblen = sizeof(newbuf); + + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "modulus", newbuf, &nblen))) { + logger(Core, Error, "%s:%s:%d Failed to get RSA public key's modulus. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + return ASN_READ_ERROR; + } + + m->size = nblen; + + m->data = malloc(m->size); + if (!m->data) { + logger(Core, Error, "%s:%s:%d Failed to allocate memory for modulus.\n", __FILE__, __func__, __LINE__); + return ASN_MEM_ERROR; + } + + memcpy((void *)m->data, newbuf, m->size); + + nblen = sizeof(newbuf); + + if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "publicExponent", newbuf, &nblen))) { + logger(Core, Error, "%s:%s:%d Failed to get RSA public key's exponent. Error = 0x%x (%s)\n", + __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); + free(m->data); + return ASN_READ_ERROR; + } + + e->size = nblen; + + e->data = malloc(e->size); + if (!e->data) { + logger(Core, Error, "%s:%s:%d Failed to allocate memory for exponent.\n", __FILE__, __func__, __LINE__); + free(m->data); + return ASN_MEM_ERROR; + } + + memcpy((void *)e->data, newbuf, e->size); + } + + return ASN_SUCCESS; } int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size) { - int asn1_rv; - asn1_node asn_cert; - - /* Parse DER encoded x.509 certificate */ - if (!asn_defs) { - if (init_asn1_lib() != 0) { - return 1; - } - } - - if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) { - logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) { - logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm", - oid, (int *)oid_size))) - { - logger(Core, Error, "%s:%s:%d Failed to get cert's public key algorithm. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - return 0; + return libtasn_read_cert_pk(data, len, oid, oid_size, NULL, NULL); } int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e) { - int asn1_rv; - asn1_node asn_cert; - - int buflen; - uint8_t buf[16384]; - - asn1_node asn_key; - int nblen; - uint8_t newbuf[16384]; - - /* Parse DER encoded x.509 certificate */ - init_asn1_lib(); - - if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.Certificate", &asn_cert))) { - logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_cert, data, len, errstr))) { - logger(Core, Error, "%s:%s:%d Failed to decode certificate object. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - buflen = sizeof(buf) - 1; - if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_cert, "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey", buf, &buflen))) { - logger(Core, Error, "%s:%s:%d Failed to get cert's public key. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - if (ASN1_SUCCESS != (asn1_rv = asn1_create_element(*asn_defs, "PKIX1Implicit88.RSAPublicKey", &asn_key))) { - logger(Core, Error, "%s:%s:%d Failed to create ASN.1 parser element. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - // As it' a BIT STRING the len constitutes the number of BITS, not BYTES - if (ASN1_SUCCESS != (asn1_rv = asn1_der_decoding(&asn_key, buf, buflen / 8, errstr))) { - logger(Core, Error, "%s:%s:%d Failed to decode public key object. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - /* Get RSA public key's modulus and exponent */ - nblen = sizeof(newbuf); - - if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "modulus", newbuf, &nblen))) { - logger(Core, Error, "%s:%s:%d Failed to get RSA public key's modulus. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - m->size = nblen; - - if (!(m->data = malloc(m->size))) { - logger(Core, Error, "%s:%s:%d Failed to allocate memory for modulus.\n", __FILE__, __func__, __LINE__); - return 1; - } - - memcpy((void *)m->data, newbuf, m->size); - - nblen = sizeof(newbuf); - - if (ASN1_SUCCESS != (asn1_rv = asn1_read_value(asn_key, "publicExponent", newbuf, &nblen))) { - logger(Core, Error, "%s:%s:%d Failed to get RSA public key's exponent. Error = 0x%x (%s)\n", - __FILE__, __func__, __LINE__, asn1_rv, asn1_strerror(asn1_rv)); - return 1; - } - - e->size = nblen; - - if (!(e->data = malloc(e->size))) { - logger(Core, Error, "%s:%s:%d Failed to allocate memory for exponent.\n", __FILE__, __func__, __LINE__); - if (m->data) { - free(m->data); - } - return 1; - } - - memcpy((void *)e->data, newbuf, e->size); - - return 0; + return libtasn_read_cert_pk(data, len, NULL, NULL, m, e); } diff --git a/asn.h b/asn.h index f783900..9e7250b 100644 --- a/asn.h +++ b/asn.h @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef _RDASN_H -#define _RDASN_H +#ifndef RDASN_H +#define RDASN_H #include #include @@ -29,17 +29,68 @@ extern "C" { #endif -#define OID_SHA_WITH_RSA_SIGNATURE "1.3.14.3.2.15" -#define OID_MD5_WITH_RSA_SIGNATURE "1.3.14.3.2.25" +#define OID_SHA_WITH_RSA_SIGNATURE "1.3.14.3.2.15" +#define OID_MD5_WITH_RSA_SIGNATURE "1.3.14.3.2.25" -int init_asn1_lib(void); -int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len); +/** + * Initialize the ASN.1 library. + * + * This function initializes the ASN.1 library and should be called before any other ASN.1 functions. + * + * Returns: 0 on success, or a non-zero error code on failure. + */ +extern int init_asn1_lib(void); -int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size); -int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e); +/** + * Encode an RSA public key into DER PKCS#1 format. + * + * This function encodes an RSA public key into DER PKCS#1 format. The modulus and exponent of the public key are + * provided as input, and the encoded key is returned in the output buffer. + * + * Parameters: + * - m: A pointer to a gnutls_datum_t structure that contains the modulus of the public key. + * - e: A pointer to a gnutls_datum_t structure that contains the exponent of the public key. + * - out: A pointer to the output buffer where the encoded key will be stored. + * - out_len: A pointer to an integer that will be set to the length of the encoded key. + * + * Returns: 0 on success, or a non-zero error code on failure. + */ +extern int write_pkcs1_der_pubkey(const gnutls_datum_t *m, const gnutls_datum_t *e, uint8_t *out, int *out_len); + +/** + * Read the public key algorithm OID from a DER encoded x.509 certificate. + * + * This function reads the public key algorithm OID from a DER encoded x.509 certificate. The certificate is provided + * as input, and the OID is returned in the output buffer. + * + * Parameters: + * - data: A pointer to the input buffer that contains the DER encoded x.509 certificate. + * - len: The length of the input buffer. + * - oid: A pointer to the output buffer where the OID will be stored. + * - oid_size: A pointer to an integer that will be set to the length of the OID. + * + * Returns: 0 on success, or a non-zero error code on failure. + */ +extern int libtasn_read_cert_pk_oid(uint8_t *data, size_t len, char *oid, size_t *oid_size); + +/** + * Read the public key parameters from a DER encoded x.509 certificate. + * + * This function reads the public key parameters (modulus and exponent) from a DER encoded x.509 certificate. The + * certificate is provided as input, and the parameters are returned in the output buffers. + * + * Parameters: + * - data: A pointer to the input buffer that contains the DER encoded x.509 certificate. + * - len: The length of the input buffer. + * - m: A pointer to a gnutls_datum_t structure that will be set to the modulus of the public key. + * - e: A pointer to a gnutls_datum_t structure that will be set to the exponent of the public key. + * + * Returns: 0 on success, or a non-zero error code on failure. + */ +extern int libtasn_read_cert_pk_parameters(uint8_t *data, size_t len, gnutls_datum_t *m, gnutls_datum_t *e); #ifdef __cplusplus } #endif -#endif /* _RDASN_H */ +#endif /* RDASN_H */ diff --git a/bitmap.c b/bitmap.c index 55c768c..b71ec78 100644 --- a/bitmap.c +++ b/bitmap.c @@ -17,10 +17,6 @@ along with this program. If not, see . */ -/* three separate function for speed when decompressing the bitmaps - when modifying one function make the change in the others - jay.sorg@gmail.com */ - /* indent is confused by this file */ /* *INDENT-OFF* */ @@ -62,857 +58,388 @@ } \ } -/* 1 byte bitmap decompress */ +#define OPCODE_FILL 0 +#define OPCODE_MIX 1 +#define OPCODE_FILL_OR_MIX 2 +#define OPCODE_COLOUR 3 +#define OPCODE_COPY 4 +#define OPCODE_BICOLOUR 8 +#define OPCODE_WHITE 0xd +#define OPCODE_BLACK 0xe + +#define WHITE_PIXEL 0xff +#define BLACK_PIXEL 0 + static RD_BOOL -bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size) +bitmap_decompress_n(uint8 *output, int width, int height, uint8 *input, int size, int bytes_per_pixel) { - uint8 *end = input + size; - uint8 *prevline = NULL, *line = NULL; - int opcode, count, offset, isfillormix, x = width; - int lastopcode = -1, insertmix = False, bicolour = False; - uint8 code; - uint8 colour1 = 0, colour2 = 0; - uint8 mixmask, mask = 0; - uint8 mix = 0xff; - int fom_mask = 0; + uint8 *end = input + size; + uint8 *prevline = NULL, *line = NULL; + int opcode, count, offset, isfillormix, x = width; + int lastopcode = -1, insertmix = False, bicolour = False; + uint8 code; + uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0}; + uint8 mixmask, mask = 0; + uint8 mix[3] = {0xff, 0xff, 0xff}; + int fom_mask = 0; - while (input < end) - { - 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) - { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) - insertmix = True; - break; - case 8: /* Bicolour */ - colour1 = CVAL(input); - colour2 = CVAL(input); - break; - case 3: /* Colour */ - colour2 = 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) - return False; - x = 0; - height--; - prevline = line; - line = output + height * width; - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == NULL) - line[x] = mix; - else - line[x] = prevline[x] ^ mix; - insertmix = False; - count--; - x++; - } - if (prevline == NULL) - { - REPEAT(line[x] = 0) - } - else - { - REPEAT(line[x] = prevline[x]) - } - break; - case 1: /* Mix */ - if (prevline == NULL) - { - REPEAT(line[x] = mix) - } - else - { - REPEAT(line[x] = prevline[x] ^ mix) - } - break; - case 2: /* Fill or Mix */ - if (prevline == NULL) - { - 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: /* Colour */ - REPEAT(line[x] = colour2) - break; - case 4: /* Copy */ - REPEAT(line[x] = CVAL(input)) - break; - case 8: /* Bicolour */ - REPEAT - ( - if (bicolour) - { - line[x] = colour2; - bicolour = False; - } - else - { - line[x] = colour1; - bicolour = True; count++; - } - ) - break; - case 0xd: /* White */ - REPEAT(line[x] = 0xff) - break; - case 0xe: /* Black */ - REPEAT(line[x] = 0) - break; - default: - logger(Core, Warning, "bitmap_decompress(), unhandled bitmap opcode 0x%x", opcode); - return False; - } - } - } - return True; -} - -/* 2 byte bitmap decompress */ -static RD_BOOL -bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size) -{ - uint8 *end = input + size; - uint16 *prevline = NULL, *line = NULL; - int opcode, count, offset, isfillormix, x = width; - int lastopcode = -1, insertmix = False, bicolour = False; - uint8 code; - uint16 colour1 = 0, colour2 = 0; - uint8 mixmask, mask = 0; - uint16 mix = 0xffff; - int fom_mask = 0; - - while (input < end) - { - 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) - { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) - insertmix = True; - break; - case 8: /* Bicolour */ - CVAL2(input, colour1); - CVAL2(input, colour2); - break; - case 3: /* Colour */ - CVAL2(input, colour2); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - CVAL2(input, mix); - 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) - return False; - x = 0; - height--; - prevline = line; - line = ((uint16 *) output) + height * width; - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == NULL) - line[x] = mix; - else - line[x] = prevline[x] ^ mix; - insertmix = False; - count--; - x++; - } - if (prevline == NULL) - { - REPEAT(line[x] = 0) - } - else - { - REPEAT(line[x] = prevline[x]) - } - break; - case 1: /* Mix */ - if (prevline == NULL) - { - REPEAT(line[x] = mix) - } - else - { - REPEAT(line[x] = prevline[x] ^ mix) - } - break; - case 2: /* Fill or Mix */ - if (prevline == NULL) - { - 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: /* Colour */ - REPEAT(line[x] = colour2) - break; - case 4: /* Copy */ - REPEAT(CVAL2(input, line[x])) - break; - case 8: /* Bicolour */ - REPEAT - ( - if (bicolour) - { - line[x] = colour2; - bicolour = False; - } - else - { - line[x] = colour1; - bicolour = True; - count++; - } - ) - break; - case 0xd: /* White */ - REPEAT(line[x] = 0xffff) - break; - case 0xe: /* Black */ - REPEAT(line[x] = 0) - break; - default: - logger(Core, Warning, "bitmap_decompress2(), unhandled bitmap opcode 0x%x", opcode); - return False; - } - } - } - return True; -} - -/* 3 byte bitmap decompress */ -static RD_BOOL -bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size) -{ - uint8 *end = input + size; - uint8 *prevline = NULL, *line = NULL; - int opcode, count, offset, isfillormix, x = width; - int lastopcode = -1, insertmix = False, bicolour = False; - uint8 code; - uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0}; - uint8 mixmask, mask = 0; - uint8 mix[3] = {0xff, 0xff, 0xff}; - int fom_mask = 0; - - while (input < end) - { - 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) - { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) - insertmix = True; - break; - case 8: /* Bicolour */ - colour1[0] = CVAL(input); - colour1[1] = CVAL(input); - colour1[2] = CVAL(input); - colour2[0] = CVAL(input); - colour2[1] = CVAL(input); - colour2[2] = CVAL(input); - break; - case 3: /* Colour */ - colour2[0] = CVAL(input); - colour2[1] = CVAL(input); - colour2[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) - return False; - x = 0; - height--; - prevline = line; - line = output + height * (width * 3); - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == NULL) - { - line[x * 3] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - } - else - { - line[x * 3] = - prevline[x * 3] ^ mix[0]; - line[x * 3 + 1] = - prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = - prevline[x * 3 + 2] ^ mix[2]; - } - insertmix = False; - count--; - x++; - } - if (prevline == NULL) - { - REPEAT - ( - line[x * 3] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - } - else - { - REPEAT - ( - line[x * 3] = prevline[x * 3]; - line[x * 3 + 1] = prevline[x * 3 + 1]; - line[x * 3 + 2] = prevline[x * 3 + 2]; - ) - } - break; - case 1: /* Mix */ - if (prevline == NULL) - { - REPEAT - ( - line[x * 3] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - ) - } - else - { - REPEAT - ( - line[x * 3] = - prevline[x * 3] ^ 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 == NULL) - { - REPEAT - ( - MASK_UPDATE(); - if (mask & mixmask) - { - line[x * 3] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - } - else - { - line[x * 3] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE(); - if (mask & mixmask) - { - line[x * 3] = - prevline[x * 3] ^ 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] = - prevline[x * 3]; - line[x * 3 + 1] = - prevline[x * 3 + 1]; - line[x * 3 + 2] = - prevline[x * 3 + 2]; - } - ) - } - break; - case 3: /* Colour */ - REPEAT - ( - line[x * 3] = colour2 [0]; - line[x * 3 + 1] = colour2 [1]; - line[x * 3 + 2] = colour2 [2]; - ) - break; - case 4: /* Copy */ - REPEAT - ( - line[x * 3] = CVAL(input); - line[x * 3 + 1] = CVAL(input); - line[x * 3 + 2] = CVAL(input); - ) - break; - case 8: /* Bicolour */ - REPEAT - ( - if (bicolour) - { - line[x * 3] = colour2[0]; - line[x * 3 + 1] = colour2[1]; - line[x * 3 + 2] = colour2[2]; - bicolour = False; - } - else - { - line[x * 3] = colour1[0]; - line[x * 3 + 1] = colour1[1]; - line[x * 3 + 2] = colour1[2]; - bicolour = True; - count++; - } - ) - break; - case 0xd: /* White */ - REPEAT - ( - line[x * 3] = 0xff; - line[x * 3 + 1] = 0xff; - line[x * 3 + 2] = 0xff; - ) - break; - case 0xe: /* Black */ - REPEAT - ( - line[x * 3] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - break; - default: - logger(Core, Warning, "bitmap_decompress3(), unhandled bitmap opcode 0x%x", opcode); - return False; - } - } - } - return True; + while (input < end) { + 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 == OPCODE_FILL_OR_MIX) || (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) { + case OPCODE_FILL: + if ((lastopcode == opcode) && !((x == width) && (prevline == NULL))) { + insertmix = True; + } + break; + case OPCODE_BICOLOUR: + for (int i = 0; i < bytes_per_pixel; i++) { + colour1[i] = CVAL(input); + colour2[i] = CVAL(input); + } + break; + case OPCODE_COLOUR: + for (int i = 0; i < bytes_per_pixel; i++) { + colour2[i] = CVAL(input); + } + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + for (int i = 0; i < bytes_per_pixel; i++) { + mix[i] = CVAL(input); + } + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = OPCODE_FILL_OR_MIX; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = OPCODE_FILL_OR_MIX; + fom_mask = 5; + break; + } + lastopcode = opcode; + mixmask = 0; + /* Output body */ + while (count > 0) { + if (x >= width) { + if (height <= 0) { + return False; + } + x = 0; + height--; + prevline = line; + line = output + height * (width * bytes_per_pixel); + } + switch (opcode) { + case OPCODE_FILL: + if (insertmix) { + if (prevline == NULL) { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = mix[i]; + } + } else { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = prevline[x * bytes_per_pixel + i] ^ mix[i]; + } + } + insertmix = False; + count--; + x++; + } + if (prevline == NULL) { + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = 0; + } + ) + } else { + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = prevline[x * bytes_per_pixel + i]; + } + ) + } + break; + case OPCODE_MIX: + if (prevline == NULL) { + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = mix[i]; + } + ) + } else { + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = prevline[x * bytes_per_pixel + i] ^ mix[i]; + } + ) + } + break; + case OPCODE_FILL_OR_MIX: + if (prevline == NULL) { + REPEAT( + MASK_UPDATE(); + if (mask & mixmask) { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = mix[i]; + } + } else { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = 0; + } + } + ) + } else { + REPEAT( + MASK_UPDATE(); + if (mask & mixmask) { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = prevline[x * bytes_per_pixel + i] ^ mix[i]; + } + } else { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = prevline[x * bytes_per_pixel + i]; + } + } + ) + } + break; + case OPCODE_COLOUR: + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = colour2[i]; + } + ) + break; + case OPCODE_COPY: + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = CVAL(input); + } + ) + break; + case OPCODE_BICOLOUR: + REPEAT( + if (bicolour) { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = colour2[i]; + } + bicolour = False; + } else { + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = colour1[i]; + } + bicolour = True; + count++; + } + ) + break; + case OPCODE_WHITE: + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = WHITE_PIXEL; + } + ) + break; + case OPCODE_BLACK: + REPEAT( + for (int i = 0; i < bytes_per_pixel; i++) { + line[x * bytes_per_pixel + i] = BLACK_PIXEL; + } + ) + break; + default: + logger(Core, Warning, "bitmap_decompress_n(), unhandled bitmap opcode 0x%x", opcode); + return False; + } + } + } + return True; } /* decompress a colour plane */ static int -process_plane(uint8 * in, int width, int height, uint8 * out, int size) +process_plane(uint8 *in, int width, int height, uint8 *out, int size) { - UNUSED(size); - int indexw; - int indexh; - int code; - int collen; - int replen; - int color; - int x; - int revcode; - uint8 * last_line; - uint8 * this_line; - uint8 * org_in; - uint8 * org_out; + UNUSED(size); + int indexw; + int indexh; + int code; + int collen; + int replen; + int color; + int x; + int revcode; + uint8 *last_line; + uint8 *this_line; + uint8 *org_in; + uint8 *org_out; - org_in = in; - org_out = out; - last_line = 0; - indexh = 0; - while (indexh < height) - { - out = (org_out + width * height * 4) - ((indexh + 1) * width * 4); - color = 0; - this_line = out; - indexw = 0; - if (last_line == 0) - { - while (indexw < width) - { - code = CVAL(in); - replen = code & 0xf; - collen = (code >> 4) & 0xf; - revcode = (replen << 4) | collen; - if ((revcode <= 47) && (revcode >= 16)) - { - replen = revcode; - collen = 0; - } - while (indexw < width && collen > 0) - { - color = CVAL(in); - *out = color; - out += 4; - indexw++; - collen--; - } - while (indexw < width && replen > 0) - { - *out = color; - out += 4; - indexw++; - replen--; - } - } - } - else - { - while (indexw < width) - { - code = CVAL(in); - replen = code & 0xf; - collen = (code >> 4) & 0xf; - revcode = (replen << 4) | collen; - if ((revcode <= 47) && (revcode >= 16)) - { - replen = revcode; - collen = 0; - } - while (indexw < width && collen > 0) - { - x = CVAL(in); - if (x & 1) - { - x = x >> 1; - x = x + 1; - color = -x; - } - else - { - x = x >> 1; - color = x; - } - x = last_line[indexw * 4] + color; - *out = x; - out += 4; - indexw++; - collen--; - } - while (indexw < width && replen > 0) - { - x = last_line[indexw * 4] + color; - *out = x; - out += 4; - indexw++; - replen--; - } - } - } - indexh++; - last_line = this_line; - } - return (int) (in - org_in); + org_in = in; + org_out = out; + last_line = 0; + indexh = 0; + while (indexh < height) { + out = (org_out + width * height * 4) - ((indexh + 1) * width * 4); + color = 0; + this_line = out; + indexw = 0; + if (last_line == 0) { + while (indexw < width) { + code = CVAL(in); + replen = code & 0xf; + collen = (code >> 4) & 0xf; + revcode = (replen << 4) | collen; + if ((revcode <= 47) && (revcode >= 16)) { + replen = revcode; + collen = 0; + } + while (indexw < width && collen > 0) { + color = CVAL(in); + *out = color; + out += 4; + indexw++; + collen--; + } + while (indexw < width && replen > 0) { + *out = color; + out += 4; + indexw++; + replen--; + } + } + } else { + while (indexw < width) { + code = CVAL(in); + replen = code & 0xf; + collen = (code >> 4) & 0xf; + revcode = (replen << 4) | collen; + if ((revcode <= 47) && (revcode >= 16)) { + replen = revcode; + collen = 0; + } + while (indexw < width && collen > 0) { + x = CVAL(in); + if (x & 1) { + x = x >> 1; + x = x + 1; + color = -x; + } else { + x = x >> 1; + color = x; + } + x = last_line[indexw * 4] + color; + *out = x; + out += 4; + indexw++; + collen--; + } + while (indexw < width && replen > 0) { + x = last_line[indexw * 4] + color; + *out = x; + out += 4; + indexw++; + replen--; + } + } + } + indexh++; + last_line = this_line; + } + return (int)(in - org_in); } /* 4 byte bitmap decompress */ static RD_BOOL -bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size) +bitmap_decompress4(uint8 *output, int width, int height, uint8 *input, int size) { - int code; - int bytes_pro; - int total_pro; + int code; + int bytes_pro; + int total_pro; - code = CVAL(input); - if (code != 0x10) - { - return False; - } - total_pro = 1; - bytes_pro = process_plane(input, width, height, output + 3, size - total_pro); - total_pro += bytes_pro; - input += bytes_pro; - bytes_pro = process_plane(input, width, height, output + 2, size - total_pro); - total_pro += bytes_pro; - input += bytes_pro; - bytes_pro = process_plane(input, width, height, output + 1, size - total_pro); - total_pro += bytes_pro; - input += bytes_pro; - bytes_pro = process_plane(input, width, height, output + 0, size - total_pro); - total_pro += bytes_pro; - return size == total_pro; + code = CVAL(input); + if (code != 0x10) { + return False; + } + total_pro = 1; + bytes_pro = process_plane(input, width, height, output + 3, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 2, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 1, size - total_pro); + total_pro += bytes_pro; + input += bytes_pro; + bytes_pro = process_plane(input, width, height, output + 0, size - total_pro); + total_pro += bytes_pro; + return size == total_pro; } /* main decompress function */ RD_BOOL -bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp) +bitmap_decompress(uint8 *output, int width, int height, uint8 *input, int size, int Bpp) { - RD_BOOL rv = False; + RD_BOOL rv = False; - 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; - case 4: - rv = bitmap_decompress4(output, width, height, input, size); - break; - default: - logger(Core, Debug, "bitmap_decompress(), unhandled BPP %d", Bpp); - break; - } - return rv; + switch (Bpp) { + case 1: + case 2: + case 3: + rv = bitmap_decompress_n(output, width, height, input, size, Bpp); + break; + case 4: + rv = bitmap_decompress4(output, width, height, input, size); + break; + default: + logger(Core, Debug, "bitmap_decompress(), unhandled BPP %d", Bpp); + break; + } + return rv; } /* *INDENT-ON* */ diff --git a/cache.c b/cache.c index bb2ac22..f047cde 100644 --- a/cache.c +++ b/cache.c @@ -20,6 +20,9 @@ */ #include "rdesktop.h" +#include +#include +#include /* BITMAP CACHE */ extern int g_pstcache_fd[]; @@ -30,22 +33,15 @@ extern int g_pstcache_fd[]; #define NOT_SET -1 #define IS_SET(idx) (idx >= 0) -/* - * TODO: Test for optimal value of BUMP_COUNT. TO_TOP gives lowest CPU utilisation but using - * a positive value will hopefully result in less frequently used bitmaps having a greater chance - * of being evicted from the cache, and thereby reducing the need to load bitmaps from disk. - * (Jeroen) - */ #define BUMP_COUNT 40 -struct bmpcache_entry -{ - RD_HBITMAP bitmap; - sint16 previous; - sint16 next; -}; +typedef struct bmpcache_entry { + RD_HBITMAP bitmap; + int16_t previous; + int16_t next; +} bmpcache_entry_t; -static struct bmpcache_entry g_bmpcache[3][0xa00]; +static bmpcache_entry_t g_bmpcache[3][0xa00]; static RD_HBITMAP g_volatile_bc[3]; static int g_bmpcache_lru[3] = { NOT_SET, NOT_SET, NOT_SET }; @@ -54,386 +50,310 @@ static int g_bmpcache_mru[3] = { NOT_SET, NOT_SET, NOT_SET }; static int g_bmpcache_count[3]; /* Setup the bitmap cache lru/mru linked list */ -void -cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count) -{ - int n = count, c = 0; - sint16 n_idx; +void cache_rebuild_bmpcache_linked_list(uint8_t id, int16_t *idx, int count) { + int n = count, c = 0; + int16_t n_idx; - /* find top, skip evicted bitmaps */ - while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL); - if (n < 0) - { - g_bmpcache_mru[id] = g_bmpcache_lru[id] = NOT_SET; - return; - } + /* find top, skip evicted bitmaps */ + while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL); + if (n < 0) { + g_bmpcache_mru[id] = g_bmpcache_lru[id] = NOT_SET; + return; + } - g_bmpcache_mru[id] = idx[n]; - g_bmpcache[id][idx[n]].next = NOT_SET; - n_idx = idx[n]; - c++; + g_bmpcache_mru[id] = idx[n]; + g_bmpcache[id][idx[n]].next = NOT_SET; + n_idx = idx[n]; + c++; - /* link list */ - while (n >= 0) - { - /* skip evicted bitmaps */ - while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL); + /* link list */ + while (n >= 0) { + /* skip evicted bitmaps */ + while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL); - if (n < 0) - break; + if (n < 0) + break; - g_bmpcache[id][n_idx].previous = idx[n]; - g_bmpcache[id][idx[n]].next = n_idx; - n_idx = idx[n]; - c++; - } + g_bmpcache[id][n_idx].previous = idx[n]; + g_bmpcache[id][idx[n]].next = n_idx; + n_idx = idx[n]; + c++; + } - g_bmpcache[id][n_idx].previous = NOT_SET; - g_bmpcache_lru[id] = n_idx; + g_bmpcache[id][n_idx].previous = NOT_SET; + g_bmpcache_lru[id] = n_idx; - if (c != g_bmpcache_count[id]) - { - logger(Core, Error, - "cache_rebuild_bmpcache_linked_list(), %d in bitmap cache linked list, %d in ui cache...", - c, g_bmpcache_count[id]); - exit(EX_SOFTWARE); - } + if (c != g_bmpcache_count[id]) { + logger(Core, Error, + "cache_rebuild_bmpcache_linked_list(), %d in bitmap cache linked list, %d in ui cache...", + c, g_bmpcache_count[id]); + exit(EXIT_FAILURE); + } } /* Move a bitmap to a new position in the linked list. */ -void -cache_bump_bitmap(uint8 id, uint16 idx, int bump) -{ - int p_idx, n_idx, n; +void cache_bump_bitmap(uint8_t id, uint16_t idx, int bump) { + int p_idx, n_idx, n; - if (!IS_PERSISTENT(id)) - return; + if (!IS_PERSISTENT(id)) + return; - if (g_bmpcache_mru[id] == idx) - return; + if (g_bmpcache_mru[id] == idx) + return; - logger(Core, Debug, "cache_bump_bitmap(), id=%d, idx=%d, bump=%d", id, idx, bump); + logger(Core, Debug, "cache_bump_bitmap(), id=%d, idx=%d, bump=%d", id, idx, bump); - n_idx = g_bmpcache[id][idx].next; - p_idx = g_bmpcache[id][idx].previous; + n_idx = g_bmpcache[id][idx].next; + p_idx = g_bmpcache[id][idx].previous; - if (IS_SET(n_idx)) - { - /* remove */ - --g_bmpcache_count[id]; - if (IS_SET(p_idx)) - g_bmpcache[id][p_idx].next = n_idx; - else - g_bmpcache_lru[id] = n_idx; - if (IS_SET(n_idx)) - g_bmpcache[id][n_idx].previous = p_idx; - else - g_bmpcache_mru[id] = p_idx; - } - else - { - p_idx = NOT_SET; - n_idx = g_bmpcache_lru[id]; - } + if (IS_SET(n_idx)) { + /* remove */ + --g_bmpcache_count[id]; + if (IS_SET(p_idx)) + g_bmpcache[id][p_idx].next = n_idx; + else + g_bmpcache_lru[id] = n_idx; + if (IS_SET(n_idx)) + g_bmpcache[id][n_idx].previous = p_idx; + else + g_bmpcache_mru[id] = p_idx; + } else { + p_idx = NOT_SET; + n_idx = g_bmpcache_lru[id]; + } - if (bump >= 0) - { - for (n = 0; n < bump && IS_SET(n_idx); n++) - { - p_idx = n_idx; - n_idx = g_bmpcache[id][p_idx].next; - } - } - else - { - p_idx = g_bmpcache_mru[id]; - n_idx = NOT_SET; - } + if (bump >= 0) { + for (n = 0; n < bump && IS_SET(n_idx); n++) { + p_idx = n_idx; + n_idx = g_bmpcache[id][p_idx].next; + } + } else { + p_idx = g_bmpcache_mru[id]; + n_idx = NOT_SET; + } - /* insert */ - ++g_bmpcache_count[id]; - g_bmpcache[id][idx].previous = p_idx; - g_bmpcache[id][idx].next = n_idx; + /* insert */ + ++g_bmpcache_count[id]; + g_bmpcache[id][idx].previous = p_idx; + g_bmpcache[id][idx].next = n_idx; - if (p_idx >= 0) - g_bmpcache[id][p_idx].next = idx; - else - g_bmpcache_lru[id] = idx; + if (p_idx >= 0) + g_bmpcache[id][p_idx].next = idx; + else + g_bmpcache_lru[id] = idx; - if (n_idx >= 0) - g_bmpcache[id][n_idx].previous = idx; - else - g_bmpcache_mru[id] = idx; + if (n_idx >= 0) + g_bmpcache[id][n_idx].previous = idx; + else + g_bmpcache_mru[id] = idx; } /* Evict the least-recently used bitmap from the cache */ -void -cache_evict_bitmap(uint8 id) -{ - uint16 idx; - int n_idx; +void cache_evict_bitmap(uint8_t id) { + uint16_t idx; + int n_idx; - if (!IS_PERSISTENT(id)) - return; + if (!IS_PERSISTENT(id)) + return; - idx = g_bmpcache_lru[id]; - n_idx = g_bmpcache[id][idx].next; + idx = g_bmpcache_lru[id]; + n_idx = g_bmpcache[id][idx].next; - logger(Core, Debug, "cache_evict_bitmap(), id=%d idx=%d n_idx=%d bmp=%p", id, idx, n_idx, - g_bmpcache[id][idx].bitmap); + logger(Core, Debug, "cache_evict_bitmap(), id=%d idx=%d n_idx=%d bmp=%p", id, idx, n_idx, + g_bmpcache[id][idx].bitmap); - ui_destroy_bitmap(g_bmpcache[id][idx].bitmap); - --g_bmpcache_count[id]; - g_bmpcache[id][idx].bitmap = 0; + ui_destroy_bitmap(g_bmpcache[id][idx].bitmap); + --g_bmpcache_count[id]; + g_bmpcache[id][idx].bitmap = 0; - g_bmpcache_lru[id] = n_idx; - g_bmpcache[id][n_idx].previous = NOT_SET; + g_bmpcache_lru[id] = n_idx; + g_bmpcache[id][n_idx].previous = NOT_SET; - pstcache_touch_bitmap(id, idx, 0); + pstcache_touch_bitmap(id, idx, 0); } /* Retrieve a bitmap from the cache */ -RD_HBITMAP -cache_get_bitmap(uint8 id, uint16 idx) -{ - if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0]))) - { - if (g_bmpcache[id][idx].bitmap || pstcache_load_bitmap(id, idx)) - { - if (IS_PERSISTENT(id)) - cache_bump_bitmap(id, idx, BUMP_COUNT); +RD_HBITMAP cache_get_bitmap(uint8_t id, uint16_t idx) { + if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0]))) { + if (g_bmpcache[id][idx].bitmap || pstcache_load_bitmap(id, idx)) { + if (IS_PERSISTENT(id)) + cache_bump_bitmap(id, idx, BUMP_COUNT); - return g_bmpcache[id][idx].bitmap; - } - } - else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff)) - { - return g_volatile_bc[id]; - } + return g_bmpcache[id][idx].bitmap; + } + } else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff)) { + return g_volatile_bc[id]; + } - logger(Core, Debug, "cache_get_bitmap(), id=%d, idx=%d", id, idx); + logger(Core, Debug, "cache_get_bitmap(), id=%d, idx=%d", id, idx); - return NULL; + return NULL; } /* Store a bitmap in the cache */ -void -cache_put_bitmap(uint8 id, uint16 idx, RD_HBITMAP bitmap) -{ - RD_HBITMAP old; +void cache_put_bitmap(uint8_t id, uint16_t idx, RD_HBITMAP bitmap) { + RD_HBITMAP old; - if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0]))) - { - old = g_bmpcache[id][idx].bitmap; - if (old != NULL) - ui_destroy_bitmap(old); - g_bmpcache[id][idx].bitmap = bitmap; + if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0]))) { + old = g_bmpcache[id][idx].bitmap; + if (old != NULL) + ui_destroy_bitmap(old); + g_bmpcache[id][idx].bitmap = bitmap; - if (IS_PERSISTENT(id)) - { - if (old == NULL) - g_bmpcache[id][idx].previous = g_bmpcache[id][idx].next = NOT_SET; + if (IS_PERSISTENT(id)) { + if (old == NULL) + g_bmpcache[id][idx].previous = g_bmpcache[id][idx].next = NOT_SET; - cache_bump_bitmap(id, idx, TO_TOP); - if (g_bmpcache_count[id] > BMPCACHE2_C2_CELLS) - cache_evict_bitmap(id); - } - } - else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff)) - { - old = g_volatile_bc[id]; - if (old != NULL) - ui_destroy_bitmap(old); - g_volatile_bc[id] = bitmap; - } - else - { - logger(Core, Error, "cache_put_bitmap(), failed, id=%d, idx=%d\n", id, idx); - } + cache_bump_bitmap(id, idx, TO_TOP); + if (g_bmpcache_count[id] > BMPCACHE2_C2_CELLS) + cache_evict_bitmap(id); + } + } else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff)) { + old = g_volatile_bc[id]; + if (old != NULL) + ui_destroy_bitmap(old); + g_volatile_bc[id] = bitmap; + } else { + logger(Core, Error, "cache_put_bitmap(), failed, id=%d, idx=%d\n", id, idx); + } } /* Updates the persistent bitmap cache MRU information on exit */ -void -cache_save_state(void) -{ - uint32 id = 0, t = 0; - int idx; +void cache_save_state(void) { + uint32_t id = 0, t = 0; + int idx; - for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++) - if (IS_PERSISTENT(id)) - { - logger(Core, Debug, - "cache_save_state(), saving cache state for bitmap cache %d", id); - idx = g_bmpcache_lru[id]; - while (idx >= 0) - { - pstcache_touch_bitmap(id, idx, ++t); - idx = g_bmpcache[id][idx].next; - } - logger(Core, Debug, "cache_save_state(), %d stamps written", t); - } + for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++) + if (IS_PERSISTENT(id)) { + logger(Core, Debug, + "cache_save_state(), saving cache state for bitmap cache %d", id); + idx = g_bmpcache_lru[id]; + while (idx >= 0) { + pstcache_touch_bitmap(id, idx, ++t); + idx = g_bmpcache[id][idx].next; + } + logger(Core, Debug, "cache_save_state(), %d stamps written", t); + } } - /* FONT CACHE */ static FONTGLYPH g_fontcache[12][256]; /* Retrieve a glyph from the font cache */ -FONTGLYPH * -cache_get_font(uint8 font, uint16 character) -{ - FONTGLYPH *glyph; +FONTGLYPH *cache_get_font(uint8_t font, uint16_t character) { + if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0]))) { + FONTGLYPH *glyph = &g_fontcache[font][character]; + if (glyph->pixmap != NULL) + return glyph; + } - if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0]))) - { - glyph = &g_fontcache[font][character]; - if (glyph->pixmap != NULL) - return glyph; - } - - logger(Core, Debug, "cache_get_font(), font=%d, char=%d", font, character); - return NULL; + logger(Core, Debug, "cache_get_font(), font=%d, char=%d", font, character); + return NULL; } /* Store a glyph in the font cache */ -void -cache_put_font(uint8 font, uint16 character, uint16 offset, - uint16 baseline, uint16 width, uint16 height, RD_HGLYPH pixmap) -{ - FONTGLYPH *glyph; +void cache_put_font(uint8_t font, uint16_t character, uint16_t offset, + uint16_t baseline, uint16_t width, uint16_t height, RD_HGLYPH pixmap) { + if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0]))) { + FONTGLYPH *glyph = &g_fontcache[font][character]; + if (glyph->pixmap != NULL) + ui_destroy_glyph(glyph->pixmap); - if ((font < NUM_ELEMENTS(g_fontcache)) && (character < NUM_ELEMENTS(g_fontcache[0]))) - { - glyph = &g_fontcache[font][character]; - if (glyph->pixmap != NULL) - ui_destroy_glyph(glyph->pixmap); - - glyph->offset = offset; - glyph->baseline = baseline; - glyph->width = width; - glyph->height = height; - glyph->pixmap = pixmap; - } - else - { - logger(Core, Error, "cache_put_font(), failed, font=%d, char=%d", font, character); - } + glyph->offset = offset; + glyph->baseline = baseline; + glyph->width = width; + glyph->height = height; + glyph->pixmap = pixmap; + } else { + logger(Core, Error, "cache_put_font(), failed, font=%d, char=%d", font, character); + } } - /* TEXT CACHE */ static DATABLOB g_textcache[256]; /* Retrieve a text item from the cache */ -DATABLOB * -cache_get_text(uint8 cache_id) -{ - DATABLOB *text; - - text = &g_textcache[cache_id]; - return text; +DATABLOB *cache_get_text(uint8_t cache_id) { + return &g_textcache[cache_id]; } /* Store a text item in the cache */ -void -cache_put_text(uint8 cache_id, void *data, int length) -{ - DATABLOB *text; - - text = &g_textcache[cache_id]; - if (text->data != NULL) - xfree(text->data); - text->data = xmalloc(length); - text->size = length; - memcpy(text->data, data, length); +void cache_put_text(uint8_t cache_id, void *data, int length) { + if (cache_id < NUM_ELEMENTS(g_textcache)) { + DATABLOB *text = &g_textcache[cache_id]; + if (text->data != NULL) + xfree(text->data); + text->data = xmalloc(length); + text->size = length; + memcpy(text->data, data, length); + } else { + logger(Core, Error, "cache_put_text(), failed, cache_id=%d", cache_id); + } } - /* DESKTOP CACHE */ -static uint8 g_deskcache[0x38400 * 4]; +static uint8_t g_deskcache[0x38400 * 4]; /* Retrieve desktop data from the cache */ -uint8 * -cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel) -{ - int length = cx * cy * bytes_per_pixel; +uint8_t *cache_get_desktop(uint32_t offset, int cx, int cy, int bytes_per_pixel) { + int length = cx * cy * bytes_per_pixel; - if (offset > sizeof(g_deskcache)) - offset = 0; + if (offset > sizeof(g_deskcache)) + offset = 0; - if ((offset + length) <= sizeof(g_deskcache)) - { - return &g_deskcache[offset]; - } + if ((offset + length) <= sizeof(g_deskcache)) { + return &g_deskcache[offset]; + } - logger(Core, Debug, "cache_get_desktop(), offset=%d, length=%d", offset, length); - return NULL; + logger(Core, Debug, "cache_get_desktop(), offset=%d, length=%d", offset, length); + return NULL; } /* Store desktop data in the cache */ -void -cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8 * data) -{ - int length = cx * cy * bytes_per_pixel; +void cache_put_desktop(uint32_t offset, int cx, int cy, int scanline, int bytes_per_pixel, uint8_t *data) { + int length = cx * cy * bytes_per_pixel; - if (offset > sizeof(g_deskcache)) - offset = 0; + if (offset > sizeof(g_deskcache)) + offset = 0; - if ((offset + length) <= sizeof(g_deskcache)) - { - cx *= bytes_per_pixel; - while (cy--) - { - memcpy(&g_deskcache[offset], data, cx); - data += scanline; - offset += cx; - } - } - else - { - logger(Core, Error, "cache_put_desktop(), offset=%d, length=%d", offset, length); - } + if ((offset + length) <= sizeof(g_deskcache)) { + cx *= bytes_per_pixel; + while (cy--) { + memcpy(&g_deskcache[offset], data, cx); + data += scanline; + offset += cx; + } + } else { + logger(Core, Error, "cache_put_desktop(), offset=%d, length=%d", offset, length); + } } - /* CURSOR CACHE */ static RD_HCURSOR g_cursorcache[0x20]; /* Retrieve cursor from cache */ -RD_HCURSOR -cache_get_cursor(uint16 cache_idx) -{ - RD_HCURSOR cursor; +RD_HCURSOR cache_get_cursor(uint16_t cache_idx) { + if (cache_idx < NUM_ELEMENTS(g_cursorcache)) { + RD_HCURSOR cursor = g_cursorcache[cache_idx]; + if (cursor != NULL) + return cursor; + } - if (cache_idx < NUM_ELEMENTS(g_cursorcache)) - { - cursor = g_cursorcache[cache_idx]; - if (cursor != NULL) - return cursor; - } - - logger(Core, Debug, "cache_get_cursor(), idx=%d", cache_idx); - return NULL; + logger(Core, Debug, "cache_get_cursor(), idx=%d", cache_idx); + return NULL; } /* Store cursor in cache */ -void -cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor) -{ - RD_HCURSOR old; +void cache_put_cursor(uint16_t cache_idx, RD_HCURSOR cursor) { + if (cache_idx < NUM_ELEMENTS(g_cursorcache)) { + RD_HCURSOR old = g_cursorcache[cache_idx]; + if (old != NULL) + ui_destroy_cursor(old); - if (cache_idx < NUM_ELEMENTS(g_cursorcache)) - { - old = g_cursorcache[cache_idx]; - if (old != NULL) - ui_destroy_cursor(old); - - g_cursorcache[cache_idx] = cursor; - } - else - { - logger(Core, Error, "cache_put_cursor(), failed, idx=%d", cache_idx); - } + g_cursorcache[cache_idx] = cursor; + } else { + logger(Core, Error, "cache_put_cursor(), failed, idx=%d", cache_idx); + } } /* BRUSH CACHE */ @@ -441,37 +361,26 @@ cache_put_cursor(uint16 cache_idx, RD_HCURSOR cursor) static BRUSHDATA g_brushcache[2][64]; /* Retrieve brush from cache */ -BRUSHDATA * -cache_get_brush_data(uint8 colour_code, uint8 idx) -{ - colour_code = colour_code == 1 ? 0 : 1; - if (idx < NUM_ELEMENTS(g_brushcache[0])) - { - return &g_brushcache[colour_code][idx]; - } - logger(Core, Debug, "cache_get_brush_data(), colour=%d, idx=%d", colour_code, idx); - return NULL; +BRUSHDATA *cache_get_brush_data(uint8_t colour_code, uint8_t idx) { + colour_code = colour_code == 1 ? 0 : 1; + if (idx < NUM_ELEMENTS(g_brushcache[0])) { + return &g_brushcache[colour_code][idx]; + } + logger(Core, Debug, "cache_get_brush_data(), colour=%d, idx=%d", colour_code, idx); + return NULL; } /* Store brush in cache */ /* this function takes over the data pointer in struct, e.g. caller gives it up */ -void -cache_put_brush_data(uint8 colour_code, uint8 idx, BRUSHDATA * brush_data) -{ - BRUSHDATA *bd; - - colour_code = colour_code == 1 ? 0 : 1; - if (idx < NUM_ELEMENTS(g_brushcache[0])) - { - bd = &g_brushcache[colour_code][idx]; - if (bd->data != 0) - { - xfree(bd->data); - } - memcpy(bd, brush_data, sizeof(BRUSHDATA)); - } - else - { - logger(Core, Error, "cache_put_brush_data(), colour=%d, idx=%d", colour_code, idx); - } +void cache_put_brush_data(uint8_t colour_code, uint8_t idx, BRUSHDATA *brush_data) { + colour_code = colour_code == 1 ? 0 : 1; + if (idx < NUM_ELEMENTS(g_brushcache[0])) { + BRUSHDATA *bd = &g_brushcache[colour_code][idx]; + if (bd->data != 0) { + xfree(bd->data); + } + memcpy(bd, brush_data, sizeof(BRUSHDATA)); + } else { + logger(Core, Error, "cache_put_brush_data(), colour=%d, idx=%d", colour_code, idx); + } }