function strChars(inS) {
	for(inSz = 0, off = 0; off < inS.length; inSz++)
		inS.charAt(off, "UTF-8");
	return inSz;
}

im = SYS.XMLNode();
im.load(tmpl, false, 3);
if(!(drawArea=im.getElementBy("drawArea")) || !(scVer=im.getElementBy("scVer")) || !(scHor=im.getElementBy("scHor")) ||
		(styles=im.getElementsBy("style")[0]).isEVal())
	return "";

//Constants
RndRange = 5;

FD_GRD = 0x1;
FD_MARKS = 0x2;
FD_LOG = 0x4;

if(!end)	end = SYS.time();
begin = end - size;
reqPer = size/hsz;

//Getting the trends data
trends = new Array();
for(off = 0; (tEl=srcs.parseLine(0,off)).length; ) {
	elO = new Object();
	elO.addr = tEl.parse(0, ":");
	elO.min = tEl.parse(1, ":"); elO.max = tEl.parse(2, ":");
	elO.color = tEl.parse(3, ":");
	elO.scale = tEl.parse(4, ":").toInt();
	elO.width = max(1, tEl.parse(5,":").toInt());
	elO.beg = begin*1e6; elO.per = reqPer*1e6;
	if((elO.srcO=SYS.nodeAt(elO.addr))) {
		if(typeof(elO.srcO) == "TCntrNode:TVal")	elO.srcO = elO.srcO.arch();
		if(typeof(elO.srcO) != "TCntrNode:TVArchive")	continue;
		elO.val = elO.srcO.getVals(elO.beg, end*1e6, elO.per, arch);
	}
	else if(!(dDt=SYS.XMLNode()).load(elO.addr).toInt() && dDt.name() == "d") {
		elO.val = new Array();
		isSec = dDt.attr("s").toInt();
		isAprox = dDt.attr("aprox").toInt();
		elO.per = dDt.attr("per").toInt() * (isSec?1e6:1);

		for(prevPos = 0, prevVal = EVAL, maxPos = elO.per ? floor(1e6*(end-begin)/elO.per) : 0, off1 = 0; true; ) {
			if((svl=dDt.text().parse(0,",",off1)).length) {
				curPos = svl.parse(0,"=").toInt(), curVal = ((curVal=svl.parse(1,"="))==EVAL)?EVAL:curVal.toReal();
				if(!maxPos) {
					elO.val.push(tVl=new Object());
					tVl.tm = curPos;
					tVl.val = curVal;
					continue;
				}
			}
			else if(!maxPos)	break;
			else curPos = maxPos+1;
			for(stPos = prevPos; prevPos < curPos; prevPos++)
				if(isAprox && !prevVal.isEVal() && !curVal.isEVal())
					elO.val.push(prevVal+(curVal-prevVal)*(prevPos-stPos)/(curPos-stPos));
				else elO.val.push(prevVal);
			if(prevPos > maxPos)	break;
			prevVal = curVal;
		}
	}
	else continue;

	trends.push(elO);
}

im.setAttr("width", hsz).setAttr("height", vsz).setAttr("viewBox", "0 0 "+hsz+" "+vsz);

//Getting the labels font
if(!(tVl=im.attr("sclMarkFont")).length)	tVl = "Arial "+max(5,floor(hsz/50));
off = 0;
styles.setText("\ntext { font-family: "+tVl.parse(0," ",off)+"; font-size: "+(mrkFontSize=tVl.parse(0," ",off).toInt())+"px; "
		"font-weight: "+(tVl.parse(0," ",off).toInt()?"bold":"normal")+"; font-style: "+(tVl.parse(0," ",off).toInt()?"italic":"normal")+"; }" + styles.text());
sclHor = (tVl=im.attr("sclHor")).length ? tVl.toInt() : FD_MARKS;
sclVer = (tVl=im.attr("sclVer")).length ? tVl.toInt() : FD_MARKS|FD_GRD;
if(!(sclColor=im.attr("sclColor")).length)			sclColor = "gray";
if(!(sclMarkColor=im.attr("sclMarkColor")).length)	sclMarkColor = "gray";

mrkFontWRange = 0.7;
mrkWidth = 5*mrkFontSize*mrkFontWRange;
mrkHeight = mrkFontSize;

tArMrg = 2;
tArX	= tArMrg;
tArW	= hsz - tArX - tArMrg;
tArY	= tArMrg;
tArH	= vsz - tArY - tArMrg;
if(sclHor&FD_MARKS) {
	if(tArH < 100) sclHor = sclHor & ~(FD_MARKS);
	else tArH -= mrkHeight*2;
}

//Calculating the vertical scale
vsPerc = true;			//Vertical scale percent mode
isLog = sclVer&FD_LOG;		//Logarithmic scale
vsMax = -3e300, vsMin = 3e300;	//Trend's vertical scale border

// Get main scale for non individual parameters
prmInGrp = 0, prmGrpLast = -1;
for(iP = 0, mainPerc = false; iP < trends.length; iP++) {
	cP = trends[iP];
	if(!cP.val.length || !cP.color.length) continue;
	cP.adjU = -3e300, cP.adjL = 3e300;
	if(cP.max > cP.min)	cP.adjL = cP.min, cP.adjU = cP.max;
	else {
		for(iDt = 0; iDt < cP.val.length; iDt++) {
			if(cP.per && cP.val[iDt] != null) { cP.adjL = min(cP.adjL, cP.val[iDt]); cP.adjU = max(cP.adjU, cP.val[iDt]); }
			else if(!cP.per && cP.val[iDt].val != null) { cP.adjL = min(cP.adjL, cP.val[iDt].val); cP.adjU = max(cP.adjU, cP.val[iDt].val); }
		}
		// Value range expanding
		//  No value
		if(cP.adjU == -3e300)	cP.adjU = 1, cP.adjL = 0;
		// Range and absolute value are very small
		else if((cP.adjU-cP.adjL) < 1e-30 && abs(cP.adjU) < 1e-30)	cP.adjU += 0.5, cP.adjL -= 0.5;
		// Only range is very small
		else if((cP.adjU-cP.adjL) < 1e-30)
			cP.adjL -= (iP/trends.length)*abs(cP.adjU), cP.adjU += (1-iP/trends.length)*abs(cP.adjU);
		// Range smaller relatively to absolute value
		else if((cP.adjU-cP.adjL) / abs(cP.adjL+(cP.adjU-cP.adjL)/2) < 0.001) {
			wnt_dp = 0.001*abs(cP.adjL+(cP.adjU-cP.adjL)/2)-(cP.adjU-cP.adjL);
			cP.adjL -= (iP/trends.length)*wnt_dp, cP.adjU += (1-iP/trends.length)*wnt_dp;
		}
	}

	cP.wScale = cP.scale&(sclVer|FD_LOG);
	if(cP.wScale&(FD_MARKS|FD_GRD))	continue;

	//  Check for value border allow
	if(!mainPerc && (vsMin > vsMax || max(abs((vsMax-cP.adjL)/(vsMax-vsMin)-1),abs((cP.adjU-vsMin)/(vsMax-vsMin)-1)) < 0.2))
	{ vsMin = min(vsMin, cP.adjL); vsMax = max(vsMax, cP.adjU); }
	else { vsMax = -3e300; vsMin = 3e300; mainPerc = true; }

	prmInGrp++; prmGrpLast = iP;
}

// Checking for individual parameters and for the possibility to merge their to groups or create a new one for no group
prmIndiv = 0, prmIndivSc = -1, prmsInd = new Array();
for(iP = 0; iP < trends.length; iP++) {
	cP = trends[iP];
	cP.isIndiv = false;
	if(!cP.val.length || !cP.color.length || !(cP.wScale&(FD_MARKS|FD_GRD))) continue;
	// Checking for include to the present one or create a new group and exclude from individual ones
	if((!prmInGrp || (vsMin < vsMax && max(abs((vsMax-cP.adjL)/(vsMax-vsMin)-1),abs((cP.adjU-vsMin)/(vsMax-vsMin)-1)) < 0.2)) &&
			(cP.scale&FD_LOG) == (sclVer&FD_LOG))
	{
		vsMin = min(vsMin, cP.adjL); vsMax = max(vsMax, cP.adjU);
		prmInGrp++; prmGrpLast = iP;
		continue;
	}
	cP.isIndiv = true;
	prmIndiv++;
	if(prmIndivSc < 0 && (cP.scale&FD_GRD)) prmIndivSc = iP;
	else prmsInd.push(iP);
	if(cP.scale&FD_LOG) {
		cP.adjU = lg(max(1e-100,cP.adjU)); cP.adjL = lg(max(1e-100,cP.adjL));
		if((cP.adjU-cP.adjL) / abs(cP.adjL+(cP.adjU-cP.adjL)/2) < 0.0001) {
			wnt_dp = 0.0001*abs(cP.adjL+(cP.adjU-cP.adjL)/2)-(cP.adjU-cP.adjL);
			cP.adjL -= wnt_dp/2; cP.adjU += wnt_dp/2;
		}
	}
}
if(prmInGrp) prmsInd.push(-1);
if(prmIndivSc >= 0) prmsInd.push(prmIndivSc);

// Final main scale adapting
if(vsMin > vsMax) { vsPerc = true; vsMax = 100; vsMin = isLog ? pow(10,min(0,2-(tArH/150))) : 0; }
else vsPerc = false;
if(isLog) {
	vsMax = lg(max(1e-100,vsMax)); vsMin = lg(max(1e-100,vsMin));
	if((vsMax-vsMin) / abs(vsMin+(vsMax-vsMin)/2) < 0.0001) {
		wnt_dp = 0.0001*abs(vsMin+(vsMax-vsMin)/2)-(vsMax-vsMin);
		vsMin -= wnt_dp/2; vsMax += wnt_dp/2;
	}
}

//Draw main and individual vertical scales
vmax_ln = tArH / ((sclVer&FD_MARKS)?(2*mrkHeight):15);
for(iP = 0; vmax_ln >= 2 && iP < prmsInd.length; iP++) {	//prmsInd[i]=-1 - for main scale
	vDiv = 1;
	if(prmsInd[iP] < 0) {	//Main scale process
		// Draw the environment
		vsPercT = vsPerc;
		isLogT = isLog;
		sclVerT = sclVer;
		clrGridT = sclColor;
		clrMrk = sclMarkColor;
		if(prmInGrp == 1 && prmGrpLast >= 0)	//Set color for single parameter in main group
			clrGridT = clrMrk = trends[prmGrpLast].color;
		// Rounding
		v_len = vsMax - vsMin;
		while(v_len > vmax_ln)						{ vDiv *= 10; v_len /= 10; }
		while(v_len && v_len < vmax_ln/10)	{ vDiv /= 10; v_len *= 10; }
		vsMin = floor(vsMin/vDiv)*vDiv; vsMax = ceil(vsMax/vDiv)*vDiv;
		while(!isLogT && ((vsMax-vsMin)/vDiv) < vmax_ln/2) vDiv /= 2;
		vsMinT = vsMin; vsMaxT = vsMax;
	}
	else {	//Individual scale process
		cP = trends[prmsInd[iP]];
		// Draw environment
		vsPercT = false;
		isLogT = cP.scale&FD_LOG;
		sclVerT = cP.wScale;
		clrGridT = clrMrk = cP.color;
		// Rounding
		v_len = cP.adjU - cP.adjL;
		while(v_len > vmax_ln)						{ vDiv *= 10; v_len /= 10; }
		while(v_len && v_len < vmax_ln/10)	{ vDiv /= 10; v_len *= 10; }
		cP.adjL = floor(cP.adjL/vDiv)*vDiv; cP.adjU = ceil(cP.adjU/vDiv)*vDiv;
		while(!isLogT && ((cP.adjU-cP.adjL)/vDiv) < vmax_ln/2) vDiv /= 2;
		vsMinT = cP.adjL; vsMaxT = cP.adjU;
	}
	if(iP < (prmsInd.length-1))	sclVerT = sclVerT&(~FD_GRD);	//Hide grid for not last scale

	// Draw vertical grid and markers
	markWdth = 0;
	if(sclVerT&(FD_MARKS|FD_GRD)) {
		scVer.childAdd("rect").setAttr("fill",clrGridT).setAttr("x",tArX-1).setAttr("y",tArY).setAttr("width",1).setAttr("height",tArH);
		for(iV = ceil(vsMinT/vDiv)*vDiv; (vsMaxT-iV)/vDiv > -0.1; iV += vDiv) {
			//  Draw grid
			v_pos = tArY + tArH - tArH*(iV-vsMinT)/(vsMaxT-vsMinT);
			if(sclVerT&FD_GRD)	scVer.childAdd("rect").setAttr("fill",sclColor).setAttr("x",tArX).setAttr("y",floor(v_pos+0.5)).setAttr("width",tArW).setAttr("height",1);
			else	scVer.childAdd("rect").setAttr("fill",clrGridT).setAttr("x",tArX-3).setAttr("y",floor(v_pos+0.5)).setAttr("width",6).setAttr("height",1);
			//  Draw markers
			if(sclVerT&FD_MARKS) {
				isPerc = vsPercT && ((vsMaxT-iV-vDiv)/vDiv <= -0.1);
				isMax = (v_pos-1-mrkHeight) < tArY;
				labVal = (isLogT?pow(10,iV):iV).toPrecision(5) + (isPerc?" %":"");
				scVer.childAdd("text").setAttr("text-anchor","start").setAttr("stroke","none")
						.setAttr("fill", clrMrk)
						.setAttr("x",tArX+2).setAttr("y",floor(v_pos-1+(isMax?mrkHeight:0)+0.5)).setText(labVal);
				markWdth = max(markWdth, labVal.length*mrkFontSize*mrkFontWRange);
			}
		}
	}
	if(iP < (prmsInd.length-1)) { tArX += markWdth?(markWdth+5):0; tArW -= markWdth?(markWdth+5):0; }
}

//Calc and draw the horizontal scale
hDiv = 1;			//Horisontal scale divisor
hmax_ln = tArW / ((sclHor&FD_MARKS)?mrkWidth:15);
if(hmax_ln >= 2) {
	hvLev = 0;
	hLen = end - begin;

	if(hLen/2635200 >= 5)		{ hvLev = 7; hDiv = 2635200; }	//Month a unstrict interval !!!! to implement !!!!
	else if(hLen/86400 >= 5)	{ hvLev = 6; hDiv =   86400; }	//More days and no time in the scale
	else if(hLen/86400 >= 2)	{ hvLev = 5; hDiv =   86400; }	//Days
	else if(hLen/3600 >= 2)	{ hvLev = 4; hDiv =    3600; }	//Hours
	else if(hLen/60 >= 2)		{ hvLev = 3; hDiv =      60; }	//Minutes
	else if(hLen/1 >= 2)		{ hvLev = 2; hDiv =       1; }	//Seconds
	else if(hLen/0.001 >= 2)	{ hvLev = 1; hDiv =   0.001; }	//Milliseconds

	// Draw the horisontal grid and markers
	if(sclHor&(FD_MARKS|FD_GRD)) {
		tm_t = 0;
		lab_tm = lab_dt = "";

		//  Draw generic grid line
		scHor.childAdd("rect").setAttr("fill",sclColor).setAttr("x",floor(tArX+0.5)).setAttr("y",floor(tArY+tArH+0.5)).setAttr("width",floor(tArW+0.5)).setAttr("height",1);

		//  Draw full trend's data and time to the trend end position
		begMarkBrd = -5;
		endMarkBrd = tArX + tArW;
		if((sclHor&FD_MARKS) && mrkHeight) {
			lab_dt = SYS.strftime(end, "%d-%m-%Y");
			if((end%60) == 0 && (end-floor(end)) == 0)
				lab_tm = SYS.strftime(end, "%H:%M");
			else if((end-floor(end)) == 0)
				lab_tm = SYS.strftime(end, "%H:%M:%S");
			else lab_tm = SYS.strftime(end, "%H:%M:%S")+"."+(end-floor(end));

			markY = tArY + tArH + mrkHeight;
			if(hvLev < 6) {
				scHor.childAdd("text").setAttr("text-anchor","end").setAttr("stroke","none")
					.setAttr("fill",sclMarkColor)
					.setAttr("x",tArX+tArW).setAttr("y",markY).setText(lab_tm);
				endMarkBrd = min(endMarkBrd, tArX + tArW - mrkFontSize*lab_tm.length*mrkFontWRange);
				markY += mrkHeight;
			}
			scHor.childAdd("text").setAttr("text-anchor","end").setAttr("stroke","none")
				.setAttr("fill",sclMarkColor)
				.setAttr("x",tArX+tArW).setAttr("y",markY).setText(lab_dt);
			endMarkBrd = min(endMarkBrd, tArX + tArW - mrkFontSize*lab_dt.length*mrkFontWRange);
		}


		hDiv_ = hDiv;
		while(hLen/hDiv_ > hmax_ln)	hDiv_ *= 10;
		while(hLen/hDiv_ < hmax_ln/5 && (1e6*hDiv_/5)%(1e6*hDiv) == 0) hDiv_ /= 5;
		while(hLen/hDiv_ < hmax_ln/2 && (hvLev < 6 || (1e6*hDiv_/2)%(1e6*hDiv) == 0)) hDiv_ /= 2;
		hDiv = hDiv_;

		UTChourDt = SYS.strptimegm(SYS.strftime(end)) - end;

		//  Draw grid and/or markers
		first_m = true;
		ttm1 = new Object();
		for(iH = begin; true; ) {
			//   Draw grid
			h_pos = tArX + tArW*(iH-begin)/(end-begin);
			if(sclHor&FD_GRD)
				scHor.childAdd("rect").setAttr("fill",sclColor).setAttr("x",floor(h_pos+0.5)).setAttr("y",floor(tArY+0.5)).setAttr("width",1).setAttr("height",tArH);
			else scHor.childAdd("rect").setAttr("fill",sclColor).setAttr("x",floor(h_pos+0.5)).setAttr("y",floor(tArY+tArH-3+0.5)).setAttr("width",1).setAttr("height",6);

			//   Draw markers
			if((sclHor&FD_MARKS) && (!(1e6*(iH+UTChourDt)%(1e6*hDiv)) || hvLev >= 7) && iH != end) {
				if(first_m)	SYS.localtime(begin-(end-begin), ttm1.sec, ttm1.min, ttm1.hour, ttm1.mday, ttm1.mon);
				ttm = new Object();
				SYS.localtime(iH, ttm.sec, ttm.min, ttm.hour, ttm.mday, ttm.mon);

				chLev = 0;
				if(ttm.year-ttm1.year)			chLev = 6;
				else if(ttm.mon-ttm1.mon) 	chLev = 5;
				else if(ttm.mday-ttm1.mday)	chLev = 4;
				else if(ttm.hour-ttm1.hour)	chLev = 3;
				else if(ttm.min-ttm1.min)		chLev = 2;
				else if(ttm.sec-ttm1.sec)		chLev = 1;

				//Checking for the data presence
				lab_dt = lab_tm = "";
				//Date
				if(hvLev == 7)
					lab_dt = SYS.strftime(iH, (chLev>=6)?"%B %Y":"%B");
				else if(/*hvLev == 5 ||*/ chLev >= 4)
					lab_dt = SYS.strftime(iH, (chLev>=5)?"%d-%m-%Y":"%d");
				//Hours and minuts
				if((hvLev == 4 || hvLev == 3 || ttm.hour || ttm.min) && !ttm.sec)
					lab_tm = SYS.strftime(iH, "%H:%M");
				//Seconds
				else if((hvLev == 2 || ttm.sec) && !((iH-floor(iH))*1e6))
					lab_tm = (chLev >= 2) ? SYS.strftime(iH, "%H:%M:%S") : (iH%60).toPrecision(6)+tr("s");
				//Milliseconds
				else if(hvLev <= 1 || (iH-floor(iH))*1e6)
					lab_tm = (chLev >= 2) ? SYS.strftime(iH, "%H:%M:%S")+(iH-floor(iH)).toPrecision(6).slice(1) :
								(chLev >= 1) ? ((iH%60)+(iH-floor(iH))).toPrecision(6)+tr("s") :
													(1e3*iH).toPrecision(6)+tr("ms");

				//SYS.messInfo("DG", "lab_tm="+lab_tm+"; hvLev="+hvLev+"; chLev="+chLev+"; iH="+iH);

				endPosTm = endPosDt = begMarkBrd, markY = tArY + tArH + mrkHeight;
				if(hvLev < 6) {
					if(lab_tm.length) {
						wdth = mrkFontSize*strChars(lab_tm)*mrkFontWRange;
						tpos = max(h_pos-wdth/2, 0);
						if(first_m || (tpos+wdth) < endMarkBrd && tpos > begMarkBrd) {
							if(first_m)	tpos = max(begMarkBrd, tpos);
							scHor.childAdd("text").setAttr("text-anchor",(first_m?"start":"middle")).setAttr("stroke","none")
								.setAttr("fill",sclMarkColor)
								.setAttr("x",floor(tpos+(first_m?0:wdth/2)+0.5)).setAttr("y",floor(markY+0.5)).setText(lab_tm);
							endPosTm = tpos + wdth;
						}
					}
					markY += mrkHeight;
				}
				if(lab_dt.length) {
					wdth = mrkFontSize*strChars(lab_dt)*mrkFontWRange;
					tpos = max(h_pos-wdth/2, 0);
					if(first_m || (tpos+wdth) < endMarkBrd && tpos > begMarkBrd) {
						if(first_m)	tpos = max(begMarkBrd, tpos);
						scHor.childAdd("text").setAttr("text-anchor",(first_m?"start":"middle")).setAttr("stroke","none")
							.setAttr("fill",sclMarkColor)
							.setAttr("x",floor(tpos+(first_m?0:wdth/2)+0.5)).setAttr("y",floor(markY+0.5)).setText(lab_dt);
						endPosDt = tpos + wdth;
					}
				}
				begMarkBrd = max(begMarkBrd, max(endPosTm,endPosDt));
				ttm1 = ttm;
				first_m = false;
			}

			//   Next
			if(iH >= end) break;
			if(hvLev >= 7) {	//Per month
				curYear = curMonth = 0;
				SYS.localtime(iH, 0, 0, 0, 0, curMonth, curYear);
				iH = SYS.mktime(0, 0, 0, 1, curMonth+1, curYear);
			} else iH = floor((iH+UTChourDt)/hDiv)*hDiv + hDiv - UTChourDt;
			iH = min(end, iH);
		}
	}
}

//Drawing the trends
for(iTr = 0; iTr < trends.length; iTr++) {
	cP = trends[iTr];

	vsPercT = cP.isIndiv ? false : vsPerc;
	isLogT = cP.isIndiv ? (cP.wScale&FD_LOG) : isLog;
	vsMaxT = cP.isIndiv ? cP.adjU : vsMax;
	vsMinT = cP.isIndiv ? cP.adjL : vsMin;

	// Prepare border for percent trend
	bordL = cP.min;
	bordU = cP.max;
	if(vsPercT && bordL >= bordU) { bordL = cP.adjL; bordU = cP.adjU; }
		/*bordU = -3e300, bordL = 3e300;
		for(iDt = 0; iDt < cP.val.length; iDt++) {
			c_val = cP.val[iDt];
			if(!c_val.isEVal()) { bordL = min(bordL, c_val); bordU = max(bordU, c_val); }
		}
		if((vMarg=(bordU-bordL)/10) == 0) vMarg = 0.5;
		bordL -= vMarg;
		bordU += vMarg;
	}*/

	trPath = 0; prev_vl = EVAL; prev_pos = prev_vpos = 0;
	for(iDt = 0; iDt < cP.val.length; iDt++) {
		if(cP.per)	c_val = cP.val[iDt], c_tm = 1e-6*(cP.beg + iDt*cP.per);
		else c_val = cP.val[iDt].val, c_tm = cP.val[iDt].tm;
		if(vsPercT && !c_val.isEVal()) c_val = 100*(c_val-bordL)/(bordU-bordL);
		if(c_tm < begin)	continue;
		if(c_tm > end)		break;
		c_pos = floor(tArX + tArW*(c_tm-begin)/(end-begin));
		if(!c_val.isEVal()) {
			c_vpos = max(tArY,min(tArY+tArH,floor(tArY + tArH - tArH*((isLogT?lg(max(1e-100,c_val)):c_val)-vsMinT)/(vsMaxT-vsMinT))));
			if(!trPath) trPath = drawArea.childAdd("path").setAttr("stroke", cP.color).setAttr("stroke-width",cP.width);
			if(prev_vl.isEVal()) trPath.setAttr("d", trPath.attr("d")+"M "+c_pos+" "+c_vpos+" ");
			else if(abs(c_pos-prev_pos) > RndRange && abs(c_vpos-prev_vpos) > RndRange) {
				// Curvature [0.1...0.5] depending the rising level
				curvLev = -0.2*(max(-2*RndRange,min(2*RndRange,prev_vpos-c_vpos))-2*RndRange)/(2*RndRange)+0.1;
				// Same drawing
				trPath.setAttr("d",trPath.attr("d")+"C "+(prev_pos+(tVl=curvLev*(c_pos-prev_pos)))+" "+prev_vpos+", "+(c_pos-tVl)+" "+c_vpos+", "+c_pos+" "+c_vpos+" ");
			}
			else trPath.setAttr("d",trPath.attr("d")+"L "+c_pos+" "+c_vpos+" ");
		}
		else if(!prev_vl.isEVal()) {
			c_vpos = max(tArY,min(tArY+tArH,floor(tArY + tArH - tArH*((isLogT?lg(max(1e-100,prev_vl)):prev_vl)-vsMinT)/(vsMaxT-vsMinT))));
			trPath.setAttr("d", trPath.attr("d")+"L "+prev_pos+".1 "+c_vpos+".1 ");
		}
		prev_vl = c_val, prev_pos = c_pos, prev_vpos = c_vpos;
	}
}

return im.save();