Skip to content

Commit

Permalink
[jsroot] dev 26/11/2024
Browse files Browse the repository at this point in the history
1. Implement cont5 draw option for `TGraph2D` using Delaunay algorithm
1. Adjust histogram title drawing with native implementation
1. Improve float to string convertion when 'g' is specified
1. Support "same" option for first histogram, draw direcly on pad
1. Support different angle coordiantes in `TGraphPolargram`
1. Fix - handle `TPave` NDC position also when fInit is not set
1. Fix - correctly position title according to gStyle->GetTitleAlign()
1. Fix - correctly handle tooltip events for `TGraphPolar`
1. Fix - align in #splitline

Many other small changes to make stressGraphics output
 very-very similar to original graphics
  • Loading branch information
linev committed Nov 26, 2024
1 parent bf2c7a0 commit b7d8ff7
Show file tree
Hide file tree
Showing 40 changed files with 2,317 additions and 1,099 deletions.
1,689 changes: 1,146 additions & 543 deletions js/build/jsroot.js

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions js/changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# JSROOT changelog

## Changes in dev
1. Implement cont5 draw option for `TGraph2D` using Delaunay algorithm
1. Adjust histogram title drawing with native implementation
1. Improve float to string convertion when 'g' is specified
1. Support "same" option for first histogram, draw direcly on pad
1. Support different angle coordiantes in `TGraphPolargram`
1. Fix - handle `TPave` NDC position also when fInit is not set
1. Fix - correctly position title according to gStyle->GetTitleAlign()
1. Fix - correctly handle tooltip events for `TGraphPolar`


## Changes in 7.8.0
1. Let use custom time zone for time display, support '&utc' and '&cet' in URL parameters
2. Support gStyle.fLegendFillStyle
Expand Down
96 changes: 60 additions & 36 deletions js/modules/base/BasePainter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,32 @@ function getAbsPosInCanvas(sel, pos) {
* @param {boolean} [ret_fmt] - when true returns array with value and actual format like ['0.1','6.4f']
* @return {string|Array} - converted value or array with value and actual format
* @private */
function floatToString(value, fmt, ret_fmt, significance) {
function floatToString(value, fmt, ret_fmt) {
if (!fmt)
fmt = '6.4g';
else if (fmt === 'g')
fmt = '8.6g';
else if (fmt === 'c')
fmt = '8.6c';
fmt = '7.5g';

fmt = fmt.trim();
const len = fmt.length;
if (len < 2)
return ret_fmt ? [value.toFixed(4), '6.4f'] : value.toFixed(4);
const kind = fmt[len-1].toLowerCase();
fmt = fmt.slice(0, len-1);

const kind = fmt[len-1].toLowerCase(),
compact = (len > 1) && (fmt[len-2] === 'c') ? 'c' : '';
fmt = fmt.slice(0, len - (compact ? 2 : 1));

if (kind === 'g') {
const se = floatToString(value, fmt+'ce', true),
sg = floatToString(value, fmt+'cf', true),
res = se[0].length < sg[0].length || ((sg[0] === '0') && value) ? se : sg;
return ret_fmt ? res : res[0];
}

let isexp, prec = fmt.indexOf('.');
prec = (prec < 0) ? 4 : parseInt(fmt.slice(prec+1));
if (!Number.isInteger(prec) || (prec <= 0)) prec = 4;
if (!Number.isInteger(prec) || (prec <= 0))
prec = 4;

switch (kind) {
case 'e':
Expand All @@ -103,45 +112,37 @@ function floatToString(value, fmt, ret_fmt, significance) {
case 'f':
isexp = false;
break;
case 'c':
case 'g': {
const se = floatToString(value, fmt+'e', true, true);
let sg = floatToString(value, fmt+'f', true, true);
const pnt = sg[0].indexOf('.');
if ((kind === 'c') && (pnt > 0)) {
let len = sg[0].length;
while ((len > pnt) && (sg[0][len-1] === '0'))
len--;
if (len === pnt) len--;
sg[0] = sg[0].slice(0, len);
}
if (se[0].length < sg[0].length) sg = se;
return ret_fmt ? sg : sg[0];
}
default:
isexp = false;
prec = 4;
}

if (isexp) {
// for exponential representation only one significant digit before point
if (significance) prec--;
if (prec < 0) prec = 0;
let se = value.toExponential(prec);

if (compact) {
const pnt = se.indexOf('.'),
pe = se.toLowerCase().indexOf('e');
if ((pnt > 0) && (pe > pnt)) {
let p = pe;
while ((p > pnt) && (se[p-1] === '0'))
p--;
if (p === pnt + 1)
p--;
if (p !== pe)
se = se.slice(0, p) + se.slice(pe);
}
}

const se = value.toExponential(prec);
return ret_fmt ? [se, `${prec+2}.${prec}e`] : se;
return ret_fmt ? [se, `${prec+2}.${prec}${compact}e`] : se;
}

let sg = value.toFixed(prec);

if (significance) {
// when using fixed representation, one could get 0
if ((value !== 0) && (Number(sg) === 0) && (prec > 0)) {
prec = 20; sg = value.toFixed(prec);
}

if (compact) {
let l = 0;
while ((l < sg.length) && (sg[l] === '0' || sg[l] === '-' || sg[l] === '.')) l++;
while ((l < sg.length) && (sg[l] === '0' || sg[l] === '-' || sg[l] === '.'))
l++;

let diff = sg.length - l - prec;
if (sg.indexOf('.') > l) diff--;
Expand All @@ -154,9 +155,22 @@ function floatToString(value, fmt, ret_fmt, significance) {
prec = 20;
sg = value.toFixed(prec);
}

const pnt = sg.indexOf('.');
if (pnt > 0) {
let p = sg.length;
while ((p > pnt) && (sg[p-1] === '0'))
p--;
if (p === pnt + 1)
p--;
sg = sg.slice(0, p);
}

if (sg === '-0')
sg = '0';
}

return ret_fmt ? [sg, `${prec+2}.${prec}f`] : sg;
return ret_fmt ? [sg, `${prec+2}.${prec}${compact}f`] : sg;
}


Expand Down Expand Up @@ -844,6 +858,16 @@ function convertDate(dt) {
return res || dt.toLocaleString('en-GB');
}

/** @summary Box decorations
* @private */
function getBoxDecorations(xx, yy, ww, hh, bmode, pww, phh)
{
const side1 = `M${xx},${yy}h${ww}l${-pww},${phh}h${2*pww-ww}v${hh-2*phh}l${-pww},${phh}z`,
side2 = `M${xx+ww},${yy+hh}v${-hh}l${-pww},${phh}v${hh-2*phh}h${2*pww-ww}l${-pww},${phh}z`;
return bmode > 0 ? [side1, side2] : [side2, side1];
}


export { prSVG, prJSON, getElementRect, getAbsPosInCanvas, getTDatime, convertDate,
DrawOptions, TRandom, floatToString, buildSvgCurve, compressSVG,
DrawOptions, TRandom, floatToString, buildSvgCurve, compressSVG, getBoxDecorations,
BasePainter, _loadJSDOM, makeTranslate, addHighlightStyle, svgToImage };
2 changes: 1 addition & 1 deletion js/modules/base/FontHandler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class FontHandler {
this.scaled = true;
}

this.size = Math.round(size || 11);
this.size = Math.round(size);
this.scale = scale;
this.index = 0;

Expand Down
3 changes: 2 additions & 1 deletion js/modules/base/ObjectPainter.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ class ObjectPainter extends BasePainter {
* @param {string} [opt] - option which will be used for redrawing
* @protected */
updateObject(obj /* , opt */) {
if (!this.matchObjectType(obj)) return false;
if (!this.matchObjectType(obj))
return false;
Object.assign(this.getObject(), obj);
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion js/modules/base/TAttLineHandler.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class TAttLineHandler {
if (args.width === undefined)
args.width = (args.color && args.color !== 'none') ? 1 : 0;

this.color = (args.width === 0) ? 'none' : args.color;
this.nocolor = args.nocolor;
this.color = (args.width === 0) || this.nocolor ? 'none' : args.color;
this.width = args.width;
this.style = args.style;
this.pattern = args.pattern || root_line_styles[this.style] || null;
Expand Down
14 changes: 9 additions & 5 deletions js/modules/base/base3d.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1553,10 +1553,14 @@ class PointsCreator {
let k = 1;

// special dots
if (!args.style) k = 1.1; else
if (args.style === 1) k = 0.3; else
if (args.style === 6) k = 0.5; else
if (args.style === 7) k = 0.7;
if (!args.style)
k = 1.1;
else if (args.style === 1)
k = 0.3;
else if (args.style === 6)
k = 0.5;
else if (args.style === 7)
k = 0.7;

const makePoints = texture => {
const material_args = { size: 3*this.scale*k };
Expand All @@ -1581,7 +1585,7 @@ class PointsCreator {
const handler = new TAttMarkerHandler({ style: args.style, color: args.color, size: 7 }),
w = handler.fill ? 1 : 7,
imgdata = `<svg width="64" height="64" xmlns="${nsSVG}">` +
`<path d="${handler.create(32, 32)}" style="stroke: ${handler.getStrokeColor()}; stroke-width: ${w}; fill: ${handler.getFillColor()}"></path>`+
`<path d="${handler.create(32, 32)}" style="stroke: ${handler.getStrokeColor()}; stroke-width: ${w}; fill: ${args.fill ?? handler.getFillColor()}"></path>`+
'</svg>',
dataUrl = prSVG + (isNodeJs() ? imgdata : encodeURIComponent(imgdata));
let promise;
Expand Down
29 changes: 14 additions & 15 deletions js/modules/base/latex.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ const latex_features = [
{ name: '#tilde{', accent: '\u02DC', hasw: true }, // '\u0303'
{ name: '#slash{', accent: '\u2215' }, // '\u0337'
{ name: '#vec{', accent: '\u02ED', hasw: true }, // '\u0350' arrowhead
{ name: '#frac{', twolines: 'line' },
{ name: '#frac{', twolines: 'line', middle: true },
{ name: '#splitmline{', twolines: true, middle: true },
{ name: '#splitline{', twolines: true },
{ name: '#sqrt[', arg: 'int', sqrt: true }, // root with arbitrary power
{ name: '#sqrt{', sqrt: true }, // square root
Expand Down Expand Up @@ -522,7 +523,7 @@ function parseLatex(node, arg, label, curr) {
},

createSubPos = fscale => {
return { lvl: curr.lvl + 1, x: 0, y: 0, fsize: curr.fsize*(fscale || 1), color: curr.color, font: curr.font, parent: curr, painter: curr.painter };
return { lvl: curr.lvl + 1, x: 0, y: 0, fsize: curr.fsize*(fscale || 1), color: curr.color, font: curr.font, parent: curr, painter: curr.painter, italic: curr.italic, bold: curr.bold };
};

while (label) {
Expand Down Expand Up @@ -560,7 +561,8 @@ function parseLatex(node, arg, label, curr) {
const g = curr.g || (alone ? node : currG()),
elem = g.append('svg:text');

if (alone && !curr.g) curr.g = elem;
if (alone && !curr.g)
curr.g = elem;

// apply font attributes only once, inherited by all other elements
if (curr.ufont) {
Expand Down Expand Up @@ -607,7 +609,7 @@ function parseLatex(node, arg, label, curr) {
elem.attr('text-decoration', curr.deco);
delete curr.deco; // inform that decoration was applied
} else
curr.xgap = xgap; // may be used in accent or somewere else
curr.xgap = xgap; // may be used in accent or somewhere else
} else
addSpaces(nendspaces);
}
Expand Down Expand Up @@ -667,15 +669,16 @@ function parseLatex(node, arg, label, curr) {
curr.twolines = true;

const line1 = extractSubLabel(), line2 = extractSubLabel(true);
if ((line1 === -1) || (line2 === -1)) return false;
if ((line1 === -1) || (line2 === -1))
return false;

const gg = createGG(),
fscale = (curr.parent && curr.parent.twolines) ? 0.7 : 1,
fscale = curr.parent?.twolines ? 0.7 : 1,
subpos1 = createSubPos(fscale);

parseLatex(gg, arg, line1, subpos1);

const path = (found.twolines === 'line') ? createPath(gg) : null,
const path = found.twolines === 'line' ? createPath(gg) : null,
subpos2 = createSubPos(fscale);

parseLatex(gg, arg, line2, subpos2);
Expand All @@ -684,9 +687,9 @@ function parseLatex(node, arg, label, curr) {
dw = subpos1.rect.width - subpos2.rect.width,
dy = -curr.fsize*0.35; // approximate position of middle line

positionGNode(subpos1, (dw < 0 ? -dw/2 : 0), dy - subpos1.rect.y2, true);
positionGNode(subpos1, found.middle && (dw < 0) ? -dw/2 : 0, dy - subpos1.rect.y2, true);

positionGNode(subpos2, (dw > 0 ? dw/2 : 0), dy - subpos2.rect.y1, true);
positionGNode(subpos2, found.middle && (dw > 0) ? dw/2 : 0, dy - subpos2.rect.y1, true);

path?.attr('d', `M0,${Math.round(dy)}h${Math.round(w - curr.fsize*0.1)}`);

Expand Down Expand Up @@ -869,11 +872,7 @@ function parseLatex(node, arg, label, curr) {

const subpos = createSubPos();

let value;
for (let c = curr; c && (value === undefined && c); c = c.parent)
value = c[found.bi];

subpos[found.bi] = !value;
subpos[found.bi] = !subpos[found.bi];

parseLatex(currG(), arg, sublabel, subpos);

Expand Down Expand Up @@ -951,7 +950,7 @@ function parseLatex(node, arg, label, curr) {
if (found.name === '#color[')
subpos.color = curr.painter.getColor(foundarg);
else if (found.name === '#font[') {
subpos.font = new FontHandler(foundarg);
subpos.font = new FontHandler(foundarg, subpos.fsize);
// here symbols embedding not works, use replacement
if ((subpos.font.name === kSymbol) && !subpos.font.isSymbol) {
subpos.font.isSymbol = kSymbol;
Expand Down
6 changes: 4 additions & 2 deletions js/modules/base/makepdf.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,20 @@ async function makePDF(svg, args) {

let doc;

const orientation = (svg.width < svg.height) ? 'portrait' : 'landscape';

if (args?.as_doc)
doc = args?.doc;

if (doc) {
doc.addPage({
orientation: 'landscape',
orientation,
unit: 'px',
format: [svg.width + 10, svg.height + 10]
});
} else {
doc = new jsPDF({
orientation: 'landscape',
orientation,
unit: 'px',
format: [svg.width + 10, svg.height + 10]
});
Expand Down
8 changes: 4 additions & 4 deletions js/modules/core.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/** @summary version id
* @desc For the JSROOT release the string in format 'major.minor.patch' like '7.0.0' */
const version_id = '7.8.0',
const version_id = 'dev',

/** @summary version date
* @desc Release date in format day/month/year like '14/04/2022' */
version_date = '11/11/2024',
version_date = '26/11/2024',

/** @summary version id and date
* @desc Produced by concatenation of {@link version_id} and {@link version_date}
Expand Down Expand Up @@ -1149,7 +1149,7 @@ function create(typename, target) {
break;
case clTPave:
create(clTBox, obj);
extend(obj, { fX1NDC: 0, fY1NDC: 0, fX2NDC: 1, fY2NDC: 1,
extend(obj, { fX1NDC: 0, fY1NDC: 0, fX2NDC: 0, fY2NDC: 0,
fBorderSize: 0, fInit: 1, fShadowColor: 1,
fCornerRadius: 0, fOption: 'brNDC', fName: '' });
break;
Expand Down Expand Up @@ -1276,7 +1276,7 @@ function create(typename, target) {
create(clTNamed, obj);
create(clTAttText, obj);
create(clTAttLine, obj);
extend(obj, { fRadian: true, fDegree: false, fGrad: false, fPolarLabelColor: 1, fRadialLabelColor: 1,
extend(obj, { fRadian: false, fDegree: false, fGrad: false, fPolarLabelColor: 1, fRadialLabelColor: 1,
fAxisAngle: 0, fPolarOffset: 0.04, fPolarTextSize: 0.04, fRadialOffset: 0.025, fRadialTextSize: 0.035,
fRwrmin: 0, fRwrmax: 1, fRwtmin: 0, fRwtmax: 2*Math.PI, fTickpolarSize: 0.02,
fPolarLabelFont: 62, fRadialLabelFont: 62, fCutRadial: 0, fNdivRad: 508, fNdivPol: 508 });
Expand Down
6 changes: 3 additions & 3 deletions js/modules/draw/TASImagePainter.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { create, settings, isNodeJs, isStr, btoa_func, clTAxis, clTPaletteAxis, clTImagePalette, getDocument } from '../core.mjs';
import { toColor } from '../base/colors.mjs';
import { assignContextMenu } from '../gui/menu.mjs';
import { assignContextMenu, kNoReorder } from '../gui/menu.mjs';
import { DrawOptions } from '../base/BasePainter.mjs';
import { ObjectPainter } from '../base/ObjectPainter.mjs';
import { TPavePainter } from '../hist/TPavePainter.mjs';
Expand Down Expand Up @@ -294,7 +294,7 @@ class TASImagePainter extends ObjectPainter {
img.style('cursor', 'pointer');
}

assignContextMenu(this);
assignContextMenu(this, kNoReorder);

if (!fp || !res.can_zoom)
return this;
Expand All @@ -307,7 +307,7 @@ class TASImagePainter extends ObjectPainter {
});
}

/** @summary Fill TASImage context */
/** @summary Fill TASImage context menu */
fillContextMenuItems(menu) {
const obj = this.getObject();
if (obj) {
Expand Down
Loading

0 comments on commit b7d8ff7

Please sign in to comment.