diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2025-01-10 15:58:57 +0100 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2025-01-10 16:02:45 +0100 |
commit | 9319d14566e5d1bfec617c479b8543a9ee3ad4ea (patch) | |
tree | b0130ae9e5ac2932c88ff99b83c83d23126d91bc /lpg/libqr/code-layout.c | |
parent | 147b8805247ca23fb96e51694f78439ab24f93a2 (diff) | |
parent | ab64314222aca47dd7e52eca2d54d2fad0a58f6c (diff) | |
download | pdf-simple-sign-9319d14566e5d1bfec617c479b8543a9ee3ad4ea.tar.gz pdf-simple-sign-9319d14566e5d1bfec617c479b8543a9ee3ad4ea.tar.xz pdf-simple-sign-9319d14566e5d1bfec617c479b8543a9ee3ad4ea.zip |
Merge remote-tracking branch 'libqr/master'
Diffstat (limited to 'lpg/libqr/code-layout.c')
-rw-r--r-- | lpg/libqr/code-layout.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/lpg/libqr/code-layout.c b/lpg/libqr/code-layout.c new file mode 100644 index 0000000..fe8caa7 --- /dev/null +++ b/lpg/libqr/code-layout.c @@ -0,0 +1,188 @@ +#include <assert.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +#include <qr/bitmap.h> +#include <qr/code.h> +#include <qr/common.h> +#include <qr/layout.h> +#include "constants.h" + +struct qr_iterator { + struct qr_code * code; + int dim; + int column; + int row; + int up; + int mask; + unsigned char * p; +}; + +void qr_layout_init_mask(struct qr_code * code) +{ + size_t x, y; + size_t dim = qr_code_width(code); + struct qr_bitmap * bmp = code->modules; + const int * am_pos = QR_ALIGNMENT_LOCATION[code->version - 1]; + size_t am_side; + + if (!bmp->mask) + qr_bitmap_add_mask(bmp); + + assert(bmp->mask); + + memset(bmp->mask, 0, bmp->height * bmp->stride); + + /* slow and stupid, but I'm sleepy */ + for (y = 0; y < bmp->height; ++y) { + unsigned char * row = bmp->mask + y * bmp->stride; + for (x = 0; x < bmp->width; ++x) { + unsigned char bit = 1 << (x % CHAR_BIT); + int off = x / CHAR_BIT; + + if (x == 6 || y == 6) /* timing */ + continue; + + if (x < 9 && y < 9) /* top-left */ + continue; + + if (x >= dim - 8 && y < 9) /* top-right */ + continue; + + if (x < 9 && y >= dim - 8) /* bottom-left */ + continue; + + /* version info */ + if (code->version >= 7) { + if (y < 6 && x >= dim - 11) + continue; + if (x < 6 && y >= dim - 11) + continue; + } + + row[off] |= bit; + } + } + + /* Alignment pattern */ + am_side = code->version > 1 ? (code->version / 7) + 2 : 0; + for (y = 0; y < am_side; ++y) { + for (x = 0; x < am_side; ++x) { + int i, j; + + if ((x == 0 && y == 0) || + (x == 0 && y == am_side - 1) || + (x == am_side - 1 && y == 0)) + continue; + + for (j = -2; j <= 2; ++j) { + unsigned char * row = bmp->mask + (am_pos[y]+j) * bmp->stride; + for (i = -2; i <= 2; ++i) { + unsigned char bit = 1 << ((am_pos[x]+i) % CHAR_BIT); + int off = (am_pos[x]+i) / CHAR_BIT; + + row[off] &= ~bit; + } + } + } + } +} + +static int is_data_bit(const struct qr_iterator * i) +{ + unsigned char bit = 1 << (i->column % CHAR_BIT); + int off = (i->row * i->code->modules->stride) + (i->column / CHAR_BIT); + + return i->code->modules->mask[off] & bit; +} + +static void set_pointer(struct qr_iterator * i) +{ + i->mask = 1 << (i->column % CHAR_BIT); + i->p = i->code->modules->bits + + i->code->modules->stride * i->row + + i->column / CHAR_BIT; +} + +static void advance(struct qr_iterator * i) +{ + do { + /* This XOR is to account for the vertical strip of + * timing bits in column 6 which displaces everything. + */ + if ((i->column < 6) ^ !(i->column % 2)) { + /* Right-hand part or at left edge */ + i->column -= 1; + } else { + /* Left-hand part */ + i->column += 1; + + if (( i->up && i->row == 0) || + (!i->up && i->row == i->dim - 1)) { + /* Hit the top / bottom */ + i->column -= 2; + i->up = !i->up; + } else { + i->row += i->up ? -1 : 1; + } + } + + if (i->column < 0) + continue; /* don't go off left edge */ + + /* Check for one-past-end */ + if (i->column == 0 && i->row >= i->dim - 8) + break; + + } while (!is_data_bit(i)); + + set_pointer(i); +} + +struct qr_iterator * qr_layout_begin(struct qr_code * code) +{ + struct qr_iterator * i; + + i = malloc(sizeof(*i)); + if (i) { + i->dim = qr_code_width(code); + i->code = code; + i->column = i->dim - 1; + i->row = i->dim - 1; + i->up = 1; + set_pointer(i); + } + + return i; +} + +void qr_layout_end(struct qr_iterator * i) +{ + free(i); +} + +unsigned int qr_layout_read(struct qr_iterator * i) +{ + unsigned int x = 0; + int b; + + for (b = 0; b < QR_WORD_BITS; ++b) { + x = (x << 1) | ((*i->p & i->mask) ? 1 : 0); + advance(i); + } + + return x; +} + +void qr_layout_write(struct qr_iterator * i, unsigned int x) +{ + int b; + + for (b = 0; b < QR_WORD_BITS; ++b) { + *i->p |= (x & 0x80) ? i->mask : 0; + advance(i); + x <<= 1; + } +} + |