From 258f799411e14223a65bccae31690407083a25e1 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Thu, 26 Sep 2024 16:57:00 +0200 Subject: [PATCH] Build and fix eslint warnings --- build/jsroot.js | 2439 ++++++++++++++------------- modules/draw/TGraphPolarPainter.mjs | 1 - modules/gpad/RAxisPainter.mjs | 1 - modules/gpad/RCanvasPainter.mjs | 2 +- modules/gpad/TAxisPainter.mjs | 2 +- modules/hist/RPavePainter.mjs | 2 - modules/hist/TPavePainter.mjs | 5 +- modules/hist2d/RH1Painter.mjs | 1 - modules/hist2d/RH2Painter.mjs | 5 +- modules/hist2d/TH1Painter.mjs | 14 +- modules/hist2d/TH2Painter.mjs | 2 - 11 files changed, 1233 insertions(+), 1241 deletions(-) diff --git a/build/jsroot.js b/build/jsroot.js index c272ad774..a1853a9d6 100644 --- a/build/jsroot.js +++ b/build/jsroot.js @@ -63264,120 +63264,119 @@ class TAxisPainter extends ObjectPainter { } } + let pr = Promise.resolve(); + for (let lcnt = 0; lcnt < label_g.length; ++lcnt) { if (lcnt > 0) side = -side; - let lastpos = 0; - const fix_coord = this.vertical ? -labeloffset * side : labeloffset * side + ticksPlusMinus * tickSize; + pr = pr.then(() => this.startTextDrawingAsync(labelsFont, 'font', label_g[lcnt])).then(() => { + let lastpos = 0; + const fix_coord = this.vertical ? -labeloffset * side : labeloffset * side + ticksPlusMinus * tickSize; - this.startTextDrawing(labelsFont, 'font', label_g[lcnt]); + for (let nmajor = 0; nmajor < lbl_pos.length; ++nmajor) { + let text = this.format(lbl_pos[nmajor], true); + if (text === null) continue; - for (let nmajor = 0; nmajor < lbl_pos.length; ++nmajor) { - let text = this.format(lbl_pos[nmajor], true); - if (text === null) continue; + const mod = this.findLabelModifier(axis, nmajor, lbl_pos); + if (mod?.fTextSize === 0) continue; - const mod = this.findLabelModifier(axis, nmajor, lbl_pos); - if (mod?.fTextSize === 0) continue; + if (mod) any_modified = true; + if (mod?.fLabText) text = mod.fLabText; - if (mod) any_modified = true; - if (mod?.fLabText) text = mod.fLabText; + const arg = { text, color: labelsFont.color, latex: 1, draw_g: label_g[lcnt], normal_side: (lcnt === 0) }; + let pos = Math.round(this.func(lbl_pos[nmajor])); - const arg = { text, color: labelsFont.color, latex: 1, draw_g: label_g[lcnt], normal_side: (lcnt === 0) }; - let pos = Math.round(this.func(lbl_pos[nmajor])); + if (mod?.fTextColor > 0) arg.color = this.getColor(mod.fTextColor); - if (mod?.fTextColor > 0) arg.color = this.getColor(mod.fTextColor); + arg.gap_before = (nmajor > 0) ? Math.abs(Math.round(pos - this.func(lbl_pos[nmajor - 1]))) : 0; - arg.gap_before = (nmajor > 0) ? Math.abs(Math.round(pos - this.func(lbl_pos[nmajor - 1]))) : 0; + arg.gap_after = (nmajor < lbl_pos.length - 1) ? Math.abs(Math.round(this.func(lbl_pos[nmajor + 1]) - pos)) : 0; - arg.gap_after = (nmajor < lbl_pos.length - 1) ? Math.abs(Math.round(this.func(lbl_pos[nmajor + 1]) - pos)) : 0; - - if (center_lbls) { - const gap = arg.gap_after || arg.gap_before; - pos = Math.round(pos - ((this.vertical !== this.reverse) ? 0.5 * gap : -0.5 * gap)); - if ((pos < -5) || (pos > (this.vertical ? h : w) + 5)) continue; - } + if (center_lbls) { + const gap = arg.gap_after || arg.gap_before; + pos = Math.round(pos - ((this.vertical !== this.reverse) ? 0.5 * gap : -0.5 * gap)); + if ((pos < -5) || (pos > (this.vertical ? h : w) + 5)) continue; + } - maxtextlen = Math.max(maxtextlen, text.length); + maxtextlen = Math.max(maxtextlen, text.length); - if (this.vertical) { - arg.x = fix_coord; - arg.y = pos; - arg.align = rotate_lbls ? ((side < 0) ? 23 : 20) : ((side < 0) ? 12 : 32); + if (this.vertical) { + arg.x = fix_coord; + arg.y = pos; + arg.align = rotate_lbls ? ((side < 0) ? 23 : 20) : ((side < 0) ? 12 : 32); - if (this.cutLabels()) { - const gap = labelsFont.size * (rotate_lbls ? 1.5 : 0.6); - if ((pos < gap) || (pos > h - gap)) continue; + if (this.cutLabels()) { + const gap = labelsFont.size * (rotate_lbls ? 1.5 : 0.6); + if ((pos < gap) || (pos > h - gap)) continue; + } + } else { + arg.x = pos; + arg.y = fix_coord; + arg.align = rotate_lbls ? ((side < 0) ? 12 : 32) : ((side < 0) ? 20 : 23); + if (this.log && !this.noexp && !this.vertical && arg.align === 23) { + arg.align = 21; + arg.y += labelsFont.size; + } else if (arg.align % 10 === 3) + arg.y -= labelsFont.size*0.1; // font takes 10% more by top align + + if (this.cutLabels()) { + const gap = labelsFont.size * (rotate_lbls ? 0.4 : 1.5); + if ((pos < gap) || (pos > w - gap)) continue; + } } - } else { - arg.x = pos; - arg.y = fix_coord; - arg.align = rotate_lbls ? ((side < 0) ? 12 : 32) : ((side < 0) ? 20 : 23); - if (this.log && !this.noexp && !this.vertical && arg.align === 23) { - arg.align = 21; - arg.y += labelsFont.size; - } else if (arg.align % 10 === 3) - arg.y -= labelsFont.size*0.1; // font takes 10% more by top align - if (this.cutLabels()) { - const gap = labelsFont.size * (rotate_lbls ? 0.4 : 1.5); - if ((pos < gap) || (pos > w - gap)) continue; - } - } + if (rotate_lbls) + arg.rotate = 270; + else if (mod && mod.fTextAngle !== -1) + arg.rotate = -mod.fTextAngle; - if (rotate_lbls) - arg.rotate = 270; - else if (mod && mod.fTextAngle !== -1) - arg.rotate = -mod.fTextAngle; + // only for major text drawing scale factor need to be checked + if (lcnt === 0) + arg.post_process = process_drawtext_ready; - // only for major text drawing scale factor need to be checked - if (lcnt === 0) - arg.post_process = process_drawtext_ready; + this.drawText(arg); - this.drawText(arg); + // workaround for symlog where labels can be compressed to close + if (this.symlog && lastpos && (pos !== lastpos) && ((this.vertical && !rotate_lbls) || (!this.vertical && rotate_lbls))) { + const axis_step = Math.abs(pos - lastpos); + textscale = Math.min(textscale, 1.1*axis_step/labelsFont.size); + } - // workaround for symlog where labels can be compressed to close - if (this.symlog && lastpos && (pos !== lastpos) && ((this.vertical && !rotate_lbls) || (!this.vertical && rotate_lbls))) { - const axis_step = Math.abs(pos - lastpos); - textscale = Math.min(textscale, 1.1*axis_step/labelsFont.size); + lastpos = pos; } - lastpos = pos; - } + if (this.order) { + let xoff = 0, yoff = 0; + if (this.name === 'xaxis') { + xoff = gStyle.fXAxisExpXOffset || 0; + yoff = gStyle.fXAxisExpYOffset || 0; + } else if (this.name === 'yaxis') { + xoff = gStyle.fYAxisExpXOffset || 0; + yoff = gStyle.fYAxisExpYOffset || 0; + } - if (this.order) { - let xoff = 0, yoff = 0; - if (this.name === 'xaxis') { - xoff = gStyle.fXAxisExpXOffset || 0; - yoff = gStyle.fXAxisExpYOffset || 0; - } else if (this.name === 'yaxis') { - xoff = gStyle.fYAxisExpXOffset || 0; - yoff = gStyle.fYAxisExpYOffset || 0; + if (xoff) xoff = Math.round(xoff * (this.getPadPainter()?.getPadWidth() ?? 0)); + if (yoff) yoff = Math.round(yoff * (this.getPadPainter()?.getPadHeight() ?? 0)); + + this.drawText({ color: labelsFont.color, + x: xoff + (this.vertical ? side*5 : w+5), + y: yoff + (this.has_obstacle ? fix_coord : (this.vertical ? -3 : -3*side)), + align: this.vertical ? ((side < 0) ? 30 : 10) : ((this.has_obstacle ^ (side < 0)) ? 13 : 10), + latex: 1, + text: '#times' + this.formatExp(10, this.order), + draw_g: label_g[lcnt] }); } - if (xoff) xoff = Math.round(xoff * (this.getPadPainter()?.getPadWidth() ?? 0)); - if (yoff) yoff = Math.round(yoff * (this.getPadPainter()?.getPadHeight() ?? 0)); + if ((lcnt > 1) && applied_scale) + this.scaleTextDrawing(applied_scale, label_g[lcnt]); - this.drawText({ color: labelsFont.color, - x: xoff + (this.vertical ? side*5 : w+5), - y: yoff + (this.has_obstacle ? fix_coord : (this.vertical ? -3 : -3*side)), - align: this.vertical ? ((side < 0) ? 30 : 10) : ((this.has_obstacle ^ (side < 0)) ? 13 : 10), - latex: 1, - text: '#times' + this.formatExp(10, this.order), - draw_g: label_g[lcnt] }); - } + return this.finishTextDrawing(label_g[lcnt], true); + }); } - this._maxlbllen = maxtextlen; // for internal use in palette painter + return pr.then(() => { + this._maxlbllen = maxtextlen; // for internal use in palette painter - // first complete major labels drawing - return this.finishTextDrawing(label_g[0], true).then(() => { - if (label_g.length > 1) { - // now complete drawing of second half with scaling if necessary - if (applied_scale) - this.scaleTextDrawing(applied_scale, label_g[1]); - return this.finishTextDrawing(label_g[1], true); - } - }).then(() => { if (lbl_tilt) { label_g[0].selectAll('text').each(function() { const txt = select(this), tr = txt.attr('transform'); @@ -63540,7 +63539,7 @@ class TAxisPainter extends ObjectPainter { .call(this.lineatt.func); } - let title_shift_x = 0, title_shift_y = 0, title_g = null, labelsMaxWidth = 0; + let title_shift_x = 0, title_shift_y = 0, title_g, labelsMaxWidth = 0; // draw labels (sometime on both sides) const labelSize = Math.max(this.labelsFont.size, 5), pr = (disable_axis_drawing || this.optionUnlab) @@ -63579,16 +63578,20 @@ class TAxisPainter extends ObjectPainter { console.warn('Why PAD element missing when search for position'); } - if (!this.fTitle || disable_axis_drawing) return true; + if (!this.fTitle || disable_axis_drawing) + return; title_g = axis_g.append('svg:g').attr('class', 'axis_title'); - let title_offest_k = side; - const rotate = axis.TestBit(EAxisBits.kRotateTitle) ? -1 : 1; + return this.startTextDrawingAsync(this.titleFont, 'font', title_g); + }).then(() => { + if (!title_g) + return; - this.startTextDrawing(this.titleFont, 'font', title_g); + const rotate = axis.TestBit(EAxisBits.kRotateTitle) ? -1 : 1, + xor_reverse = swap_side ^ this.titleOpposite, myxor = (rotate < 0) ^ xor_reverse; - const xor_reverse = swap_side ^ this.titleOpposite, myxor = (rotate < 0) ^ xor_reverse; + let title_offest_k = side; this.title_align = this.titleCenter ? 'middle' : (myxor ? 'begin' : 'end'); @@ -63600,16 +63603,16 @@ class TAxisPainter extends ObjectPainter { title_shift_y = Math.round(this.titleCenter ? h/2 : (xor_reverse ? h : 0)); this.drawText({ align: this.title_align+';middle', - rotate: (rotate < 0) ? 90 : 270, - text: this.fTitle, color: this.titleFont.color, draw_g: title_g }); + rotate: (rotate < 0) ? 90 : 270, + text: this.fTitle, color: this.titleFont.color, draw_g: title_g }); } else { title_offest_k *= 1.6; title_shift_x = Math.round(this.titleCenter ? w/2 : (xor_reverse ? 0 : w)); title_shift_y = Math.round(title_offest_k * this.titleOffset); this.drawText({ align: this.title_align+';middle', - rotate: (rotate < 0) ? 180 : 0, - text: this.fTitle, color: this.titleFont.color, draw_g: title_g }); + rotate: (rotate < 0) ? 180 : 0, + text: this.fTitle, color: this.titleFont.color, draw_g: title_g }); } this.addTitleDrag(title_g, this.vertical, title_offest_k, swap_side, this.vertical ? h : w); @@ -63621,7 +63624,7 @@ class TAxisPainter extends ObjectPainter { title_shift_x = Math.round(-side * ((labelsMaxWidth || labelSize) + 0.7*this.offsetScaling*this.titleSize)); makeTranslate(title_g, title_shift_x, title_shift_y); title_g.property('shift_x', title_shift_x) - .property('shift_y', title_shift_y); + .property('shift_y', title_shift_y); } return this; @@ -72386,11 +72389,9 @@ class TPavePainter extends ObjectPainter { this.createAttText({ attr: pave, can_rotate: false }); - this.startTextDrawing(this.textatt.font, height/1.2); - - this.drawText(this.textatt.createArg({ width, height, text: pave.fLabel, norotate: true })); - - return this.finishTextDrawing(); + return this.startTextDrawingAsync(this.textatt.font, height/1.2) + .then(() => this.drawText(this.textatt.createArg({ width, height, text: pave.fLabel, norotate: true }))) + .then(() => this.finishTextDrawing()); } /** @summary draw TPaveStats object */ @@ -72426,73 +72427,73 @@ class TPavePainter extends ObjectPainter { this.createAttText({ attr: pt, can_rotate: false }); - this.startTextDrawing(this.textatt.font, height/(nlines * 1.2)); + return this.startTextDrawingAsync(this.textatt.font, height/(nlines * 1.2)).then(() => { + if (nlines === 1) + this.drawText(this.textatt.createArg({ width, height, text: lines[0], latex: 1, norotate: true })); + else { + for (let j = 0; j < nlines; ++j) { + const y = j*stepy, + color = (colors[j] > 1) ? this.getColor(colors[j]) : this.textatt.color; + + if (first_stat && (j >= first_stat)) { + const parts = lines[j].split('|'); + for (let n = 0; n < parts.length; ++n) { + this.drawText({ align: 'middle', x: width * n / num_cols, y, latex: 0, + width: width/num_cols, height: stepy, text: parts[n], color }); + } + } else if (lines[j].indexOf('=') < 0) { + if (j === 0) { + has_head = true; + const max_hlen = Math.max(maxlen, Math.round((width-2*margin_x)/stepy/0.65)); + if (lines[j].length > max_hlen + 5) + lines[j] = lines[j].slice(0, max_hlen+2) + '...'; + } + this.drawText({ align: (j === 0) ? 'middle' : 'start', x: margin_x, y, + width: width-2*margin_x, height: stepy, text: lines[j], color }); + } else { + const parts = lines[j].split('='), args = []; + + for (let n = 0; n < 2; ++n) { + const arg = { + align: (n === 0) ? 'start' : 'end', x: margin_x, y, + width: width - 2*margin_x, height: stepy, text: n > 0 ? parts[n].trimStart() : parts[n].trimEnd(), color, + _expected_width: width-2*margin_x, _args: args, + post_process(painter) { + if (this._args[0].ready && this._args[1].ready) + painter.scaleTextDrawing(1.05*(this._args[0].result_width+this._args[1].result_width)/this._expected_width, painter.draw_g); + } + }; + args.push(arg); + } - if (nlines === 1) - this.drawText(this.textatt.createArg({ width, height, text: lines[0], latex: 1, norotate: true })); - else { - for (let j = 0; j < nlines; ++j) { - const y = j*stepy, - color = (colors[j] > 1) ? this.getColor(colors[j]) : this.textatt.color; - - if (first_stat && (j >= first_stat)) { - const parts = lines[j].split('|'); - for (let n = 0; n < parts.length; ++n) { - this.drawText({ align: 'middle', x: width * n / num_cols, y, latex: 0, - width: width/num_cols, height: stepy, text: parts[n], color }); + for (let n = 0; n < 2; ++n) + this.drawText(args[n]); } - } else if (lines[j].indexOf('=') < 0) { - if (j === 0) { - has_head = true; - const max_hlen = Math.max(maxlen, Math.round((width-2*margin_x)/stepy/0.65)); - if (lines[j].length > max_hlen + 5) - lines[j] = lines[j].slice(0, max_hlen+2) + '...'; - } - this.drawText({ align: (j === 0) ? 'middle' : 'start', x: margin_x, y, - width: width-2*margin_x, height: stepy, text: lines[j], color }); - } else { - const parts = lines[j].split('='), args = []; - - for (let n = 0; n < 2; ++n) { - const arg = { - align: (n === 0) ? 'start' : 'end', x: margin_x, y, - width: width - 2*margin_x, height: stepy, text: n > 0 ? parts[n].trimStart() : parts[n].trimEnd(), color, - _expected_width: width-2*margin_x, _args: args, - post_process(painter) { - if (this._args[0].ready && this._args[1].ready) - painter.scaleTextDrawing(1.05*(this._args[0].result_width+this._args[1].result_width)/this._expected_width, painter.draw_g); - } - }; - args.push(arg); - } - - for (let n = 0; n < 2; ++n) - this.drawText(args[n]); } } - } - let lpath = ''; + let lpath = ''; - if ((pt.fBorderSize > 0) && has_head) - lpath += `M0,${Math.round(stepy)}h${width}`; + if ((pt.fBorderSize > 0) && has_head) + lpath += `M0,${Math.round(stepy)}h${width}`; - if ((first_stat > 0) && (num_cols > 1)) { - for (let nrow = first_stat; nrow < nlines; ++nrow) - lpath += `M0,${Math.round(nrow * stepy)}h${width}`; - for (let ncol = 0; ncol < num_cols - 1; ++ncol) - lpath += `M${Math.round(width / num_cols * (ncol + 1))},${Math.round(first_stat * stepy)}V${height}`; - } + if ((first_stat > 0) && (num_cols > 1)) { + for (let nrow = first_stat; nrow < nlines; ++nrow) + lpath += `M0,${Math.round(nrow * stepy)}h${width}`; + for (let ncol = 0; ncol < num_cols - 1; ++ncol) + lpath += `M${Math.round(width / num_cols * (ncol + 1))},${Math.round(first_stat * stepy)}V${height}`; + } - if (lpath) this.draw_g.append('svg:path').attr('d', lpath).call(this.lineatt.func); + if (lpath) this.draw_g.append('svg:path').attr('d', lpath).call(this.lineatt.func); - // this.draw_g.classed('most_upper_primitives', true); // this primitive will remain on top of list + // this.draw_g.classed('most_upper_primitives', true); // this primitive will remain on top of list - return this.finishTextDrawing(undefined, (nlines > 1)); + return this.finishTextDrawing(undefined, (nlines > 1)); + }); } /** @summary draw TPaveText object */ - drawPaveText(width, height, _dummy_arg, text_g) { + async drawPaveText(width, height, _dummy_arg, text_g) { const pt = this.getObject(), arr = pt.fLines?.arr || [], nlines = arr.length, @@ -72513,98 +72514,101 @@ class TPavePainter extends ObjectPainter { if (!text_g) text_g = this.draw_g; const fast = (nlines === 1) && pp._fast_drawing; - let num_default = 0, is_any_text = false; + let num_txt = 0, num_custom = 0; + + arr.forEach(entry => { + if ((entry._typename !== clTText) && (entry._typename !== clTLatex)) return; + if (!entry.fTitle || !entry.fTitle.trim()) return; + num_txt++; + if (entry.fX || entry.fY || entry.fTextSize) + num_custom++; + }); - for (let nline = 0; nline < nlines; ++nline) { - const entry = arr[nline], texty = nline*stepy; + const pr = (num_txt > num_custom) ? this.startTextDrawingAsync(this.textatt.font, 0.85*height/nlines, text_g, max_font_size) : Promise.resolve(); - switch (entry._typename) { - case clTText: - case clTLatex: { - if (!entry.fTitle || !entry.fTitle.trim()) continue; - - let color = entry.fTextColor ? this.getColor(entry.fTextColor) : ''; - if (!color) color = this.textatt.color; - is_any_text = true; - if (entry.fX || entry.fY || entry.fTextSize) { - // individual positioning - const align = entry.fTextAlign || this.textatt.align, - halign = Math.floor(align/10), - valign = align % 10, - x = entry.fX ? entry.fX*width : (halign === 1 ? margin_x : (halign === 2 ? width / 2 : width - margin_x)), - y = entry.fY ? (1 - entry.fY)*height : (texty + (valign === 2 ? stepy / 2 : (valign === 3 ? stepy : 0))), - sub_g = text_g.append('svg:g'); - - this.startTextDrawing(this.textatt.font, this.textatt.getAltSize(entry.fTextSize, pad_height), sub_g); - - this.drawText({ align, x, y, text: entry.fTitle, color, - latex: (entry._typename === clTText) ? 0 : 1, draw_g: sub_g, fast }); - - promises.push(this.finishTextDrawing(sub_g)); - } else { - // default position - if (num_default++ === 0) - this.startTextDrawing(this.textatt.font, 0.85*height/nlines, text_g, max_font_size); - - this.drawText({ x: margin_x, y: texty, width: width - 2*margin_x, height: stepy, - align: entry.fTextAlign || this.textatt.align, - draw_g: text_g, latex: (entry._typename === clTText) ? 0 : 1, - text: entry.fTitle, color, fast }); + return pr.then(() => { + for (let nline = 0; nline < nlines; ++nline) { + const entry = arr[nline], texty = nline*stepy; + + switch (entry._typename) { + case clTText: + case clTLatex: { + if (!entry.fTitle || !entry.fTitle.trim()) continue; + + let color = entry.fTextColor ? this.getColor(entry.fTextColor) : ''; + if (!color) color = this.textatt.color; + if (entry.fX || entry.fY || entry.fTextSize) { + // individual positioning + const align = entry.fTextAlign || this.textatt.align, + halign = Math.floor(align/10), + valign = align % 10, + x = entry.fX ? entry.fX*width : (halign === 1 ? margin_x : (halign === 2 ? width / 2 : width - margin_x)), + y = entry.fY ? (1 - entry.fY)*height : (texty + (valign === 2 ? stepy / 2 : (valign === 3 ? stepy : 0))), + draw_g = text_g.append('svg:g'); + + promises.push(this.startTextDrawingAsync(this.textatt.font, this.textatt.getAltSize(entry.fTextSize, pad_height), draw_g) + .then(() => this.drawText({ align, x, y, text: entry.fTitle, color, + latex: (entry._typename === clTText) ? 0 : 1, draw_g, fast })) + .then(() => this.finishTextDrawing(draw_g))); + } else { + this.drawText({ x: margin_x, y: texty, width: width - 2*margin_x, height: stepy, + align: entry.fTextAlign || this.textatt.align, + draw_g: text_g, latex: (entry._typename === clTText) ? 0 : 1, + text: entry.fTitle, color, fast }); + } + break; } - break; - } - case clTLine: { - const lx1 = entry.fX1 ? Math.round(entry.fX1*width) : 0, - lx2 = entry.fX2 ? Math.round(entry.fX2*width) : width, - ly1 = entry.fY1 ? Math.round((1 - entry.fY1)*height) : Math.round(texty + stepy*0.5), - ly2 = entry.fY2 ? Math.round((1 - entry.fY2)*height) : Math.round(texty + stepy*0.5), - lineatt = this.createAttLine(entry); - text_g.append('svg:path') - .attr('d', `M${lx1},${ly1}L${lx2},${ly2}`) - .call(lineatt.func); - break; - } - case clTBox: { - const bx1 = entry.fX1 ? Math.round(entry.fX1*width) : 0, - bx2 = entry.fX2 ? Math.round(entry.fX2*width) : width, - by1 = entry.fY1 ? Math.round((1 - entry.fY1)*height) : Math.round(texty), - by2 = entry.fY2 ? Math.round((1 - entry.fY2)*height) : Math.round(texty + stepy), - fillatt = this.createAttFill(entry); - text_g.append('svg:path') - .attr('d', `M${bx1},${by1}H${bx2}V${by2}H${bx1}Z`) - .call(fillatt.func); - break; + case clTLine: { + const lx1 = entry.fX1 ? Math.round(entry.fX1*width) : 0, + lx2 = entry.fX2 ? Math.round(entry.fX2*width) : width, + ly1 = entry.fY1 ? Math.round((1 - entry.fY1)*height) : Math.round(texty + stepy*0.5), + ly2 = entry.fY2 ? Math.round((1 - entry.fY2)*height) : Math.round(texty + stepy*0.5), + lineatt = this.createAttLine(entry); + text_g.append('svg:path') + .attr('d', `M${lx1},${ly1}L${lx2},${ly2}`) + .call(lineatt.func); + break; + } + case clTBox: { + const bx1 = entry.fX1 ? Math.round(entry.fX1*width) : 0, + bx2 = entry.fX2 ? Math.round(entry.fX2*width) : width, + by1 = entry.fY1 ? Math.round((1 - entry.fY1)*height) : Math.round(texty), + by2 = entry.fY2 ? Math.round((1 - entry.fY2)*height) : Math.round(texty + stepy), + fillatt = this.createAttFill(entry); + text_g.append('svg:path') + .attr('d', `M${bx1},${by1}H${bx2}V${by2}H${bx1}Z`) + .call(fillatt.func); + break; + } } } - } - if (num_default > 0) - promises.push(this.finishTextDrawing(text_g, num_default > 1)); + if (num_txt > num_custom) + promises.push(this.finishTextDrawing(text_g, num_txt > num_custom + 1)); - if (this.isTitle()) - this.draw_g.style('display', !is_any_text ? 'none' : null); + if (this.isTitle()) + this.draw_g.style('display', !num_txt ? 'none' : null); - if (draw_header) { - const x = Math.round(width*0.25), - y = Math.round(-height*0.02), - w = Math.round(width*0.5), - h = Math.round(height*0.04), - lbl_g = text_g.append('svg:g'); + if (draw_header) { + const x = Math.round(width*0.25), + y = Math.round(-height*0.02), + w = Math.round(width*0.5), + h = Math.round(height*0.04), + lbl_g = text_g.append('svg:g'); - lbl_g.append('svg:path') - .attr('d', `M${x},${y}h${w}v${h}h${-w}z`) - .call(this.fillatt.func) - .call(this.lineatt.func); - - this.startTextDrawing(this.textatt.font, h/1.5, lbl_g); + lbl_g.append('svg:path') + .attr('d', `M${x},${y}h${w}v${h}h${-w}z`) + .call(this.fillatt.func) + .call(this.lineatt.func); - this.drawText({ align: 22, x, y, width: w, height: h, text: pt.fLabel, color: this.textatt.color, draw_g: lbl_g }); - - promises.push(this.finishTextDrawing(lbl_g)); - } + promises.push(this.startTextDrawingAsync(this.textatt.font, h/1.5, lbl_g) + .then(() => this.drawText({ align: 22, x, y, width: w, height: h, text: pt.fLabel, color: this.textatt.color, draw_g: lbl_g })) + .then(() => promises.push(this.finishTextDrawing(lbl_g)))); + } - return Promise.all(promises).then(() => this); + return Promise.all(promises).then(() => this); + }); } /** @summary Method used to convert value to string according specified format @@ -72698,149 +72702,147 @@ class TPavePainter extends ObjectPainter { if (tsz && (tsz < font_size)) font_size = max_font_size = tsz; - if (any_text && !custom_textg) - this.startTextDrawing(this.textatt.font, font_size, this.draw_g, max_font_size); + const pr = any_text && !custom_textg ? this.startTextDrawingAsync(this.textatt.font, font_size, this.draw_g, max_font_size) : Promise.resolve(); - for (let ii = 0, i = -1; ii < nlines; ++ii) { - const entry = legend.fPrimitives.arr[ii]; - if (isEmpty(entry)) continue; // let discard empty entry - - if (ncols === 1) ++i; else i = ii; - - const lopt = entry.fOption.toLowerCase(), - icol = i % ncols, irow = (i - icol) / ncols, - x0 = Math.round(column_pos[icol]), - column_width = Math.round(column_pos[icol + 1] - column_pos[icol]), - tpos_x = x0 + Math.round(legend.fMargin*w/ncols), - mid_x = Math.round((x0 + tpos_x)/2), - pos_y = Math.round(irow*step_y + padding_y), // top corner - mid_y = Math.round((irow+0.5)*step_y + padding_y), // center line - mo = entry.fObject, - draw_fill = lopt.indexOf('f') !== -1, - draw_line = lopt.indexOf('l') !== -1, - draw_error = lopt.indexOf('e') !== -1, - draw_marker = lopt.indexOf('p') !== -1; - - let o_fill = entry, o_marker = entry, o_line = entry, - painter = null, isany = false; - - if (isObject(mo)) { - if ('fLineColor' in mo) o_line = mo; - if ('fFillColor' in mo) o_fill = mo; - if ('fMarkerColor' in mo) o_marker = mo; - painter = pp.findPainterFor(mo); - } - - // Draw fill pattern (in a box) - if (draw_fill) { - const fillatt = painter?.fillatt?.used ? painter.fillatt : this.createAttFill(o_fill); - let lineatt; - if (!draw_line && !draw_error && !draw_marker) { - lineatt = painter?.lineatt?.used ? painter.lineatt : this.createAttLine(o_line); - if (lineatt.empty()) lineatt = null; - } - - if (!fillatt.empty() || lineatt) { - isany = true; - // box total height is yspace*0.7 - // define x,y as the center of the symbol for this entry - this.draw_g.append('svg:path') - .attr('d', `M${x0 + padding_x},${Math.round(pos_y+step_y*0.1)}v${Math.round(step_y*0.8)}h${tpos_x-2*padding_x-x0}v${-Math.round(step_y*0.8)}z`) - .call(fillatt.func) - .call(lineatt ? lineatt.func : () => {}); - } - } + return pr.then(() => { + for (let ii = 0, i = -1; ii < nlines; ++ii) { + const entry = legend.fPrimitives.arr[ii]; + if (isEmpty(entry)) continue; // let discard empty entry - // Draw line and/or error (when specified) - if (draw_line || draw_error) { - const lineatt = painter?.lineatt?.used ? painter.lineatt : this.createAttLine(o_line); - if (!lineatt.empty()) { - isany = true; - if (draw_line) { + if (ncols === 1) ++i; else i = ii; + + const lopt = entry.fOption.toLowerCase(), + icol = i % ncols, irow = (i - icol) / ncols, + x0 = Math.round(column_pos[icol]), + column_width = Math.round(column_pos[icol + 1] - column_pos[icol]), + tpos_x = x0 + Math.round(legend.fMargin*w/ncols), + mid_x = Math.round((x0 + tpos_x)/2), + pos_y = Math.round(irow*step_y + padding_y), // top corner + mid_y = Math.round((irow+0.5)*step_y + padding_y), // center line + mo = entry.fObject, + draw_fill = lopt.indexOf('f') !== -1, + draw_line = lopt.indexOf('l') !== -1, + draw_error = lopt.indexOf('e') !== -1, + draw_marker = lopt.indexOf('p') !== -1; + + let o_fill = entry, o_marker = entry, o_line = entry, + painter = null, isany = false; + + if (isObject(mo)) { + if ('fLineColor' in mo) o_line = mo; + if ('fFillColor' in mo) o_fill = mo; + if ('fMarkerColor' in mo) o_marker = mo; + painter = pp.findPainterFor(mo); + } + + // Draw fill pattern (in a box) + if (draw_fill) { + const fillatt = painter?.fillatt?.used ? painter.fillatt : this.createAttFill(o_fill); + let lineatt; + if (!draw_line && !draw_error && !draw_marker) { + lineatt = painter?.lineatt?.used ? painter.lineatt : this.createAttLine(o_line); + if (lineatt.empty()) lineatt = null; + } + + if (!fillatt.empty() || lineatt) { + isany = true; + // box total height is yspace*0.7 + // define x,y as the center of the symbol for this entry this.draw_g.append('svg:path') - .attr('d', `M${x0 + padding_x},${mid_y}H${tpos_x - padding_x}`) - .call(lineatt.func); + .attr('d', `M${x0 + padding_x},${Math.round(pos_y+step_y*0.1)}v${Math.round(step_y*0.8)}h${tpos_x-2*padding_x-x0}v${-Math.round(step_y*0.8)}z`) + .call(fillatt.func) + .call(lineatt ? lineatt.func : () => {}); } - if (draw_error) { - let endcaps = 0, edx = step_y*0.05; - if (isFunc(painter?.getHisto) && painter.options?.ErrorKind === 1) - endcaps = 1; // draw bars for e1 option in histogram - else if (isFunc(painter?.getGraph) && mo?.fLineWidth !== undefined && mo?.fMarkerSize !== undefined) { - endcaps = painter.options?.Ends ?? 1; // default is 1 - edx = mo.fLineWidth + gStyle.fEndErrorSize; - if (endcaps > 1) edx = Math.max(edx, mo.fMarkerSize*8*0.66); + } + + // Draw line and/or error (when specified) + if (draw_line || draw_error) { + const lineatt = painter?.lineatt?.used ? painter.lineatt : this.createAttLine(o_line); + if (!lineatt.empty()) { + isany = true; + if (draw_line) { + this.draw_g.append('svg:path') + .attr('d', `M${x0 + padding_x},${mid_y}H${tpos_x - padding_x}`) + .call(lineatt.func); } + if (draw_error) { + let endcaps = 0, edx = step_y*0.05; + if (isFunc(painter?.getHisto) && painter.options?.ErrorKind === 1) + endcaps = 1; // draw bars for e1 option in histogram + else if (isFunc(painter?.getGraph) && mo?.fLineWidth !== undefined && mo?.fMarkerSize !== undefined) { + endcaps = painter.options?.Ends ?? 1; // default is 1 + edx = mo.fLineWidth + gStyle.fEndErrorSize; + if (endcaps > 1) edx = Math.max(edx, mo.fMarkerSize*8*0.66); + } - const eoff = (endcaps === 3) ? 0.03 : 0, - ey1 = Math.round(pos_y+step_y*(0.1 + eoff)), - ey2 = Math.round(pos_y+step_y*(0.9 - eoff)), - edy = Math.round(edx * 0.66); - edx = Math.round(edx); - let path = `M${mid_x},${ey1}V${ey2}`; - switch (endcaps) { - case 1: path += `M${mid_x-edx},${ey1}h${2*edx}M${mid_x-edx},${ey2}h${2*edx}`; break; // bars - case 2: path += `M${mid_x-edx},${ey1+edy}v${-edy}h${2*edx}v${edy}M${mid_x-edx},${ey2-edy}v${edy}h${2*edx}v${-edy}`; break; // ] - case 3: path += `M${mid_x-edx},${ey1}h${2*edx}l${-edx},${-edy}zM${mid_x-edx},${ey2}h${2*edx}l${-edx},${edy}z`; break; // triangle - case 4: path += `M${mid_x-edx},${ey1+edy}l${edx},${-edy}l${edx},${edy}M${mid_x-edx},${ey2-edy}l${edx},${edy}l${edx},${-edy}`; break; // arrow + const eoff = (endcaps === 3) ? 0.03 : 0, + ey1 = Math.round(pos_y+step_y*(0.1 + eoff)), + ey2 = Math.round(pos_y+step_y*(0.9 - eoff)), + edy = Math.round(edx * 0.66); + edx = Math.round(edx); + let path = `M${mid_x},${ey1}V${ey2}`; + switch (endcaps) { + case 1: path += `M${mid_x-edx},${ey1}h${2*edx}M${mid_x-edx},${ey2}h${2*edx}`; break; // bars + case 2: path += `M${mid_x-edx},${ey1+edy}v${-edy}h${2*edx}v${edy}M${mid_x-edx},${ey2-edy}v${edy}h${2*edx}v${-edy}`; break; // ] + case 3: path += `M${mid_x-edx},${ey1}h${2*edx}l${-edx},${-edy}zM${mid_x-edx},${ey2}h${2*edx}l${-edx},${edy}z`; break; // triangle + case 4: path += `M${mid_x-edx},${ey1+edy}l${edx},${-edy}l${edx},${edy}M${mid_x-edx},${ey2-edy}l${edx},${edy}l${edx},${-edy}`; break; // arrow + } + this.draw_g.append('svg:path') + .attr('d', path) + .call(lineatt.func) + .style('fill', endcaps > 1 ? 'none' : null); } - this.draw_g.append('svg:path') - .attr('d', path) - .call(lineatt.func) - .style('fill', endcaps > 1 ? 'none' : null); } } - } - // Draw Poly marker - if (draw_marker) { - const marker = painter?.markeratt?.used ? painter.markeratt : this.createAttMarker(o_marker); - if (!marker.empty()) { - isany = true; - this.draw_g - .append('svg:path') - .attr('d', marker.create((x0 + tpos_x)/2, mid_y)) - .call(marker.func); + // Draw Poly marker + if (draw_marker) { + const marker = painter?.markeratt?.used ? painter.markeratt : this.createAttMarker(o_marker); + if (!marker.empty()) { + isany = true; + this.draw_g + .append('svg:path') + .attr('d', marker.create((x0 + tpos_x)/2, mid_y)) + .call(marker.func); + } } - } - - // special case - nothing draw, try to show rect with line attributes - if (!isany && painter?.lineatt && !painter.lineatt.empty()) { - this.draw_g.append('svg:path') - .attr('d', `M${x0 + padding_x},${Math.round(pos_y+step_y*0.1)}v${Math.round(step_y*0.8)}h${tpos_x-2*padding_x-x0}v${-Math.round(step_y*0.8)}z`) - .style('fill', 'none') - .call(painter.lineatt.func); - } - - let pos_x = tpos_x; - if (isStr(lopt) && (lopt.toLowerCase() !== 'h')) - any_opt = true; - else if (!any_opt) - pos_x = x0 + padding_x; - if (entry.fLabel) { - let lbl_g = this.draw_g; - const textatt = this.createAttText({ attr: entry, std: false, attr_alt: legend }); - if (custom_textg) { - lbl_g = this.draw_g.append('svg:g'); - const entry_font_size = textatt.getSize(pp.getPadHeight()); - this.startTextDrawing(textatt.font, entry_font_size, lbl_g, max_font_size); + // special case - nothing draw, try to show rect with line attributes + if (!isany && painter?.lineatt && !painter.lineatt.empty()) { + this.draw_g.append('svg:path') + .attr('d', `M${x0 + padding_x},${Math.round(pos_y+step_y*0.1)}v${Math.round(step_y*0.8)}h${tpos_x-2*padding_x-x0}v${-Math.round(step_y*0.8)}z`) + .style('fill', 'none') + .call(painter.lineatt.func); + } + + let pos_x = tpos_x; + if (isStr(lopt) && (lopt.toLowerCase() !== 'h')) + any_opt = true; + else if (!any_opt) + pos_x = x0 + padding_x; + + if (entry.fLabel) { + const textatt = this.createAttText({ attr: entry, std: false, attr_alt: legend }), + arg = { draw_g: this.draw_g, align: textatt.align, x: pos_x, y: pos_y, + scale: (custom_textg && !entry.fTextSize) || !legend.fTextSize, + width: x0+column_width-pos_x-padding_x, height: step_y, + text: entry.fLabel, color: textatt.color }; + if (custom_textg) { + arg.draw_g = this.draw_g.append('svg:g'); + text_promises.push(this.startTextDrawingAsync(textatt.font, textatt.getSize(pp.getPadHeight()), arg.draw_g, max_font_size) + .then(() => this.drawText(arg)) + .then(() => this.finishTextDrawing(arg.draw_g))); + } else + this.drawText(arg); } - - this.drawText({ draw_g: lbl_g, align: textatt.align, x: pos_x, y: pos_y, - scale: (custom_textg && !entry.fTextSize) || !legend.fTextSize, - width: x0+column_width-pos_x-padding_x, height: step_y, - text: entry.fLabel, color: textatt.color }); - - if (custom_textg) - text_promises.push(this.finishTextDrawing(lbl_g)); } - } - if (any_text && !custom_textg) - text_promises.push(this.finishTextDrawing()); + if (any_text && !custom_textg) + text_promises.push(this.finishTextDrawing()); - // rescale after all entries are shown - return Promise.all(text_promises); + // rescale after all entries are shown + return Promise.all(text_promises); + }); } /** @summary draw color palette with axis */ @@ -77672,7 +77674,7 @@ let TH2Painter$2 = class TH2Painter extends THistPainter { } // loop over bins } - let pr = Promise.resolve(true); + let pr = Promise.resolve(); if (textbins.length > 0) { const color = this.getColor(histo.fMarkerColor), @@ -77680,35 +77682,35 @@ let TH2Painter$2 = class TH2Painter extends THistPainter { text_g = this.draw_g.append('svg:g').attr('class', 'th2poly_text'), text_size = ((histo.fMarkerSize !== 1) && rotate) ? Math.round(0.02*h*histo.fMarkerSize) : 12; - this.startTextDrawing(42, text_size, text_g, text_size); + pr = this.startTextDrawingAsync(42, text_size, text_g, text_size).then(() => { + for (i = 0; i < textbins.length; ++i) { + const textbin = textbins[i]; - for (i = 0; i < textbins.length; ++i) { - const textbin = textbins[i]; + bin = textbin.bin; - bin = textbin.bin; + if (textbin.sum > 0) { + textbin.midx = Math.round(textbin.sumx / textbin.sum); + textbin.midy = Math.round(textbin.sumy / textbin.sum); + } else { + textbin.midx = Math.round(funcs.grx((bin.fXmin + bin.fXmax)/2)); + textbin.midy = Math.round(funcs.gry((bin.fYmin + bin.fYmax)/2)); + } - if (textbin.sum > 0) { - textbin.midx = Math.round(textbin.sumx / textbin.sum); - textbin.midy = Math.round(textbin.sumy / textbin.sum); - } else { - textbin.midx = Math.round(funcs.grx((bin.fXmin + bin.fXmax)/2)); - textbin.midy = Math.round(funcs.gry((bin.fYmin + bin.fYmax)/2)); - } + let text; - let text; + if (!this.options.TextKind) + text = (Math.round(bin.fContent) === bin.fContent) ? bin.fContent.toString() : floatToString(bin.fContent, gStyle.fPaintTextFormat); + else { + text = bin.fPoly?.fName; + if (!text || (text === 'Graph')) + text = bin.fNumber.toString(); + } - if (!this.options.TextKind) - text = (Math.round(bin.fContent) === bin.fContent) ? bin.fContent.toString() : floatToString(bin.fContent, gStyle.fPaintTextFormat); - else { - text = bin.fPoly?.fName; - if (!text || (text === 'Graph')) - text = bin.fNumber.toString(); + this.drawText({ align: 22, x: textbin.midx, y: textbin.midy, rotate, text, color, latex: 0, draw_g: text_g }); } - this.drawText({ align: 22, x: textbin.midx, y: textbin.midy, rotate, text, color, latex: 0, draw_g: text_g }); - } - - pr = this.finishTextDrawing(text_g, true); + return this.finishTextDrawing(text_g, true); + }); } return pr.then(() => { return { poly: true }; }); @@ -77722,59 +77724,56 @@ let TH2Painter$2 = class TH2Painter extends THistPainter { rotate = -1*this.options.TextAngle, draw_g = this.draw_g.append('svg:g').attr('class', 'th2_text'), show_err = (this.options.TextKind === 'E'), - latex = (show_err && !this.options.TextLine) ? 1 : 0; - let x, y, width, height, - text_size = 20, text_offset = 0; + latex = (show_err && !this.options.TextLine) ? 1 : 0, + text_offset = histo.fBarOffset*1e-3, + text_size = ((histo.fMarkerSize === 1) || !rotate) ? 20 : Math.round(0.02*histo.fMarkerSize*this.getFramePainter().getFrameHeight()); if (!handle) handle = this.prepareDraw({ rounding: false }); - if ((histo.fMarkerSize !== 1) && rotate) - text_size = Math.round(0.02*histo.fMarkerSize*this.getFramePainter().getFrameHeight()); - - if (histo.fBarOffset !== 0) text_offset = histo.fBarOffset*1e-3; + return this.startTextDrawingAsync(42, text_size, draw_g, text_size).then(() => { + for (let i = handle.i1; i < handle.i2; ++i) { + const binw = handle.grx[i+1] - handle.grx[i]; + for (let j = handle.j1; j < handle.j2; ++j) { + const binz = histo.getBinContent(i + 1, j + 1); + if ((binz === 0) && !this.options.ShowEmpty) continue; - this.startTextDrawing(42, text_size, draw_g, text_size); + if (test_cutg && !test_cutg.IsInside(histo.fXaxis.GetBinCoord(i + 0.5), + histo.fYaxis.GetBinCoord(j + 0.5))) continue; - for (let i = handle.i1; i < handle.i2; ++i) { - const binw = handle.grx[i+1] - handle.grx[i]; - for (let j = handle.j1; j < handle.j2; ++j) { - const binz = histo.getBinContent(i+1, j+1); - if ((binz === 0) && !this.options.ShowEmpty) continue; + const binh = handle.gry[j] - handle.gry[j+1]; - if (test_cutg && !test_cutg.IsInside(histo.fXaxis.GetBinCoord(i + 0.5), - histo.fYaxis.GetBinCoord(j + 0.5))) continue; + let text = (binz === Math.round(binz)) ? binz.toString() : floatToString(binz, gStyle.fPaintTextFormat); - const binh = handle.gry[j] - handle.gry[j+1]; + if (show_err) { + const errz = histo.getBinError(histo.getBin(i+1, j+1)), + lble = (errz === Math.round(errz)) ? errz.toString() : floatToString(errz, gStyle.fPaintTextFormat); + if (this.options.TextLine) + text += '\xB1' + lble; + else + text = `#splitline{${text}}{#pm${lble}}`; + } - let text = (binz === Math.round(binz)) ? binz.toString() : floatToString(binz, gStyle.fPaintTextFormat); + let x, y, width, height; - if (show_err) { - const errz = histo.getBinError(histo.getBin(i+1, j+1)), - lble = (errz === Math.round(errz)) ? errz.toString() : floatToString(errz, gStyle.fPaintTextFormat); - if (this.options.TextLine) - text += '\xB1' + lble; - else - text = `#splitline{${text}}{#pm${lble}}`; - } + if (rotate) { + x = Math.round(handle.grx[i] + binw*0.5); + y = Math.round(handle.gry[j+1] + binh*(0.5 + text_offset)); + width = height = 0; + } else { + x = Math.round(handle.grx[i] + binw*0.1); + y = Math.round(handle.gry[j+1] + binh*(0.1 + text_offset)); + width = Math.round(binw*0.8); + height = Math.round(binh*0.8); + } - if (rotate) { - x = Math.round(handle.grx[i] + binw*0.5); - y = Math.round(handle.gry[j+1] + binh*(0.5 + text_offset)); - width = height = 0; - } else { - x = Math.round(handle.grx[i] + binw*0.1); - y = Math.round(handle.gry[j+1] + binh*(0.1 + text_offset)); - width = Math.round(binw*0.8); - height = Math.round(binh*0.8); + this.drawText({ align: 22, x, y, width, height, rotate, text, color, latex, draw_g }); } - - this.drawText({ align: 22, x, y, width, height, rotate, text, color, latex, draw_g }); } - } - handle.hide_only_zeros = true; // text drawing suppress only zeros + handle.hide_only_zeros = true; // text drawing suppress only zeros - return this.finishTextDrawing(draw_g, true).then(() => handle); + return this.finishTextDrawing(draw_g, true); + }).then(() => handle); } /** @summary Draw TH2 bins as arrows */ @@ -78611,7 +78610,7 @@ let TH2Painter$2 = class TH2Painter extends THistPainter { } /** @summary Draw TH2 in circular mode */ - drawBinsCircular() { + async drawBinsCircular() { this.getFrameSvg().style('display', 'none'); this._hide_frame = true; @@ -78637,74 +78636,74 @@ let TH2Painter$2 = class TH2Painter extends THistPainter { const nbins = Math.min(this.nbinsx, this.nbinsy); - this.startTextDrawing(42, text_size, this.draw_g); - - const pnts = []; + return this.startTextDrawingAsync(42, text_size, this.draw_g).then(() => { + const pnts = []; - for (let n = 0; n < nbins; n++) { - const a = (0.5 - n/nbins)*Math.PI*2, - cx = Math.round((0.9*rect.width/2 - 2*circle_size) * Math.cos(a)), - cy = Math.round((0.9*rect.height/2 - 2*circle_size) * Math.sin(a)), - x = Math.round(0.9*rect.width/2 * Math.cos(a)), - y = Math.round(0.9*rect.height/2 * Math.sin(a)), - color = palette?.calcColor(n, nbins) ?? 'black'; - let rotate = Math.round(a/Math.PI*180), align = 12; + for (let n = 0; n < nbins; n++) { + const a = (0.5 - n/nbins)*Math.PI*2, + cx = Math.round((0.9*rect.width/2 - 2*circle_size) * Math.cos(a)), + cy = Math.round((0.9*rect.height/2 - 2*circle_size) * Math.sin(a)), + x = Math.round(0.9*rect.width/2 * Math.cos(a)), + y = Math.round(0.9*rect.height/2 * Math.sin(a)), + color = palette?.calcColor(n, nbins) ?? 'black'; + let rotate = Math.round(a/Math.PI*180), align = 12; - pnts.push({ x: cx, y: cy, a, color }); // remember points coordinates + pnts.push({ x: cx, y: cy, a, color }); // remember points coordinates - if ((rotate < -90) || (rotate > 90)) { rotate += 180; align = 32; } + if ((rotate < -90) || (rotate > 90)) { rotate += 180; align = 32; } - const s2 = Math.round(text_size/2), s1 = 2*s2; + const s2 = Math.round(text_size/2), s1 = 2*s2; - this.draw_g.append('path') - .attr('d', `M${cx-s2},${cy} a${s2},${s2},0,1,0,${s1},0a${s2},${s2},0,1,0,${-s1},0z`) - .style('stroke', color) - .style('fill', 'none'); + this.draw_g.append('path') + .attr('d', `M${cx-s2},${cy} a${s2},${s2},0,1,0,${s1},0a${s2},${s2},0,1,0,${-s1},0z`) + .style('stroke', color) + .style('fill', 'none'); - this.drawText({ align, rotate, x, y, text: getBinLabel(n) }); - } + this.drawText({ align, rotate, x, y, text: getBinLabel(n) }); + } - const max_width = circle_size/2; - let max_value = 0, min_value = 0; - if (this.options.Circular > 11) { - for (let i = 0; i < nbins - 1; ++i) { - for (let j = i+1; j < nbins; ++j) { - const cont = hist.getBinContent(i+1, j+1); - if (cont > 0) { - max_value = Math.max(max_value, cont); - if (!min_value || (cont < min_value)) min_value = cont; - } + const max_width = circle_size/2; + let max_value = 0, min_value = 0; + if (this.options.Circular > 11) { + for (let i = 0; i < nbins - 1; ++i) { + for (let j = i+1; j < nbins; ++j) { + const cont = hist.getBinContent(i+1, j+1); + if (cont > 0) { + max_value = Math.max(max_value, cont); + if (!min_value || (cont < min_value)) min_value = cont; + } + } } } - } - for (let i = 0; i < nbins-1; ++i) { - const pi = pnts[i]; - let path = ''; + for (let i = 0; i < nbins-1; ++i) { + const pi = pnts[i]; + let path = ''; - for (let j = i+1; j < nbins; ++j) { - const cont = hist.getBinContent(i+1, j+1); - if (cont <= 0) continue; + for (let j = i+1; j < nbins; ++j) { + const cont = hist.getBinContent(i+1, j+1); + if (cont <= 0) continue; - const pj = pnts[j], - a = (pi.a + pj.a)/2, - qr = 0.5*(1-Math.abs(pi.a - pj.a)/Math.PI), // how far Q point will be away from center - qx = Math.round(qr*rect.width/2 * Math.cos(a)), - qy = Math.round(qr*rect.height/2 * Math.sin(a)); + const pj = pnts[j], + a = (pi.a + pj.a)/2, + qr = 0.5*(1-Math.abs(pi.a - pj.a)/Math.PI), // how far Q point will be away from center + qx = Math.round(qr*rect.width/2 * Math.cos(a)), + qy = Math.round(qr*rect.height/2 * Math.sin(a)); - path += `M${pi.x},${pi.y}Q${qx},${qy},${pj.x},${pj.y}`; + path += `M${pi.x},${pi.y}Q${qx},${qy},${pj.x},${pj.y}`; - if ((this.options.Circular > 11) && (max_value > min_value)) { - const width = Math.round((cont - min_value) / (max_value - min_value) * (max_width - 1) + 1); - this.draw_g.append('path').attr('d', path).style('stroke', pi.color).style('stroke-width', width).style('fill', 'none'); - path = ''; + if ((this.options.Circular > 11) && (max_value > min_value)) { + const width = Math.round((cont - min_value) / (max_value - min_value) * (max_width - 1) + 1); + this.draw_g.append('path').attr('d', path).style('stroke', pi.color).style('stroke-width', width).style('fill', 'none'); + path = ''; + } } + if (path) + this.draw_g.append('path').attr('d', path).style('stroke', pi.color).style('fill', 'none'); } - if (path) - this.draw_g.append('path').attr('d', path).style('stroke', pi.color).style('fill', 'none'); - } - return this.finishTextDrawing(); + return this.finishTextDrawing(); + }); } /** @summary Draw histogram bins as chord diagram */ @@ -82045,12 +82044,11 @@ let TH1Painter$2 = class TH1Painter extends THistPainter { async drawBars(funcs, height) { const left = this.getSelectIndex('x', 'left', -1), right = this.getSelectIndex('x', 'right', 1), - histo = this.getHisto(), xaxis = histo.fXaxis, + histo = this.getHisto(), + xaxis = histo.fXaxis, show_text = this.options.Text; let text_col, text_angle, text_size, - i, x1, x2, grx1, grx2, y, gry1, w, - bars = '', barsl = '', barsr = '', - side = (this.options.BarStyle > 10) ? this.options.BarStyle % 10 : 0; + side = (this.options.BarStyle > 10) ? this.options.BarStyle % 10 : 0, pr = Promise.resolve(); if (side > 4) side = 4; const gry2 = this.getBarBaseline(funcs, height); @@ -82063,77 +82061,81 @@ let TH1Painter$2 = class TH1Painter extends THistPainter { if ((histo.fMarkerSize !== 1) && text_angle) text_size = 0.02*height*histo.fMarkerSize; - this.startTextDrawing(42, text_size, this.draw_g, text_size); + pr = this.startTextDrawingAsync(42, text_size, this.draw_g, text_size); } - for (i = left; i < right; ++i) { - x1 = xaxis.GetBinLowEdge(i+1); - x2 = xaxis.GetBinLowEdge(i+2); + return pr.then(() => { + let bars = '', barsl = '', barsr = ''; - if (funcs.logx && (x2 <= 0)) continue; + for (let i = left; i < right; ++i) { + const x1 = xaxis.GetBinLowEdge(i + 1), + x2 = xaxis.GetBinLowEdge(i + 2); - grx1 = Math.round(funcs.grx(x1)); - grx2 = Math.round(funcs.grx(x2)); + if (funcs.logx && (x2 <= 0)) continue; - y = histo.getBinContent(i+1); - if (funcs.logy && (y < funcs.scale_ymin)) continue; - gry1 = Math.round(funcs.gry(y)); + let grx1 = Math.round(funcs.grx(x1)), + grx2 = Math.round(funcs.grx(x2)), + w = grx2 - grx1; + const y = histo.getBinContent(i+1); - w = grx2 - grx1; - grx1 += Math.round(histo.fBarOffset/1000*w); - w = Math.round(histo.fBarWidth/1000*w); + if (funcs.logy && (y < funcs.scale_ymin)) continue; + const gry1 = Math.round(funcs.gry(y)); - if (funcs.swap_xy) - bars += `M${gry2},${grx1}h${gry1-gry2}v${w}h${gry2-gry1}z`; - else - bars += `M${grx1},${gry1}h${w}v${gry2-gry1}h${-w}z`; + grx1 += Math.round(histo.fBarOffset/1000*w); + w = Math.round(histo.fBarWidth/1000*w); - if (side > 0) { - grx2 = grx1 + w; - w = Math.round(w * side / 10); - if (funcs.swap_xy) { - barsl += `M${gry2},${grx1}h${gry1-gry2}v${w}h${gry2-gry1}z`; - barsr += `M${gry2},${grx2}h${gry1-gry2}v${-w}h${gry2-gry1}z`; - } else { - barsl += `M${grx1},${gry1}h${w}v${gry2-gry1}h${-w}z`; - barsr += `M${grx2},${gry1}h${-w}v${gry2-gry1}h${w}z`; + if (funcs.swap_xy) + bars += `M${gry2},${grx1}h${gry1-gry2}v${w}h${gry2-gry1}z`; + else + bars += `M${grx1},${gry1}h${w}v${gry2-gry1}h${-w}z`; + + if (side > 0) { + grx2 = grx1 + w; + w = Math.round(w * side / 10); + if (funcs.swap_xy) { + barsl += `M${gry2},${grx1}h${gry1-gry2}v${w}h${gry2-gry1}z`; + barsr += `M${gry2},${grx2}h${gry1-gry2}v${-w}h${gry2-gry1}z`; + } else { + barsl += `M${grx1},${gry1}h${w}v${gry2-gry1}h${-w}z`; + barsr += `M${grx2},${gry1}h${-w}v${gry2-gry1}h${w}z`; + } } - } - if (show_text && y) { - const text = (y === Math.round(y)) ? y.toString() : floatToString(y, gStyle.fPaintTextFormat); + if (show_text && y) { + const text = (y === Math.round(y)) ? y.toString() : floatToString(y, gStyle.fPaintTextFormat); - if (funcs.swap_xy) - this.drawText({ align: 12, x: Math.round(gry1 + text_size/2), y: Math.round(grx1+0.1), height: Math.round(w*0.8), text, color: text_col, latex: 0 }); - else if (text_angle) - this.drawText({ align: 12, x: grx1+w/2, y: Math.round(gry1 - 2 - text_size/5), width: 0, height: 0, rotate: text_angle, text, color: text_col, latex: 0 }); - else - this.drawText({ align: 22, x: Math.round(grx1 + w*0.1), y: Math.round(gry1 - 2 - text_size), width: Math.round(w*0.8), height: text_size, text, color: text_col, latex: 0 }); + if (funcs.swap_xy) + this.drawText({ align: 12, x: Math.round(gry1 + text_size/2), y: Math.round(grx1+0.1), height: Math.round(w*0.8), text, color: text_col, latex: 0 }); + else if (text_angle) + this.drawText({ align: 12, x: grx1+w/2, y: Math.round(gry1 - 2 - text_size/5), width: 0, height: 0, rotate: text_angle, text, color: text_col, latex: 0 }); + else + this.drawText({ align: 22, x: Math.round(grx1 + w*0.1), y: Math.round(gry1 - 2 - text_size), width: Math.round(w*0.8), height: text_size, text, color: text_col, latex: 0 }); + } } - } - if (bars) { - this.draw_g.append('svg:path') - .attr('d', bars) - .call(this.fillatt.func); - } - - if (barsl) { - this.draw_g.append('svg:path') - .attr('d', barsl) - .call(this.fillatt.func) - .style('fill', rgb(this.fillatt.color).brighter(0.5).formatRgb()); - } + if (bars) { + this.draw_g.append('svg:path') + .attr('d', bars) + .call(this.fillatt.func); + } - if (barsr) { - this.draw_g.append('svg:path') - .attr('d', barsr) + if (barsl) { + this.draw_g.append('svg:path') + .attr('d', barsl) .call(this.fillatt.func) - .style('fill', rgb(this.fillatt.color).darker(0.5).formatRgb()); - } + .style('fill', rgb(this.fillatt.color).brighter(0.5).formatRgb()); + } - if (show_text) - return this.finishTextDrawing(); + if (barsr) { + this.draw_g.append('svg:path') + .attr('d', barsr) + .call(this.fillatt.func) + .style('fill', rgb(this.fillatt.color).darker(0.5).formatRgb()); + } + + if (show_text) + return this.finishTextDrawing(); + }); } /** @summary Draw histogram as filled errors */ @@ -82165,7 +82167,7 @@ let TH1Painter$2 = class TH1Painter extends THistPainter { /** @summary Draw TH1 as hist/line/curve * @return Promise or scalar value */ - drawNormal(funcs, width, height) { + async drawNormal(funcs, width, height) { const left = this.getSelectIndex('x', 'left', -1), right = this.getSelectIndex('x', 'right', 2), histo = this.getHisto(), @@ -82185,7 +82187,8 @@ let TH1Painter$2 = class TH1Painter extends THistPainter { hints_err = null, hints_marker = null, hsz = 5, do_marker = false, do_err = false, dend = 0, dlw = 0, my, yerr1, yerr2, bincont, binerr, mx1, mx2, midx, lx, ly, mmx1, mmx2, - text_col, text_angle, text_size; + text_col, text_angle, text_size, + pr = Promise.resolve(); if (show_errors && !show_markers && (histo.fMarkerStyle > 1)) show_markers = true; @@ -82224,7 +82227,10 @@ let TH1Painter$2 = class TH1Painter extends THistPainter { const draw_markers = show_errors || show_markers, draw_any_but_hist = draw_markers || show_text || show_line || show_curve, - draw_hist = this.options.Hist && (!this.lineatt.empty() || !this.fillatt.empty()); + draw_hist = this.options.Hist && (!this.lineatt.empty() || !this.fillatt.empty()), + // if there are too many points, exclude many vertical drawings at the same X position + // instead define min and max value and made min-max drawing + use_minmax = draw_any_but_hist || ((right - left) > 3*width); if (!draw_hist && !draw_any_but_hist) return this.removeG(); @@ -82245,282 +82251,280 @@ let TH1Painter$2 = class TH1Painter extends THistPainter { } } - this.startTextDrawing(42, text_size, this.draw_g, text_size); + pr = this.startTextDrawingAsync(42, text_size, this.draw_g, text_size); } - // if there are too many points, exclude many vertical drawings at the same X position - // instead define min and max value and made min-max drawing - const use_minmax = draw_any_but_hist || ((right - left) > 3*width), - - // just to get correct values for the specified bin - extract_bin = bin => { - bincont = histo.getBinContent(bin+1); - if (exclude_zero && (bincont === 0)) return false; - mx1 = Math.round(funcs.grx(xaxis.GetBinLowEdge(bin+1))); - mx2 = Math.round(funcs.grx(xaxis.GetBinLowEdge(bin+2))); - midx = Math.round((mx1 + mx2) / 2); - if (startmidx === undefined) startmidx = midx; - my = Math.round(funcs.gry(bincont)); - if (show_errors) { - binerr = histo.getBinError(bin+1); - yerr1 = Math.round(my - funcs.gry(bincont + binerr)); // up - yerr2 = Math.round(funcs.gry(bincont - binerr) - my); // down - } else - yerr1 = yerr2 = 20; + return pr.then(() => { + // just to get correct values for the specified bin + const extract_bin = bin => { + bincont = histo.getBinContent(bin+1); + if (exclude_zero && (bincont === 0)) return false; + mx1 = Math.round(funcs.grx(xaxis.GetBinLowEdge(bin+1))); + mx2 = Math.round(funcs.grx(xaxis.GetBinLowEdge(bin+2))); + midx = Math.round((mx1 + mx2) / 2); + if (startmidx === undefined) startmidx = midx; + my = Math.round(funcs.gry(bincont)); + if (show_errors) { + binerr = histo.getBinError(bin+1); + yerr1 = Math.round(my - funcs.gry(bincont + binerr)); // up + yerr2 = Math.round(funcs.gry(bincont - binerr) - my); // down + } else + yerr1 = yerr2 = 20; - return true; - }, draw_errbin = () => { - let edx = 5; - if (this.options.errorX > 0) { - edx = Math.round((mx2 - mx1) * this.options.errorX); - mmx1 = midx - edx; - mmx2 = midx + edx; + return true; + }, draw_errbin = () => { + let edx = 5; + if (this.options.errorX > 0) { + edx = Math.round((mx2 - mx1) * this.options.errorX); + mmx1 = midx - edx; + mmx2 = midx + edx; + if (this.options.ErrorKind === 1) + path_err += `M${mmx1+dend},${my-dlw}v${2*dlw}m0,-${dlw}h${mmx2-mmx1-2*dend}m0,-${dlw}v${2*dlw}`; + else + path_err += `M${mmx1+dend},${my}h${mmx2-mmx1-2*dend}`; + } if (this.options.ErrorKind === 1) - path_err += `M${mmx1+dend},${my-dlw}v${2*dlw}m0,-${dlw}h${mmx2-mmx1-2*dend}m0,-${dlw}v${2*dlw}`; + path_err += `M${midx-dlw},${my-yerr1+dend}h${2*dlw}m${-dlw},0v${yerr1+yerr2-2*dend}m${-dlw},0h${2*dlw}`; else - path_err += `M${mmx1+dend},${my}h${mmx2-mmx1-2*dend}`; - } - if (this.options.ErrorKind === 1) - path_err += `M${midx-dlw},${my-yerr1+dend}h${2*dlw}m${-dlw},0v${yerr1+yerr2-2*dend}m${-dlw},0h${2*dlw}`; - else - path_err += `M${midx},${my-yerr1+dend}v${yerr1+yerr2-2*dend}`; - if (hints_err !== null) { - const he1 = Math.max(yerr1, 5), he2 = Math.max(yerr2, 5); - hints_err += `M${midx-edx},${my-he1}h${2*edx}v${he1+he2}h${-2*edx}z`; - } - }, draw_marker = () => { - if (funcs.swap_xy) { - path_marker += this.markeratt.create(my, midx); - if (hints_marker !== null) - hints_marker += `M${my-hsz},${midx-hsz}v${2*hsz}h${2*hsz}v${-2*hsz}z`; - } else { - path_marker += this.markeratt.create(midx, my); - if (hints_marker !== null) - hints_marker += `M${midx-hsz},${my-hsz}h${2*hsz}v${2*hsz}h${-2*hsz}z`; - } - }, draw_bin = bin => { - if (extract_bin(bin)) { - if (show_text) { - const cont = text_profile ? histo.fBinEntries[bin+1] : bincont; - - if (cont !== 0) { - const arg = text_angle - ? { align: 12, x: midx, y: Math.round(my - 2 - text_size / 5), width: 0, height: 0, rotate: text_angle } - : { align: 22, x: Math.round(mx1 + (mx2 - mx1) * 0.1), y: Math.round(my - 2 - text_size), width: Math.round((mx2 - mx1) * 0.8), height: text_size }; - arg.text = (cont === Math.round(cont)) ? cont.toString() : floatToString(cont, gStyle.fPaintTextFormat); - arg.color = text_col; - arg.latex = 0; - if (funcs.swap_xy) { - arg.x = my; - arg.y = Math.round(midx - text_size/2); + path_err += `M${midx},${my-yerr1+dend}v${yerr1+yerr2-2*dend}`; + if (hints_err !== null) { + const he1 = Math.max(yerr1, 5), he2 = Math.max(yerr2, 5); + hints_err += `M${midx-edx},${my-he1}h${2*edx}v${he1+he2}h${-2*edx}z`; + } + }, draw_marker = () => { + if (funcs.swap_xy) { + path_marker += this.markeratt.create(my, midx); + if (hints_marker !== null) + hints_marker += `M${my-hsz},${midx-hsz}v${2*hsz}h${2*hsz}v${-2*hsz}z`; + } else { + path_marker += this.markeratt.create(midx, my); + if (hints_marker !== null) + hints_marker += `M${midx-hsz},${my-hsz}h${2*hsz}v${2*hsz}h${-2*hsz}z`; + } + }, draw_bin = bin => { + if (extract_bin(bin)) { + if (show_text) { + const cont = text_profile ? histo.fBinEntries[bin+1] : bincont; + + if (cont !== 0) { + const arg = text_angle + ? { align: 12, x: midx, y: Math.round(my - 2 - text_size / 5), width: 0, height: 0, rotate: text_angle } + : { align: 22, x: Math.round(mx1 + (mx2 - mx1) * 0.1), y: Math.round(my - 2 - text_size), width: Math.round((mx2 - mx1) * 0.8), height: text_size }; + arg.text = (cont === Math.round(cont)) ? cont.toString() : floatToString(cont, gStyle.fPaintTextFormat); + arg.color = text_col; + arg.latex = 0; + if (funcs.swap_xy) { + arg.x = my; + arg.y = Math.round(midx - text_size/2); + } + this.drawText(arg); } - this.drawText(arg); } - } - if (show_line) { - if (funcs.swap_xy) - path_line += (path_line ? 'L' : 'M') + `${my},${midx}`; // no optimization - else if (path_line.length === 0) - path_line = `M${midx},${my}`; - else if (lx === midx) - path_line += `v${my-ly}`; - else if (ly === my) - path_line += `h${midx-lx}`; - else - path_line += `l${midx-lx},${my-ly}`; - lx = midx; ly = my; - } else if (show_curve) - grpnts.push({ grx: (mx1 + mx2) / 2, gry: funcs.gry(bincont) }); - - if (draw_markers) { - if ((my >= -yerr1) && (my <= height + yerr2)) { - if (path_fill !== null) - path_fill += `M${mx1},${my-yerr1}h${mx2-mx1}v${yerr1+yerr2+1}h${mx1-mx2}z`; - if ((path_marker !== null) && do_marker) - draw_marker(); - if ((path_err !== null) && do_err) - draw_errbin(); + if (show_line) { + if (funcs.swap_xy) + path_line += (path_line ? 'L' : 'M') + `${my},${midx}`; // no optimization + else if (path_line.length === 0) + path_line = `M${midx},${my}`; + else if (lx === midx) + path_line += `v${my-ly}`; + else if (ly === my) + path_line += `h${midx-lx}`; + else + path_line += `l${midx-lx},${my-ly}`; + lx = midx; ly = my; + } else if (show_curve) + grpnts.push({ grx: (mx1 + mx2) / 2, gry: funcs.gry(bincont) }); + + if (draw_markers) { + if ((my >= -yerr1) && (my <= height + yerr2)) { + if (path_fill !== null) + path_fill += `M${mx1},${my-yerr1}h${mx2-mx1}v${yerr1+yerr2+1}h${mx1-mx2}z`; + if ((path_marker !== null) && do_marker) + draw_marker(); + if ((path_err !== null) && do_err) + draw_errbin(); + } } } - } - }; + }; - // check if we should draw markers or error marks directly, skipping optimization - if (do_marker || do_err) { - if (!settings.OptimizeDraw || ((right-left < 50000) && (settings.OptimizeDraw === 1))) { - for (i = left; i < right; ++i) { - if (extract_bin(i)) { - if (path_marker !== null) - draw_marker(); - if (path_err !== null) - draw_errbin(); + // check if we should draw markers or error marks directly, skipping optimization + if (do_marker || do_err) { + if (!settings.OptimizeDraw || ((right-left < 50000) && (settings.OptimizeDraw === 1))) { + for (i = left; i < right; ++i) { + if (extract_bin(i)) { + if (path_marker !== null) + draw_marker(); + if (path_err !== null) + draw_errbin(); + } } + do_err = do_marker = false; } - do_err = do_marker = false; } - } - for (i = left; i <= right; ++i) { - x = xaxis.GetBinLowEdge(i+1); + for (i = left; i <= right; ++i) { + x = xaxis.GetBinLowEdge(i+1); - if (this.logx && (x <= 0)) continue; + if (this.logx && (x <= 0)) continue; - grx = Math.round(funcs.grx(x)); + grx = Math.round(funcs.grx(x)); - lastbin = (i === right); + lastbin = (i === right); - if (lastbin && (left curry_max) - bestimin = i; - - curry_min = Math.min(curry_min, gry); - curry_max = Math.max(curry_max, gry); - curry = gry; - } else { - if (draw_any_but_hist) { - if (bestimin === bestimax) - draw_bin(bestimin); - else if (bestimin < bestimax) { - draw_bin(bestimin); draw_bin(bestimax); - } else { - draw_bin(bestimax); draw_bin(bestimin); + if (lastbin && (left curry_max) + bestimin = i; + + curry_min = Math.min(curry_min, gry); + curry_max = Math.max(curry_max, gry); + curry = gry; + } else { + if (draw_any_but_hist) { + if (bestimin === bestimax) + draw_bin(bestimin); + else if (bestimin < bestimax) { + draw_bin(bestimin); draw_bin(bestimax); + } else { + draw_bin(bestimax); draw_bin(bestimin); + } } - } - // when several points at same X differs, need complete logic - if (draw_hist && ((curry_min !== curry_max) || (prevy !== curry_min))) { - if (prevx !== currx) - res += 'h'+(currx-prevx); + // when several points at same X differs, need complete logic + if (draw_hist && ((curry_min !== curry_max) || (prevy !== curry_min))) { + if (prevx !== currx) + res += 'h'+(currx-prevx); - if (curry === curry_min) { - if (curry_max !== prevy) - res += 'v' + (curry_max - prevy); - if (curry_min !== curry_max) - res += 'v' + (curry_min - curry_max); - } else { - if (curry_min !== prevy) - res += 'v' + (curry_min - prevy); - if (curry_max !== curry_min) - res += 'v' + (curry_max - curry_min); - if (curry !== curry_max) - res += 'v' + (curry - curry_max); - } + if (curry === curry_min) { + if (curry_max !== prevy) + res += 'v' + (curry_max - prevy); + if (curry_min !== curry_max) + res += 'v' + (curry_min - curry_max); + } else { + if (curry_min !== prevy) + res += 'v' + (curry_min - prevy); + if (curry_max !== curry_min) + res += 'v' + (curry_max - curry_min); + if (curry !== curry_max) + res += 'v' + (curry - curry_max); + } - prevx = currx; - prevy = curry; - } + prevx = currx; + prevy = curry; + } - if (lastbin && (prevx !== grx)) - res += 'h' + (grx-prevx); + if (lastbin && (prevx !== grx)) + res += 'h' + (grx-prevx); - bestimin = bestimax = i; - curry_min = curry_max = curry = gry; + bestimin = bestimax = i; + curry_min = curry_max = curry = gry; + currx = grx; + } + // end of use_minmax + } else if ((gry !== curry) || lastbin) { + if (grx !== currx) res += `h${grx-currx}`; + if (gry !== curry) res += `v${gry-curry}`; + curry = gry; currx = grx; } - // end of use_minmax - } else if ((gry !== curry) || lastbin) { - if (grx !== currx) res += `h${grx-currx}`; - if (gry !== curry) res += `v${gry-curry}`; - curry = gry; - currx = grx; - } - } - - const fill_for_interactive = want_tooltip && this.fillatt.empty() && draw_hist && !draw_markers && !show_line && !show_curve, - add_hist = () => { - this.draw_g.append('svg:path') - .attr('d', res + ((!this.fillatt.empty() || fill_for_interactive) ? close_path : '')) - .style('stroke-linejoin', 'miter') - .call(this.lineatt.func) - .call(this.fillatt.func); - }; - let h0 = height + 3; - if (!fill_for_interactive) { - const gry0 = Math.round(funcs.gry(0)); - if (gry0 <= 0) - h0 = -3; - else if (gry0 < height) - h0 = gry0; - } - const close_path = `L${currx},${h0}H${startx}Z`; - - if (res && draw_hist && !this.fillatt.empty()) { - add_hist(); - res = ''; - } - - if (draw_markers || show_line || show_curve) { - if (!path_line && grpnts.length) { - if (funcs.swap_xy) - grpnts.forEach(pnt => { const d = pnt.grx; pnt.grx = pnt.gry; pnt.gry = d; }); - path_line = buildSvgCurve(grpnts); } - if (path_fill) { + const fill_for_interactive = want_tooltip && this.fillatt.empty() && draw_hist && !draw_markers && !show_line && !show_curve, + add_hist = () => { this.draw_g.append('svg:path') - .attr('d', path_fill) - .call(this.fillatt.func); - } else if (path_line && !this.fillatt.empty() && !draw_hist) { - this.draw_g.append('svg:path') - .attr('d', path_line + `L${midx},${h0}H${startmidx}Z`) - .call(this.fillatt.func); + .attr('d', res + ((!this.fillatt.empty() || fill_for_interactive) ? close_path : '')) + .style('stroke-linejoin', 'miter') + .call(this.lineatt.func) + .call(this.fillatt.func); + }; + let h0 = height + 3; + if (!fill_for_interactive) { + const gry0 = Math.round(funcs.gry(0)); + if (gry0 <= 0) + h0 = -3; + else if (gry0 < height) + h0 = gry0; } + const close_path = `L${currx},${h0}H${startx}Z`; - if (path_err) { - this.draw_g.append('svg:path') - .attr('d', path_err) - .call(this.lineatt.func); + if (res && draw_hist && !this.fillatt.empty()) { + add_hist(); + res = ''; } - if (hints_err) { - this.draw_g.append('svg:path') - .attr('d', hints_err) - .style('fill', 'none') - .style('pointer-events', this.isBatchMode() ? null : 'visibleFill'); - } + if (draw_markers || show_line || show_curve) { + if (!path_line && grpnts.length) { + if (funcs.swap_xy) + grpnts.forEach(pnt => { const d = pnt.grx; pnt.grx = pnt.gry; pnt.gry = d; }); + path_line = buildSvgCurve(grpnts); + } - if (path_line) { - this.draw_g.append('svg:path') - .attr('d', path_line) - .style('fill', 'none') - .call(this.lineatt.func); - } + if (path_fill) { + this.draw_g.append('svg:path') + .attr('d', path_fill) + .call(this.fillatt.func); + } else if (path_line && !this.fillatt.empty() && !draw_hist) { + this.draw_g.append('svg:path') + .attr('d', path_line + `L${midx},${h0}H${startmidx}Z`) + .call(this.fillatt.func); + } - if (path_marker) { - this.draw_g.append('svg:path') - .attr('d', path_marker) - .call(this.markeratt.func); - } + if (path_err) { + this.draw_g.append('svg:path') + .attr('d', path_err) + .call(this.lineatt.func); + } - if (hints_marker) { - this.draw_g.append('svg:path') - .attr('d', hints_marker) - .style('fill', 'none') - .style('pointer-events', this.isBatchMode() ? null : 'visibleFill'); + if (hints_err) { + this.draw_g.append('svg:path') + .attr('d', hints_err) + .style('fill', 'none') + .style('pointer-events', this.isBatchMode() ? null : 'visibleFill'); + } + + if (path_line) { + this.draw_g.append('svg:path') + .attr('d', path_line) + .style('fill', 'none') + .call(this.lineatt.func); + } + + if (path_marker) { + this.draw_g.append('svg:path') + .attr('d', path_marker) + .call(this.markeratt.func); + } + + if (hints_marker) { + this.draw_g.append('svg:path') + .attr('d', hints_marker) + .style('fill', 'none') + .style('pointer-events', this.isBatchMode() ? null : 'visibleFill'); + } } - } - if (res && draw_hist) - add_hist(); + if (res && draw_hist) + add_hist(); - if (show_text) - return this.finishTextDrawing(); + if (show_text) + return this.finishTextDrawing(); + }); } /** @summary Draw TH1 bins in SVG element @@ -151773,8 +151777,9 @@ class TGraphPolargramPainter extends ObjectPainter { } /** @summary Redraw polargram */ - redraw() { - if (!this.isMainPainter()) return; + async redraw() { + if (!this.isMainPainter()) + return; const polar = this.getObject(), rect = this.getPadPainter().getFrameRect(); @@ -151795,8 +151800,12 @@ class TGraphPolargramPainter extends ObjectPainter { this.r = linear().domain([this.scale_rmin, this.scale_rmax]).range([0, this.szx]); this.angle = polar.fAxisAngle || 0; - const ticks = this.r.ticks(5); - let nminor = Math.floor((polar.fNdivRad % 10000) / 100); + const ticks = this.r.ticks(5), + fontsize = Math.round(polar.fPolarTextSize * this.szy * 2); + let nminor = Math.floor((polar.fNdivRad % 10000) / 100), + nmajor = polar.fNdivPol % 100; + if (nmajor !== 3) + nmajor = 8; this.createAttLine({ attr: polar }); if (!this.gridatt) this.gridatt = this.createAttLine({ color: polar.fLineColor, style: 2, width: 1, std: false }); @@ -151823,47 +151832,44 @@ class TGraphPolargramPainter extends ObjectPainter { exclude_last = true; } - this.startTextDrawing(polar.fRadialLabelFont, Math.round(polar.fRadialTextSize * this.szy * 2)); - - for (let n = 0; n < ticks.length; ++n) { - let rx = this.r(ticks[n]), ry = rx/this.szx*this.szy; - this.draw_g.append('ellipse') - .attr('cx', 0) - .attr('cy', 0) - .attr('rx', Math.round(rx)) - .attr('ry', Math.round(ry)) - .style('fill', 'none') - .call(this.lineatt.func); + return this.startTextDrawingAsync(polar.fRadialLabelFont, Math.round(polar.fRadialTextSize * this.szy * 2)).then(() => { + for (let n = 0; n < ticks.length; ++n) { + let rx = this.r(ticks[n]), ry = rx/this.szx*this.szy; + this.draw_g.append('ellipse') + .attr('cx', 0) + .attr('cy', 0) + .attr('rx', Math.round(rx)) + .attr('ry', Math.round(ry)) + .style('fill', 'none') + .call(this.lineatt.func); - if ((n < ticks.length-1) || !exclude_last) { - this.drawText({ align: 23, x: Math.round(rx), y: Math.round(polar.fRadialTextSize * this.szy * 0.5), - text: this.format(ticks[n]), color: this.getColor(polar.fRadialLabelColor), latex: 0 }); - } - - if ((nminor>1) && ((n < ticks.length-1) || !exclude_last)) { - const dr = (ticks[1] - ticks[0]) / nminor; - for (let nn = 1; nn < nminor; ++nn) { - const gridr = ticks[n] + dr*nn; - if (gridr > this.scale_rmax) break; - rx = this.r(gridr); ry = rx/this.szx*this.szy; - this.draw_g.append('ellipse') - .attr('cx', 0) - .attr('cy', 0) - .attr('rx', Math.round(rx)) - .attr('ry', Math.round(ry)) - .style('fill', 'none') - .call(this.gridatt.func); + if ((n < ticks.length-1) || !exclude_last) { + this.drawText({ align: 23, x: Math.round(rx), y: Math.round(polar.fRadialTextSize * this.szy * 0.5), + text: this.format(ticks[n]), color: this.getColor(polar.fRadialLabelColor), latex: 0 }); + } + + if ((nminor>1) && ((n < ticks.length-1) || !exclude_last)) { + const dr = (ticks[1] - ticks[0]) / nminor; + for (let nn = 1; nn < nminor; ++nn) { + const gridr = ticks[n] + dr*nn; + if (gridr > this.scale_rmax) break; + rx = this.r(gridr); ry = rx/this.szx*this.szy; + this.draw_g.append('ellipse') + .attr('cx', 0) + .attr('cy', 0) + .attr('rx', Math.round(rx)) + .attr('ry', Math.round(ry)) + .style('fill', 'none') + .call(this.gridatt.func); + } } } - } - - let nmajor = polar.fNdivPol % 100; - if ((nmajor !== 8) && (nmajor !== 3)) nmajor = 8; - return this.finishTextDrawing().then(() => { - const fontsize = Math.round(polar.fPolarTextSize * this.szy * 2); - this.startTextDrawing(polar.fPolarLabelFont, fontsize); + return this.finishTextDrawing(); + }).then(() => { + return this.startTextDrawingAsync(polar.fPolarLabelFont, fontsize); + }).then(() => { lbls = (nmajor === 8) ? ['0', '#frac{#pi}{4}', '#frac{#pi}{2}', '#frac{3#pi}{4}', '#pi', '#frac{5#pi}{4}', '#frac{3#pi}{2}', '#frac{7#pi}{4}'] : ['0', '#frac{2#pi}{3}', '#frac{4#pi}{3}']; const aligns = [12, 11, 21, 31, 32, 33, 23, 13]; @@ -153791,30 +153797,31 @@ class TWebPaintingPainter extends ObjectPainter { const height = (attr.fTextSize > 1) ? attr.fTextSize : this.getPadPainter().getPadHeight() * attr.fTextSize, group = this.draw_g.append('svg:g'); - let angle = attr.fTextAngle, - txt = arr[k].slice(1); - - if (angle >= 360) angle -= Math.floor(angle/360) * 360; - - this.startTextDrawing(attr.fTextFont, height, group); - if (oper === 'h') { - let res = ''; - for (n = 0; n < txt.length; n += 2) - res += String.fromCharCode(parseInt(txt.slice(n, n+2), 16)); - txt = res; - } - - // todo - correct support of angle - this.drawText({ align: attr.fTextAlign, - x: func.x(obj.fBuf[indx++]), - y: func.y(obj.fBuf[indx++]), - rotate: -angle, - text: txt, - color: getColor(attr.fTextColor), - latex: 0, draw_g: group }); + return this.startTextDrawingAsync(attr.fTextFont, height, group).then(() => { + let text = arr[k].slice(1), + angle = attr.fTextAngle; + if (angle >= 360) + angle -= Math.floor(angle/360) * 360; + + if (oper === 'h') { + let res = ''; + for (n = 0; n < text.length; n += 2) + res += String.fromCharCode(parseInt(text.slice(n, n+2), 16)); + text = res; + } - return this.finishTextDrawing(group).then(() => process(k)); + // todo - correct support of angle + this.drawText({ align: attr.fTextAlign, + x: func.x(obj.fBuf[indx++]), + y: func.y(obj.fBuf[indx++]), + rotate: -angle, + text, + color: getColor(attr.fTextColor), + latex: 0, draw_g: group }); + + return this.finishTextDrawing(group); + }).then(() => process(k)); } continue; } @@ -156765,67 +156772,67 @@ class RAxisPainter extends RObjectPainter { label_g.property('fix_offset', fix_offset); - this.startTextDrawing(this.labelsFont, 'font', label_g); - - for (let nmajor = 0; nmajor < lbl_pos.length; ++nmajor) { - const lbl = this.format(lbl_pos[nmajor], true); - if (lbl === null) continue; + return this.startTextDrawingAsync(this.labelsFont, 'font', label_g).then(() => { + for (let nmajor = 0; nmajor < lbl_pos.length; ++nmajor) { + const lbl = this.format(lbl_pos[nmajor], true); + if (lbl === null) continue; - const arg = { text: lbl, latex: 1, draw_g: label_g }; - let pos = Math.round(this.func(lbl_pos[nmajor])); + const arg = { text: lbl, latex: 1, draw_g: label_g }; + let pos = Math.round(this.func(lbl_pos[nmajor])); - arg.gap_before = (nmajor > 0) ? Math.abs(Math.round(pos - this.func(lbl_pos[nmajor-1]))) : 0; - arg.gap_after = (nmajor < lbl_pos.length-1) ? Math.abs(Math.round(this.func(lbl_pos[nmajor+1])-pos)) : 0; + arg.gap_before = (nmajor > 0) ? Math.abs(Math.round(pos - this.func(lbl_pos[nmajor-1]))) : 0; + arg.gap_after = (nmajor < lbl_pos.length-1) ? Math.abs(Math.round(this.func(lbl_pos[nmajor+1])-pos)) : 0; - if (center_lbls) { - const gap = arg.gap_after || arg.gap_before; - pos = Math.round(pos - (this.vertical ? 0.5*gap : -0.5*gap)); - if (!this.isInsideGrRange(pos, 5)) continue; - } + if (center_lbls) { + const gap = arg.gap_after || arg.gap_before; + pos = Math.round(pos - (this.vertical ? 0.5*gap : -0.5*gap)); + if (!this.isInsideGrRange(pos, 5)) continue; + } - maxtextlen = Math.max(maxtextlen, lbl.length); + maxtextlen = Math.max(maxtextlen, lbl.length); - pos -= this.axis_shift; + pos -= this.axis_shift; - if ((this.startingSize || this.endingSize) && !this.isInsideGrRange(pos, -Math.abs(this.startingSize), -Math.abs(this.endingSize))) continue; + if ((this.startingSize || this.endingSize) && !this.isInsideGrRange(pos, -Math.abs(this.startingSize), -Math.abs(this.endingSize))) continue; - if (this.vertical) { - arg.x = fix_coord; - arg.y = pos; - arg.align = rotate_lbls ? ((side < 0) ? 23 : 20) : ((side < 0) ? 12 : 32); - } else { - arg.x = pos; - arg.y = fix_coord; - arg.align = rotate_lbls ? ((side < 0) ? 12 : 32) : ((side < 0) ? 20 : 23); - if (this.log && !this.noexp && !this.vertical && arg.align === 23) { - arg.align = 21; - arg.y += this.labelsFont.size; + if (this.vertical) { + arg.x = fix_coord; + arg.y = pos; + arg.align = rotate_lbls ? ((side < 0) ? 23 : 20) : ((side < 0) ? 12 : 32); + } else { + arg.x = pos; + arg.y = fix_coord; + arg.align = rotate_lbls ? ((side < 0) ? 12 : 32) : ((side < 0) ? 20 : 23); + if (this.log && !this.noexp && !this.vertical && arg.align === 23) { + arg.align = 21; + arg.y += this.labelsFont.size; + } } - } - arg.post_process = process_drawtext_ready; + arg.post_process = process_drawtext_ready; - this.drawText(arg); + this.drawText(arg); - if (lastpos && (pos !== lastpos) && ((this.vertical && !rotate_lbls) || (!this.vertical && rotate_lbls))) { - const axis_step = Math.abs(pos-lastpos); - textscale = Math.min(textscale, 0.9*axis_step/this.labelsFont.size); - } + if (lastpos && (pos !== lastpos) && ((this.vertical && !rotate_lbls) || (!this.vertical && rotate_lbls))) { + const axis_step = Math.abs(pos-lastpos); + textscale = Math.min(textscale, 0.9*axis_step/this.labelsFont.size); + } - lastpos = pos; - } + lastpos = pos; + } - if (this.order) { - this.drawText({ x: this.vertical ? side*5 : this.getGrRange(5), - y: this.has_obstacle ? fix_coord : (this.vertical ? this.getGrRange(3) : -3*side), - align: this.vertical ? ((side < 0) ? 30 : 10) : ((this.has_obstacle ^ (side < 0)) ? 13 : 10), - latex: 1, - text: '#times' + this.formatExp(10, this.order), - draw_g: label_g }); - } + if (this.order) { + this.drawText({ x: this.vertical ? side*5 : this.getGrRange(5), + y: this.has_obstacle ? fix_coord : (this.vertical ? this.getGrRange(3) : -3*side), + align: this.vertical ? ((side < 0) ? 30 : 10) : ((this.has_obstacle ^ (side < 0)) ? 13 : 10), + latex: 1, + text: '#times' + this.formatExp(10, this.order), + draw_g: label_g }); + } - return this.finishTextDrawing(label_g).then(() => { - if (lbls_tilt) { + return this.finishTextDrawing(label_g); + }).then(() => { + if (lbls_tilt) { label_g.selectAll('text').each(function() { const txt = select(this), tr = txt.attr('transform'); txt.attr('transform', tr + ' rotate(25)').style('text-anchor', 'start'); @@ -156869,34 +156876,35 @@ class RAxisPainter extends RObjectPainter { const title_g = axis_g.append('svg:g').attr('class', 'axis_title'), rotated = this.isTitleRotated(); - let title_shift_x = 0, title_shift_y = 0, title_basepos = 0; - this.startTextDrawing(this.titleFont, 'font', title_g); + return this.startTextDrawingAsync(this.titleFont, 'font', title_g).then(() => { + let title_shift_x = 0, title_shift_y = 0, title_basepos = 0; - this.title_align = this.titleCenter ? 'middle' : (this.titleOpposite ^ (this.isReverseAxis() || rotated) ? 'begin' : 'end'); + this.title_align = this.titleCenter ? 'middle' : (this.titleOpposite ^ (this.isReverseAxis() || rotated) ? 'begin' : 'end'); - if (this.vertical) { - title_basepos = Math.round(-side*(lgaps[side])); - title_shift_x = title_basepos + Math.round(-side*this.titleOffset); - title_shift_y = Math.round(this.titleCenter ? this.gr_range/2 : (this.titleOpposite ? 0 : this.gr_range)); - this.drawText({ align: [this.title_align, ((side < 0) ^ rotated ? 'top' : 'bottom')], - text: this.fTitle, draw_g: title_g }); - } else { - title_shift_x = Math.round(this.titleCenter ? this.gr_range/2 : (this.titleOpposite ? 0 : this.gr_range)); - title_basepos = Math.round(side*lgaps[side]); - title_shift_y = title_basepos + Math.round(side*this.titleOffset); - this.drawText({ align: [this.title_align, ((side > 0) ^ rotated ? 'top' : 'bottom')], - text: this.fTitle, draw_g: title_g }); - } + if (this.vertical) { + title_basepos = Math.round(-side*(lgaps[side])); + title_shift_x = title_basepos + Math.round(-side*this.titleOffset); + title_shift_y = Math.round(this.titleCenter ? this.gr_range/2 : (this.titleOpposite ? 0 : this.gr_range)); + this.drawText({ align: [this.title_align, ((side < 0) ^ rotated ? 'top' : 'bottom')], + text: this.fTitle, draw_g: title_g }); + } else { + title_shift_x = Math.round(this.titleCenter ? this.gr_range/2 : (this.titleOpposite ? 0 : this.gr_range)); + title_basepos = Math.round(side*lgaps[side]); + title_shift_y = title_basepos + Math.round(side*this.titleOffset); + this.drawText({ align: [this.title_align, ((side > 0) ^ rotated ? 'top' : 'bottom')], + text: this.fTitle, draw_g: title_g }); + } - makeTranslate(title_g, title_shift_x, title_shift_y) - .property('basepos', title_basepos) - .property('shift_x', title_shift_x) - .property('shift_y', title_shift_y); + makeTranslate(title_g, title_shift_x, title_shift_y) + .property('basepos', title_basepos) + .property('shift_x', title_shift_x) + .property('shift_y', title_shift_y); - this.addTitleDrag(title_g, side); + this.addTitleDrag(title_g, side); - return this.finishTextDrawing(title_g); + return this.finishTextDrawing(title_g); + }); } /** @summary Extract major draw attributes, which are also used in interactive operations @@ -160804,16 +160812,13 @@ function drawRFrameTitle(reason, drag) { makeTranslate(this.draw_g, fx, Math.round(fy-title_margin-title_height)); - const arg = { x: title_width/2, y: title_height/2, text: title.fText, latex: 1 }; - - this.startTextDrawing(textFont, 'font'); - - this.drawText(arg); - - return this.finishTextDrawing().then(() => + return this.startTextDrawingAsync(textFont, 'font').then(() => { + this.drawText({ x: title_width/2, y: title_height/2, text: title.fText, latex: 1 }); + return this.finishTextDrawing(); + }).then(() => { addDragHandler(this, { x: fx, y: Math.round(fy-title_margin-title_height), width: title_width, height: title_height, - minwidth: 20, minheight: 20, no_change_x: true, redraw: d => this.redraw('drag', d) }) - ); + minwidth: 20, minheight: 20, no_change_x: true, redraw: d => this.redraw('drag', d) }); + }); } // ========================================================== @@ -161053,11 +161058,10 @@ function drawText() { this.createG(clipping ? 'main_layer' : (onframe ? 'upper_layer' : false)); - this.startTextDrawing(textFont, 'font'); - - this.drawText({ x: p.x, y: p.y, text: text.fText, latex: 1 }); - - return this.finishTextDrawing(); + return this.startTextDrawingAsync(textFont, 'font').then(() => { + this.drawText({ x: p.x, y: p.y, text: text.fText, latex: 1 }); + return this.finishTextDrawing(); + }); } /** @summary draw RLine object @@ -161558,62 +161562,63 @@ class RLegendPainter extends RPavePainter { if (!nlines || !pp) return this; const stepy = height / nlines, margin_x = 0.02 * width; - let posy = 0; textFont.setSize(height/(nlines * 1.2)); - this.startTextDrawing(textFont, 'font'); + return this.startTextDrawingAsync(textFont, 'font').then(() => { + let posy = 0; - if (legend.fTitle) { - this.drawText({ latex: 1, width: width - 2*margin_x, height: stepy, x: margin_x, y: posy, text: legend.fTitle }); - posy += stepy; - } + if (legend.fTitle) { + this.drawText({ latex: 1, width: width - 2*margin_x, height: stepy, x: margin_x, y: posy, text: legend.fTitle }); + posy += stepy; + } - for (let i = 0; i < legend.fEntries.length; ++i) { - const entry = legend.fEntries[i], w4 = Math.round(width/4); - let objp = null; + for (let i = 0; i < legend.fEntries.length; ++i) { + const entry = legend.fEntries[i], w4 = Math.round(width/4); + let objp = null; - this.drawText({ latex: 1, width: 0.75*width - 3*margin_x, height: stepy, x: 2*margin_x + w4, y: posy, text: entry.fLabel }); + this.drawText({ latex: 1, width: 0.75*width - 3*margin_x, height: stepy, x: 2*margin_x + w4, y: posy, text: entry.fLabel }); - if (entry.fDrawableId !== 'custom') - objp = pp.findSnap(entry.fDrawableId, true); - else if (entry.fDrawable.fIO) { - objp = new RObjectPainter(this.getPadPainter(), entry.fDrawable.fIO); - if (entry.fLine) objp.createv7AttLine(); - if (entry.fFill) objp.createv7AttFill(); - if (entry.fMarker) objp.createv7AttMarker(); - } + if (entry.fDrawableId !== 'custom') + objp = pp.findSnap(entry.fDrawableId, true); + else if (entry.fDrawable.fIO) { + objp = new RObjectPainter(this.getPadPainter(), entry.fDrawable.fIO); + if (entry.fLine) objp.createv7AttLine(); + if (entry.fFill) objp.createv7AttFill(); + if (entry.fMarker) objp.createv7AttMarker(); + } - if (entry.fFill && objp?.fillatt) { - this.draw_g - .append('svg:path') - .attr('d', `M${Math.round(margin_x)},${Math.round(posy + stepy*0.1)}h${w4}v${Math.round(stepy*0.8)}h${-w4}z`) - .call(objp.fillatt.func); - } + if (entry.fFill && objp?.fillatt) { + this.draw_g + .append('svg:path') + .attr('d', `M${Math.round(margin_x)},${Math.round(posy + stepy*0.1)}h${w4}v${Math.round(stepy*0.8)}h${-w4}z`) + .call(objp.fillatt.func); + } - if (entry.fLine && objp?.lineatt) { - this.draw_g - .append('svg:path') - .attr('d', `M${Math.round(margin_x)},${Math.round(posy + stepy/2)}h${w4}`) - .call(objp.lineatt.func); - } + if (entry.fLine && objp?.lineatt) { + this.draw_g + .append('svg:path') + .attr('d', `M${Math.round(margin_x)},${Math.round(posy + stepy/2)}h${w4}`) + .call(objp.lineatt.func); + } - if (entry.fError && objp?.lineatt) { - this.draw_g - .append('svg:path') - .attr('d', `M${Math.round(margin_x + width/8)},${Math.round(posy + stepy*0.2)}v${Math.round(stepy*0.6)}`) - .call(objp.lineatt.func); - } + if (entry.fError && objp?.lineatt) { + this.draw_g + .append('svg:path') + .attr('d', `M${Math.round(margin_x + width/8)},${Math.round(posy + stepy*0.2)}v${Math.round(stepy*0.6)}`) + .call(objp.lineatt.func); + } - if (entry.fMarker && objp?.markeratt) { - this.draw_g.append('svg:path') - .attr('d', objp.markeratt.create(margin_x + width/8, posy + stepy/2)) - .call(objp.markeratt.func); - } + if (entry.fMarker && objp?.markeratt) { + this.draw_g.append('svg:path') + .attr('d', objp.markeratt.create(margin_x + width/8, posy + stepy/2)) + .call(objp.markeratt.func); + } - posy += stepy; - } + posy += stepy; + } - return this.finishTextDrawing(); + return this.finishTextDrawing(); + }); } /** @summary draw RLegend object */ @@ -161634,7 +161639,7 @@ class RLegendPainter extends RPavePainter { class RPaveTextPainter extends RPavePainter { /** @summary draw RPaveText content */ - drawContent() { + async drawContent() { const pavetext = this.getObject(), textFont = this.v7EvalFont('text', { size: 12, color: 'black', align: 22 }), width = this.pave_width, @@ -161644,20 +161649,15 @@ class RPaveTextPainter extends RPavePainter { if (!nlines) return; const stepy = height / nlines, margin_x = 0.02 * width; - let posy = 0; textFont.setSize(height/(nlines * 1.2)); - this.startTextDrawing(textFont, 'font'); + return this.startTextDrawingAsync(textFont, 'font').then(() => { + for (let i = 0, posy = 0; i < pavetext.fText.length; ++i, posy += stepy) + this.drawText({ latex: 1, width: width - 2*margin_x, height: stepy, x: margin_x, y: posy, text: pavetext.fText[i] }); - for (let i = 0; i < pavetext.fText.length; ++i) { - const line = pavetext.fText[i]; - - this.drawText({ latex: 1, width: width - 2*margin_x, height: stepy, x: margin_x, y: posy, text: line }); - posy += stepy; - } - - return this.finishTextDrawing(undefined, true); + return this.finishTextDrawing(undefined, true); + }); } /** @summary draw RPaveText object */ @@ -161769,7 +161769,7 @@ class RHistStatsPainter extends RPavePainter { menu.addchk((obj.fShowMask & (1< menu.show()); + }).then(menu => menu.show()); } /** @summary Draw statistic */ @@ -161802,66 +161802,66 @@ class RHistStatsPainter extends RPavePainter { text_g.selectAll('*').remove(); textFont.setSize(height/(nlines * 1.2)); - this.startTextDrawing(textFont, 'font', text_g); + return this.startTextDrawingAsync(textFont, 'font', text_g).then(() => { + if (nlines === 1) + this.drawText({ width, height, text: lines[0], latex: 1, draw_g: text_g }); + else { + for (let j = 0; j < nlines; ++j) { + const posy = j*stepy; + + if (first_stat && (j >= first_stat)) { + const parts = lines[j].split('|'); + for (let n = 0; n < parts.length; ++n) { + this.drawText({ align: 'middle', x: width * n / num_cols, y: posy, latex: 0, + width: width/num_cols, height: stepy, text: parts[n], draw_g: text_g }); + } + } else if (lines[j].indexOf('=') < 0) { + if (j === 0) { + has_head = true; + const max_hlen = Math.max(maxlen, Math.round((width-2*margin_x)/stepy/0.65)); + if (lines[j].length > max_hlen + 5) + lines[j] = lines[j].slice(0, max_hlen+2) + '...'; + } + this.drawText({ align: (j === 0) ? 'middle' : 'start', x: margin_x, y: posy, + width: width - 2*margin_x, height: stepy, text: lines[j], draw_g: text_g }); + } else { + const parts = lines[j].split('='), args = []; + + for (let n = 0; n < 2; ++n) { + const arg = { + align: (n === 0) ? 'start' : 'end', x: margin_x, y: posy, + width: width-2*margin_x, height: stepy, text: parts[n], draw_g: text_g, + _expected_width: width-2*margin_x, _args: args, + post_process(painter) { + if (this._args[0].ready && this._args[1].ready) + painter.scaleTextDrawing(1.05*(this._args[0].result_width && this._args[1].result_width)/this.__expected_width, this.draw_g); + } + }; + args.push(arg); + } - if (nlines === 1) - this.drawText({ width, height, text: lines[0], latex: 1, draw_g: text_g }); - else { - for (let j = 0; j < nlines; ++j) { - const posy = j*stepy; - - if (first_stat && (j >= first_stat)) { - const parts = lines[j].split('|'); - for (let n = 0; n < parts.length; ++n) { - this.drawText({ align: 'middle', x: width * n / num_cols, y: posy, latex: 0, - width: width/num_cols, height: stepy, text: parts[n], draw_g: text_g }); - } - } else if (lines[j].indexOf('=') < 0) { - if (j === 0) { - has_head = true; - const max_hlen = Math.max(maxlen, Math.round((width-2*margin_x)/stepy/0.65)); - if (lines[j].length > max_hlen + 5) - lines[j] = lines[j].slice(0, max_hlen+2) + '...'; + for (let n = 0; n < 2; ++n) + this.drawText(args[n]); } - this.drawText({ align: (j === 0) ? 'middle' : 'start', x: margin_x, y: posy, - width: width - 2*margin_x, height: stepy, text: lines[j], draw_g: text_g }); - } else { - const parts = lines[j].split('='), args = []; - - for (let n = 0; n < 2; ++n) { - const arg = { - align: (n === 0) ? 'start' : 'end', x: margin_x, y: posy, - width: width-2*margin_x, height: stepy, text: parts[n], draw_g: text_g, - _expected_width: width-2*margin_x, _args: args, - post_process(painter) { - if (this._args[0].ready && this._args[1].ready) - painter.scaleTextDrawing(1.05*(this._args[0].result_width && this._args[1].result_width)/this.__expected_width, this.draw_g); - } - }; - args.push(arg); - } - - for (let n = 0; n < 2; ++n) - this.drawText(args[n]); } } - } - let lpath = ''; + let lpath = ''; - if (has_head) - lpath += 'M0,' + Math.round(stepy) + 'h' + width; + if (has_head) + lpath += 'M0,' + Math.round(stepy) + 'h' + width; - if ((first_stat > 0) && (num_cols > 1)) { - for (let nrow = first_stat; nrow < nlines; ++nrow) - lpath += 'M0,' + Math.round(nrow * stepy) + 'h' + width; - for (let ncol = 0; ncol < num_cols - 1; ++ncol) - lpath += 'M' + Math.round(width / num_cols * (ncol + 1)) + ',' + Math.round(first_stat * stepy) + 'V' + height; - } + if ((first_stat > 0) && (num_cols > 1)) { + for (let nrow = first_stat; nrow < nlines; ++nrow) + lpath += 'M0,' + Math.round(nrow * stepy) + 'h' + width; + for (let ncol = 0; ncol < num_cols - 1; ++ncol) + lpath += 'M' + Math.round(width / num_cols * (ncol + 1)) + ',' + Math.round(first_stat * stepy) + 'V' + height; + } - if (lpath) this.draw_g.append('svg:path').attr('d', lpath); + if (lpath) this.draw_g.append('svg:path').attr('d', lpath); - return this.finishTextDrawing(text_g); + return this.finishTextDrawing(text_g); + }); } /** @summary Redraw stats box */ @@ -163093,7 +163093,7 @@ let RH1Painter$2 = class RH1Painter extends RHistPainter { path_fill = null, path_err = null, path_marker = null, path_line = null, hints_err = null, endx = '', endy = '', dend = 0, my, yerr1, yerr2, bincont, binerr, mx1, mx2, midx, - text_font; + text_font, pr = Promise.resolve(); if (show_errors && !show_markers && (this.v7EvalAttr('marker_style', 1) > 1)) show_markers = true; @@ -163130,206 +163130,208 @@ let RH1Painter$2 = class RH1Painter extends RHistPainter { } } - this.startTextDrawing(text_font, 'font'); + pr = this.startTextDrawingAsync(text_font, 'font'); } - // if there are too many points, exclude many vertical drawings at the same X position - // instead define min and max value and made min-max drawing - let use_minmax = ((right-left) > 3*width); - - if (options.ErrorKind === 1) { - const lw = this.lineatt.width + gStyle.fEndErrorSize; - endx = `m0,${lw}v${-2*lw}m0,${lw}`; - endy = `m${lw},0h${-2*lw}m${lw},0`; - dend = Math.floor((this.lineatt.width-1)/2); - } - - const draw_markers = show_errors || show_markers; - - if (draw_markers || show_text || show_line) use_minmax = true; + return pr.then(() => { + // if there are too many points, exclude many vertical drawings at the same X position + // instead define min and max value and made min-max drawing + let use_minmax = ((right-left) > 3*width); + + if (options.ErrorKind === 1) { + const lw = this.lineatt.width + gStyle.fEndErrorSize; + endx = `m0,${lw}v${-2*lw}m0,${lw}`; + endy = `m${lw},0h${-2*lw}m${lw},0`; + dend = Math.floor((this.lineatt.width-1)/2); + } + + const draw_markers = show_errors || show_markers; + + if (draw_markers || show_text || show_line) use_minmax = true; + + const draw_bin = besti => { + bincont = histo.getBinContent(besti+1); + if (!exclude_zero || (bincont !== 0)) { + mx1 = Math.round(funcs.grx(xaxis.GetBinCoord(besti))); + mx2 = Math.round(funcs.grx(xaxis.GetBinCoord(besti+di))); + midx = Math.round((mx1+mx2)/2); + my = Math.round(funcs.gry(bincont)); + yerr1 = yerr2 = 20; + if (show_errors) { + binerr = histo.getBinError(besti+1); + yerr1 = Math.round(my - funcs.gry(bincont + binerr)); // up + yerr2 = Math.round(funcs.gry(bincont - binerr) - my); // down + } - const draw_bin = besti => { - bincont = histo.getBinContent(besti+1); - if (!exclude_zero || (bincont !== 0)) { - mx1 = Math.round(funcs.grx(xaxis.GetBinCoord(besti))); - mx2 = Math.round(funcs.grx(xaxis.GetBinCoord(besti+di))); - midx = Math.round((mx1+mx2)/2); - my = Math.round(funcs.gry(bincont)); - yerr1 = yerr2 = 20; - if (show_errors) { - binerr = histo.getBinError(besti+1); - yerr1 = Math.round(my - funcs.gry(bincont + binerr)); // up - yerr2 = Math.round(funcs.gry(bincont - binerr) - my); // down - } + if (show_text && (bincont !== 0)) { + const lbl = (bincont === Math.round(bincont)) ? bincont.toString() : floatToString(bincont, gStyle.fPaintTextFormat); - if (show_text && (bincont !== 0)) { - const lbl = (bincont === Math.round(bincont)) ? bincont.toString() : floatToString(bincont, gStyle.fPaintTextFormat); + if (text_font.angle) + this.drawText({ align: 12, x: midx, y: Math.round(my - 2 - text_font.size / 5), text: lbl, latex: 0 }); + else + this.drawText({ x: Math.round(mx1 + (mx2 - mx1) * 0.1), y: Math.round(my - 2 - text_font.size), width: Math.round((mx2 - mx1) * 0.8), height: text_font.size, text: lbl, latex: 0 }); + } - if (text_font.angle) - this.drawText({ align: 12, x: midx, y: Math.round(my - 2 - text_font.size / 5), text: lbl, latex: 0 }); - else - this.drawText({ x: Math.round(mx1 + (mx2 - mx1) * 0.1), y: Math.round(my - 2 - text_font.size), width: Math.round((mx2 - mx1) * 0.8), height: text_font.size, text: lbl, latex: 0 }); - } - - if (show_line && (path_line !== null)) - path_line += ((path_line.length === 0) ? 'M' : 'L') + midx + ',' + my; - - if (draw_markers) { - if ((my >= -yerr1) && (my <= height + yerr2)) { - if (path_fill !== null) - path_fill += `M${mx1},${my-yerr1}h${mx2-mx1}v${yerr1+yerr2+1}h${mx1-mx2}z`; - if (path_marker !== null) - path_marker += this.markeratt.create(midx, my); - if (path_err !== null) { - let edx = 5; - if (this.options.errorX > 0) { - edx = Math.round((mx2-mx1)*this.options.errorX); - const mmx1 = midx - edx, mmx2 = midx + edx; - path_err += `M${mmx1+dend},${my}${endx}h${mmx2-mmx1-2*dend}${endx}`; + if (show_line && (path_line !== null)) + path_line += ((path_line.length === 0) ? 'M' : 'L') + midx + ',' + my; + + if (draw_markers) { + if ((my >= -yerr1) && (my <= height + yerr2)) { + if (path_fill !== null) + path_fill += `M${mx1},${my-yerr1}h${mx2-mx1}v${yerr1+yerr2+1}h${mx1-mx2}z`; + if (path_marker !== null) + path_marker += this.markeratt.create(midx, my); + if (path_err !== null) { + let edx = 5; + if (this.options.errorX > 0) { + edx = Math.round((mx2-mx1)*this.options.errorX); + const mmx1 = midx - edx, mmx2 = midx + edx; + path_err += `M${mmx1+dend},${my}${endx}h${mmx2-mmx1-2*dend}${endx}`; + } + path_err += `M${midx},${my-yerr1+dend}${endy}v${yerr1+yerr2-2*dend}${endy}`; + if (hints_err !== null) + hints_err += `M${midx-edx},${my-yerr1}h${2*edx}v${yerr1+yerr2}h${-2*edx}z`; } - path_err += `M${midx},${my-yerr1+dend}${endy}v${yerr1+yerr2-2*dend}${endy}`; - if (hints_err !== null) - hints_err += `M${midx-edx},${my-yerr1}h${2*edx}v${yerr1+yerr2}h${-2*edx}z`; } } } - } - }; + }; - for (i = left; i <= right; i += di) { - x = xaxis.GetBinCoord(i); + for (i = left; i <= right; i += di) { + x = xaxis.GetBinCoord(i); - if (funcs.logx && (x <= 0)) continue; + if (funcs.logx && (x <= 0)) continue; - grx = Math.round(funcs.grx(x)); + grx = Math.round(funcs.grx(x)); - lastbin = (i > right - di); + lastbin = (i > right - di); - if (lastbin && (left < right)) - gry = curry; - else { - y = histo.getBinContent(i+1); - gry = Math.round(funcs.gry(y)); - } + if (lastbin && (left < right)) + gry = curry; + else { + y = histo.getBinContent(i+1); + gry = Math.round(funcs.gry(y)); + } - if (res.length === 0) { - bestimin = bestimax = i; - prevx = startx = currx = grx; - prevy = curry_min = curry_max = curry = gry; - res = 'M'+currx+','+curry; - } else - if (use_minmax) { - if ((grx === currx) && !lastbin) { - if (gry < curry_min) bestimax = i; else - if (gry > curry_max) bestimin = i; - curry_min = Math.min(curry_min, gry); - curry_max = Math.max(curry_max, gry); - curry = gry; - } else { - if (draw_markers || show_text || show_line) { - if (bestimin === bestimax) draw_bin(bestimin); else - if (bestimin < bestimax) { draw_bin(bestimin); draw_bin(bestimax); } else { - draw_bin(bestimax); draw_bin(bestimin); - } - } + if (res.length === 0) { + bestimin = bestimax = i; + prevx = startx = currx = grx; + prevy = curry_min = curry_max = curry = gry; + res = 'M'+currx+','+curry; + } else + if (use_minmax) { + if ((grx === currx) && !lastbin) { + if (gry < curry_min) bestimax = i; else + if (gry > curry_max) bestimin = i; + curry_min = Math.min(curry_min, gry); + curry_max = Math.max(curry_max, gry); + curry = gry; + } else { + if (draw_markers || show_text || show_line) { + if (bestimin === bestimax) draw_bin(bestimin); else + if (bestimin < bestimax) { draw_bin(bestimin); draw_bin(bestimax); } else { + draw_bin(bestimax); draw_bin(bestimin); + } + } - // when several points as same X differs, need complete logic - if (!draw_markers && ((curry_min !== curry_max) || (prevy !== curry_min))) { - if (prevx !== currx) - res += 'h'+(currx-prevx); + // when several points as same X differs, need complete logic + if (!draw_markers && ((curry_min !== curry_max) || (prevy !== curry_min))) { + if (prevx !== currx) + res += 'h'+(currx-prevx); - if (curry === curry_min) { - if (curry_max !== prevy) - res += 'v' + (curry_max - prevy); - if (curry_min !== curry_max) - res += 'v' + (curry_min - curry_max); - } else { - if (curry_min !== prevy) - res += 'v' + (curry_min - prevy); - if (curry_max !== curry_min) - res += 'v' + (curry_max - curry_min); - if (curry !== curry_max) - res += 'v' + (curry - curry_max); - } + if (curry === curry_min) { + if (curry_max !== prevy) + res += 'v' + (curry_max - prevy); + if (curry_min !== curry_max) + res += 'v' + (curry_min - curry_max); + } else { + if (curry_min !== prevy) + res += 'v' + (curry_min - prevy); + if (curry_max !== curry_min) + res += 'v' + (curry_max - curry_min); + if (curry !== curry_max) + res += 'v' + (curry - curry_max); + } - prevx = currx; - prevy = curry; - } + prevx = currx; + prevy = curry; + } - if (lastbin && (prevx !== grx)) - res += 'h'+(grx-prevx); + if (lastbin && (prevx !== grx)) + res += 'h'+(grx-prevx); - bestimin = bestimax = i; - curry_min = curry_max = curry = gry; + bestimin = bestimax = i; + curry_min = curry_max = curry = gry; + currx = grx; + } + } else + if ((gry !== curry) || lastbin) { + if (grx !== currx) res += 'h'+(grx-currx); + if (gry !== curry) res += 'v'+(gry-curry); + curry = gry; currx = grx; } - } else - if ((gry !== curry) || lastbin) { - if (grx !== currx) res += 'h'+(grx-currx); - if (gry !== curry) res += 'v'+(gry-curry); - curry = gry; - currx = grx; } - } - const fill_for_interactive = !this.isBatchMode() && this.fillatt.empty() && options.Hist && settings.Tooltip && !draw_markers && !show_line; - let h0 = height + 3; - if (!fill_for_interactive) { - const gry0 = Math.round(funcs.gry(0)); - if (gry0 <= 0) - h0 = -3; - else if (gry0 < height) - h0 = gry0; - } - const close_path = `L${currx},${h0}H${startx}Z`; - - if (draw_markers || show_line) { - if (path_fill) { - this.draw_g.append('svg:path') - .attr('d', path_fill) - .call(this.fillatt.func); + const fill_for_interactive = !this.isBatchMode() && this.fillatt.empty() && options.Hist && settings.Tooltip && !draw_markers && !show_line; + let h0 = height + 3; + if (!fill_for_interactive) { + const gry0 = Math.round(funcs.gry(0)); + if (gry0 <= 0) + h0 = -3; + else if (gry0 < height) + h0 = gry0; } + const close_path = `L${currx},${h0}H${startx}Z`; - if (path_err) { - this.draw_g.append('svg:path') - .attr('d', path_err) - .call(this.lineatt.func); - } + if (draw_markers || show_line) { + if (path_fill) { + this.draw_g.append('svg:path') + .attr('d', path_fill) + .call(this.fillatt.func); + } - if (hints_err) { - this.draw_g.append('svg:path') - .attr('d', hints_err) - .style('fill', 'none') - .style('pointer-events', this.isBatchMode() ? null : 'visibleFill'); - } + if (path_err) { + this.draw_g.append('svg:path') + .attr('d', path_err) + .call(this.lineatt.func); + } - if (path_line) { - if (!this.fillatt.empty() && !options.Hist) { + if (hints_err) { this.draw_g.append('svg:path') - .attr('d', path_line + close_path) - .call(this.fillatt.func); + .attr('d', hints_err) + .style('fill', 'none') + .style('pointer-events', this.isBatchMode() ? null : 'visibleFill'); } - this.draw_g.append('svg:path') - .attr('d', path_line) - .style('fill', 'none') - .call(this.lineatt.func); - } + if (path_line) { + if (!this.fillatt.empty() && !options.Hist) { + this.draw_g.append('svg:path') + .attr('d', path_line + close_path) + .call(this.fillatt.func); + } + + this.draw_g.append('svg:path') + .attr('d', path_line) + .style('fill', 'none') + .call(this.lineatt.func); + } - if (path_marker) { + if (path_marker) { + this.draw_g.append('svg:path') + .attr('d', path_marker) + .call(this.markeratt.func); + } + } else if (res && options.Hist) { this.draw_g.append('svg:path') - .attr('d', path_marker) - .call(this.markeratt.func); + .attr('d', res + ((!this.fillatt.empty() || fill_for_interactive) ? close_path : '')) + .style('stroke-linejoin', 'miter') + .call(this.lineatt.func) + .call(this.fillatt.func); } - } else if (res && options.Hist) { - this.draw_g.append('svg:path') - .attr('d', res + ((!this.fillatt.empty() || fill_for_interactive) ? close_path : '')) - .style('stroke-linejoin', 'miter') - .call(this.lineatt.func) - .call(this.fillatt.func); - } - return show_text ? this.finishTextDrawing() : true; + return show_text ? this.finishTextDrawing() : true; + }); } /** @summary Provide text information (tooltips) for histogram bin */ @@ -164318,47 +164320,48 @@ let RH2Painter$2 = class RH2Painter extends RHistPainter { } /** @summary Draw RH2 bins as text */ - drawBinsText(handle) { - if (handle === null) handle = this.prepareDraw({ rounding: false }); + async drawBinsText(handle) { + if (!handle) + handle = this.prepareDraw({ rounding: false }); const histo = this.getHisto(), textFont = this.v7EvalFont('text', { size: 20, color: 'black', align: 22 }), text_offset = this.options.BarOffset || 0, text_g = this.draw_g.append('svg:g').attr('class', 'th2_text'), di = handle.stepi, dj = handle.stepj; - let i, j, binz, binw, binh, text, x, y, width, height; - this.startTextDrawing(textFont, 'font', text_g); + return this.startTextDrawingAsync(textFont, 'font', text_g).then(() => { + for (let i = handle.i1; i < handle.i2; i += di) { + for (let j = handle.j1; j < handle.j2; j += dj) { + let binz = histo.getBinContent(i+1, j+1); + if ((binz === 0) && !this._show_empty_bins) continue; - for (i = handle.i1; i < handle.i2; i += di) { - for (j = handle.j1; j < handle.j2; j += dj) { - binz = histo.getBinContent(i+1, j+1); - if ((binz === 0) && !this._show_empty_bins) continue; + const binw = handle.grx[i+di] - handle.grx[i], + binh = handle.gry[j] - handle.gry[j+dj]; - binw = handle.grx[i+di] - handle.grx[i]; - binh = handle.gry[j] - handle.gry[j+dj]; + const text = (binz === Math.round(binz)) ? binz.toString() : floatToString(binz, gStyle.fPaintTextFormat); - text = (binz === Math.round(binz)) ? binz.toString() : floatToString(binz, gStyle.fPaintTextFormat); + let x, y, width, height; - if (textFont.angle) { - x = Math.round(handle.grx[i] + binw*0.5); - y = Math.round(handle.gry[j+dj] + binh*(0.5 + text_offset)); - width = height = 0; - } else { - x = Math.round(handle.grx[i] + binw*0.1); - y = Math.round(handle.gry[j+dj] + binh*(0.1 + text_offset)); - width = Math.round(binw*0.8); - height = Math.round(binh*0.8); - } + if (textFont.angle) { + x = Math.round(handle.grx[i] + binw*0.5); + y = Math.round(handle.gry[j+dj] + binh*(0.5 + text_offset)); + width = height = 0; + } else { + x = Math.round(handle.grx[i] + binw*0.1); + y = Math.round(handle.gry[j+dj] + binh*(0.1 + text_offset)); + width = Math.round(binw*0.8); + height = Math.round(binh*0.8); + } - this.drawText({ align: 22, x, y, width, height, text, latex: 0, draw_g: text_g }); + this.drawText({ align: 22, x, y, width, height, text, latex: 0, draw_g: text_g }); + } } - } - return this.finishTextDrawing(text_g, true).then(() => { handle.hide_only_zeros = true; // text drawing suppress only zeros - return handle; - }); + + return this.finishTextDrawing(text_g, true); + }).then(() => handle); } /** @summary Draw RH2 bins as arrows */ diff --git a/modules/draw/TGraphPolarPainter.mjs b/modules/draw/TGraphPolarPainter.mjs index ff75c4be2..a932bc112 100644 --- a/modules/draw/TGraphPolarPainter.mjs +++ b/modules/draw/TGraphPolarPainter.mjs @@ -227,7 +227,6 @@ class TGraphPolargramPainter extends ObjectPainter { }).then(() => { return this.startTextDrawingAsync(polar.fPolarLabelFont, fontsize); }).then(() => { - lbls = (nmajor === 8) ? ['0', '#frac{#pi}{4}', '#frac{#pi}{2}', '#frac{3#pi}{4}', '#pi', '#frac{5#pi}{4}', '#frac{3#pi}{2}', '#frac{7#pi}{4}'] : ['0', '#frac{2#pi}{3}', '#frac{4#pi}{3}']; const aligns = [12, 11, 21, 31, 32, 33, 23, 13]; diff --git a/modules/gpad/RAxisPainter.mjs b/modules/gpad/RAxisPainter.mjs index 6785202e9..5a714b478 100644 --- a/modules/gpad/RAxisPainter.mjs +++ b/modules/gpad/RAxisPainter.mjs @@ -651,7 +651,6 @@ class RAxisPainter extends RObjectPainter { label_g.property('fix_offset', fix_offset); return this.startTextDrawingAsync(this.labelsFont, 'font', label_g).then(() => { - for (let nmajor = 0; nmajor < lbl_pos.length; ++nmajor) { const lbl = this.format(lbl_pos[nmajor], true); if (lbl === null) continue; diff --git a/modules/gpad/RCanvasPainter.mjs b/modules/gpad/RCanvasPainter.mjs index 03b8e6312..aac198b3e 100644 --- a/modules/gpad/RCanvasPainter.mjs +++ b/modules/gpad/RCanvasPainter.mjs @@ -762,7 +762,7 @@ function drawRFrameTitle(reason, drag) { return this.finishTextDrawing(); }).then(() => { addDragHandler(this, { x: fx, y: Math.round(fy-title_margin-title_height), width: title_width, height: title_height, - minwidth: 20, minheight: 20, no_change_x: true, redraw: d => this.redraw('drag', d) }) + minwidth: 20, minheight: 20, no_change_x: true, redraw: d => this.redraw('drag', d) }); }); } diff --git a/modules/gpad/TAxisPainter.mjs b/modules/gpad/TAxisPainter.mjs index cd472abc5..689b1c07a 100644 --- a/modules/gpad/TAxisPainter.mjs +++ b/modules/gpad/TAxisPainter.mjs @@ -1155,7 +1155,7 @@ class TAxisPainter extends ObjectPainter { this.scaleTextDrawing(applied_scale, label_g[lcnt]); return this.finishTextDrawing(label_g[lcnt], true); - }) + }); } return pr.then(() => { diff --git a/modules/hist/RPavePainter.mjs b/modules/hist/RPavePainter.mjs index 76339bda6..7f778f867 100644 --- a/modules/hist/RPavePainter.mjs +++ b/modules/hist/RPavePainter.mjs @@ -178,7 +178,6 @@ class RLegendPainter extends RPavePainter { textFont.setSize(height/(nlines * 1.2)); return this.startTextDrawingAsync(textFont, 'font').then(() => { - let posy = 0; if (legend.fTitle) { @@ -417,7 +416,6 @@ class RHistStatsPainter extends RPavePainter { textFont.setSize(height/(nlines * 1.2)); return this.startTextDrawingAsync(textFont, 'font', text_g).then(() => { - if (nlines === 1) this.drawText({ width, height, text: lines[0], latex: 1, draw_g: text_g }); else { diff --git a/modules/hist/TPavePainter.mjs b/modules/hist/TPavePainter.mjs index 5de075915..130b50232 100644 --- a/modules/hist/TPavePainter.mjs +++ b/modules/hist/TPavePainter.mjs @@ -398,7 +398,6 @@ class TPavePainter extends ObjectPainter { this.createAttText({ attr: pt, can_rotate: false }); return this.startTextDrawingAsync(this.textatt.font, height/(nlines * 1.2)).then(() => { - if (nlines === 1) this.drawText(this.textatt.createArg({ width, height, text: lines[0], latex: 1, norotate: true })); else { @@ -498,7 +497,6 @@ class TPavePainter extends ObjectPainter { const pr = (num_txt > num_custom) ? this.startTextDrawingAsync(this.textatt.font, 0.85*height/nlines, text_g, max_font_size) : Promise.resolve(); return pr.then(() => { - for (let nline = 0; nline < nlines; ++nline) { const entry = arr[nline], texty = nline*stepy; @@ -804,9 +802,8 @@ class TPavePainter extends ObjectPainter { text_promises.push(this.startTextDrawingAsync(textatt.font, textatt.getSize(pp.getPadHeight()), arg.draw_g, max_font_size) .then(() => this.drawText(arg)) .then(() => this.finishTextDrawing(arg.draw_g))); - } else { + } else this.drawText(arg); - } } } diff --git a/modules/hist2d/RH1Painter.mjs b/modules/hist2d/RH1Painter.mjs index d109b618e..0f0bb9f95 100644 --- a/modules/hist2d/RH1Painter.mjs +++ b/modules/hist2d/RH1Painter.mjs @@ -399,7 +399,6 @@ class RH1Painter extends RHistPainter { } return pr.then(() => { - // if there are too many points, exclude many vertical drawings at the same X position // instead define min and max value and made min-max drawing let use_minmax = ((right-left) > 3*width); diff --git a/modules/hist2d/RH2Painter.mjs b/modules/hist2d/RH2Painter.mjs index f3389e596..71ca20b48 100644 --- a/modules/hist2d/RH2Painter.mjs +++ b/modules/hist2d/RH2Painter.mjs @@ -536,14 +536,13 @@ class RH2Painter extends RHistPainter { profile2d = false; return this.startTextDrawingAsync(textFont, 'font', text_g).then(() => { - for (let i = handle.i1; i < handle.i2; i += di) { for (let j = handle.j1; j < handle.j2; j += dj) { let binz = histo.getBinContent(i+1, j+1); if ((binz === 0) && !this._show_empty_bins) continue; - let binw = handle.grx[i+di] - handle.grx[i], - binh = handle.gry[j] - handle.gry[j+dj]; + const binw = handle.grx[i+di] - handle.grx[i], + binh = handle.gry[j] - handle.gry[j+dj]; if (profile2d) binz = histo.getBinEntries(i+1, j+1); diff --git a/modules/hist2d/TH1Painter.mjs b/modules/hist2d/TH1Painter.mjs index 131d78e28..dd9d02396 100644 --- a/modules/hist2d/TH1Painter.mjs +++ b/modules/hist2d/TH1Painter.mjs @@ -405,7 +405,7 @@ class TH1Painter extends THistPainter { xaxis = histo.fXaxis, show_text = this.options.Text; let text_col, text_angle, text_size, - side = (this.options.BarStyle > 10) ? this.options.BarStyle % 10 : 0 , pr = Promise.resolve(); + side = (this.options.BarStyle > 10) ? this.options.BarStyle % 10 : 0, pr = Promise.resolve(); if (side > 4) side = 4; const gry2 = this.getBarBaseline(funcs, height); @@ -425,18 +425,18 @@ class TH1Painter extends THistPainter { let bars = '', barsl = '', barsr = ''; for (let i = left; i < right; ++i) { - let x1 = xaxis.GetBinLowEdge(i + 1), - x2 = xaxis.GetBinLowEdge(i + 2); + const x1 = xaxis.GetBinLowEdge(i + 1), + x2 = xaxis.GetBinLowEdge(i + 2); if (funcs.logx && (x2 <= 0)) continue; let grx1 = Math.round(funcs.grx(x1)), - grx2 = Math.round(funcs.grx(x2)); + grx2 = Math.round(funcs.grx(x2)), + w = grx2 - grx1; + const y = histo.getBinContent(i+1); - let y = histo.getBinContent(i+1); if (funcs.logy && (y < funcs.scale_ymin)) continue; - let gry1 = Math.round(funcs.gry(y)), - w = grx2 - grx1; + const gry1 = Math.round(funcs.gry(y)); grx1 += Math.round(histo.fBarOffset/1000*w); w = Math.round(histo.fBarWidth/1000*w); diff --git a/modules/hist2d/TH2Painter.mjs b/modules/hist2d/TH2Painter.mjs index cffd83ff4..93de3aec2 100644 --- a/modules/hist2d/TH2Painter.mjs +++ b/modules/hist2d/TH2Painter.mjs @@ -1702,7 +1702,6 @@ class TH2Painter extends THistPainter { text_size = ((histo.fMarkerSize !== 1) && rotate) ? Math.round(0.02*h*histo.fMarkerSize) : 12; pr = this.startTextDrawingAsync(42, text_size, text_g, text_size).then(() => { - for (i = 0; i < textbins.length; ++i) { const textbin = textbins[i]; @@ -2659,7 +2658,6 @@ class TH2Painter extends THistPainter { const nbins = Math.min(this.nbinsx, this.nbinsy); return this.startTextDrawingAsync(42, text_size, this.draw_g).then(() => { - const pnts = []; for (let n = 0; n < nbins; n++) {