textObject.js 7.63 KB
Newer Older
1 2 3 4 5 6 7
/**
 *  ABook Viewer for WEB
 *	Drawing HTML Text Library
 *	**this library depend on htmlparser.js**
 *  Copyright (C) Agentec Co, Ltd. All rights reserved.
 */

8 9 10
 //グローバルの名前空間用のオブジェクトを用意する
var TEXTOBJECT = {};

11
/**
vietdo committed
12
 * get HTML Text Image URL
13
 */
14
TEXTOBJECT.getTextObjectImage = function(width, height, htmlData) {
vietdo committed
15

16 17 18
	var canvas = document.createElement('canvas');
	canvas.width = width;
	canvas.height = height;
vietdo committed
19

20 21 22 23 24 25 26 27 28 29
	var context = canvas.getContext('2d');
	var dataHtml = '';
	var currentLine = 0;
	var lineHeight = 0;
	var nextLinePosition = 0;
	var lineWidth = width;			// 1行の幅
	var startPosition = 0;			// テキスト描画の開始位置
	var hasUnderLine = false;		// アンダーラインの有無
	var textAlign = 'left';			// テキスト揃え
	var margin = 2;
vietdo committed
30 31 32 33 34
	var newLine = false;
	var startPoint = 0;
	var flag = 0;
	var frontLine = 0;
	var startRight = 0;
35 36 37
	/* remove escape charactor '\' */
	dataHtml = htmlData.replace(/\\/, '');
	//console.log('dataHtml:' + dataHtml);
vietdo committed
38

39 40 41 42 43 44 45 46 47 48 49 50 51
	// parse
	HTMLParser(dataHtml,
		{
		    start: function (tag, attrs, unary) {
		        var t = tag.toLowerCase();
		        /*
		        * DIVタグ
		        */
		        if (t == 'div') {
		            var align;
		            for (var i = 0; i < attrs.length; i++) {
		                var attrName = attrs[i].name.toLowerCase();
		                if (attrName == 'align') {
vietdo committed
52
		                	newLine = true;
53 54
		                    align = attrs[i].escaped;
		                    textAlign = align;
vietdo committed
55 56
		                } else {
		                	newLine = false;
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
		                }
		            }
		            if (align == 'left') {
		                startPosition = 0;
		                context.textAlign = 'left';
		            } else if (align == 'center') {
		                startPosition = lineWidth / 2;
		                context.textAlign = 'center';
		            } else if (align == 'right') {
		                startPosition = lineWidth;
		                context.textAlign = 'right';
		            }
		        }
		        /*
		        * FONTタグ
		        */
		        if (t == 'font') {
		            var fontFace = 'MS Pゴシック';
		            var fontSize = '11px';
		            var fontColor = '#000000';
vietdo committed
77
		            newLine = false;
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
		            for (var i = 0; i < attrs.length; i++) {

		                var attrName = attrs[i].name.toLowerCase();

		                if (attrName == 'face') {
		                    fontFace = attrs[i].escaped;
		                }
		                if (attrName == 'style') {
		                    var styleBase = attrs[i].escaped;
		                    var styles = styleBase.split(';');
		                    for (var j = 0; j < styles.length; j++) {
		                        var style = styles[j].split(':');
		                        if (style[0].toLowerCase() == 'font-size') {
		                            fontSize = style[1];
		                        }
		                        if (style[0].toLowerCase() == 'line-height') {
		                            lineHeight = parseInt(style[1].replace('px', ''));
		                        }
		                    }
		                }
		                if (attrName == 'color') {
		                    fontColor = attrs[i].escaped;
		                }
		            }
		            // context に設定
		            context.font = fontSize + " " + "'" + fontFace + "'";
		            context.fillStyle = fontColor;

vietdo committed
106
		            // 行間
107
		            nextLinePosition = parseInt(fontSize.replace('px', '')) * (lineHeight / 100);
vietdo committed
108

109 110 111 112 113 114 115 116
		        }

		        /*
		        * BR タグ
		        */
		        if (t == 'br') {
		            currentLine += (nextLinePosition + margin);
		        }
vietdo committed
117 118 119 120 121 122 123
		        if(newLine == true && flag > 0) {
		        	frontLine = currentLine;
		        	currentLine += nextLinePosition;
		        }  else if(flag == 0){
		        	currentLine = 20;
		        }
		        flag++;
124 125 126 127 128
		        /*
		        * Uタグ
		        */
		        if (t == 'u') {
		            hasUnderLine = true;
vietdo committed
129 130
		        } else {
		        	hasUnderLine = false;
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
		        }
		    },

		    end: function (tag) {

		        var t = tag.toLowerCase();
		        /*
		        * Uタグ
		        */
		        if (t == 'u') {
		            hasUnderLine = false;
		        }
		    },

		    chars: function (text) {
		        // エンティティ文字を置換
		        // &nbsp; &gt; &lt; &amp; &yen; &copy; &reg; のみ対応
		        text = text.replace(/&nbsp;/g, ' ');
		        text = text.replace(/&gt;/g, '>');
		        text = text.replace(/&lt;/g, '<');
		        text = text.replace(/&amp;/g, '&');
		        text = text.replace(/&copy;/g, '(C)');
		        text = text.replace(/&reg;/g, '(R)');
		        text = text.replace(/&yen;/g, '\\');
		        // 初期描画位置を考慮
		        if (currentLine == 0) {
157
		            //2014/02 フォントを大きくすると文字の上側が隠れる問題の対応
vietdo committed
158
		           // currentLine += nextLinePosition / 2;
159
		            currentLine += nextLinePosition;
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
		        }

		        //長い文字列を考慮する
		        var w = 0;
		        var index = 0;
		        var fillText = '';
		        for (var i = 0; i < text.length; i++) {
		            var metrices = context.measureText(fillText + text.charAt(i), startPosition, currentLine);

		            // 幅に収まるならバッファに蓄える
		            if (metrices.width < lineWidth) {
		                fillText += text.charAt(i);
		            }
		            // はみ出す場合
		            else {
		                context.fillText(fillText, startPosition, currentLine + margin);
		                // アンダーライン
		                if (hasUnderLine) {
		                    context.beginPath();
		                    context.moveTo(0, currentLine + margin);
		                    context.lineTo(lineWidth, currentLine + margin);
		                    context.strokeStyle = context.fillStyle;
		                    context.stroke();
		                }
		                currentLine += (nextLinePosition + margin);
		                fillText = text.charAt(i);
		            }
		        }
		        if (fillText.length > 0) {
vietdo committed
189
	        		context.fillText(fillText, startPosition, currentLine + margin);
190 191 192
		            // アンダーライン
		            if (hasUnderLine) {
		                var x1, x2;
vietdo committed
193 194 195 196 197 198 199 200 201 202
		                if(currentLine > frontLine) {
	                		if(newLine == false) {
		                		startPoint = startPosition;
		                	} else {
		                		startPoint = 0;
		                		startPosition = 0;
		                	}
			            } else {
				            startPoint = startPosition;
			            }
203
		                if (textAlign == 'left') {
vietdo committed
204 205
		                    x1 = startPoint;
		                    x2 = startPoint + metrices.width;
206
		                } else if (textAlign == 'center') {
vietdo committed
207 208 209 210 211
		                    x1 = startPoint - (metrices.width / 2);
		                    x2 = startPoint + (metrices.width / 2);
		                } else if (textAlign = 'right') {
		                    x1 = width;
		                    x2 = width - metrices.width;
212 213 214
		                }
		                context.beginPath();
		                context.moveTo(x1, currentLine + margin);
vietdo committed
215
                		context.lineTo(x2, currentLine + margin);
216 217 218
		                context.strokeStyle = context.fillStyle;
		                context.stroke();
		            }
vietdo committed
219 220
		            startPosition +=metrices.width;
		            //currentLine += (nextLinePosition + margin);
221 222 223 224
		        }
		    }
		}
	);
vietdo committed
225
	//context.fillText("helloworld",0, currentLine + margin);
226 227 228 229
	// 描画したイメージを返却する
	var imageUrl = canvas.toDataURL();
	return imageUrl;
};