PDF: Add support for line height (#3066)

Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
Richard Schreiber
2023-02-02 19:07:10 +01:00
committed by GitHub
co-authored by Raphael Michel
parent 7b301b6027
commit b4e372ce04
4 changed files with 45 additions and 17 deletions
+15 -3
View File
@@ -848,12 +848,17 @@ class Renderer:
'center': TA_CENTER, 'center': TA_CENTER,
'right': TA_RIGHT 'right': TA_RIGHT
} }
# lineheight display differs from browser canvas. This calc is just empirical values to get
# reportlab render similarly to browser canvas.
# for backwards compatability use „uncorrected“ lineheight of 1.0 instead of 1.15
lineheight = float(o['lineheight']) * 1.15 if 'lineheight' in o else 1.0
style = ParagraphStyle( style = ParagraphStyle(
name=uuid.uuid4().hex, name=uuid.uuid4().hex,
fontName=font, fontName=font,
fontSize=float(o['fontsize']), fontSize=float(o['fontsize']),
leading=float(o['fontsize']), leading=lineheight * float(o['fontsize']),
autoLeading="max", # for backwards compatability use autoLeading if no lineheight is given
autoLeading='off' if 'lineheight' in o else 'max',
textColor=Color(o['color'][0] / 255, o['color'][1] / 255, o['color'][2] / 255), textColor=Color(o['color'][0] / 255, o['color'][1] / 255, o['color'][2] / 255),
alignment=align_map[o['align']] alignment=align_map[o['align']]
) )
@@ -882,8 +887,15 @@ class Renderer:
if o.get('downward', False): if o.get('downward', False):
canvas.translate(float(o['left']) * mm, float(o['bottom']) * mm) canvas.translate(float(o['left']) * mm, float(o['bottom']) * mm)
canvas.rotate(o.get('rotation', 0) * -1) canvas.rotate(o.get('rotation', 0) * -1)
p.drawOn(canvas, 0, -h - ad[1] / 2) p.drawOn(canvas, 0, -h - ad[1] / 2.5)
else: else:
if lineheight != 1.0:
# lineheight adds to ascent/descent offsets, just empirical values again to get
# reportlab to render similarly to browser canvas
ad = (
ad[0],
ad[1] + (lineheight - 1.0) * float(o['fontsize']) * 1.05
)
canvas.translate(float(o['left']) * mm, float(o['bottom']) * mm + h) canvas.translate(float(o['left']) * mm, float(o['bottom']) * mm + h)
canvas.rotate(o.get('rotation', 0) * -1) canvas.rotate(o.get('rotation', 0) * -1)
p.drawOn(canvas, 0, -h - ad[1]) p.drawOn(canvas, 0, -h - ad[1])
@@ -275,6 +275,18 @@
<input type="number" value="13" class="input-block-level form-control" step="0.1" <input type="number" value="13" class="input-block-level form-control" step="0.1"
id="toolbox-fontsize"> id="toolbox-fontsize">
</div> </div>
<div class="col-sm-6">
<label>{% trans "Line height" %}</label><br>
<input type="number" value="1" class="input-block-level form-control" step="0.1"
id="toolbox-lineheight">
</div>
</div>
<div class="row control-group text">
<div class="col-sm-6">
<label>{% trans "Text color" %}</label><br>
<input type="text" value="#000000" class="input-block-level form-control colorpickerfield"
id="toolbox-col">
</div>
<div class="col-sm-6"> <div class="col-sm-6">
<label>&nbsp;</label><br> <label>&nbsp;</label><br>
<div class="btn-group btn-group-justified" role="group"> <div class="btn-group btn-group-justified" role="group">
@@ -295,15 +307,6 @@
</button> </button>
</div> </div>
</div> </div>
</div>
</div>
<div class="row control-group text">
<div class="col-sm-6">
<label>{% trans "Text color" %}</label><br>
<input type="text" value="#000000" class="input-block-level form-control colorpickerfield"
id="toolbox-col">
</div>
<div class="col-sm-6">
<label>&nbsp;</label><br> <label>&nbsp;</label><br>
<div class="btn-group btn-group-justified" id="toolbox-align"> <div class="btn-group btn-group-justified" id="toolbox-align">
<div class="btn-group" role="group"> <div class="btn-group" role="group">
@@ -161,8 +161,8 @@ var editor = {
left: editor._px2mm(left).toFixed(2), left: editor._px2mm(left).toFixed(2),
bottom: editor._px2mm(bottom).toFixed(2), bottom: editor._px2mm(bottom).toFixed(2),
fontsize: editor._px2pt(o.getFontSize()).toFixed(1), fontsize: editor._px2pt(o.getFontSize()).toFixed(1),
lineheight: o.lineHeight,
color: col, color: col,
//lineheight: o.lineHeight,
fontfamily: o.fontFamily, fontfamily: o.fontFamily,
bold: o.fontWeight === 'bold', bold: o.fontWeight === 'bold',
italic: o.fontStyle === 'italic', italic: o.fontStyle === 'italic',
@@ -241,7 +241,7 @@ var editor = {
o = editor._add_text(); o = editor._add_text();
o.setColor('rgb(' + d.color[0] + ',' + d.color[1] + ',' + d.color[2] + ')'); o.setColor('rgb(' + d.color[0] + ',' + d.color[1] + ',' + d.color[2] + ')');
o.setFontSize(editor._pt2px(d.fontsize)); o.setFontSize(editor._pt2px(d.fontsize));
//o.setLineHeight(d.lineheight); o.setLineHeight(d.lineheight || 1);
o.setFontFamily(d.fontfamily); o.setFontFamily(d.fontfamily);
o.setFontWeight(d.bold ? 'bold' : 'normal'); o.setFontWeight(d.bold ? 'bold' : 'normal');
o.setFontStyle(d.italic ? 'italic' : 'normal'); o.setFontStyle(d.italic ? 'italic' : 'normal');
@@ -483,7 +483,7 @@ var editor = {
var col = (new fabric.Color(o.getFill()))._source; var col = (new fabric.Color(o.getFill()))._source;
$("#toolbox-col").val("#" + ((1 << 24) + (col[0] << 16) + (col[1] << 8) + col[2]).toString(16).slice(1)); $("#toolbox-col").val("#" + ((1 << 24) + (col[0] << 16) + (col[1] << 8) + col[2]).toString(16).slice(1));
$("#toolbox-fontsize").val(editor._px2pt(o.fontSize).toFixed(1)); $("#toolbox-fontsize").val(editor._px2pt(o.fontSize).toFixed(1));
//$("#toolbox-lineheight").val(o.lineHeight); $("#toolbox-lineheight").val(o.lineHeight || 1);
$("#toolbox-fontfamily").val(o.fontFamily); $("#toolbox-fontfamily").val(o.fontFamily);
$("#toolbox").find("button[data-action=bold]").toggleClass('active', o.fontWeight === 'bold'); $("#toolbox").find("button[data-action=bold]").toggleClass('active', o.fontWeight === 'bold');
$("#toolbox").find("button[data-action=italic]").toggleClass('active', o.fontStyle === 'italic'); $("#toolbox").find("button[data-action=italic]").toggleClass('active', o.fontStyle === 'italic');
@@ -600,7 +600,7 @@ var editor = {
} else if (o.type === "textarea" || o.type === "text") { } else if (o.type === "textarea" || o.type === "text") {
o.setColor($("#toolbox-col").val()); o.setColor($("#toolbox-col").val());
o.setFontSize(editor._pt2px($("#toolbox-fontsize").val())); o.setFontSize(editor._pt2px($("#toolbox-fontsize").val()));
//o.setLineHeight($("#toolbox-lineheight").val()); o.setLineHeight($("#toolbox-lineheight").val() || 1);
o.setFontFamily($("#toolbox-fontfamily").val()); o.setFontFamily($("#toolbox-fontfamily").val());
o.setFontWeight($("#toolbox").find("button[data-action=bold]").is('.active') ? 'bold' : 'normal'); o.setFontWeight($("#toolbox").find("button[data-action=bold]").is('.active') ? 'bold' : 'normal');
o.setFontStyle($("#toolbox").find("button[data-action=italic]").is('.active') ? 'italic' : 'normal'); o.setFontStyle($("#toolbox").find("button[data-action=italic]").is('.active') ? 'italic' : 'normal');
@@ -861,6 +861,7 @@ var editor = {
thing.setCoords(); thing.setCoords();
editor._create_savepoint(); editor._create_savepoint();
break; break;
case 8: /* Backspace */
case 46: /* Delete */ case 46: /* Delete */
editor._delete(); editor._delete();
break; break;
@@ -240,7 +240,19 @@
"pattern": "[a-zA-Z-]*" "pattern": "[a-zA-Z-]*"
}, },
"fontsize": { "fontsize": {
"description": "Font size.", "description": "Font size",
"oneOf": [
{
"type": "number"
},
{
"type": "string",
"pattern": "^[0-9]+(\\.[0-9]+)?$"
}
]
},
"lineheight": {
"description": "Line height",
"oneOf": [ "oneOf": [
{ {
"type": "number" "type": "number"