fix(bbb-export-annotations): Handle text rendering issue (#20857)

* Handle error when imagemagick fails to render

* Update bbb-export-annotations/workers/process.js

Co-authored-by: Anton Georgiev <antobinary@users.noreply.github.com>

* Update bbb-export-annotations/workers/process.js

Co-authored-by: Anton Georgiev <antobinary@users.noreply.github.com>

* Add more detailed logs

---------

Co-authored-by: Anton Georgiev <antobinary@users.noreply.github.com>
This commit is contained in:
Daniel Petri Rocha 2024-08-06 22:21:45 +02:00 committed by GitHub
parent 352f3ebd58
commit 656cdb44cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -130,6 +130,7 @@ function escapeText(string) {
.replace(/</g, '\\&lt;'); .replace(/</g, '\\&lt;');
} }
// Rasterizes text into an image. Returns true if successful, false otherwise.
function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth = null) { function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth = null) {
fontSize = to_pt(fontSize) * config.process.textScaleFactor; fontSize = to_pt(fontSize) * config.process.textScaleFactor;
text = escapeText(text); text = escapeText(text);
@ -155,12 +156,15 @@ function render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxW
path.join(dropbox, `text${id}.png`), path.join(dropbox, `text${id}.png`),
]); ]);
try { const result = cp.spawnSync(config.shared.imagemagick, commands, {shell: false});
cp.spawnSync(config.shared.imagemagick, commands, {shell: false});
} catch (error) { if (result.error || result.status !== 0) {
logger.error(`ImageMagick failed to render textbox in job ${jobId}: ${error.message}`); logger.error(`ImageMagick failed to render textbox in job ${jobId}: ${error.message}`);
statusUpdate.setError(); statusUpdate.setError();
return false;
} }
return true;
} }
function get_gap(dash, size) { function get_gap(dash, size) {
@ -607,10 +611,10 @@ function overlay_shape_label(svg, annotation) {
const label_center_x = shape_x + shape_width * x_offset; const label_center_x = shape_x + shape_width * x_offset;
const label_center_y = shape_y + shape_height * y_offset; const label_center_y = shape_y + shape_height * y_offset;
render_textbox(fontColor, font, fontSize, textAlign, text, id); const renderStatus = render_textbox(fontColor, font, fontSize, textAlign, text, id);
const shape_label = path.join(dropbox, `text${id}.png`); const shape_label = path.join(dropbox, `text${id}.png`);
if (fs.existsSync(shape_label)) { if (fs.existsSync(shape_label) && renderStatus) {
// Poll results must fit inside shape, unlike other rectangle labels. // Poll results must fit inside shape, unlike other rectangle labels.
// Linewrapping handled by client. // Linewrapping handled by client.
const ref = `file://${dropbox}/text${id}.png`; const ref = `file://${dropbox}/text${id}.png`;
@ -634,6 +638,8 @@ function overlay_shape_label(svg, annotation) {
'height': labelHeight, 'height': labelHeight,
'xlink:href': ref, 'xlink:href': ref,
}).up(); }).up();
} else {
logger.warn(`Could not render status in overlay_shape_label for ${annotation}`);
} }
} }
@ -651,25 +657,29 @@ function overlay_sticky(svg, annotation) {
const text = annotation.text; const text = annotation.text;
const id = sanitize(annotation.id); const id = sanitize(annotation.id);
render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth); const renderStatus = render_textbox(textColor, font, fontSize, textAlign, text, id, textBoxWidth);
// Overlay transparent text image over empty sticky note // Overlay transparent text image over empty sticky note
svg.ele('g', { if (renderStatus) {
transform: `rotate(${rotation}, ${textBox_x + (textBoxWidth / 2)}, ${textBox_y + (textBoxHeight / 2)})`, svg.ele('g', {
}).ele('rect', { transform: `rotate(${rotation}, ${textBox_x + (textBoxWidth / 2)}, ${textBox_y + (textBoxHeight / 2)})`,
x: textBox_x, }).ele('rect', {
y: textBox_y, x: textBox_x,
width: textBoxWidth, y: textBox_y,
height: textBoxHeight, width: textBoxWidth,
fill: backgroundColor, height: textBoxHeight,
}).up() fill: backgroundColor,
.ele('image', { }).up()
'x': textBox_x, .ele('image', {
'y': textBox_y, 'x': textBox_x,
'width': textBoxWidth, 'y': textBox_y,
'height': textBoxHeight, 'width': textBoxWidth,
'xlink:href': `file://${dropbox}/text${id}.png`, 'height': textBoxHeight,
}).up(); 'xlink:href': `file://${dropbox}/text${id}.png`,
}).up();
} else {
logger.warn(`Could not render status in overlay_sticky for ${annotation}`);
}
} }
function overlay_triangle(svg, annotation) { function overlay_triangle(svg, annotation) {
@ -719,20 +729,24 @@ function overlay_text(svg, annotation) {
const rotation = rad_to_degree(annotation.rotation); const rotation = rad_to_degree(annotation.rotation);
const [textBox_x, textBox_y] = annotation.point; const [textBox_x, textBox_y] = annotation.point;
render_textbox(fontColor, font, fontSize, textAlign, text, id); const renderStatus = render_textbox(fontColor, font, fontSize, textAlign, text, id);
const rotation_x = textBox_x + (textBoxWidth / 2); if (renderStatus) {
const rotation_y = textBox_y + (textBoxHeight / 2); const rotation_x = textBox_x + (textBoxWidth / 2);
const rotation_y = textBox_y + (textBoxHeight / 2);
svg.ele('g', { svg.ele('g', {
transform: `rotate(${rotation} ${rotation_x} ${rotation_y})`, transform: `rotate(${rotation} ${rotation_x} ${rotation_y})`,
}).ele('image', { }).ele('image', {
'x': textBox_x, 'x': textBox_x,
'y': textBox_y, 'y': textBox_y,
'width': textBoxWidth, 'width': textBoxWidth,
'height': textBoxHeight, 'height': textBoxHeight,
'xlink:href': `file://${dropbox}/text${id}.png`, 'xlink:href': `file://${dropbox}/text${id}.png`,
}).up(); }).up();
} else {
logger.warn(`Could not render status in render_textbox for ${annotation}`);
}
} }
function overlay_annotation(svg, currentAnnotation) { function overlay_annotation(svg, currentAnnotation) {