#include "pgzint.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(bc_generate); Datum bc_generate(PG_FUNCTION_ARGS) { bytea *result; struct zint_symbol *barcode; unsigned char *input; int error = 0; int rotation_angle = 0; barcode = ZBarcode_Create(); barcode->input_mode = UNICODE_MODE; barcode->output_options |= BARCODE_MEMORY_FILE; // "print" image to memory strcpy(barcode->outfile, "mem.png"); // no file created, extension used to set format if (PG_ARGISNULL(0)) { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("No input text provided"), errhint("Input text is required to generate a barcode"))); } else { size_t len = VARSIZE(PG_GETARG_TEXT_P(0)) - VARHDRSZ; input = palloc0(len + 1); memcpy(input, VARDATA(PG_GETARG_TEXT_P(0)), len); input[len] = '\0'; } if (!PG_ARGISNULL(1)) { int symbology = PG_GETARG_INT32(1); if (symbology >= 1) { barcode->symbology = symbology; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid symbology provided: %d", symbology), errhint("Symbology must be greater than or equal to 1. " "This is not checked against the list of symbologies so the caller must ensure validity."))); } } if (!PG_ARGISNULL(2)) { float8 height = PG_GETARG_FLOAT8(2); if (height >= 0.01) { barcode->height = height; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid height provided: %f", height), errhint("Height must be greater than or equal to 0.01"))); } } if (!PG_ARGISNULL(3)) { float8 scale = PG_GETARG_FLOAT8(3); if (scale >= 0.01) { barcode->scale = scale; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid scale provided: %f", scale), errhint("Scale must be greater than or equal to 0.01"))); } } if (!PG_ARGISNULL(4)) { int whitespace_width = PG_GETARG_INT32(4); if (whitespace_width >= 0 && whitespace_width <= 1000) { barcode->whitespace_width = whitespace_width; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid whitespace width provided: %d", whitespace_width), errhint("Whitespace width must be between 0 to 1000"))); } } if (!PG_ARGISNULL(5)) { int border_width = PG_GETARG_INT32(5); if (border_width >= 0 && border_width <= 1000) { barcode->border_width = border_width; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid border width provided: %d", border_width), errhint("Border width must be between 0 to 1000"))); } } if (!PG_ARGISNULL(6)) { int output_options = PG_GETARG_INT32(6); if (output_options >= 0) { barcode->output_options = output_options; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid output option provided: %d", output_options), errhint("Output options must be greater than or equal to 0"))); } } if (!PG_ARGISNULL(7)) { size_t len = VARSIZE(PG_GETARG_TEXT_P(7)) - VARHDRSZ; if (len > strlen(barcode->fgcolour)) len = strlen(barcode->fgcolour); memcpy(barcode->fgcolour, VARDATA(PG_GETARG_TEXT_P(7)), len); barcode->fgcolour[len] = '\0'; } else strcpy(barcode->fgcolour, "000000"); if (!PG_ARGISNULL(8)) { size_t len = VARSIZE(PG_GETARG_TEXT_P(8)) - VARHDRSZ; if (len > strlen(barcode->bgcolour)) len = strlen(barcode->bgcolour); memcpy(barcode->bgcolour, VARDATA(PG_GETARG_TEXT_P(8)), len); barcode->bgcolour[len] = '\0'; } else strcpy(barcode->bgcolour, "FFFFFF"); if (!PG_ARGISNULL(9) && PG_GETARG_BOOL(9)) barcode->show_hrt = 1; else barcode->show_hrt = 0; if (!PG_ARGISNULL(10)) { int option_1 = PG_GETARG_INT32(10); if (option_1 >= 0) { barcode->option_1 = option_1; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid option provided: %d", option_1), errhint("Option 1 must be greater than or equal to 0"))); } } if (!PG_ARGISNULL(11)) { int option_2 = PG_GETARG_INT32(11); if (option_2 >= 0) { barcode->option_2 = option_2; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid option provided: %d", option_2), errhint("Option 2 must be greater than or equal to 0"))); } } if (!PG_ARGISNULL(12)) { int option_3 = PG_GETARG_INT32(12); if (option_3 >= 0) { barcode->option_3 = option_3; } else { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid option provided: %d", option_3), errhint("Option 3 must be greater than or equal to 0"))); } } if (!PG_ARGISNULL(13)) { rotation_angle = PG_GETARG_INT32(13); if (rotation_angle != 0 && rotation_angle != 90 && rotation_angle != 180 && rotation_angle != 270) { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Error creating barcode"), errdetail("Invalid rotation angle provided: %d", rotation_angle), errhint("Rotation angle must be either 0, 90, 180, or 270, defaults to 0"))); } } error = ZBarcode_Encode_and_Print(barcode, input, 0, rotation_angle); if (error >= ZINT_WARN_INVALID_OPTION) { ZBarcode_Delete(barcode); ereport(ERROR, (errmsg("Zint Error: %s", barcode->errtxt))); } result = (bytea *) palloc0(VARHDRSZ + barcode->memfile_size); SET_VARSIZE(result, VARHDRSZ + barcode->memfile_size); // need to skip the header.. memcpy(&result[1], barcode->memfile, barcode->memfile_size); ZBarcode_Delete(barcode); PG_RETURN_BYTEA_P(result); }