wz_jsgraphics.js 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108
  1. /* This notice must be untouched at all times.
  2. wz_jsgraphics.js v. 3.05
  3. The latest version is available at
  4. http://www.walterzorn.com
  5. or http://www.devira.com
  6. or http://www.walterzorn.de
  7. Copyright (c) 2002-2009 Walter Zorn. All rights reserved.
  8. Created 3. 11. 2002 by Walter Zorn (Web: http://www.walterzorn.com )
  9. Last modified: 2. 2. 2009
  10. Performance optimizations for Internet Explorer
  11. by Thomas Frank and John Holdsworth.
  12. fillPolygon method implemented by Matthieu Haller.
  13. High Performance JavaScript Graphics Library.
  14. Provides methods
  15. - to draw lines, rectangles, ellipses, polygons
  16. with specifiable line thickness,
  17. - to fill rectangles, polygons, ellipses and arcs
  18. - to draw text.
  19. NOTE: Operations, functions and branching have rather been optimized
  20. to efficiency and speed than to shortness of source code.
  21. LICENSE: LGPL
  22. This library is free software; you can redistribute it and/or
  23. modify it under the terms of the GNU Lesser General Public
  24. License (LGPL) as published by the Free Software Foundation; either
  25. version 2.1 of the License, or (at your option) any later version.
  26. This library is distributed in the hope that it will be useful,
  27. but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  29. Lesser General Public License for more details.
  30. You should have received a copy of the GNU Lesser General Public
  31. License along with this library; if not, write to the Free Software
  32. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
  33. or see http://www.gnu.org/copyleft/lesser.html
  34. */
  35. var jg_ok, jg_ie, jg_fast, jg_dom, jg_moz;
  36. function _chkDHTM(wnd, x, i)
  37. // Under XUL, owner of 'document' must be specified explicitly
  38. {
  39. x = wnd.document.body || null;
  40. jg_ie = x && typeof x.insertAdjacentHTML != "undefined" && wnd.document.createElement;
  41. jg_dom = (x && !jg_ie &&
  42. typeof x.appendChild != "undefined" &&
  43. typeof wnd.document.createRange != "undefined" &&
  44. typeof (i = wnd.document.createRange()).setStartBefore != "undefined" &&
  45. typeof i.createContextualFragment != "undefined");
  46. jg_fast = jg_ie && wnd.document.all && !wnd.opera;
  47. jg_moz = jg_dom && typeof x.style.MozOpacity != "undefined";
  48. jg_ok = !!(jg_ie || jg_dom);
  49. };
  50. function _pntCnvDom()
  51. {
  52. var x = this.wnd.document.createRange();
  53. x.setStartBefore(this.cnv);
  54. x = x.createContextualFragment(jg_fast? this._htmRpc() : this.htm);
  55. if(this.cnv) this.cnv.appendChild(x);
  56. this.htm = "";
  57. };
  58. function _pntCnvIe()
  59. {
  60. if(this.cnv) this.cnv.insertAdjacentHTML("BeforeEnd", jg_fast? this._htmRpc() : this.htm);
  61. this.htm = "";
  62. };
  63. function _pntDoc()
  64. {
  65. this.wnd.document.write(jg_fast? this._htmRpc() : this.htm);
  66. this.htm = '';
  67. };
  68. function _pntN()
  69. {
  70. ;
  71. };
  72. function _mkDiv(x, y, w, h)
  73. {
  74. this.htm += '<div style="position:absolute;'+
  75. 'left:' + x + 'px;'+
  76. 'top:' + y + 'px;'+
  77. 'width:' + w + 'px;'+
  78. 'height:' + h + 'px;'+
  79. 'clip:rect(0,'+w+'px,'+h+'px,0);'+
  80. 'background-color:' + this.color +
  81. (!jg_moz? ';overflow:hidden' : '')+
  82. ';"><\/div>';
  83. };
  84. function _mkDivIe(x, y, w, h)
  85. {
  86. this.htm += '%%'+this.color+';'+x+';'+y+';'+w+';'+h+';';
  87. };
  88. function _mkDivPrt(x, y, w, h)
  89. {
  90. this.htm += '<div style="position:absolute;'+
  91. 'border-left:' + w + 'px solid ' + this.color + ';'+
  92. 'left:' + x + 'px;'+
  93. 'top:' + y + 'px;'+
  94. 'width:0px;'+
  95. 'height:' + h + 'px;'+
  96. 'clip:rect(0,'+w+'px,'+h+'px,0);'+
  97. 'background-color:' + this.color +
  98. (!jg_moz? ';overflow:hidden' : '')+
  99. ';"><\/div>';
  100. };
  101. var _regex = /%%([^;]+);([^;]+);([^;]+);([^;]+);([^;]+);/g;
  102. function _htmRpc()
  103. {
  104. return this.htm.replace(
  105. _regex,
  106. '<div style="overflow:hidden;position:absolute;background-color:'+
  107. '$1;left:$2px;top:$3px;width:$4px;height:$5px"></div>\n');
  108. };
  109. function _htmPrtRpc()
  110. {
  111. return this.htm.replace(
  112. _regex,
  113. '<div style="overflow:hidden;position:absolute;background-color:'+
  114. '$1;left:$2px;top:$3px;width:$4px;height:$5px;border-left:$4px solid $1"></div>\n');
  115. };
  116. function _mkLin(x1, y1, x2, y2)
  117. {
  118. if(x1 > x2)
  119. {
  120. var _x2 = x2;
  121. var _y2 = y2;
  122. x2 = x1;
  123. y2 = y1;
  124. x1 = _x2;
  125. y1 = _y2;
  126. }
  127. var dx = x2-x1, dy = Math.abs(y2-y1),
  128. x = x1, y = y1,
  129. yIncr = (y1 > y2)? -1 : 1;
  130. if(dx >= dy)
  131. {
  132. var pr = dy<<1,
  133. pru = pr - (dx<<1),
  134. p = pr-dx,
  135. ox = x;
  136. while(dx > 0)
  137. {--dx;
  138. ++x;
  139. if(p > 0)
  140. {
  141. this._mkDiv(ox, y, x-ox, 1);
  142. y += yIncr;
  143. p += pru;
  144. ox = x;
  145. }
  146. else p += pr;
  147. }
  148. this._mkDiv(ox, y, x2-ox+1, 1);
  149. }
  150. else
  151. {
  152. var pr = dx<<1,
  153. pru = pr - (dy<<1),
  154. p = pr-dy,
  155. oy = y;
  156. if(y2 <= y1)
  157. {
  158. while(dy > 0)
  159. {--dy;
  160. if(p > 0)
  161. {
  162. this._mkDiv(x++, y, 1, oy-y+1);
  163. y += yIncr;
  164. p += pru;
  165. oy = y;
  166. }
  167. else
  168. {
  169. y += yIncr;
  170. p += pr;
  171. }
  172. }
  173. this._mkDiv(x2, y2, 1, oy-y2+1);
  174. }
  175. else
  176. {
  177. while(dy > 0)
  178. {--dy;
  179. y += yIncr;
  180. if(p > 0)
  181. {
  182. this._mkDiv(x++, oy, 1, y-oy);
  183. p += pru;
  184. oy = y;
  185. }
  186. else p += pr;
  187. }
  188. this._mkDiv(x2, oy, 1, y2-oy+1);
  189. }
  190. }
  191. };
  192. function _mkLin2D(x1, y1, x2, y2)
  193. {
  194. if(x1 > x2)
  195. {
  196. var _x2 = x2;
  197. var _y2 = y2;
  198. x2 = x1;
  199. y2 = y1;
  200. x1 = _x2;
  201. y1 = _y2;
  202. }
  203. var dx = x2-x1, dy = Math.abs(y2-y1),
  204. x = x1, y = y1,
  205. yIncr = (y1 > y2)? -1 : 1;
  206. var s = this.stroke;
  207. if(dx >= dy)
  208. {
  209. if(dx > 0 && s-3 > 0)
  210. {
  211. var _s = (s*dx*Math.sqrt(1+dy*dy/(dx*dx))-dx-(s>>1)*dy) / dx;
  212. _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;
  213. }
  214. else var _s = s;
  215. var ad = Math.ceil(s/2);
  216. var pr = dy<<1,
  217. pru = pr - (dx<<1),
  218. p = pr-dx,
  219. ox = x;
  220. while(dx > 0)
  221. {--dx;
  222. ++x;
  223. if(p > 0)
  224. {
  225. this._mkDiv(ox, y, x-ox+ad, _s);
  226. y += yIncr;
  227. p += pru;
  228. ox = x;
  229. }
  230. else p += pr;
  231. }
  232. this._mkDiv(ox, y, x2-ox+ad+1, _s);
  233. }
  234. else
  235. {
  236. if(s-3 > 0)
  237. {
  238. var _s = (s*dy*Math.sqrt(1+dx*dx/(dy*dy))-(s>>1)*dx-dy) / dy;
  239. _s = (!(s-4)? Math.ceil(_s) : Math.round(_s)) + 1;
  240. }
  241. else var _s = s;
  242. var ad = Math.round(s/2);
  243. var pr = dx<<1,
  244. pru = pr - (dy<<1),
  245. p = pr-dy,
  246. oy = y;
  247. if(y2 <= y1)
  248. {
  249. ++ad;
  250. while(dy > 0)
  251. {--dy;
  252. if(p > 0)
  253. {
  254. this._mkDiv(x++, y, _s, oy-y+ad);
  255. y += yIncr;
  256. p += pru;
  257. oy = y;
  258. }
  259. else
  260. {
  261. y += yIncr;
  262. p += pr;
  263. }
  264. }
  265. this._mkDiv(x2, y2, _s, oy-y2+ad);
  266. }
  267. else
  268. {
  269. while(dy > 0)
  270. {--dy;
  271. y += yIncr;
  272. if(p > 0)
  273. {
  274. this._mkDiv(x++, oy, _s, y-oy+ad);
  275. p += pru;
  276. oy = y;
  277. }
  278. else p += pr;
  279. }
  280. this._mkDiv(x2, oy, _s, y2-oy+ad+1);
  281. }
  282. }
  283. };
  284. function _mkLinDott(x1, y1, x2, y2)
  285. {
  286. if(x1 > x2)
  287. {
  288. var _x2 = x2;
  289. var _y2 = y2;
  290. x2 = x1;
  291. y2 = y1;
  292. x1 = _x2;
  293. y1 = _y2;
  294. }
  295. var dx = x2-x1, dy = Math.abs(y2-y1),
  296. x = x1, y = y1,
  297. yIncr = (y1 > y2)? -1 : 1,
  298. drw = true;
  299. if(dx >= dy)
  300. {
  301. var pr = dy<<1,
  302. pru = pr - (dx<<1),
  303. p = pr-dx;
  304. while(dx > 0)
  305. {--dx;
  306. if(drw) this._mkDiv(x, y, 1, 1);
  307. drw = !drw;
  308. if(p > 0)
  309. {
  310. y += yIncr;
  311. p += pru;
  312. }
  313. else p += pr;
  314. ++x;
  315. }
  316. }
  317. else
  318. {
  319. var pr = dx<<1,
  320. pru = pr - (dy<<1),
  321. p = pr-dy;
  322. while(dy > 0)
  323. {--dy;
  324. if(drw) this._mkDiv(x, y, 1, 1);
  325. drw = !drw;
  326. y += yIncr;
  327. if(p > 0)
  328. {
  329. ++x;
  330. p += pru;
  331. }
  332. else p += pr;
  333. }
  334. }
  335. if(drw) this._mkDiv(x, y, 1, 1);
  336. };
  337. function _mkOv(left, top, width, height)
  338. {
  339. var a = (++width)>>1, b = (++height)>>1,
  340. wod = width&1, hod = height&1,
  341. cx = left+a, cy = top+b,
  342. x = 0, y = b,
  343. ox = 0, oy = b,
  344. aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,
  345. st = (aa2>>1)*(1-(b<<1)) + bb2,
  346. tt = (bb2>>1) - aa2*((b<<1)-1),
  347. w, h;
  348. while(y > 0)
  349. {
  350. if(st < 0)
  351. {
  352. st += bb2*((x<<1)+3);
  353. tt += bb4*(++x);
  354. }
  355. else if(tt < 0)
  356. {
  357. st += bb2*((x<<1)+3) - aa4*(y-1);
  358. tt += bb4*(++x) - aa2*(((y--)<<1)-3);
  359. w = x-ox;
  360. h = oy-y;
  361. if((w&2) && (h&2))
  362. {
  363. this._mkOvQds(cx, cy, x-2, y+2, 1, 1, wod, hod);
  364. this._mkOvQds(cx, cy, x-1, y+1, 1, 1, wod, hod);
  365. }
  366. else this._mkOvQds(cx, cy, x-1, oy, w, h, wod, hod);
  367. ox = x;
  368. oy = y;
  369. }
  370. else
  371. {
  372. tt -= aa2*((y<<1)-3);
  373. st -= aa4*(--y);
  374. }
  375. }
  376. w = a-ox+1;
  377. h = (oy<<1)+hod;
  378. y = cy-oy;
  379. this._mkDiv(cx-a, y, w, h);
  380. this._mkDiv(cx+ox+wod-1, y, w, h);
  381. };
  382. function _mkOv2D(left, top, width, height)
  383. {
  384. var s = this.stroke;
  385. width += s+1;
  386. height += s+1;
  387. var a = width>>1, b = height>>1,
  388. wod = width&1, hod = height&1,
  389. cx = left+a, cy = top+b,
  390. x = 0, y = b,
  391. aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,
  392. st = (aa2>>1)*(1-(b<<1)) + bb2,
  393. tt = (bb2>>1) - aa2*((b<<1)-1);
  394. if(s-4 < 0 && (!(s-2) || width-51 > 0 && height-51 > 0))
  395. {
  396. var ox = 0, oy = b,
  397. w, h,
  398. pxw;
  399. while(y > 0)
  400. {
  401. if(st < 0)
  402. {
  403. st += bb2*((x<<1)+3);
  404. tt += bb4*(++x);
  405. }
  406. else if(tt < 0)
  407. {
  408. st += bb2*((x<<1)+3) - aa4*(y-1);
  409. tt += bb4*(++x) - aa2*(((y--)<<1)-3);
  410. w = x-ox;
  411. h = oy-y;
  412. if(w-1)
  413. {
  414. pxw = w+1+(s&1);
  415. h = s;
  416. }
  417. else if(h-1)
  418. {
  419. pxw = s;
  420. h += 1+(s&1);
  421. }
  422. else pxw = h = s;
  423. this._mkOvQds(cx, cy, x-1, oy, pxw, h, wod, hod);
  424. ox = x;
  425. oy = y;
  426. }
  427. else
  428. {
  429. tt -= aa2*((y<<1)-3);
  430. st -= aa4*(--y);
  431. }
  432. }
  433. this._mkDiv(cx-a, cy-oy, s, (oy<<1)+hod);
  434. this._mkDiv(cx+a+wod-s, cy-oy, s, (oy<<1)+hod);
  435. }
  436. else
  437. {
  438. var _a = (width-(s<<1))>>1,
  439. _b = (height-(s<<1))>>1,
  440. _x = 0, _y = _b,
  441. _aa2 = (_a*_a)<<1, _aa4 = _aa2<<1, _bb2 = (_b*_b)<<1, _bb4 = _bb2<<1,
  442. _st = (_aa2>>1)*(1-(_b<<1)) + _bb2,
  443. _tt = (_bb2>>1) - _aa2*((_b<<1)-1),
  444. pxl = new Array(),
  445. pxt = new Array(),
  446. _pxb = [];
  447. pxl[0] = 0;
  448. pxt[0] = b;
  449. _pxb[0] = _b-1;
  450. while(y > 0)
  451. {
  452. if(st < 0)
  453. {
  454. pxl[pxl.length] = x;
  455. pxt[pxt.length] = y;
  456. st += bb2*((x<<1)+3);
  457. tt += bb4*(++x);
  458. }
  459. else if(tt < 0)
  460. {
  461. pxl[pxl.length] = x;
  462. st += bb2*((x<<1)+3) - aa4*(y-1);
  463. tt += bb4*(++x) - aa2*(((y--)<<1)-3);
  464. pxt[pxt.length] = y;
  465. }
  466. else
  467. {
  468. tt -= aa2*((y<<1)-3);
  469. st -= aa4*(--y);
  470. }
  471. if(_y > 0)
  472. {
  473. if(_st < 0)
  474. {
  475. _st += _bb2*((_x<<1)+3);
  476. _tt += _bb4*(++_x);
  477. _pxb[_pxb.length] = _y-1;
  478. }
  479. else if(_tt < 0)
  480. {
  481. _st += _bb2*((_x<<1)+3) - _aa4*(_y-1);
  482. _tt += _bb4*(++_x) - _aa2*(((_y--)<<1)-3);
  483. _pxb[_pxb.length] = _y-1;
  484. }
  485. else
  486. {
  487. _tt -= _aa2*((_y<<1)-3);
  488. _st -= _aa4*(--_y);
  489. _pxb[_pxb.length-1]--;
  490. }
  491. }
  492. }
  493. var ox = -wod, oy = b,
  494. _oy = _pxb[0],
  495. l = pxl.length,
  496. w, h;
  497. for(var i = 0; i < l; i++)
  498. {
  499. if(typeof _pxb[i] != "undefined")
  500. {
  501. if(_pxb[i] < _oy || pxt[i] < oy)
  502. {
  503. x = pxl[i];
  504. this._mkOvQds(cx, cy, x, oy, x-ox, oy-_oy, wod, hod);
  505. ox = x;
  506. oy = pxt[i];
  507. _oy = _pxb[i];
  508. }
  509. }
  510. else
  511. {
  512. x = pxl[i];
  513. this._mkDiv(cx-x, cy-oy, 1, (oy<<1)+hod);
  514. this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
  515. ox = x;
  516. oy = pxt[i];
  517. }
  518. }
  519. this._mkDiv(cx-a, cy-oy, 1, (oy<<1)+hod);
  520. this._mkDiv(cx+ox+wod, cy-oy, 1, (oy<<1)+hod);
  521. }
  522. };
  523. function _mkOvDott(left, top, width, height)
  524. {
  525. var a = (++width)>>1, b = (++height)>>1,
  526. wod = width&1, hod = height&1, hodu = hod^1,
  527. cx = left+a, cy = top+b,
  528. x = 0, y = b,
  529. aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,
  530. st = (aa2>>1)*(1-(b<<1)) + bb2,
  531. tt = (bb2>>1) - aa2*((b<<1)-1),
  532. drw = true;
  533. while(y > 0)
  534. {
  535. if(st < 0)
  536. {
  537. st += bb2*((x<<1)+3);
  538. tt += bb4*(++x);
  539. }
  540. else if(tt < 0)
  541. {
  542. st += bb2*((x<<1)+3) - aa4*(y-1);
  543. tt += bb4*(++x) - aa2*(((y--)<<1)-3);
  544. }
  545. else
  546. {
  547. tt -= aa2*((y<<1)-3);
  548. st -= aa4*(--y);
  549. }
  550. if(drw && y >= hodu) this._mkOvQds(cx, cy, x, y, 1, 1, wod, hod);
  551. drw = !drw;
  552. }
  553. };
  554. function _mkRect(x, y, w, h)
  555. {
  556. var s = this.stroke;
  557. this._mkDiv(x, y, w, s);
  558. this._mkDiv(x+w, y, s, h);
  559. this._mkDiv(x, y+h, w+s, s);
  560. this._mkDiv(x, y+s, s, h-s);
  561. };
  562. function _mkRectDott(x, y, w, h)
  563. {
  564. this.drawLine(x, y, x+w, y);
  565. this.drawLine(x+w, y, x+w, y+h);
  566. this.drawLine(x, y+h, x+w, y+h);
  567. this.drawLine(x, y, x, y+h);
  568. };
  569. function jsgFont()
  570. {
  571. this.PLAIN = 'font-weight:normal;';
  572. this.BOLD = 'font-weight:bold;';
  573. this.ITALIC = 'font-style:italic;';
  574. this.ITALIC_BOLD = this.ITALIC + this.BOLD;
  575. this.BOLD_ITALIC = this.ITALIC_BOLD;
  576. };
  577. var Font = new jsgFont();
  578. function jsgStroke()
  579. {
  580. this.DOTTED = -1;
  581. };
  582. var Stroke = new jsgStroke();
  583. function jsGraphics(cnv, wnd)
  584. {
  585. this.setColor = function(x)
  586. {
  587. this.color = x.toLowerCase();
  588. };
  589. this.setStroke = function(x)
  590. {
  591. this.stroke = x;
  592. if(!(x+1))
  593. {
  594. this.drawLine = _mkLinDott;
  595. this._mkOv = _mkOvDott;
  596. this.drawRect = _mkRectDott;
  597. }
  598. else if(x-1 > 0)
  599. {
  600. this.drawLine = _mkLin2D;
  601. this._mkOv = _mkOv2D;
  602. this.drawRect = _mkRect;
  603. }
  604. else
  605. {
  606. this.drawLine = _mkLin;
  607. this._mkOv = _mkOv;
  608. this.drawRect = _mkRect;
  609. }
  610. };
  611. this.setPrintable = function(arg)
  612. {
  613. this.printable = arg;
  614. if(jg_fast)
  615. {
  616. this._mkDiv = _mkDivIe;
  617. this._htmRpc = arg? _htmPrtRpc : _htmRpc;
  618. }
  619. else this._mkDiv = arg? _mkDivPrt : _mkDiv;
  620. };
  621. this.setFont = function(fam, sz, sty)
  622. {
  623. this.ftFam = fam;
  624. this.ftSz = sz;
  625. this.ftSty = sty || Font.PLAIN;
  626. };
  627. this.drawPolyline = this.drawPolyLine = function(x, y)
  628. {
  629. for (var i=x.length - 1; i;)
  630. {--i;
  631. this.drawLine(x[i], y[i], x[i+1], y[i+1]);
  632. }
  633. };
  634. this.fillRect = function(x, y, w, h)
  635. {
  636. this._mkDiv(x, y, w, h);
  637. };
  638. this.drawPolygon = function(x, y)
  639. {
  640. this.drawPolyline(x, y);
  641. this.drawLine(x[x.length-1], y[x.length-1], x[0], y[0]);
  642. };
  643. this.drawEllipse = this.drawOval = function(x, y, w, h)
  644. {
  645. this._mkOv(x, y, w, h);
  646. };
  647. this.fillEllipse = this.fillOval = function(left, top, w, h)
  648. {
  649. var a = w>>1, b = h>>1,
  650. wod = w&1, hod = h&1,
  651. cx = left+a, cy = top+b,
  652. x = 0, y = b, oy = b,
  653. aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,
  654. st = (aa2>>1)*(1-(b<<1)) + bb2,
  655. tt = (bb2>>1) - aa2*((b<<1)-1),
  656. xl, dw, dh;
  657. if(w) while(y > 0)
  658. {
  659. if(st < 0)
  660. {
  661. st += bb2*((x<<1)+3);
  662. tt += bb4*(++x);
  663. }
  664. else if(tt < 0)
  665. {
  666. st += bb2*((x<<1)+3) - aa4*(y-1);
  667. xl = cx-x;
  668. dw = (x<<1)+wod;
  669. tt += bb4*(++x) - aa2*(((y--)<<1)-3);
  670. dh = oy-y;
  671. this._mkDiv(xl, cy-oy, dw, dh);
  672. this._mkDiv(xl, cy+y+hod, dw, dh);
  673. oy = y;
  674. }
  675. else
  676. {
  677. tt -= aa2*((y<<1)-3);
  678. st -= aa4*(--y);
  679. }
  680. }
  681. this._mkDiv(cx-a, cy-oy, w, (oy<<1)+hod);
  682. };
  683. this.fillArc = function(iL, iT, iW, iH, fAngA, fAngZ)
  684. {
  685. var a = iW>>1, b = iH>>1,
  686. iOdds = (iW&1) | ((iH&1) << 16),
  687. cx = iL+a, cy = iT+b,
  688. x = 0, y = b, ox = x, oy = y,
  689. aa2 = (a*a)<<1, aa4 = aa2<<1, bb2 = (b*b)<<1, bb4 = bb2<<1,
  690. st = (aa2>>1)*(1-(b<<1)) + bb2,
  691. tt = (bb2>>1) - aa2*((b<<1)-1),
  692. // Vars for radial boundary lines
  693. xEndA, yEndA, xEndZ, yEndZ,
  694. iSects = (1 << (Math.floor((fAngA %= 360.0)/180.0) << 3))
  695. | (2 << (Math.floor((fAngZ %= 360.0)/180.0) << 3))
  696. | ((fAngA >= fAngZ) << 16),
  697. aBndA = new Array(b+1), aBndZ = new Array(b+1);
  698. // Set up radial boundary lines
  699. fAngA *= Math.PI/180.0;
  700. fAngZ *= Math.PI/180.0;
  701. xEndA = cx+Math.round(a*Math.cos(fAngA));
  702. yEndA = cy+Math.round(-b*Math.sin(fAngA));
  703. _mkLinVirt(aBndA, cx, cy, xEndA, yEndA);
  704. xEndZ = cx+Math.round(a*Math.cos(fAngZ));
  705. yEndZ = cy+Math.round(-b*Math.sin(fAngZ));
  706. _mkLinVirt(aBndZ, cx, cy, xEndZ, yEndZ);
  707. while(y > 0)
  708. {
  709. if(st < 0) // Advance x
  710. {
  711. st += bb2*((x<<1)+3);
  712. tt += bb4*(++x);
  713. }
  714. else if(tt < 0) // Advance x and y
  715. {
  716. st += bb2*((x<<1)+3) - aa4*(y-1);
  717. ox = x;
  718. tt += bb4*(++x) - aa2*(((y--)<<1)-3);
  719. this._mkArcDiv(ox, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);
  720. oy = y;
  721. }
  722. else // Advance y
  723. {
  724. tt -= aa2*((y<<1)-3);
  725. st -= aa4*(--y);
  726. if(y && (aBndA[y] != aBndA[y-1] || aBndZ[y] != aBndZ[y-1]))
  727. {
  728. this._mkArcDiv(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);
  729. ox = x;
  730. oy = y;
  731. }
  732. }
  733. }
  734. this._mkArcDiv(x, 0, oy, cx, cy, iOdds, aBndA, aBndZ, iSects);
  735. if(iOdds >> 16) // Odd height
  736. {
  737. if(iSects >> 16) // Start-angle > end-angle
  738. {
  739. var xl = (yEndA <= cy || yEndZ > cy)? (cx - x) : cx;
  740. this._mkDiv(xl, cy, x + cx - xl + (iOdds & 0xffff), 1);
  741. }
  742. else if((iSects & 0x01) && yEndZ > cy)
  743. this._mkDiv(cx - x, cy, x, 1);
  744. }
  745. };
  746. /* fillPolygon method, implemented by Matthieu Haller.
  747. This javascript function is an adaptation of the gdImageFilledPolygon for Walter Zorn lib.
  748. C source of GD 1.8.4 found at http://www.boutell.com/gd/
  749. THANKS to Kirsten Schulz for the polygon fixes!
  750. The intersection finding technique of this code could be improved
  751. by remembering the previous intertersection, and by using the slope.
  752. That could help to adjust intersections to produce a nice
  753. interior_extrema. */
  754. this.fillPolygon = function(array_x, array_y)
  755. {
  756. var i;
  757. var y;
  758. var miny, maxy;
  759. var x1, y1;
  760. var x2, y2;
  761. var ind1, ind2;
  762. var ints;
  763. var n = array_x.length;
  764. if(!n) return;
  765. miny = array_y[0];
  766. maxy = array_y[0];
  767. for(i = 1; i < n; i++)
  768. {
  769. if(array_y[i] < miny)
  770. miny = array_y[i];
  771. if(array_y[i] > maxy)
  772. maxy = array_y[i];
  773. }
  774. for(y = miny; y <= maxy; y++)
  775. {
  776. var polyInts = [];
  777. ints = 0;
  778. for(i = 0; i < n; i++)
  779. {
  780. if(!i)
  781. {
  782. ind1 = n-1;
  783. ind2 = 0;
  784. }
  785. else
  786. {
  787. ind1 = i-1;
  788. ind2 = i;
  789. }
  790. y1 = array_y[ind1];
  791. y2 = array_y[ind2];
  792. if(y1 < y2)
  793. {
  794. x1 = array_x[ind1];
  795. x2 = array_x[ind2];
  796. }
  797. else if(y1 > y2)
  798. {
  799. y2 = array_y[ind1];
  800. y1 = array_y[ind2];
  801. x2 = array_x[ind1];
  802. x1 = array_x[ind2];
  803. }
  804. else continue;
  805. // Modified 11. 2. 2004 Walter Zorn
  806. if((y >= y1) && (y < y2))
  807. polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);
  808. else if((y == maxy) && (y > y1) && (y <= y2))
  809. polyInts[ints++] = Math.round((y-y1) * (x2-x1) / (y2-y1) + x1);
  810. }
  811. polyInts.sort(_CompInt);
  812. for(i = 0; i < ints; i+=2)
  813. this._mkDiv(polyInts[i], y, polyInts[i+1]-polyInts[i]+1, 1);
  814. }
  815. };
  816. this.drawString = function(txt, x, y)
  817. {
  818. this.htm += '<div style="position:absolute;white-space:nowrap;'+
  819. 'left:' + x + 'px;'+
  820. 'top:' + y + 'px;'+
  821. 'font-family:' + this.ftFam + ';'+
  822. 'font-size:' + this.ftSz + ';'+
  823. 'color:' + this.color + ';' + this.ftSty + '">'+
  824. txt +
  825. '<\/div>';
  826. };
  827. /* drawStringRect() added by Rick Blommers.
  828. Allows to specify the size of the text rectangle and to align the
  829. text both horizontally (e.g. right) and vertically within that rectangle */
  830. this.drawStringRect = function(txt, x, y, width, halign)
  831. {
  832. this.htm += '<div style="position:absolute;overflow:hidden;'+
  833. 'left:' + x + 'px;'+
  834. 'top:' + y + 'px;'+
  835. 'width:'+width +'px;'+
  836. 'text-align:'+halign+';'+
  837. 'font-family:' + this.ftFam + ';'+
  838. 'font-size:' + this.ftSz + ';'+
  839. 'color:' + this.color + ';' + this.ftSty + '">'+
  840. txt +
  841. '<\/div>';
  842. };
  843. this.drawImage = function(imgSrc, x, y, w, h, a)
  844. {
  845. this.htm += '<div style="position:absolute;'+
  846. 'left:' + x + 'px;'+
  847. 'top:' + y + 'px;'+
  848. // w (width) and h (height) arguments are now optional.
  849. // Added by Mahmut Keygubatli, 14.1.2008
  850. (w? ('width:' + w + 'px;') : '') +
  851. (h? ('height:' + h + 'px;'):'')+'">'+
  852. '<img src="' + imgSrc +'"'+ (w ? (' width="' + w + '"'):'')+ (h ? (' height="' + h + '"'):'') + (a? (' '+a) : '') + '>'+
  853. '<\/div>';
  854. };
  855. this.clear = function()
  856. {
  857. this.htm = "";
  858. if(this.cnv) this.cnv.innerHTML = "";
  859. };
  860. this._mkOvQds = function(cx, cy, x, y, w, h, wod, hod)
  861. {
  862. var xl = cx - x, xr = cx + x + wod - w, yt = cy - y, yb = cy + y + hod - h;
  863. if(xr > xl+w)
  864. {
  865. this._mkDiv(xr, yt, w, h);
  866. this._mkDiv(xr, yb, w, h);
  867. }
  868. else
  869. w = xr - xl + w;
  870. this._mkDiv(xl, yt, w, h);
  871. this._mkDiv(xl, yb, w, h);
  872. };
  873. this._mkArcDiv = function(x, y, oy, cx, cy, iOdds, aBndA, aBndZ, iSects)
  874. {
  875. var xrDef = cx + x + (iOdds & 0xffff), y2, h = oy - y, xl, xr, w;
  876. if(!h) h = 1;
  877. x = cx - x;
  878. if(iSects & 0xff0000) // Start-angle > end-angle
  879. {
  880. y2 = cy - y - h;
  881. if(iSects & 0x00ff)
  882. {
  883. if(iSects & 0x02)
  884. {
  885. xl = Math.max(x, aBndZ[y]);
  886. w = xrDef - xl;
  887. if(w > 0) this._mkDiv(xl, y2, w, h);
  888. }
  889. if(iSects & 0x01)
  890. {
  891. xr = Math.min(xrDef, aBndA[y]);
  892. w = xr - x;
  893. if(w > 0) this._mkDiv(x, y2, w, h);
  894. }
  895. }
  896. else
  897. this._mkDiv(x, y2, xrDef - x, h);
  898. y2 = cy + y + (iOdds >> 16);
  899. if(iSects & 0xff00)
  900. {
  901. if(iSects & 0x0100)
  902. {
  903. xl = Math.max(x, aBndA[y]);
  904. w = xrDef - xl;
  905. if(w > 0) this._mkDiv(xl, y2, w, h);
  906. }
  907. if(iSects & 0x0200)
  908. {
  909. xr = Math.min(xrDef, aBndZ[y]);
  910. w = xr - x;
  911. if(w > 0) this._mkDiv(x, y2, w, h);
  912. }
  913. }
  914. else
  915. this._mkDiv(x, y2, xrDef - x, h);
  916. }
  917. else
  918. {
  919. if(iSects & 0x00ff)
  920. {
  921. if(iSects & 0x02)
  922. xl = Math.max(x, aBndZ[y]);
  923. else
  924. xl = x;
  925. if(iSects & 0x01)
  926. xr = Math.min(xrDef, aBndA[y]);
  927. else
  928. xr = xrDef;
  929. y2 = cy - y - h;
  930. w = xr - xl;
  931. if(w > 0) this._mkDiv(xl, y2, w, h);
  932. }
  933. if(iSects & 0xff00)
  934. {
  935. if(iSects & 0x0100)
  936. xl = Math.max(x, aBndA[y]);
  937. else
  938. xl = x;
  939. if(iSects & 0x0200)
  940. xr = Math.min(xrDef, aBndZ[y]);
  941. else
  942. xr = xrDef;
  943. y2 = cy + y + (iOdds >> 16);
  944. w = xr - xl;
  945. if(w > 0) this._mkDiv(xl, y2, w, h);
  946. }
  947. }
  948. };
  949. this.setStroke(1);
  950. this.setFont("verdana,geneva,helvetica,sans-serif", "12px", Font.PLAIN);
  951. this.color = "#000000";
  952. this.htm = "";
  953. this.wnd = wnd || window;
  954. if(!jg_ok) _chkDHTM(this.wnd);
  955. if(jg_ok)
  956. {
  957. if(cnv)
  958. {
  959. if(typeof(cnv) == "string")
  960. this.cont = document.all? (this.wnd.document.all[cnv] || null)
  961. : document.getElementById? (this.wnd.document.getElementById(cnv) || null)
  962. : null;
  963. else if(cnv == window.document)
  964. this.cont = document.getElementsByTagName("body")[0];
  965. // If cnv is a direct reference to a canvas DOM node
  966. // (option suggested by Andreas Luleich)
  967. else this.cont = cnv;
  968. // Create new canvas inside container DIV. Thus the drawing and clearing
  969. // methods won't interfere with the container's inner html.
  970. // Solution suggested by Vladimir.
  971. this.cnv = this.wnd.document.createElement("div");
  972. this.cnv.style.fontSize=0;
  973. this.cont.appendChild(this.cnv);
  974. this.paint = jg_dom? _pntCnvDom : _pntCnvIe;
  975. }
  976. else
  977. this.paint = _pntDoc;
  978. }
  979. else
  980. this.paint = _pntN;
  981. this.setPrintable(false);
  982. };
  983. function _mkLinVirt(aLin, x1, y1, x2, y2)
  984. {
  985. var dx = Math.abs(x2-x1), dy = Math.abs(y2-y1),
  986. x = x1, y = y1,
  987. xIncr = (x1 > x2)? -1 : 1,
  988. yIncr = (y1 > y2)? -1 : 1,
  989. p,
  990. i = 0;
  991. if(dx >= dy)
  992. {
  993. var pr = dy<<1,
  994. pru = pr - (dx<<1);
  995. p = pr-dx;
  996. while(dx > 0)
  997. {--dx;
  998. if(p > 0) // Increment y
  999. {
  1000. aLin[i++] = x;
  1001. y += yIncr;
  1002. p += pru;
  1003. }
  1004. else p += pr;
  1005. x += xIncr;
  1006. }
  1007. }
  1008. else
  1009. {
  1010. var pr = dx<<1,
  1011. pru = pr - (dy<<1);
  1012. p = pr-dy;
  1013. while(dy > 0)
  1014. {--dy;
  1015. y += yIncr;
  1016. aLin[i++] = x;
  1017. if(p > 0) // Increment x
  1018. {
  1019. x += xIncr;
  1020. p += pru;
  1021. }
  1022. else p += pr;
  1023. }
  1024. }
  1025. for(var len = aLin.length, i = len-i; i;)
  1026. aLin[len-(i--)] = x;
  1027. };
  1028. function _CompInt(x, y)
  1029. {
  1030. return(x - y);
  1031. };