1 
  2 /**
  3  * @name	CeL SVG function
  4  * @fileoverview
  5  * 本檔案包含了 SVG 的 functions。
  6  * @since	
  7  */
  8 
  9 
 10 /*
 11 TODO
 12 對無顯示 SVG 的多一項警告。
 13 
 14 ASCIIsvg.js
 15 http://www1.chapman.edu/~jipsen/svg/asciisvg.html
 16 */
 17 
 18 if (typeof CeL === 'function'){
 19 
 20 /**
 21  * 本 module 之 name(id),<span style="text-decoration:line-through;">不設定時會從呼叫時之 path 取得</span>。
 22  * @type	String
 23  * @constant
 24  * @inner
 25  * @ignore
 26  */
 27 var module_name = 'net.SVG';
 28 
 29 //===================================================
 30 /**
 31  * 若欲 include 整個 module 時,需囊括之 code。
 32  * @type	Function
 33  * @param	{Function} library_namespace	namespace of library
 34  * @param	load_arguments	呼叫時之 argument(s)
 35  * @return
 36  * @name	CeL.net.SVG
 37  * @constant
 38  * @inner
 39  * @ignore
 40  */
 41 var code_for_including = function(library_namespace, load_arguments) {
 42 
 43 //	requires
 44 if (eval(library_namespace.use_function(
 45 		'net.web.XML_node,net.web.set_attribute,net.web.remove_all_child,net.web.set_class,data.split_String_to_Object')))
 46 	return;
 47 
 48 
 49 // ============================================================================
 50 //	definition of module SVG
 51 
 52 /*
 53 
 54 TODO:
 55 animation
 56 .add_image
 57 */
 58 
 59 //	in 運算子會檢查物件是否有名稱為 property 的屬性。它也會檢查物件的原型,查看 property 是否屬於原型鏈結的一部分。如果 property 是在物件或原型鏈結中,則 in 運算子會傳回 true,否則會傳回 false。	http://msdn2.microsoft.com/zh-tw/library/11e33275(VS.80).aspx
 60 
 61 //g_SVG[generateCode.dLK]='set_attribute,XML_node,remove_all_child';//removeNode
 62 
 63 /**
 64  * module SVG 物件之 constructor。<br/>
 65  * 設定 SVG document fragment 並將之插入網頁中。
 66 
 67  * @class	generation of Scalable Vector Graphics<br/>
 68  * 輔助繪圖的基本功能物件,生成 SVG 操作函數。
 69  * @since	2006/12/7,10-12
 70  * @deprecated	Use toolkit listed below instead:<br/>
 71  * <a href="http://code.google.com/p/svgweb/" accessdate="2009/11/15 16:34" title="svgweb - Project Hosting on Google Code">svgweb</a><br/>
 72  * <a href="https://launchpad.net/scour" accessdate="2009/11/15 16:35" title="Scour - Cleaning SVG Files in Launchpad">Scour</a>
 73 
 74  * @constructor
 75  * @param	{int} _width	width of the canvas
 76  * @param	{int} _height	height of the canvas
 77  * @param	{color String} [_backgroundColor]	background color of the canvas (UNDO)
 78  * @requires	set_attribute,XML_node,remove_all_child//removeNode
 79  * @type	CeL.net.SVG
 80  * @return	{CeL.net.SVG} CeL.net.SVG object created
 81 
 82  * @see	<a href="http://www.w3.org/TR/SVG/" accessdate="2009/11/15 16:31">Scalable Vector Graphics (SVG) 1.1 Specification</a><br/>
 83  * <a href="http://zvon.org/xxl/svgReference/Output/" accessdate="2009/11/15 16:31">SVG 1.1 reference with examples</a><br/>
 84  * <a href="http://www.permadi.com/tutorial/jsFunc/index.html" accessdate="2009/11/15 16:31" title="Introduction and Features of JavaScript "Function" Objects">Introduction and Features of JavaScript "Function" Objects</a><br/>
 85  * <a href="http://volity.org/wiki/index.cgi?SVG_Script_Tricks" accessdate="2009/11/15 16:31">Volity Wiki: SVG Script Tricks</a><br/>
 86  * <a href="http://pilat.free.fr/english/routines/js_dom.htm" accessdate="2009/11/15 16:31">Javascript SVG et DOM</a>
 87  */
 88 CeL.net.SVG
 89 = function(_width, _height, _backgroundColor){
 90  var _f = _, _s;
 91 /*
 92  if(!_f.createENS()){
 93   //alert('Your browser doesn't support SVG!');
 94   return;
 95  }
 96 */
 97 
 98  /**
 99   * SVG document fragment
100   * @property
101   * @see	<a href="http://www.w3.org/TR/SVG/struct.html#NewDocument" accessdate="2009/11/15 16:53">Defining an SVG document fragment: the 'svg' element</a>
102   */
103  this.svg=_s=	//	raw
104 	arguments.length===1 && arguments[0] && typeof arguments[0]==='object' && arguments[0].tagName.toLowerCase()==='svg'
105 	?arguments[0]
106 	:_f.createNode('svg')
107 	;
108  if(!_s)return;	//	error!
109 
110  //	http://www.w3.org/TR/SVG/struct.html#DefsElement	http://www.svgbasics.com/defs.html
111  _s.appendChild(this.defs=_f.createNode('defs'));	//	raw
112 
113  //	調整大小
114  this.setSize(_width,_height);
115  //	set_attribute(_s,{xmlns:_f.NS.SVG});
116  set_attribute(_s,{xmlns:'http://www.w3.org/2000/svg'});
117  //	may cause error! should use .setAttributeNS()??
118  _s.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
119  //viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"
120 
121  /**
122   * 包含了插入元件的原始資訊。<br/>
123   * Use {@link #addContain} to add contains.
124   * @property
125   * @type	Array
126   */
127  this.contains = [];
128  /**
129   * 所插入之網頁元素
130   * @property
131   */
132  this.div = null;
133 
134  //document.body.appendChild(this.svg);
135  return this;//return this.createNode(_nodeN);
136 };
137 //_.NS={SVG:'http://www.w3.org/2000/svg',XLink:'http://www.w3.org/1999/xlink'};
138 _.defaultColor = '#222';
139 
140 CeL.net.SVG
141 .
142 /**
143  * default stroke width. 單位: px
144  * 
145  * @unit px
146  * @type Number
147  * @memberOf CeL.net.SVG
148  */
149 defaultStrokeWidth = .5;	
150 
151 //_.defaultColor='#444';_.defaultStrokeWidth=1;
152 
153 CeL.net.SVG
154 .
155 /**
156  * 所有造出 id 之 prefix
157  * @type	string
158  * @memberOf	CeL.net.SVG
159  */
160 idPrefix =
161 	// +'_SVG_';
162 	library_namespace.to_module_name(module_name) + '.';
163 
164 // _.bout closure.
165 //_.createENS=document.createElementNS?function(){return document.createElementNS(arguments[0],arguments[1]);}:null;
166 CeL.net.SVG
167 .
168 /**
169  * create SVG document fragment (only for .createNode)
170  * @param _ns	namespaceURI
171  * @param _qn	qualifiedName
172  * @param _a	propertyA
173  * @param _i	innerObj
174  * @return
175  * @memberOf	CeL.net.SVG
176  * @function
177  * @private
178  */
179 createENS = function(_ns, _qn, _a, _i) {
180 	return (
181 		// document.createElementNS?XML_node(_ns+':'+_qn,_a,0,_i):null;
182 		XML_node(_ns + ':' + _qn, _a, 0, _i));
183 };
184 
185 CeL.net.SVG
186 .
187 /**
188  * create SVG document fragment 元件(component)。<br/>
189  * SVG 之 document fragment 與 HTML 不同 namespace,因此我們需要使用到 <a href="http://www.w3.org/2000/svg">http://www.w3.org/2000/svg</a> 來作為 XML elements 的 namespace。為了未來的兼容性,我們將這個功能獨立出來。
190  * @param _nodeN	node/tag name
191  * @param {hash|string}_a	attribute/property
192  * @param _i	inner object
193  * @return	node created or null
194  * @memberOf	CeL.net.SVG
195  * @private
196  * @function
197  */
198 createNode = function(_nodeN,_a,_i){
199  //return this.createENS?this.createENS('svg',_nodeN||'svg'):null;
200  return _.createENS('svg', _nodeN || 'svg', _a, _i);
201 
202  //	Error: uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object"  nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)"  location: "JS frame :: file:///C:/kanashimi/www/cgi-bin/program/tmp/JavaScript%20Framework/dojo/dojo-0.4.0-ajax/a.htm :: anonymous :: line 29"  data: no]
203  //	http://www.codingforums.com/archive/index.php?t-94573.html	When you do var x = document.getElementById and then x('hello') you are executing the function x in the context of the window object instead of the document object. Gecko probably utilizes the scoping of the document object to access some internal methods to execute getElementById, which the window object doesn't have.
204  //	http://developer.mozilla.org/en/docs/Safely_accessing_content_DOM_from_chrome	http://developer.mozilla.org/en/docs/Working_around_the_Firefox_1.0.3_DHTML_regression	http://www.codingforums.com/archive/index.php?t-68554.html
205  // OK?
206  //return this.createENS?this.createENS.call(document,'svg',_nodeN||'svg'):null;
207  // fault:
208  //return this.createENS===document.createElementNS?document.createElementNS('svg',_nodeN||'svg'):this.createENS?this.createENS('svg',_nodeN||'svg'):null;
209  //return this.createENS?(alert(this.createENS===document.createElementNS),Function.apply(this.createENS,['svg',(_nodeN||'svg')])):null;
210  //return this.createENS?(alert(this.createENS===document.createElementNS),this.createENS.apply(document.createElementNS,['svg',(_nodeN||'svg')])):null;
211 };
212 /*
213 _.createLink=function(_ref){
214  return this.createENS('xLink','xlink:href');
215 };
216 */
217 
218 CeL.net.SVG
219 .
220 /**
221  * 從 id 獲得 node
222  * @param id	id
223  * @return	node
224  * @memberOf	CeL.net.SVG
225  * @private
226  */
227 getNodeById = function(id) {
228 	// return this.svg.getElementById(_i);//useless?
229 
230 	// lookupPrefix()
231 	return document.getElementById(id);
232 };
233 
234 CeL.net.SVG
235 .
236 /**
237  * get a random ID to use.
238  * @param tag	tag name(nodeType)
239  * @return	a random ID
240  * @memberOf	CeL.net.SVG
241  * @private
242  */
243 getRandomID = function(tag) {
244 	if (typeof tag === 'object')
245 		tag = tag.tagName/* nodeType */;
246 	var _j;
247 	while (_.getNodeById(_j = _.idPrefix + tag + '_'
248 			+ ('' + Math.random()).slice(2, 6)))
249 		;
250 	return _j;
251 };
252 CeL.net.SVG
253 .
254 /**
255  * give a random ID to the specified node.
256  * @param _n	node
257  * @return	id of the specified node
258  * @memberOf	CeL.net.SVG
259  * @private
260  */
261 setRandomID = function(_n) {
262 	if (_n && typeof _n === 'object') {
263 		/**
264 		 * id of the specified node
265 		 * @inner
266 		 * @ignore
267 		 */
268 		var _i = set_attribute(_n, 'id');
269 		if (!_i)
270 			set_attribute(_n, {
271 				id : _i = _.getRandomID(_n)
272 			});
273 		return _i;
274 	}
275 };
276 
277 CeL.net.SVG
278 .
279 /**
280  * 改變 text
281  * @param text_node	text object
282  * @param text	change to this text
283  * @return
284  * @memberOf	CeL.net.SVG
285  * @see
286  * <a href="http://www.w3.org/TR/SVG/text.html" accessdate="2009/12/15 0:2">Text - SVG 1.1 - 20030114</a>
287  * <tref xlink:href="#ReferencedText"/>
288  */
289 changeText = function(text_node, text) {
290 	//if (typeof remove_all_child === 'function')
291 	//	remove_all_child(text_node);
292 	//else throw new Error(1, 'changeText: function remove_all_child is not included!');
293 	remove_all_child(text_node);
294 
295 	if (text)
296 		text_node.appendChild(document.createTextNode(text));
297 	//else removeNode(_textO);
298 };
299 
300 CeL.net.SVG
301 .
302 addTitle = function(_o, _t_d) {
303 	if (_t)
304 		_o.appendChild(this.createNode('title', 0, _t));
305 	// A more descriptive label should be put in a <desc> child element
306 	if (_t)
307 		_o.appendChild(this.createNode('desc', 0, _t));
308 };
309 
310 
311 /*	transform	http://www.w3.org/TR/SVG/coords.html#TransformAttribute	http://archive.dojotoolkit.org/nightly/tests/gfx/test_image.html
312 recommend for performance reasons to use transformation matrices whenever possible.	http://www.mecxpert.de/svg/transform.html
313  * @memberOf	module SVG
314  */
315 CeL.net.SVG
316 .
317 setTransform = function(_o, _t) {
318 	//	TODO
319 	throw new Error(1, 'setTransform: yet implement!');
320 	set_attribute(_o, {
321 				transform : _t
322 			});
323 };
324 
325 // ============================================================================
326 //	definition of module SVG object
327 
328 _.prototype={
329 
330 /**
331  * 顯現 this module SVG object
332  * @param _v	visible
333  * @return	this module SVG object
334  * @memberOf	CeL.net.SVG
335  */
336 show : function(_v) {
337 	var _d = this.div;
338 	if (this.svg)
339 		if (_d) {// _s.parentNode
340 			_d.style.display = typeof _v == 'undefined' ? _d.style.display === 'none' ? 'block'
341 					: 'none'
342 						: _v ? 'block' : 'none'; // block怪怪的
343 		} else if (_v || typeof _v == 'undefined')
344 			this.div = XML_node('div', 0, [ document.body ],
345 					this.svg);
346 	return this;
347 },
348 setAttribute : function() {
349 	this.svg && this.svg.setAttribute(arguments);
350 	return this;
351 },
352 //setDimensions
353 /**
354  * 調整 canvas 大小
355  * @unit	px
356  * @param {Integer} _width	width in px
357  * @param {Integer} _height	height in px
358  * @return	this module SVG object
359  * @memberOf	CeL.net.SVG
360  */
361 setSize : function(_width, _height) {
362 	_width = parseInt(_width) || 0;
363 	_height = parseInt(_height) || 0;
364 
365 	if (_width > 0 && _height > 0)
366 		set_attribute(this.svg, {
367 			width : _width,
368 			height : _height
369 		});
370 
371 	return this;
372 },
373 getSize : function() {
374 	return set_attribute(this.svg, 'width,height');
375 },
376 
377 /**
378  * 將本 Object 附在 _n 上(attach to node)
379  * @param _n	HTML/SVG object
380  * @return
381  */
382 attach : function(_n) {
383 	if (typeof _n === 'string')
384 		_n = _.getNodeById(_n);
385 
386 	if (!_n)
387 		return this;
388 
389 	var _t = _n.tagName.toLowerCase();
390 	if (_t === 'svg')
391 		//	TODO: 若不想創建新 node..
392 		return new _(_n);
393 
394 	if (_t === 'div') {
395 		//if(this.div){TODO: 原先已經 attach}
396 		this.div = _n;
397 		_n.appendChild(this.svg);
398 	}
399 
400 	return this;
401 },
402 
403 get_XML : function() {
404 	var _t = document.createElement('div'), _x, _s = this.svg;
405 
406 	if (!_s)
407 		// error!
408 		return;
409 
410 	//	TODO: 效率不高!
411 	_t.appendChild(_s = _s.cloneNode(true));
412 	_x = _t.innerHTML;
413 	_t.removeChild(_s);
414 	// 確保在此環境下 create 出來的會被 destory
415 	_t = null;
416 	// ugly hack
417 	// <?xml version="1.0" encoding="UTF-8" standalone="no"?>
418 	_x = _x.replace(/(\s)(href=['"])/g, '$1xlink:$2');
419 
420 	return _x;
421 },
422 
423 /**
424  * 清除 canvas<br/>
425  * 很可能會出問題!
426  * @return	this SVG
427  * @memberOf	CeL.net.SVG
428  * @since	2009/12/18 21:17:09
429  */
430 clean : function() {
431 	var s = this.svg;
432 	//	[0]: <defs>
433 	while (s.childNodes.length > 1)
434 		//library_namespace.debug(s.childNodes.length + ',' + s.lastChild),
435 		s.removeChild(s.lastChild);
436 
437 	// remove childrens of <defs>
438 	//remove_all_child(s.lastChild, 1);
439 	s = s.lastChild;
440 	while (s.hasChildNodes())
441 		//library_namespace.debug(s.childNodes.length + ',' + s.lastChild),
442 		s.removeChild(s.lastChild);
443 
444 	return this;
445 },
446 
447 /**
448  * 創建本物件之 SVG 群組。<br/>
449  * 利用 SVG 群組我們可以同時操作多個 SVG elements。
450  * @param {hash|string}_a	attribute/property
451  * @param _i	inner object
452  * @return	this SVG
453  * @memberOf	CeL.net.SVG
454  */
455 createGroup : function(_a, _i) {
456 	var _g = _.createNode('g', _a, _i);
457 	this.group = _g;
458 	return this;
459 },
460 /**
461  * 綁定 SVG elements 至本物件群組。<br/>
462  * 這函數將已存在的 SVG elements 綁定至本物件之群組中。若群組不存在,則創建出一個。
463  * @param _n	node
464  * @return	this module SVG object
465  * @memberOf	CeL.net.SVG
466  */
467 attachGroup : function(_n) {
468 	if (!this.group)
469 		this.createGroup();
470 	this.group.appendChild(_n);
471 	return this;
472 },
473 
474 createSymbol : function(_a, _i) {
475 	var _s = _.createNode('symbol', _a, _i);
476 	this.symbol = _s;
477 	return this;
478 },
479 attachSymbol : function(_n) {
480 	if (!this.symbol)
481 		this.createSymbol();
482 	this.symbol.appendChild(_n);
483 	return this;
484 },
485 
486 //	TODO
487 setFill:function(){throw new Error(1,'setFill: yet implement!');},
488 setStroke:function(){throw new Error(1,'setStroke: yet implement!');},
489 setShape:function(){throw new Error(1,'setShape: yet implement!');},
490 setTransform:function(){throw new Error(1,'setTransform: yet implement!');},
491 
492 //<animateMotion>,<animateColor>
493 
494 /**
495  * 最後一個增加的 instance
496  * @memberOf	CeL.net.SVG
497  */
498 lastAdd: null,
499 /**
500  * 最後一個增加的 definition
501  * @memberOf	CeL.net.SVG
502  */
503 lastAddDefs: null,
504 /**
505  * 增加 SVG element。<br/>
506  * 結合 .prototype.addDefs 與 .prototype.addUse,作完定義後隨即使用之。
507  * @param _n	tagName(nodeType)
508  * @param {hash|string} _a	attribute/property
509  * @param _i	inner object
510  * @return
511  * @memberOf	CeL.net.SVG
512  */
513 addNode : function(_n, _a, _i) {
514 	if (typeof _n == 'string')
515 		_n = _.createNode(_n, _a, _i);
516 	if (_n) {
517 		this.addDefs(_n);
518 		this.addUse(_n);
519 	}
520 	return this;
521 },
522 
523 /**
524  * 增加 SVG 定義。<br/>
525  * SVG 規範中聲明,SVG 的 <use> element 不能引用外部文件或其 elements。因此我們在創建實例之前,需要先在本物件中作定義。
526  * @param _n	node
527  * @return
528  * @memberOf	CeL.net.SVG
529  */
530 addDefs : function(_n) {
531 	// var _d=this.defs;
532 	if (_n) {
533 		_.setRandomID(_n);
534 		this.defs.appendChild(this.lastAddDefs = _n);
535 	}
536 	return this;
537 },
538 /**
539  * 增加 SVG 實例。<br/>
540  * 利用本物件中之定義創建實例並增添至本物件中。<br/>
541  * 在裝載 b.svg 時,將 a.svg 中的 defs 中的圖元裝載到 b.svg 中(文件上是兩者是保持獨立的,但在內存中將二者合二為一),這樣就可以在b.svg中直接引用這些圖元了。<br/>
542  * SVG 規範中聲明,SVG 的 <use> element 不能引用外部文件或其 elements。因此我們在創建實例之前,需要先在本物件中作定義。
543  * @param _i	id
544  * @param _a
545  * @return
546  * @memberOf	CeL.net.SVG
547  */
548 addUse : function(_i, _a) {
549 	var _s = this.svg, _o = _.createNode('use', _a);
550 	if (_o && _s && _i) {
551 		if (typeof _i == 'object')
552 			_i = _.setRandomID(_i);
553 		set_attribute(_o, {
554 			'xlink:href' : '#' + _i
555 		});
556 		_s.appendChild(this.lastAdd = _o);
557 	}
558 	return this;
559 },
560 
561 /**
562  * 增加插入的元件。<br/>
563  * 應該用 <a href="http://www.w3.org/TR/SVG/struct.html#SymbolElement">symbol</a>
564  * @param _o	object reference
565  * @param _type	type of this component
566  * @param [propertyO]	other properties
567  * @return
568  * @requires	split_String_to_Object
569  * @memberOf	CeL.net.SVG
570  */
571 addContain : function(_o, _type, propertyO) {
572 	if (_type && this.contains) {
573 		if (typeof propertyO === 'string')
574 			propertyO = split_String_to_Object(propertyO);
575 		if (propertyO.o || propertyO.t)
576 			this.contains.push( {
577 				o : _o,
578 				t : _type,
579 				p : propertyO
580 			});
581 		else
582 			propertyO.o = _o, propertyO.t = _type, this.contains
583 			.push(propertyO);
584 	}
585 	return this;
586 },
587 
588 
589 /**
590  * 繪製直線。<br/>
591  * 此函數利用 _.eNode 造出直線元件之後,再用 .prototype.addNode 將之插入本物件中。
592  * @param _left
593  * @param _top
594  * @param _width
595  * @param _height
596  * @param _color
597  * @param _strokeWidth
598  * @return
599  * @memberOf	CeL.net.SVG
600  */
601 addLine : function(_left, _top, _width, _height, _color,
602 		_strokeWidth) {
603 	var _l = _.createNode('line', {
604 		x1 : _top,
605 		y1 : _left,
606 		x2 : _top + _width,
607 		y2 : _left + _height,
608 		stroke : _color || this.addLine.defaultColor,
609 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth
610 	});
611 	if (_l && this.svg) {
612 		//this.svg.appendChild(_l);
613 		this.addNode(_l);
614 	}
615 	return this;
616 },
617 
618 
619 /**
620  * 繪製曲線路徑。<br/>
621  * 此函數利用 _.eNode 造出路徑元件之後再用 .prototype.addNode 將之插入本物件中。
622  * @param _d
623  * @param _color
624  * @param _strokeWidth
625  * @param _fill
626  * @return
627  * @memberOf	CeL.net.SVG
628  */
629 addPath : function(_d, _color, _strokeWidth, _fill) {
630 	var _p = _.createNode('path', {
631 		d : _d,
632 		stroke : _color || this.addLine.defaultColor,
633 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
634 		fill : _fill || 'none'
635 	});
636 	if (_p && this.svg)
637 		this.addNode(_p);
638 	return this;
639 },
640 
641 
642 //xml:space="default|preserve"
643 /**
644  * 添加文字。<br/>
645  * 此函數利用 _.eNode 造出文字元件之後再用 .prototype.addNode 將之插入本物件中。
646  * @param _text
647  * @param _left
648  * @param _baseLine
649  * @param _color
650  * @param _font
651  * @return
652  * @memberOf	CeL.net.SVG
653  */
654 addText : function(_text,_left,_baseLine,_color,_font){
655 	if (_color)
656 		this.addText.defaultColor = _color;
657 	else
658 		_color = this.addText.defaultColor;
659 
660 	if (_font)
661 		this.addText.defaultFont = _font;
662 	else
663 		_font = this.addText.defaultFont;
664 
665  //	http://www.w3.org/TR/SVG/text.html	<tref xlink:href="#ReferencedText"/>
666  //var _o=document.createTextNode(_text);
667  //var _o=_.createNode('tspan',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},_text);
668  //this.addNode(_.createNode('text',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},_o));
669  //this.lastAdd=_o;
670 
671 	// ugly hack: 說是_baseLine,其實還是會再往下一點點。
672 	_baseLine -= 2;
673 	this.addNode(_.createNode('text', {
674 		x : _left,
675 		y : _baseLine,
676 		stroke : _color || this.addText.defaultColor,
677 		style : _font ? 'font-family:"' + _font + '"' : null
678 	}, _text));
679 	//(text|g).pointer-events="none": Make text unselectable
680 
681 /*	本法為標準,但FF尚未支援。
682  var _s=this.svg,_i=_.getRandomID('text')_.SVG.createNode('text',{id:_i},_text);
683  this.addDefs(this.lastAddDefs=_o);
684  _o=_.createNode('text',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},0,_t=_.createNode('tref'));
685  _t.setAttributeNS('xLink','xlink:href','#'+_i);
686  _o.appendChild(_t);
687  _s.appendChild(this.lastAdd=_o);
688 */
689 
690 	return this;
691 },
692 
693 /**
694  * add numbers
695  * @param _text
696  * @param _left
697  * @param _baseLine
698  * @param _tW
699  * @param _color
700  * @param _font
701  * @return
702  * @see
703  * _left: http://www.w3.org/TR/SVG/text.html#TSpanElementXAttribute
704  */
705 addNum : function(_text, _left, _baseLine, _tW, _color, _font) {
706 	if (!isNaN(_text)) {
707 		//	說是_baseLine,其實還是會再往下一點點。
708 		_baseLine -= 2;
709 		//_text=''+_text;
710 		_text += '';
711 
712 		var _o = [], _i = 0, _s = this.svg;
713 		for (; _i < _text.length; _i++)
714 			// _text.split('')
715 			_o.push(_.createNode('tspan', {
716 				x : _left + _i * _tW
717 				//, y:_baseLine
718 			}, _text.charAt(_i)));
719 
720 		if (_s)
721 			_s.appendChild(this.lastAdd = _.createNode('text', {
722 				y : _baseLine,
723 				stroke : _color || this.addText.defaultColor,
724 				style : _font ? 'font-family:"' + _font + '"'
725 						: null
726 			}, _o));
727 	}
728 	return this;
729 },
730 
731 
732 /**
733  * add parallel graph
734  * @param _ds
735  * @param _h
736  * @param _d
737  * @param _us
738  * @param tramA
739  * @return
740  * @since	2006/12/18 0:35
741  */
742 addParallelG : function(_ds, _h, _d, _us, tramA) {
743 	if (_ds && _h) {
744 		if (isNaN(_us) || _us === '')
745 			_us = _ds;
746 		set_attribute(this
747 				.addPath('M' + _ds + ',' + _h + ' H0 L' + (_d || 0)
748 						+ ',0' + (_us ? ' h' + _us : '') + ' z'), {
749 			transform : tramA
750 		}); //	0==''
751 	}
752 	return this;
753 },
754 
755 lastQuadrilateral : null,
756 lastQuadrilateralDefs : null,
757 /**
758  * 畫簡單長方形或平行四邊形、梯形
759  * @param _ds
760  * @param _h
761  * @param _d
762  * @param _us
763  * @param tramA
764  * @return
765  * @see	<a href="http://zh.wikipedia.org/wiki/%E5%B9%B3%E8%A1%8C%E5%9B%9B%E8%BE%B9%E5%BD%A2">平行四邊形</a>
766  * @memberOf	CeL.net.SVG
767  */
768 addQuadrilateral:function(_ds,_h,_d,_us,tramA){	//	down side,height,upper distance,upper side
769  this.addParallelG(_ds,_h,_d,_us,tramA).addContain(this.lastQuadrilateralDefs=this.lastAddDefs,'quadrilateral',{down_side:_ds,hight:_h,distance:_d,upper_side:_us});
770  this.lastQuadrilateral=this.lastAdd;	//	set_attribute(s.lastQuadrilateral,'fill=none');
771  return this;
772 },
773 
774 lastTriangle : null,
775 lastTriangleDefs : null,
776 /**
777  * 畫簡單三角形
778  * @since	2006/12/17 12:38
779  * @param _ds
780  * @param _h
781  * @param _d
782  * @param tramA
783  * @return
784  * @memberOf	CeL.net.SVG
785  */
786 addTriangle : function(_ds, _h, _d, tramA) {
787 	this.addParallelG(_ds, _h, _d, 0, tramA).addContain(
788 			this.lastTriangleDefs = this.lastAddDefs, 'triangle', {
789 				down_side : _ds,
790 				hight : _h,
791 				distance : _d
792 			});
793 	this.lastTriangle = this.lastAdd;
794 	return this;
795 },
796 
797 
798 /**
799  * 繪製橢圓曲線。<br/>
800  * 此函數利用 _.eNode 造出橢圓曲線元件之後,再用 .prototype.addNode 將之插入本物件中。
801  * @param _rx
802  * @param _ry
803  * @param _cx
804  * @param _cy
805  * @param _color
806  * @param _strokeWidth
807  * @param _fill
808  * @param tramA
809  * @return
810  * @memberOf	CeL.net.SVG
811  */
812 addEllipsePath : function(_rx, _ry, _cx, _cy, _color, _strokeWidth,
813 		_fill, tramA) {
814 	if (_rx) {
815 		var _e, _p = {
816 				rx : _rx,
817 				ry : _ry,
818 				cx : _cx,
819 				cy : _cy,
820 				stroke : _color || this.addEllipsePath.defaultColor,
821 				'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
822 				fill : _fill || 'none',
823 				transform : tramA
824 		};
825 
826 		if (!_ry)
827 			_e = 'circle', _p.r = _rx;
828 		else
829 			_e = 'ellipse', _p.rx = _rx, _p.ry = _ry;
830 
831 		_e = _.createNode(_e, _p);
832 
833 		if (_e && this.svg)
834 			this.addNode(_e);
835 	}
836 	return this;
837 },
838 
839 
840 lastCircle : null,
841 lastCircleDefs : null,
842 /**
843  * 繪製圓形。<br/>
844  * 此函數利用 _.type.addEllipsePath 來畫簡單圓形。
845  * @param _r
846  * @param _cx
847  * @param _cy
848  * @return
849  * @memberOf	CeL.net.SVG
850  */
851 addCircle : function(_r, _cx, _cy) {
852 	if (_r)
853 		this.addEllipsePath(_r, '', _cx, _cy).addContain(
854 				this.lastCircleDefs = this.lastAddDefs, 'circle', {
855 					r : _r
856 				});
857 	return this;
858 },
859 
860 lastEllipse : null,
861 lastEllipseDefs : null,
862 /**
863  * 繪製簡單圓形/橢圓。<br/>
864  * 此函數利用 .prototype.addEllipsePath 來畫簡單橢圓。
865  * @param _rx
866  * @param _ry
867  * @param _cx
868  * @param _cy
869  * @return
870  * @memberOf	CeL.net.SVG
871  */
872 addEllipse : function(_rx, _ry, _cx, _cy) {
873 	if (_rx) {
874 		this.addEllipsePath(_rx, _ry, _cx, _cy).addContain(
875 				this.lastEllipseDefs = this.lastAddDefs, 'ellipse',
876 				{
877 					rx : _rx,
878 					ry : _ry
879 				});
880 		this.lastEllipse = this.lastAdd;
881 	}
882 	return this;
883 },
884 
885 
886 /**
887  * 繪製矩形。<br/>
888  * 此函數利用 _.eNode 造出矩形路徑元件之後,再用 .prototype.addNode 將之插入本物件中。
889  * @param _w
890  * @param _h
891  * @param _x
892  * @param _y
893  * @param _color
894  * @param _strokeWidth
895  * @param _fill
896  * @param tramA
897  * @return
898  * @memberOf	CeL.net.SVG
899  */
900 addRect : function(_w, _h, _x, _y, _color, _strokeWidth, _fill,
901 		tramA) {
902 	this.addNode(_.createNode('rect', {
903 		width : _w,
904 		height : _h,
905 		x : _x,
906 		y : _y,
907 		stroke : _color || this.addRect.defaultColor,
908 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
909 		fill : _fill || 'none',
910 		transform : tramA
911 	}));
912 	return this;
913 },
914 
915 
916 /**
917  * 繪製多邊形。<br/>
918  * 此函數利用 _.eNode 造出多邊形路徑元件之後再用 .prototype.addNode 將之插入本物件中。
919  * @param {int array} _pA	[x1,y1,x2,y2,x3,y3,..]
920  * @param _color
921  * @param _strokeWidth
922  * @param _fill
923  * @param tramA
924  * @return
925  * @memberOf	CeL.net.SVG
926  */
927 addPolyline : function(_pA, _color, _strokeWidth, _fill, tramA) {
928 	var _i = 0, _p = [];
929 	while (_i < _pA.length)
930 		_p.push(_pA[_i++] + ',' + _pA[_i++]);
931 	this.addNode(_.createNode('polyline', {
932 		points : _p.join(' '),
933 		stroke : _color || this.addRect.defaultColor,
934 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
935 		fill : _fill || 'none',
936 		transform : tramA
937 	}));
938 	return this;
939 },
940 
941 
942 addImage : function() {
943 	//	TODO
944 	throw new Error(1, 'addImage: yet implement!');
945 },
946 
947 /**
948  * 功能正常嗎?
949  * @return	{Boolean} 功能正常
950  */
951 status_OK : function() {
952 	// !!: dual-unary operator
953 	return !!this.svg;
954 }
955 
956 };	//	_.prototype={
957 
958 
959 //	other manual setting
960 with (_.prototype) {
961 	addLine.defaultColor = _.defaultColor;
962 	addPath.defaultColor = _.defaultColor;
963 	addText.defaultColor = _.defaultColor;
964 	addText.defaultFont = null;
965 	addEllipsePath.defaultColor = _.defaultColor;
966 	addRect.defaultColor = _.defaultColor;
967 	addPolyline.defaultColor = _.defaultColor;
968 
969 }
970 
971 //	↑definition of module SVG object
972 
973 //	↑definition of module SVG
974 // ============================================================================
975 
976 
977 /**#@+
978  * @description	use {@link CeL.net.SVG} to draw:
979  */
980 
981 /*
982 draw_circle[generateCode.dLK]
983 	=draw_ellipse[generateCode.dLK]
984 	=draw_triangle[generateCode.dLK]
985 	=draw_quadrilateral[generateCode.dLK]
986 	='g_SVG';
987 */
988 
989 CeL.net.SVG
990 .
991 /**
992  * 繪製圓形。
993  * @since	2006/12/19 18:05
994  * @param _r
995  * @param svgO
996  * @param _color
997  * @param _fill
998  * @return	module SVG object
999  * @memberOf	CeL.net.SVG
1000  */
1001 draw_circle = function(_r, svgO, _color, _fill) {
1002 	var g_SVG = library_namespace.net.SVG;
1003 	if (_r
1004 			&& (svgO || (svgO = new g_SVG(
1005 					(_r + g_SVG.defaultStrokeWidth) * 2,
1006 					(_r + g_SVG.defaultStrokeWidth) * 2).show()))
1007 					&& svgO.status_OK()) {
1008 		svgO.addCircle(_r, _r + g_SVG.defaultStrokeWidth, _r
1009 				+ g_SVG.defaultStrokeWidth);
1010 		return svgO;
1011 	}
1012 };
1013 CeL.net.SVG
1014 .
1015 /**
1016  * 繪製橢圓。
1017  * @param _rx
1018  * @param _ry
1019  * @param svgO
1020  * @param _color
1021  * @param _fill
1022  * @return	module SVG object
1023  * @memberOf	CeL.net.SVG
1024  */
1025 draw_ellipse = function(_rx, _ry, svgO, _color, _fill) {
1026 	var g_SVG = library_namespace.net.SVG;
1027 	if (_rx
1028 			&& _ry
1029 			&& (svgO || (svgO = new g_SVG(
1030 					(_rx + g_SVG.defaultStrokeWidth) * 2,
1031 					(_ry + g_SVG.defaultStrokeWidth) * 2).show()))
1032 					&& svgO.status_OK()) {
1033 		svgO.addEllipse(_rx, _ry, _rx + g_SVG.defaultStrokeWidth, _ry
1034 				+ g_SVG.defaultStrokeWidth);
1035 		return svgO;
1036 	}
1037 };
1038 
1039 
1040 CeL.net.SVG
1041 .
1042 /**
1043  * 畫簡單梯形。
1044  * @since	2006/12/17 12:38
1045  * @requires	split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_quadrilateral
1046  * @param _ds
1047  * @param _h
1048  * @param _d
1049  * @param _us
1050  * @param svgO
1051  * @param _color
1052  * @param _fill
1053  * @return	module SVG object
1054  * @memberOf	CeL.net.SVG
1055  */
1056 draw_quadrilateral = function(_ds, _h, _d, _us, svgO, _color, _fill) {
1057 	var g_SVG = library_namespace.net.SVG;
1058 	if (isNaN(_us) || _us === '')
1059 		_us = _ds;
1060 	if (_ds
1061 			&& _h
1062 			&& (svgO || (svgO = new g_SVG((_ds > _d + _us ? _ds : _d
1063 					+ _us)
1064 					+ g_SVG.defaultStrokeWidth, _h
1065 					+ g_SVG.defaultStrokeWidth).show()))
1066 					&& svgO.status_OK()) {
1067 		set_attribute(svgO.addQuadrilateral(_ds, _h, _d, _us).lastQuadrilateral,
1068 				{
1069 			stroke : _color,
1070 			fill : _fill
1071 				});
1072 		return svgO;
1073 	}
1074 };
1075 
1076 CeL.net.SVG
1077 .
1078 /**
1079  * 畫簡單三角形。
1080  * @since	2006/12/17 12:38
1081  * @requires	split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_triangle
1082  * @param _ds
1083  * @param _h
1084  * @param _d
1085  * @param svgO
1086  * @param _color
1087  * @param _fill
1088  * @return	module SVG object
1089  * @memberOf	CeL.net.SVG
1090  */
1091 draw_triangle = function(_ds, _h, _d, svgO, _color, _fill) {
1092 	var g_SVG = library_namespace.net.SVG;
1093 	if (_ds
1094 			&& _h
1095 			&& (svgO || (svgO = new g_SVG((_ds > _d ? _ds : _d)
1096 					+ g_SVG.defaultStrokeWidth, _h
1097 					+ g_SVG.defaultStrokeWidth).show()))
1098 					&& svgO.status_OK()) {
1099 		set_attribute(svgO.addTriangle(_ds, _h, _d).lastTriangleDefs, {
1100 			stroke : _color,
1101 			fill : _fill
1102 		});
1103 		return svgO;
1104 	}
1105 };
1106 
1107 /*
1108 draw_addition[generateCode.dLK]
1109 	=draw_multiplication[generateCode.dLK]
1110 	=draw_long_division[generateCode.dLK]
1111 	='g_SVG,draw_scale';
1112 */
1113 
1114 /**
1115  * default 畫筆。
1116  * @inner
1117  * @private
1118  */
1119 var draw_scale = {
1120 		/**
1121 		 * text width
1122 		 * @inner
1123 		 * @private
1124 		 */
1125 		tW : 10,
1126 		/**
1127 		 * text height
1128 		 * @inner
1129 		 * @private
1130 		 */
1131 		tH : 2 * (10/* tW */- 2),
1132 		/**
1133 		 * decimal separator, 小數點
1134 		 * @see
1135 		 * <a href="http://en.wikipedia.org/wiki/Decimal_separator" accessdate="2010/1/20 18:29">Decimal separator</a>
1136 		 */
1137 		ds : '.',
1138 		/**
1139 		 * width of decimal separator
1140 		 */
1141 		dsw : 4,
1142 		/**
1143 		 * line height
1144 		 * @inner
1145 		 * @private
1146 		 */
1147 		lH : 4,
1148 		/**
1149 		 * margin left
1150 		 * @inner
1151 		 * @private
1152 		 */
1153 		mL : 0,
1154 		/**
1155 		 * margin top
1156 		 * @inner
1157 		 * @private
1158 		 */
1159 		mT : 0,
1160 		/**
1161 		 * 根號寬, squire width
1162 		 * @inner
1163 		 * @private
1164 		 */
1165 		sW : 10
1166 };
1167 //draw_scale.tH=22,draw_scale.tW=12;	//	for print
1168 CeL.net.SVG
1169 .
1170 /**
1171  * 利用 module SVG 物件來演示直式加法。
1172  * @since	2006/12/26 17:47
1173  * @param num1
1174  * @param num2
1175  * @param svgO
1176  * @param _color
1177  * @param _font
1178  * @return	module SVG object
1179  * @memberOf	CeL.net.SVG
1180  */
1181 draw_addition=function(num1, num2, svgO, _color, _font) {
1182 	if (!num1 && !num2)
1183 		return;
1184 	var g_SVG = library_namespace.net.SVG;
1185 	var _op = '+';
1186 	if (num2 < 0)
1187 		_op = '-', num2 = -num2;
1188 
1189 	var _a = _op == '+' ? (num1 - 0) + (num2 - 0) : num1 - num2,
1190 	_h = 3,
1191 	_w = (num2 += '').length + 2,
1192 	tW = draw_scale.tW,
1193 	tH = draw_scale.tH,
1194 	lH = draw_scale.lH,
1195 	mL = draw_scale.mL,
1196 	mT = draw_scale.mT;
1197 
1198 	if ((_a += '').length + 1 > _w)
1199 		_w = _a.length + 1;
1200 	if ((num1 += '').length + 1 > _w)
1201 		_w = num1.length + 1;
1202 	_h = _h * tH + 2 * lH + 2 * mT;
1203 	_w = (2 + _w) * tW + 2 * mL;
1204 
1205 	if (svgO && svgO.status_OK())
1206 		svgO.clean();
1207 	else if (!(svgO = new g_SVG).show().status_OK())
1208 		return null;
1209 
1210 	svgO.setSize(_w, _h);
1211 
1212 	_w -= mL + tW;
1213 
1214 	//	TODO: 讓 IE8 顯示起來像 111+111=222, 而非 +111111222
1215 	svgO
1216 		.addNum(num1, _w - num1.length * tW, mT + tH, tW, _color, _font)
1217 		.addNum(num2, _w - num2.length * tW, mT + 2 * tH, tW, _color, _font)
1218 		.addText(_op, mL + tW, mT + 2 * tH, _color, _font)
1219 		.addPath('M' + mL + ',' + (mT + 2 * tH + lH / 2) + ' H' + (_w + tW))
1220 		.addNum(_a, _w - _a.length * tW, mT + 3 * tH + lH, tW, _color, _font);
1221 
1222 	return svgO;
1223 };
1224 //draw_subtraction[generateCode.dLK]='draw_addition';
1225 CeL.net.SVG
1226 .
1227 /**
1228  * 呼叫 draw_subtraction 來演示直式減法。因為直式加減法的運算與機制過程非常相似,因此我們以 draw_addition 來一併的處理這兩個相似的運算過程。
1229  * @since	2006/12/26 17:47
1230  * @param num1
1231  * @param num2
1232  * @param svgO
1233  * @param _color
1234  * @param _font
1235  * @return	module SVG object
1236  * @memberOf	CeL.net.SVG
1237  */
1238 draw_subtraction = function(num1, num2, svgO, _color, _font) {
1239 	return _.draw_addition.call(this, num1, -num2, svgO, _color, _font);
1240 };
1241 
1242 CeL.net.SVG
1243 .
1244 /**
1245  * 利用 module SVG 物件來演示直式乘法。<br/>
1246  * TODO: 小數的乘法
1247  * @since	2006/12/26 17:47
1248  * @param num1
1249  * @param num2
1250  * @param svgO
1251  * @param _color
1252  * @param _font
1253  * @return	module SVG object
1254  * @memberOf	CeL.net.SVG
1255  * @see
1256  * <a href="http://203.71.239.19/math/courses/cs04/M4_6.php" accessdate="2010/1/20 18:5">小數篇:小數的乘法</a>
1257  */
1258 draw_multiplication=function(num1, num2, svgO, _color, _font) {
1259 	if (!num1 && !num2)
1260 		return;
1261 
1262 	var g_SVG = library_namespace.net.SVG;
1263 	var _op = '×', _j, _C = 1, _a = num1 * num2, _h = 0, _w = (num2 += '').length + 2, tW = draw_scale.tW, tH = draw_scale.tH, lH = draw_scale.lH, mL = draw_scale.mL, mT = draw_scale.mT;
1264 	if ((_a += '').length > _w)
1265 		_w = _a.length;
1266 	if ((num1 += '').length > _w)
1267 		_w = num1.length;
1268 	for (_j = 0; _j < num2.length; _j++)
1269 		if (num2.charAt(_j) - 0)
1270 			_h++;
1271 	if (_h == 1)
1272 		_h = 0, _C = 0;
1273 	_h = (3 + _h) * tH + 2 * lH + 2 * mT;
1274 	_w = (2 + _w) * tW + 2 * mL;
1275 
1276 	if (svgO && svgO.status_OK())
1277 		svgO.clean();
1278 	else if (!(svgO = new g_SVG).show().status_OK())
1279 		return null;
1280 
1281 	svgO.setSize(_w, _h);
1282 
1283 	_w -= mL + tW;
1284 
1285 	svgO
1286 		.addNum(num1, _w - num1.length * tW, mT + tH, tW, _color, _font)
1287 		.addNum(num2, _w - num2.length * tW, mT + 2 * tH, tW, _color, _font)
1288 		.addText(_op, mL + tW, mT + 2 * tH, _color, _font)
1289 		.addPath('M' + mL + ',' + (_h = mT + 2 * tH + lH / 2) + ' H' + (_w + tW));
1290 
1291 	_op = '';
1292 	_h += lH / 2;
1293 	var _w2 = _w, _n;
1294 	if (_C) {
1295 		for (_j = num2.length - 1; _j >= 0; _j--)
1296 			if (_n = num2.charAt(_j) - 0)
1297 				svgO.addNum(_n = (num1 * _n) + _op, _w2 - _n.length
1298 						* tW, _h += tH, tW, _color, _font), _w2 -= tW
1299 						* (_op.length + 1), _op = '';
1300 			else
1301 				_op += '0';
1302 		svgO
1303 		.addPath('M' + mL + ',' + (_h += lH / 2) + ' H'
1304 				+ (_w + tW));
1305 	}
1306 
1307 	svgO.addNum(_a, _w - _a.length * tW, _h + lH / 2 + tH, tW, _color, _font);
1308 
1309 	return svgO;
1310 };
1311 
1312 /*
1313 TODO:
1314 小數
1315 換基底
1316 */
1317 //draw_long_division[generateCode.dLK]='g_SVG,set_class';//split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_long_division
1318 CeL.net.SVG
1319 .
1320 /**
1321  * 利用 module SVG 物件來展示<a href="http://en.wikipedia.org/wiki/Long_division" title="long division">直式除法</a>。<br/>
1322  * !! 尚有許多 bug<br/>
1323  * @since	2006/12/11-12 11:36
1324  * @param dividend
1325  * @param divisor
1326  * @param	digits_after	TODO: 小數直式除法: 小數點後位數, how many digits after the decimal separator
1327  * @param svgO
1328  * @param _color
1329  * @param _font
1330  * @return	module SVG object
1331  * @example
1332  * // include module
1333  * CeL.use('net.SVG');
1334  * 
1335  * //	way 1
1336  * var SVG_object = new CeL.SVG;
1337  * SVG_object.attach('panel_for_SVG').show(1);
1338  * CeL.draw_long_division(452, 34, SVG_object);
1339  * // You can also put here.
1340  * //SVG_object.attach('panel_for_SVG').show(1);
1341  * 
1342  * //	way 2
1343  * var SVG_object = CeL.draw_long_division(100000, 7);
1344  * SVG_object.attach('panel_for_SVG').show(1);
1345  * 
1346  * // 另一次顯示
1347  * CeL.draw_long_division(100, 7, SVG_object);
1348  * @memberOf	CeL.net.SVG
1349  */
1350 draw_long_division = function(dividend, divisor, svgO, _color, _font) {
1351 	if (isNaN(dividend) || isNaN(divisor) || !divisor)
1352 		return;
1353 
1354 	var g_SVG = library_namespace.net.SVG;
1355 	/**
1356 	 * 餘數 remainder
1357 	 * @inner
1358 	 * @ignore
1359 	 */
1360 	var remainder;
1361 	/**
1362 	 * 商 quotient
1363 	 * @inner
1364 	 * @ignore
1365 	 */
1366 	var quotient = '' + Math.floor(dividend / divisor),
1367 		tW = draw_scale.tW,
1368 		tH = draw_scale.tH,
1369 		lH = draw_scale.lH,
1370 		mL = draw_scale.mL,
1371 		mT = draw_scale.mT,
1372 		sW = draw_scale.sW,
1373 		bx = mL + ('' + divisor).length * tW + sW,
1374 		by = mT + lH + 2 * tH;
1375 
1376 	dividend += '';
1377 	if (svgO && svgO.status_OK())
1378 		svgO.clean();
1379 	else if (!(svgO = new g_SVG).show().status_OK())
1380 		return null;
1381 
1382 	svgO
1383 	//.show(1)
1384 	// 調整大小
1385 	.setSize(
1386 			2
1387 			* mL
1388 			+ (('' + divisor).length + dividend.length + 2)
1389 			* tW + sW,
1390 			2 * mT + by + quotient.length * (tH * 2 + lH))
1391 	// 除數 divisor
1392 	.addNum(divisor, mL, by, tW, _color, _font)
1393 	// 商 quotient
1394 	.addNum(quotient,
1395 			bx + (dividend.length - quotient.length) * tW,
1396 			mT + tH, tW, _color, _font)
1397 	// 被除數 dividend
1398 	.addNum(dividend, bx, by, tW, _color, _font)
1399 	// .addNode('path',{d:'M'+(bx+(dividend.length+1)*tW)+','+(by-lH/2-tH)+'
1400 	// H'+(bx-tW)+' a'+tW/2+','+(lH+tH)+' 0 0,1
1401 	// -'+tW/2+','+(lH+tH),stroke:'#000',style:'fill:none;'})
1402 	.addPath(
1403 			'M' + (bx - (tW + sW) / 2) + ',' + (by + lH / 2)
1404 			+ ' a' + tW / 2 + ',' + (lH + tH)
1405 			+ ' 0 0,0 ' + tW / 2 + ',-' + (lH + tH)
1406 			+ ' h' + (dividend.length + 2) * tW);
1407 
1408 	svgO.addDefs(g_SVG.createNode('line', {
1409 		x1 : 0,
1410 		y1 : 0,
1411 		x2 : (dividend.length + 1) * tW,
1412 		y2 : 0,
1413 		// 'stroke-width':'1px',
1414 		stroke : svgO.addLine.defaultColor
1415 	}));
1416 
1417 	if (svgO.div)
1418 		// svgO.div.className='long_division';
1419 		set_class(svgO.div, 'long_division');
1420 
1421 	// 用 symbol??
1422 	svgO.addContain(0, 'long_division', {
1423 		dividend : dividend,
1424 		divisor : divisor
1425 	});
1426 
1427 	var _k = 0, a, b, l = svgO.lastAddDefs,
1428 	/**
1429 	 * 被除數處理到第幾位
1430 	 * @inner
1431 	 * @ignore
1432 	 */
1433 	dt = 1;
1434 	remainder = dividend.charAt(0);
1435 	for (; _k < quotient.length;) {
1436 		a = quotient.charAt(_k);
1437 		// if(!a)continue;
1438 		a = '' + a * divisor, b = dividend.length
1439 		- quotient.length + _k + 1;
1440 
1441 		svgO.addUse(l, {
1442 			x : bx,
1443 			y : (by + tH + lH / 2)
1444 		}).addNum(a, bx + (b - a.length) * tW, by + tH, tW, _color,
1445 				_font);
1446 
1447 		// 以下..ugly hack
1448 		// 先算出餘數
1449 		while ((a == 0 || remainder - a < 0) && dt < dividend.length)
1450 			remainder += dividend.charAt(dt++);
1451 		remainder -= a;
1452 		if (!remainder)
1453 			remainder = '';
1454 		//alert(remainder+','+quotient.charAt(_k+1)+'\n'+(i<quotient.length))
1455 		// 再添加到夠減的位數
1456 		while (quotient.charAt(++_k) == 0 && _k < quotient.length) {
1457 			b++;
1458 			if (remainder || dividend.charAt(dt) > 0)
1459 				remainder += dividend.charAt(dt);
1460 			dt++;
1461 		}
1462 		// 顯示位數微調
1463 		if (dt < dividend.length) {
1464 			b++;
1465 			// 加一位
1466 			remainder += dividend.charAt(dt++);
1467 		} else if (!remainder)
1468 			b--;
1469 		//alert(remainder+','+a+','+dt+'\n'+(remainder<a));
1470 		svgO.addNum(remainder || 0, bx + (b - ('' + remainder).length)
1471 				* tW, by += 2 * tH + lH, tW, _color, _font);
1472 	}
1473 
1474 	return svgO;
1475 };
1476 
1477 
1478 /**#@-*/
1479 //	↑@memberOf	module SVG
1480 
1481 
1482 
1483 
1484 return (
1485 	CeL.net.SVG
1486 );
1487 };
1488 
1489 //===================================================
1490 
1491 CeL.setup_module(module_name, code_for_including);
1492 
1493 };
1494