parse.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. function htmlEditor() {
  2. const fontArr = []
  3. for(var ii = 9; ii < 41; ii++){
  4. fontArr.push(ii+'pt')
  5. }
  6. $('.htmlEditor').dxHtmlEditor({
  7. onContentReady: function(e) {
  8. e.component.format("font", "맑은고딕");
  9. e.component.format("size", "18pt");
  10. e.component.format("color", "springgreen");
  11. e.component.getQuillInstance().blur();
  12. e.component.getQuillInstance().focus();
  13. },
  14. toolbar: {
  15. items: [
  16. 'alignLeft', 'alignCenter','alignRight',
  17. 'separator',
  18. ,
  19. {
  20. name: 'font',
  21. acceptedValues: ['맑은고딕','굴림체', '궁서체', '돋움체', '바탕체'],
  22. options: {
  23. //value:'맑은 고딕',
  24. //width: 170
  25. },
  26. },
  27. 'separator',
  28. {
  29. name: 'color',
  30. acceptedValues: ['red', 'springgreen','yellow'],
  31. options: {
  32. //value:"springgreen",
  33. //width: 170,
  34. // icon: "color"
  35. }
  36. },
  37. 'separator',
  38. {
  39. name: 'size',
  40. acceptedValues: fontArr,
  41. options: {
  42. //value:"18pt",
  43. //width: 170,
  44. }
  45. },
  46. 'separator',
  47. 'bold'
  48. ],
  49. //container: ".htmlToolBar"
  50. },
  51. onValueChanged(e) {
  52. let color = $(".dx-htmleditor-content").find("span").css("color")
  53. if(color == null) {
  54. e.component.format("font", "맑은고딕");
  55. e.component.format("size", "18pt");
  56. e.component.format("color", "springgreen");
  57. e.component.getQuillInstance().blur();
  58. e.component.getQuillInstance().focus();
  59. }
  60. $('.value-content').text(e.component.option('value'));
  61. let htmlTextVal = $('.value-content').text()
  62. parsHtml(htmlTextVal)
  63. },
  64. })
  65. }
  66. function parsHtml(htmlTextVal) {
  67. // 돋움 : Dotum
  68. // 돋움체 : DotumChe
  69. // 굴림 : Gulim
  70. // 굴림체 : GulimChe
  71. // 바탕 : Batang
  72. // 바탕체 : BatangChe
  73. // 궁서 : Gungsuh
  74. // 궁서체 : GungsuhChe
  75. // 새굴림: New Gulim
  76. // 맑은 고딕 : Malgun Gothic, ==> Default Font
  77. const fontNameMap = new Map();
  78. fontNameMap.set("맑은 고딕", 1);
  79. fontNameMap.set("HY견명조", 2);
  80. fontNameMap.set("굴림체", 3);
  81. fontNameMap.set("궁서체", 4);
  82. fontNameMap.set("돋움체", 5);
  83. fontNameMap.set("바탕체", 6);
  84. const fontCodeMap = new Map();
  85. fontCodeMap.set(1, "맑은 고딕");
  86. fontCodeMap.set(2, "HY견명조");
  87. fontCodeMap.set(3, "굴림체");
  88. fontCodeMap.set(4, "궁서체");
  89. fontCodeMap.set(5, "돋움체");
  90. fontCodeMap.set(6, "바탕체");
  91. class Text {
  92. constructor(name, size, color, bold, width, height, htmlText, text) {
  93. this.name = name;
  94. this.size = size;
  95. this.color = color;
  96. this.bold = bold;
  97. this.width = width;
  98. this.height = height;
  99. this.htmlText = htmlText;
  100. this.text = text;
  101. this.x = 0;
  102. this.y = 0;
  103. }
  104. }
  105. class Line {
  106. constructor(align) {
  107. this.align = align;
  108. this.width = 0;
  109. this.height = 0;
  110. this.texts = new Array();
  111. }
  112. }
  113. class Form {
  114. constructor(color, width, height) {
  115. this.color = color;
  116. this.width = width;
  117. this.height = height;
  118. this.textHeight = 0;
  119. this.lines = new Array();
  120. }
  121. }
  122. // Map 으로 저장해서 처리하는 것으로 수정하는 것이 좋음.
  123. function getTextAlignFromData(align) {
  124. //(0:left, 1:right, 2:center
  125. if (align === "center") {
  126. return 2;
  127. }
  128. if (align === "right") {
  129. return 1;
  130. }
  131. return 0;
  132. }
  133. function getTextAlignFromCode(align) {
  134. //(0:left, 1:right, 2:center
  135. if (align === 2) {
  136. return "center";
  137. }
  138. if (align === 1) {
  139. return "right";
  140. }
  141. return "left";
  142. }
  143. var $log = $("#log");
  144. var str = "";
  145. // str += '<p style="text-align: center;">';
  146. // str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 맑은 고딕;">맑은 고딕</strong>';
  147. // str += ' <strong style="color: rgb(0, 255, 0); font-size: 18pt; font-family: 맑은 고딕;">굴림체</strong>';
  148. // str += ' <strong style="color: rgb(0, 0, 255); font-size: 18pt; font-family: 맑은 고딕;">HY견명조</strong></p>';
  149. // str += '<p style="text-align: center;">';
  150. // str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 궁서체;">궁서체</strong>';
  151. // str += ' <strong style="color: rgb(0, 255, 0); font-size: 18pt; font-family: 궁서체;">돋움체</strong>';
  152. // str += ' <strong style="color: rgb(0, 0, 255); font-size: 18pt; font-family: 궁서체;">바탕체</strong></p>';
  153. // str += '<p style="text-align: left;">';
  154. // str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 맑은 고딕;">맑은 afdsa 고딕</strong>';
  155. // str += ' <strong style="color: rgb(0, 255, 0); font-size: 18pt; font-family: 굴림체;">굴림체</strong>';
  156. // str += ' <strong style="color: rgb(0, 0, 255); font-size: 18pt; font-family: HY견명조;">HY견명조</strong></p>';
  157. // str += '<p style="text-align: right;">';
  158. // str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 궁서체;">궁서체</strong>';
  159. // str += ' <strong style="color: rgb(0, 255, 0); font-size: 18pt; font-family: 돋움체;">돋움체</strong>';
  160. // str += ' <strong style="color: rgb(0, 0, 255); font-size: 18pt; font-family: 바탕체;">바탕체</strong></p>';
  161. str = htmlTextVal;
  162. // '<p style="text-align: left;"><span style="color: red; font-size: 12pt;">동해물과 백두산이</span> <span style="font-family: 굴림체; color: springgreen; font-size: 12pt;">마르고 닳도록</span></p><p style="text-align: right;"><span style="font-family: 궁서체; font-size: 12pt; color: yellow;">하나님이 보우하사</span> <span style="font-family: 돋움체; font-size: 12pt; color: red;">우리나라 만세</span></p>';
  163. // '<p><span style="color: red; font-family: 나눔고딕;">기본폰트 </span><span style="font-family: Sunflower; color: springgreen;">나눔고딕 </span><span style="font-family: 나눔명조;">나눔명조</span></p><p><span style="font-family: 나눔고딕;">썬플라워</span> <span style="font-family: 나눔고딕;">햄릿</span><span style="font-family: Hahmlet;"> </span><span style="font-family: 나눔고딕;">노토산즈</span></p><p><br></p>';
  164. var html = $.parseHTML(str);
  165. var nodeNames = [];
  166. let line = 0;
  167. ////console.log("=====================================================");
  168. // HTML TAG Parsing....................
  169. const el = document.createElement("html");
  170. el.innerHTML = str;
  171. const pTags = el.getElementsByTagName("p");
  172. //console.log(el);
  173. //console.log(pTags);
  174. const objForm = new Form("rgb(0,0,0)", 384, 64);
  175. for (let ii = 0; ii < pTags.length; ii++) {
  176. const p = pTags[ii];
  177. const textAlign = getTextAlignFromData(p.style.textAlign);
  178. const children = p.children;
  179. //console.log("----------------------------------------------------------------");
  180. if (children.length == 0) {
  181. console.warn("object not found....");
  182. continue;
  183. }
  184. const objLine = new Line(textAlign);
  185. for (let jj = 0; jj < children.length; jj++) {
  186. const obj = children[jj];
  187. const fontName = obj.style.fontFamily;
  188. const fontSize = Number(obj.style.fontSize.replace("pt", "").replace("px", ""));
  189. const fontBold = obj.nodeName === "STRONG" ? true : obj.style.fontWeight === "bold";
  190. let fontColor = obj.style.color.replaceAll(" ", "");
  191. if (fontColor === "") {
  192. fontColor = "rgb(0,0,0)";
  193. }
  194. const htmlText = obj.innerText;
  195. const text = htmlText.trim();
  196. const result = getTextInfo(fontName, fontSize, fontBold, htmlText);
  197. const textWidth = result.width;
  198. const textHeight = result.height;
  199. objLine.width += textWidth;
  200. if (textHeight > objLine.height) {
  201. objLine.height = textHeight;
  202. }
  203. const objText = new Text(fontName, fontSize, fontColor, fontBold, textWidth, textHeight, htmlText, text);
  204. objLine.texts.push(objText);
  205. //console.log(
  206. // `line ${line}, objects ${jj}, font-Name: ${fontName}, bold: ${fontBold}, size: ${fontSize}, color: ${fontColor}, text: ${text}, [${htmlText}], text-height: ${textHeight}, text-width: ${textWidth}`
  207. // );
  208. }
  209. //console.log(
  210. // `line ${line}, objects: [${children.length}], text-align: [${textAlign}]${getTextAlignFromCode(textAlign)}, line-width: ${objLine.width}, line-height: ${
  211. // objLine.height
  212. // }`
  213. // );
  214. objForm.textHeight += objLine.height;
  215. objForm.lines.push(objLine);
  216. line++;
  217. }
  218. // 텍스트 위치 계산
  219. let textTop = objForm.height - objForm.textHeight;
  220. if (textTop <= 0) {
  221. textTop = 0;
  222. } else {
  223. textTop /= 2;
  224. }
  225. objForm.lines.forEach((line, idx) => {
  226. let left = 0; // left
  227. if (line.align == 1) {
  228. // right
  229. left = objForm.width - line.width;
  230. if (left <= 0) {
  231. left = 0;
  232. }
  233. } else if (line.align == 2) {
  234. // center
  235. left = objForm.width - line.width;
  236. if (left <= 0) {
  237. left = 0;
  238. } else {
  239. left /= 2;
  240. }
  241. }
  242. line.texts.forEach((text, seq) => {
  243. text.x = left;
  244. text.y = textTop + (line.height - text.height);
  245. left += text.width;
  246. });
  247. textTop += line.height;
  248. });
  249. //console.log(objForm);
  250. // 미리보기 폼을 캔버스에 그린다.
  251. drawPreviewForm(objForm);
  252. $log.html(html);
  253. //$("#previewCanvas").append("<h3>Preview:</h3>");
  254. // $log.append("<h3>Preview:</h3>");
  255. function getTextInfo2(fontName, fontSize, fontBold, htmlText) {
  256. var text = document.createElement("span");
  257. document.body.appendChild(text);
  258. //text.style.backgroundColor = "#FF0000";
  259. //text.style.lineHeight = "100%";
  260. text.style.border = "none";
  261. text.style.margin = "0px";
  262. text.style.padding = "0px";
  263. text.style.font = fontName;
  264. if (fontBold) {
  265. text.style.fontWeight = "bold";
  266. }
  267. text.style.fontFamily = fontName;
  268. text.style.fontSize = fontSize + "pt";
  269. text.style.height = "auto";
  270. text.style.width = "auto";
  271. text.style.position = "absolute";
  272. text.style.whiteSpace = "pre"; //"nowrap";
  273. text.innerHTML = htmlText;
  274. ////console.log("getTextInfo: ", text.getBoundingClientRect());
  275. const width = Math.ceil(text.clientWidth);
  276. const height = Math.ceil(text.clientHeight);
  277. document.body.removeChild(text);
  278. //console.log("getTextInfo: ", width, height);
  279. return {
  280. width: width,
  281. height: height,
  282. };
  283. }
  284. function getTextInfo(fontName, fontSize, fontBold, htmlText) {
  285. const canvas = document.getElementById("previewCanvas");
  286. const ctx = canvas.getContext("2d");
  287. ctx.fillStyle = "rgb(0,0,0)";
  288. ctx.fillRect(0, 0, canvas.width, canvas.height);
  289. const bold = fontBold ? "bold" : "";
  290. ctx.font = `${bold} ${fontSize}pt ${fontName}`;
  291. ctx.textBaseline = "hanging";
  292. ctx.fillStyle = "rgb(255,0,0)";
  293. ctx.fillText(htmlText, 0, 0);
  294. const metrics = ctx.measureText(htmlText);
  295. const textWidth = metrics.width;
  296. const fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
  297. const actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
  298. //console.log(metrics);
  299. // //console.log(fontHeight, actualHeight);
  300. const width = Math.ceil(textWidth);
  301. const height = Math.ceil(fontHeight);
  302. return {
  303. width: width,
  304. height: height,
  305. };
  306. }
  307. function drawPreviewForm(form) {
  308. const canvas = document.getElementById("previewCanvas");
  309. const ctx = canvas.getContext("2d");
  310. ctx.fillStyle = form.color;
  311. ctx.fillRect(0, 0, canvas.width, canvas.height);
  312. form.lines.forEach((line, idx) => {
  313. line.texts.forEach((text, seq) => {
  314. const bold = text.bold ? "bold" : "";
  315. ctx.font = `${bold} ${text.size}pt ${text.name}`;
  316. ctx.textBaseline = "hanging";
  317. ctx.fillStyle = text.color;
  318. ctx.fillText(text.text, text.x, text.y);
  319. });
  320. });
  321. }
  322. }