Skip to content

Commit

Permalink
Properly support global <Barcode>
Browse files Browse the repository at this point in the history
The <Barcode> XML node directly in <Output> behaves like <Image>:
* it indents subsequent <Line> content
* it can be suppressed

Added C and PHP API to suppress global <Barcode>

Added new C unit tests and fixed <Image> and <Barcode> layout
and driver behaviour where needed:

* layout_barcode2_test exercises <Barcode> as part of <Output>
* layout_barcode3_test exercises suppression <Barcode>
* layout_barcode4_test exercises multiple <Line> elements
  that grow over the previous global <Barcode> vertically
* layout_xml3_ver2_test exercises multiple <Line> elements
  that grow over the previous global <Image> vertically

Extended documentation.

Signed-off-by: Zoltán Böszörményi <[email protected]>
  • Loading branch information
zboszor committed Mar 3, 2024
1 parent 06fa3bd commit fc98cd8
Show file tree
Hide file tree
Showing 48 changed files with 5,413 additions and 64 deletions.
17 changes: 17 additions & 0 deletions bindings/php/opencreport.c
Original file line number Diff line number Diff line change
Expand Up @@ -5239,6 +5239,18 @@ PHP_METHOD(opencreport_barcode, set_value_delayed) {
ocrpt_barcode_set_value_delayed(bco->bc, expr_string ? ZSTR_VAL(expr_string) : NULL);
}

PHP_METHOD(opencreport_barcode, set_suppress) {
zval *object = ZEND_THIS;
php_opencreport_barcode_object *bco = Z_OPENCREPORT_BARCODE_P(object);
zend_string *expr_string = NULL;

ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 1)
Z_PARAM_STR_EX(expr_string, 1, 0);
ZEND_PARSE_PARAMETERS_END();

ocrpt_barcode_set_suppress(bco->bc, expr_string ? ZSTR_VAL(expr_string) : NULL);
}

PHP_METHOD(opencreport_barcode, set_type) {
zval *object = ZEND_THIS;
php_opencreport_barcode_object *bco = Z_OPENCREPORT_BARCODE_P(object);
Expand Down Expand Up @@ -5307,6 +5319,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_opencreport_barcode_set_value_de
ZEND_ARG_TYPE_INFO(0, expr_string, IS_STRING, 1)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_opencreport_barcode_set_suppress, 0, 1, IS_VOID, 0)
ZEND_ARG_TYPE_INFO(0, expr_string, IS_STRING, 1)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_opencreport_barcode_set_type, 0, 1, IS_VOID, 0)
ZEND_ARG_TYPE_INFO(0, expr_string, IS_STRING, 1)
ZEND_END_ARG_INFO()
Expand All @@ -5330,6 +5346,7 @@ ZEND_END_ARG_INFO()
static const zend_function_entry opencreport_barcode_class_methods[] = {
PHP_ME(opencreport_barcode, set_value, arginfo_opencreport_barcode_set_value, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(opencreport_barcode, set_value_delayed, arginfo_opencreport_barcode_set_value_delayed, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(opencreport_barcode, set_suppress, arginfo_opencreport_barcode_set_suppress, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(opencreport_barcode, set_type, arginfo_opencreport_barcode_set_type, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(opencreport_barcode, set_width, arginfo_opencreport_barcode_set_width, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(opencreport_barcode, set_height, arginfo_opencreport_barcode_set_height, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
Expand Down
15 changes: 15 additions & 0 deletions doc/c-api-reference.sgm
Original file line number Diff line number Diff line change
Expand Up @@ -2733,6 +2733,21 @@ ocrpt_barcode_set_value_delayed(ocrpt_barcode *bc,
const char *expr_string);</programlisting>
</para>
</sect4>
<sect4 id="barcodesetsuppress">
<title>Set barcode suppression</title>
<para>
Set the barcode's suppression value from
an expression string. The expression
must evaluate to a boolean value.
<programlisting>void
ocrpt_barcode_set_suppress(ocrpt_barcode *bc,
const char *expr_string);</programlisting>
</para>
<para>
Default value is <literal>false</literal>,
i.e. no suppression.
</para>
</sect4>
<sect4 id="barcodesettype">
<title>Set barcode type</title>
<para>
Expand Down
15 changes: 15 additions & 0 deletions doc/php-api-reference.sgm
Original file line number Diff line number Diff line change
Expand Up @@ -3672,6 +3672,21 @@ OpenCReport\Barcode::set_value_delayed(
?string $expr_string = null): void;</programlisting>
</para>
</sect2>
<sect2 id="phpbarcodesetsuppress">
<title>Set the barcode suppression</title>
<para>
Set the barcode's suppression value from
an expression string. The expression
must evaluate to a boolean value.
<programlisting>public final
OpenCReport\Barcode::set_suppress(
?string $expr_string = null): void;</programlisting>
</para>
<para>
Default value is <literal>false</literal>,
i.e. no suppression.
</para>
</sect2>
<sect2 id="phpbarcodesettype">
<title>Set the barcode type</title>
<para>
Expand Down
22 changes: 22 additions & 0 deletions doc/xmldescription.sgm
Original file line number Diff line number Diff line change
Expand Up @@ -3698,6 +3698,28 @@ report_height_after_last="no"</programlisting>
</para>
<sect2 id="barcodeatts">
<title>Barcode element attributes</title>
<sect3 id="bcsuppressattr" xreflabel="Barcode suppression">
<title>Suppress</title>
<para>
<literal>&lt;Barcode&gt;</literal> elements
in <literal>&lt;Output&gt;</literal> may be
suppressed.
<programlisting>&lt;Line&gt;
&lt;Barcode suppress="yes" ... /&gt;
&lt;/Line&gt;</programlisting>
</para>
<para>
Default value is <literal>false</literal>,
i.e. no suppression.
</para>
<para>
The expression for <literal>suppress</literal>
must be a constant expression. An environment
variable (since it can't - or shouldn't - change
during the report execution) is considered
constant. See <xref linkend="expressions"/>.
</para>
</sect3>
<sect3 id="bcvalueattr" xreflabel="Barcode string value">
<title>Value</title>
<para>
Expand Down
1 change: 1 addition & 0 deletions include/opencreport.h
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,7 @@ ocrpt_barcode *ocrpt_line_add_barcode(ocrpt_line *line);

void ocrpt_barcode_set_value(ocrpt_barcode *bc, const char *expr_string);
void ocrpt_barcode_set_value_delayed(ocrpt_barcode *bc, const char *expr_string);
void ocrpt_barcode_set_suppress(ocrpt_barcode *bc, const char *expr_string);
void ocrpt_barcode_set_type(ocrpt_barcode *bc, const char *expr_string);
void ocrpt_barcode_set_width(ocrpt_barcode *bc, const char *expr_string);
void ocrpt_barcode_set_height(ocrpt_barcode *bc, const char *expr_string);
Expand Down
21 changes: 19 additions & 2 deletions libsrc/common-output.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,16 @@ void ocrpt_common_get_text_sizes(opencreport *o, ocrpt_part *p, ocrpt_part_row *
w *= l->font_width;
} else if (ocrpt_list_length(l->elements) == 1) {
w = total_width;
w -= output->current_image_width;

double diff;
if (output->current_image)
diff = output->current_image->image_width;
else if (output->current_barcode)
diff = output->current_barcode->barcode_width;
else
diff = 0.0;

w -= diff;
} else {
PangoRectangle logical_rect;

Expand All @@ -279,7 +288,15 @@ void ocrpt_common_get_text_sizes(opencreport *o, ocrpt_part *p, ocrpt_part_row *
if (last && w < total_width - le->start)
w = total_width - le->start;

w -= output->current_image_width;
double diff;
if (output->current_image)
diff = output->current_image->image_width;
else if (output->current_barcode)
diff = output->current_barcode->barcode_width;
else
diff = 0.0;

w -= diff;
}

le->width_computed = w;
Expand Down
43 changes: 30 additions & 13 deletions libsrc/html-output.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,16 @@ static void ocrpt_html_start_data_row(opencreport *o, ocrpt_part *p, ocrpt_part_
}

static void ocrpt_html_end_data_row(opencreport *o, ocrpt_part *p, ocrpt_part_row *pr, ocrpt_part_column *pd, ocrpt_report *r, ocrpt_break *br, ocrpt_output *output, ocrpt_line *l) {
html_private_data *priv = o->output_private;

ocrpt_mem_string_append(o->output_buffer, "</p>\n");

/*
* Cheat a little in accounting for line heights.
* Lines (despite everything is in "pt") have gaps between them.
* Add two pt for every line finished.
*/
priv->curr_pos_from_last_image += l->line_height + 2.0;
}

static void ocrpt_html_add_new_page_epilogue(opencreport *o) {
Expand Down Expand Up @@ -179,9 +188,16 @@ static void ocrpt_html_draw_text(opencreport *o, ocrpt_part *p, ocrpt_part_row *
if (pd && (le->start > pd->real_width))
return;


ocrpt_mem_string_append_printf(o->output_buffer,
"<span style=\"line-height: %.2lfpt; ",
l->line_height);

if (l->elements->data == le && priv->image_indent > 0.0 && priv->curr_pos_from_last_image >= priv->image_height)
ocrpt_mem_string_append_printf(o->output_buffer,
"margin-left: %.2lfpt; ",
priv->image_indent);

if (le->width) {
bool text_fits = (pd && (le->start + le->width_computed < pd->column_width)) || !pd;
ocrpt_mem_string_append_printf(o->output_buffer,
Expand Down Expand Up @@ -326,6 +342,8 @@ static void ocrpt_html_draw_image(opencreport *o, ocrpt_part *p, ocrpt_part_row
ocrpt_html_truncate_file_prefix(priv, img->img_file->name), w, h);

priv->image_indent = w;
priv->image_height = h;
priv->curr_pos_from_last_image = 0.0;
}
}

Expand Down Expand Up @@ -394,21 +412,18 @@ static void ocrpt_html_draw_barcode(opencreport *o, ocrpt_part *p, ocrpt_part_ro
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bc->encoded_width - first_space + 20.0, bc->barcode_height);
cairo_t *cr = cairo_create(surface);

ocrpt_color bg, fg;
ocrpt_color bg = { 1.0, 1.0, 1.0 };
ocrpt_color fg = { 0.0, 0.0, 0.0 };

char *color_name = NULL;
if (bc->color && bc->color->result[o->residx] && bc->color->result[o->residx]->type == OCRPT_RESULT_STRING && bc->color->result[o->residx]->string)
color_name = bc->color->result[o->residx]->string->str;
ocrpt_get_color(bc->color->result[o->residx]->string->str, &fg, false);
else if (line && line->color && line->color->result[o->residx] && line->color->result[o->residx]->type == OCRPT_RESULT_STRING && line->color->result[o->residx]->string)
ocrpt_get_color(line->color->result[o->residx]->string->str, &fg, false);

ocrpt_get_color(color_name, &fg, false);

if (bc->encoded_width > 0) {
color_name = NULL;
if (bc->bgcolor && bc->bgcolor->result[o->residx] && bc->bgcolor->result[o->residx]->type == OCRPT_RESULT_STRING && bc->bgcolor->result[o->residx]->string)
color_name = bc->bgcolor->result[o->residx]->string->str;

ocrpt_get_color(color_name, &bg, true);
}
if (bc->bgcolor && bc->bgcolor->result[o->residx] && bc->bgcolor->result[o->residx]->type == OCRPT_RESULT_STRING && bc->bgcolor->result[o->residx]->string)
ocrpt_get_color(bc->bgcolor->result[o->residx]->string->str, &bg, true);
else if (line && line->bgcolor && line->bgcolor->result[o->residx] && line->bgcolor->result[o->residx]->type == OCRPT_RESULT_STRING && line->bgcolor->result[o->residx]->string)
ocrpt_get_color(line->bgcolor->result[o->residx]->string->str, &bg, false);

cairo_save(cr);

Expand Down Expand Up @@ -478,10 +493,12 @@ static void ocrpt_html_draw_barcode(opencreport *o, ocrpt_part *p, ocrpt_part_ro
"<!--image start section--><section style=\"clear: both; width: %.2lfpt; \">\n",
pd->real_width);
ocrpt_mem_string_append_printf(o->output_buffer,
"<img src=\"%s\" style=\"float: left; width: %.2lfpt; height: %.2lfpt; \" alt=\"background image\">\n",
"<img src=\"data:image/png;base64,%s\" style=\"float: left; width: %.2lfpt; height: %.2lfpt; \" alt=\"background image\">\n",
priv->pngbase64->str, w, h);

priv->image_indent = w;
priv->image_height = h;
priv->curr_pos_from_last_image = 0.0;
}
}

Expand Down
2 changes: 2 additions & 0 deletions libsrc/html-output.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ struct html_private_data {
char *cwd;
size_t cwdlen;
double image_indent;
double image_height;
double curr_pos_from_last_image;
ocrpt_string *png;
ocrpt_string *pngbase64;
};
Expand Down
1 change: 0 additions & 1 deletion libsrc/json-output.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ static void ocrpt_json_draw_barcode(opencreport *o, ocrpt_part *p, ocrpt_part_ro
yajl_gen_string(priv->yajl_gen, (ystr)"color", 5);
yajl_gen_string(priv->yajl_gen, (ystr)priv->base.data->str, priv->base.data->len);


yajl_gen_string(priv->yajl_gen, (ystr)"value", 5);
if (bc->value && bc->value->result[o->residx] && bc->value->result[o->residx]->type == OCRPT_RESULT_STRING)
yajl_gen_string(priv->yajl_gen, (ystr)bc->value->result[o->residx]->string->str, bc->value->result[o->residx]->string->len);
Expand Down
Loading

0 comments on commit fc98cd8

Please sign in to comment.