| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487 |
- #include "../barcode_app.h"
- #include "barcode_view.h"
- #include "../encodings.h"
- /**
- * @brief Draws a single bit from a barcode at a specified location
- * @param canvas
- * @param bit a 1 or a 0 to signify a bit of data
- * @param x the top left x coordinate
- * @param y the top left y coordinate
- * @param width the width of the bit
- * @param height the height of the bit
- */
- static void draw_bit(Canvas* canvas, int bit, int x, int y, int width, int height) {
- if(bit == 1) {
- canvas_set_color(canvas, ColorBlack);
- } else {
- canvas_set_color(canvas, ColorWhite);
- }
- canvas_draw_box(canvas, x, y, width, height);
- }
- /**
- * Draws the error name and message on the screen
- */
- static void draw_error_str(Canvas* canvas, const char* title, const char* error) {
- canvas_clear(canvas);
- elements_multiline_text_aligned(canvas, 0, 0, AlignLeft, AlignTop, title);
- elements_multiline_text_aligned(canvas, 0, 12, AlignLeft, AlignTop, error);
- }
- /**
- * @param bits a string of 1's and 0's
- * @returns the x coordinate after the bits have been drawn, useful for drawing the next section of bits
- */
- static int draw_bits(Canvas* canvas, const char* bits, int x, int y, int width, int height) {
- int bits_length = strlen(bits);
- for(int i = 0; i < bits_length; i++) {
- char c = bits[i];
- int num = c - '0';
- draw_bit(canvas, num, x, y, width, height);
- x += width;
- }
- return x;
- }
- /**
- * Draws an EAN-8 type barcode, does not check if the barcode is valid
- * @param canvas the canvas
- * @param barcode_digits the digits in the barcode, must be 8 characters long
- */
- static void draw_ean_8(Canvas* canvas, BarcodeData* barcode_data) {
- FuriString* barcode_digits = barcode_data->correct_data;
- BarcodeTypeObj* type_obj = barcode_data->type_obj;
- int barcode_length = furi_string_size(barcode_digits);
- int x = type_obj->start_pos;
- int y = BARCODE_Y_START;
- int width = 1;
- int height = BARCODE_HEIGHT;
- //the guard patterns for the beginning, center, ending
- const char* end_bits = "101";
- const char* center_bits = "01010";
- //draw the starting guard pattern
- x = draw_bits(canvas, end_bits, x, y, width, height + 5);
- FuriString* code_part = furi_string_alloc();
- //loop through each digit, find the encoding, and draw it
- for(int i = 0; i < barcode_length; i++) {
- char current_digit = furi_string_get_char(barcode_digits, i);
- //the actual number and the index of the bits
- int index = current_digit - '0';
- //use the L-codes for the first 4 digits and the R-Codes for the last 4 digits
- if(i <= 3) {
- furi_string_set_str(code_part, UPC_EAN_L_CODES[index]);
- } else {
- furi_string_set_str(code_part, UPC_EAN_R_CODES[index]);
- }
- //convert the current_digit char into a string so it can be printed
- char current_digit_string[2];
- snprintf(current_digit_string, 2, "%c", current_digit);
- //set the canvas color to black to print the digit
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string);
- //draw the bits of the barcode
- x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height);
- //if the index has reached 3, that means 4 digits have been drawn and now draw the center guard pattern
- if(i == 3) {
- x = draw_bits(canvas, center_bits, x, y, width, height + 5);
- }
- }
- furi_string_free(code_part);
- //draw the ending guard pattern
- x = draw_bits(canvas, end_bits, x, y, width, height + 5);
- }
- static void draw_ean_13(Canvas* canvas, BarcodeData* barcode_data) {
- FuriString* barcode_digits = barcode_data->correct_data;
- BarcodeTypeObj* type_obj = barcode_data->type_obj;
- int barcode_length = furi_string_size(barcode_digits);
- int x = type_obj->start_pos;
- int y = BARCODE_Y_START;
- int width = 1;
- int height = BARCODE_HEIGHT;
- //the guard patterns for the beginning, center, ending
- const char* end_bits = "101";
- const char* center_bits = "01010";
- //draw the starting guard pattern
- x = draw_bits(canvas, end_bits, x, y, width, height + 5);
- FuriString* left_structure = furi_string_alloc();
- FuriString* code_part = furi_string_alloc();
- //loop through each digit, find the encoding, and draw it
- for(int i = 0; i < barcode_length; i++) {
- char current_digit = furi_string_get_char(barcode_digits, i);
- int index = current_digit - '0';
- if(i == 0) {
- furi_string_set_str(left_structure, EAN_13_STRUCTURE_CODES[index]);
- //convert the current_digit char into a string so it can be printed
- char current_digit_string[2];
- snprintf(current_digit_string, 2, "%c", current_digit);
- //set the canvas color to black to print the digit
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_str(canvas, x - 10, y + height + 8, current_digit_string);
- continue;
- } else {
- //use the L-codes for the first 6 digits and the R-Codes for the last 6 digits
- if(i <= 6) {
- //get the encoding type at the current barcode bit position
- char encoding_type = furi_string_get_char(left_structure, i - 1);
- if(encoding_type == 'L') {
- furi_string_set_str(code_part, UPC_EAN_L_CODES[index]);
- } else {
- furi_string_set_str(code_part, EAN_G_CODES[index]);
- }
- } else {
- furi_string_set_str(code_part, UPC_EAN_R_CODES[index]);
- }
- //convert the current_digit char into a string so it can be printed
- char current_digit_string[2];
- snprintf(current_digit_string, 2, "%c", current_digit);
- //set the canvas color to black to print the digit
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string);
- //draw the bits of the barcode
- x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height);
- //if the index has reached 6, that means 6 digits have been drawn and we now draw the center guard pattern
- if(i == 6) {
- x = draw_bits(canvas, center_bits, x, y, width, height + 5);
- }
- }
- }
- furi_string_free(left_structure);
- furi_string_free(code_part);
- //draw the ending guard pattern
- x = draw_bits(canvas, end_bits, x, y, width, height + 5);
- }
- /**
- * Draw a UPC-A barcode
- */
- static void draw_upc_a(Canvas* canvas, BarcodeData* barcode_data) {
- FuriString* barcode_digits = barcode_data->correct_data;
- BarcodeTypeObj* type_obj = barcode_data->type_obj;
- int barcode_length = furi_string_size(barcode_digits);
- int x = type_obj->start_pos;
- int y = BARCODE_Y_START;
- int width = 1;
- int height = BARCODE_HEIGHT;
- //the guard patterns for the beginning, center, ending
- char* end_bits = "101";
- char* center_bits = "01010";
- //draw the starting guard pattern
- x = draw_bits(canvas, end_bits, x, y, width, height + 5);
- FuriString* code_part = furi_string_alloc();
- //loop through each digit, find the encoding, and draw it
- for(int i = 0; i < barcode_length; i++) {
- char current_digit = furi_string_get_char(barcode_digits, i);
- int index = current_digit - '0'; //convert the number into an int (also the index)
- //use the L-codes for the first 6 digits and the R-Codes for the last 6 digits
- if(i <= 5) {
- furi_string_set_str(code_part, UPC_EAN_L_CODES[index]);
- } else {
- furi_string_set_str(code_part, UPC_EAN_R_CODES[index]);
- }
- //convert the current_digit char into a string so it can be printed
- char current_digit_string[2];
- snprintf(current_digit_string, 2, "%c", current_digit);
- //set the canvas color to black to print the digit
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_str(canvas, x + 1, y + height + 8, current_digit_string);
- //draw the bits of the barcode
- x = draw_bits(canvas, furi_string_get_cstr(code_part), x, y, width, height);
- //if the index has reached 6, that means 6 digits have been drawn and we now draw the center guard pattern
- if(i == 5) {
- x = draw_bits(canvas, center_bits, x, y, width, height + 5);
- }
- }
- furi_string_free(code_part);
- //draw the ending guard pattern
- x = draw_bits(canvas, end_bits, x, y, width, height + 5);
- }
- static void draw_code_39(Canvas* canvas, BarcodeData* barcode_data) {
- FuriString* raw_data = barcode_data->raw_data;
- FuriString* barcode_digits = barcode_data->correct_data;
- //BarcodeTypeObj* type_obj = barcode_data->type_obj;
- int barcode_length = furi_string_size(barcode_digits);
- int total_pixels = 0;
- for(int i = 0; i < barcode_length; i++) {
- //1 for wide, 0 for narrow
- char wide_or_narrow = furi_string_get_char(barcode_digits, i);
- int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
- if(wn_digit == 1) {
- total_pixels += 3;
- } else {
- total_pixels += 1;
- }
- if((i + 1) % 9 == 0) {
- total_pixels += 1;
- }
- }
- int x = (128 - total_pixels) / 2;
- int y = BARCODE_Y_START;
- int width = 1;
- int height = BARCODE_HEIGHT;
- bool filled_in = true;
- //set the canvas color to black to print the digit
- canvas_set_color(canvas, ColorBlack);
- // canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error);
- canvas_draw_str_aligned(
- canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data));
- for(int i = 0; i < barcode_length; i++) {
- //1 for wide, 0 for narrow
- char wide_or_narrow = furi_string_get_char(barcode_digits, i);
- int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
- if(filled_in) {
- if(wn_digit == 1) {
- x = draw_bits(canvas, "111", x, y, width, height);
- } else {
- x = draw_bits(canvas, "1", x, y, width, height);
- }
- filled_in = false;
- } else {
- if(wn_digit == 1) {
- x = draw_bits(canvas, "000", x, y, width, height);
- } else {
- x = draw_bits(canvas, "0", x, y, width, height);
- }
- filled_in = true;
- }
- if((i + 1) % 9 == 0) {
- x = draw_bits(canvas, "0", x, y, width, height);
- filled_in = true;
- }
- }
- }
- static void draw_code_128(Canvas* canvas, BarcodeData* barcode_data) {
- FuriString* raw_data = barcode_data->raw_data;
- FuriString* barcode_digits = barcode_data->correct_data;
- int barcode_length = furi_string_size(barcode_digits);
- int x = (128 - barcode_length) / 2;
- int y = BARCODE_Y_START;
- int width = 1;
- int height = BARCODE_HEIGHT;
- x = draw_bits(canvas, furi_string_get_cstr(barcode_digits), x, y, width, height);
- //set the canvas color to black to print the digit
- canvas_set_color(canvas, ColorBlack);
- // canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error);
- canvas_draw_str_aligned(
- canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data));
- }
- static void draw_codabar(Canvas* canvas, BarcodeData* barcode_data) {
- FuriString* raw_data = barcode_data->raw_data;
- FuriString* barcode_digits = barcode_data->correct_data;
- //BarcodeTypeObj* type_obj = barcode_data->type_obj;
- int barcode_length = furi_string_size(barcode_digits);
- int total_pixels = 0;
- for(int i = 0; i < barcode_length; i++) {
- //1 for wide, 0 for narrow
- char wide_or_narrow = furi_string_get_char(barcode_digits, i);
- int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
- if(wn_digit == 1) {
- total_pixels += 3;
- } else {
- total_pixels += 1;
- }
- if((i + 1) % 7 == 0) {
- total_pixels += 1;
- }
- }
- int x = (128 - total_pixels) / 2;
- int y = BARCODE_Y_START;
- int width = 1;
- int height = BARCODE_HEIGHT;
- bool filled_in = true;
- //set the canvas color to black to print the digit
- canvas_set_color(canvas, ColorBlack);
- // canvas_draw_str_aligned(canvas, 62, 30, AlignCenter, AlignCenter, error);
- canvas_draw_str_aligned(
- canvas, 62, y + height + 8, AlignCenter, AlignBottom, furi_string_get_cstr(raw_data));
- for(int i = 0; i < barcode_length; i++) {
- //1 for wide, 0 for narrow
- char wide_or_narrow = furi_string_get_char(barcode_digits, i);
- int wn_digit = wide_or_narrow - '0'; //wide(1) or narrow(0) digit
- if(filled_in) {
- if(wn_digit == 1) {
- x = draw_bits(canvas, "111", x, y, width, height);
- } else {
- x = draw_bits(canvas, "1", x, y, width, height);
- }
- filled_in = false;
- } else {
- if(wn_digit == 1) {
- x = draw_bits(canvas, "000", x, y, width, height);
- } else {
- x = draw_bits(canvas, "0", x, y, width, height);
- }
- filled_in = true;
- }
- if((i + 1) % 7 == 0) {
- x = draw_bits(canvas, "0", x, y, width, height);
- filled_in = true;
- }
- }
- }
- static void barcode_draw_callback(Canvas* canvas, void* ctx) {
- furi_assert(ctx);
- BarcodeModel* barcode_model = ctx;
- BarcodeData* data = barcode_model->data;
- // const char* barcode_digits =;
- canvas_clear(canvas);
- if(data->valid) {
- switch(data->type_obj->type) {
- case UPCA:
- draw_upc_a(canvas, data);
- break;
- case EAN8:
- draw_ean_8(canvas, data);
- break;
- case EAN13:
- draw_ean_13(canvas, data);
- break;
- case CODE39:
- draw_code_39(canvas, data);
- break;
- case CODE128:
- case CODE128C:
- draw_code_128(canvas, data);
- break;
- case CODABAR:
- draw_codabar(canvas, data);
- break;
- case UNKNOWN:
- default:
- break;
- }
- } else {
- draw_error_str(
- canvas, get_error_code_name(data->reason), get_error_code_message(data->reason));
- }
- }
- bool barcode_input_callback(InputEvent* input_event, void* ctx) {
- UNUSED(ctx);
- //furi_assert(ctx);
- //Barcode* test_view_object = ctx;
- if(input_event->key == InputKeyBack) {
- return false;
- } else {
- return true;
- }
- }
- Barcode* barcode_view_allocate(BarcodeApp* barcode_app) {
- furi_assert(barcode_app);
- Barcode* barcode = malloc(sizeof(Barcode));
- barcode->view = view_alloc();
- barcode->barcode_app = barcode_app;
- view_set_context(barcode->view, barcode);
- view_allocate_model(barcode->view, ViewModelTypeLocking, sizeof(BarcodeModel));
- view_set_draw_callback(barcode->view, barcode_draw_callback);
- view_set_input_callback(barcode->view, barcode_input_callback);
- return barcode;
- }
- void barcode_free_model(Barcode* barcode) {
- with_view_model(
- barcode->view,
- BarcodeModel * model,
- {
- if(model->file_path != NULL) {
- furi_string_free(model->file_path);
- }
- if(model->data != NULL) {
- if(model->data->raw_data != NULL) {
- furi_string_free(model->data->raw_data);
- }
- if(model->data->correct_data != NULL) {
- furi_string_free(model->data->correct_data);
- }
- free(model->data);
- }
- },
- false);
- }
- void barcode_free(Barcode* barcode) {
- furi_assert(barcode);
- barcode_free_model(barcode);
- view_free(barcode->view);
- free(barcode);
- }
- View* barcode_get_view(Barcode* barcode) {
- furi_assert(barcode);
- return barcode->view;
- }
|