|
@@ -0,0 +1,339 @@
|
|
|
+<html lang="en">
|
|
|
+ <head>
|
|
|
+ <meta charset="utf-8" />
|
|
|
+ <title>jQuery.parseHTML demo</title>
|
|
|
+ <script src="https://code.jquery.com/jquery-3.5.0.js"></script>
|
|
|
+ <style>
|
|
|
+ #previewDiv {
|
|
|
+ margin-left: 0px;
|
|
|
+ margin-top: 0px;
|
|
|
+ margin-right: 0px;
|
|
|
+ background-color: #000000;
|
|
|
+ border: 1px solid #ff0000;
|
|
|
+ width: 386px;
|
|
|
+ height: 65px;
|
|
|
+ }
|
|
|
+ #previewCanvas {
|
|
|
+ margin-left: 1px;
|
|
|
+ margin-top: 1px;
|
|
|
+ margin-right: 1px;
|
|
|
+ background-color: #000000;
|
|
|
+ width: 384px;
|
|
|
+ height: 64px;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+ <div id="log">
|
|
|
+ <h3>Content:</h3>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div id="previewDiv" class="previewDiv">
|
|
|
+ <canvas id="previewCanvas" class="previewCanvas" width="384" height="64"> VMS Form Preview </canvas>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ // 돋움 : Dotum
|
|
|
+ // 돋움체 : DotumChe
|
|
|
+ // 굴림 : Gulim
|
|
|
+ // 굴림체 : GulimChe
|
|
|
+ // 바탕 : Batang
|
|
|
+ // 바탕체 : BatangChe
|
|
|
+ // 궁서 : Gungsuh
|
|
|
+ // 궁서체 : GungsuhChe
|
|
|
+ // 새굴림: New Gulim
|
|
|
+ // 맑은 고딕 : Malgun Gothic, ==> Default Font
|
|
|
+
|
|
|
+ const fontNameMap = new Map();
|
|
|
+ fontNameMap.set("맑은 고딕", 1);
|
|
|
+ fontNameMap.set("HY견명조", 2);
|
|
|
+ fontNameMap.set("굴림체", 3);
|
|
|
+ fontNameMap.set("궁서체", 4);
|
|
|
+ fontNameMap.set("돋움체", 5);
|
|
|
+ fontNameMap.set("바탕체", 6);
|
|
|
+
|
|
|
+ const fontCodeMap = new Map();
|
|
|
+ fontCodeMap.set(1, "맑은 고딕");
|
|
|
+ fontCodeMap.set(2, "HY견명조");
|
|
|
+ fontCodeMap.set(3, "굴림체");
|
|
|
+ fontCodeMap.set(4, "궁서체");
|
|
|
+ fontCodeMap.set(5, "돋움체");
|
|
|
+ fontCodeMap.set(6, "바탕체");
|
|
|
+
|
|
|
+ class Text {
|
|
|
+ constructor(name, size, color, bold, width, height, htmlText, text) {
|
|
|
+ this.name = name;
|
|
|
+ this.size = size;
|
|
|
+ this.color = color;
|
|
|
+ this.bold = bold;
|
|
|
+ this.width = width;
|
|
|
+ this.height = height;
|
|
|
+ this.htmlText = htmlText;
|
|
|
+ this.text = text;
|
|
|
+ this.x = 0;
|
|
|
+ this.y = 0;
|
|
|
+ this.middle = 0;
|
|
|
+ this.bottom = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ class Line {
|
|
|
+ constructor(align) {
|
|
|
+ this.align = align;
|
|
|
+ this.width = 0;
|
|
|
+ this.height = 0;
|
|
|
+ this.texts = new Array();
|
|
|
+ this.gothic = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ class Form {
|
|
|
+ constructor(color, width, height) {
|
|
|
+ this.color = color;
|
|
|
+ this.width = width;
|
|
|
+ this.height = height;
|
|
|
+ this.textHeight = 0;
|
|
|
+ this.lines = new Array();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Map 으로 저장해서 처리하는 것으로 수정하는 것이 좋음.
|
|
|
+ function getTextAlignFromData(align) {
|
|
|
+ //(0:left, 1:right, 2:center
|
|
|
+ if (align === "center") {
|
|
|
+ return 2;
|
|
|
+ }
|
|
|
+ if (align === "right") {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ function getTextAlignFromCode(align) {
|
|
|
+ //(0:left, 1:right, 2:center
|
|
|
+ if (align === 2) {
|
|
|
+ return "center";
|
|
|
+ }
|
|
|
+ if (align === 1) {
|
|
|
+ return "right";
|
|
|
+ }
|
|
|
+ return "left";
|
|
|
+ }
|
|
|
+
|
|
|
+ var $log = $("#log");
|
|
|
+ var str = "";
|
|
|
+ // str += '<p style="text-align: center;">';
|
|
|
+ // str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 맑은 고딕;">맑은 고딕</strong>';
|
|
|
+ // str += ' <strong style="color: rgb(0, 255, 0); font-size: 18pt; font-family: 맑은 고딕;">굴림체</strong>';
|
|
|
+ // str += ' <strong style="color: rgb(0, 0, 255); font-size: 18pt; font-family: 맑은 고딕;">HY견명조</strong></p>';
|
|
|
+ // str += '<p style="text-align: center;">';
|
|
|
+ // str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 궁서체;">궁서체</strong>';
|
|
|
+ // str += ' <strong style="color: rgb(0, 255, 0); font-size: 18pt; font-family: 궁서체;">돋움체</strong>';
|
|
|
+ // str += ' <strong style="color: rgb(0, 0, 255); font-size: 18pt; font-family: 궁서체;">바탕체</strong></p>';
|
|
|
+ str += '<p style="text-align: center;">';
|
|
|
+ str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 맑은 고딕;">맑은 afdsa 고딕</strong>';
|
|
|
+ str += ' <strong style="color: rgb(0, 255, 0); font-size: 16pt; font-family: 굴림체;">굴림체</strong>';
|
|
|
+ str += ' <strong style="color: rgb(255, 255, 0); font-size: 18pt; font-family: HY견명조;">HY견명조</strong></p>';
|
|
|
+ str += '<p style="text-align: center;">';
|
|
|
+ str += ' <strong style="color: rgb(255, 0, 0); font-size: 18pt; font-family: 궁서체;">궁서체</strong>';
|
|
|
+ str += ' <strong style="color: rgb(0, 255, 0); font-size: 18pt; font-family: 돋움체;">돋움체</strong>';
|
|
|
+ str += ' <strong style="color: rgb(255, 255, 0); font-size: 18pt; font-family: 바탕체;">바탕체</strong></p>';
|
|
|
+
|
|
|
+ //str =
|
|
|
+ // '<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>';
|
|
|
+ var html = $.parseHTML(str);
|
|
|
+ var nodeNames = [];
|
|
|
+
|
|
|
+ let line = 0;
|
|
|
+
|
|
|
+ console.log("=====================================================");
|
|
|
+
|
|
|
+ // HTML TAG Parsing....................
|
|
|
+ const el = document.createElement("html");
|
|
|
+ el.innerHTML = str;
|
|
|
+ const pTags = el.getElementsByTagName("p");
|
|
|
+ console.log(el);
|
|
|
+ console.log(pTags);
|
|
|
+
|
|
|
+ const objForm = new Form("rgb(0,0,0)", 384, 64);
|
|
|
+
|
|
|
+ for (let ii = 0; ii < pTags.length; ii++) {
|
|
|
+ const p = pTags[ii];
|
|
|
+ const textAlign = getTextAlignFromData(p.style.textAlign);
|
|
|
+ const children = p.children;
|
|
|
+ console.log("----------------------------------------------------------------");
|
|
|
+ if (children.length == 0) {
|
|
|
+ console.warn("object not found....");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ const objLine = new Line(textAlign);
|
|
|
+ for (let jj = 0; jj < children.length; jj++) {
|
|
|
+ const obj = children[jj];
|
|
|
+ const fontName = obj.style.fontFamily;
|
|
|
+ const fontSize = Number(obj.style.fontSize.replace("pt", "").replace("px", ""));
|
|
|
+ const fontBold = obj.nodeName === "STRONG" ? true : obj.style.fontWeight === "bold";
|
|
|
+ let fontColor = obj.style.color.replaceAll(" ", "");
|
|
|
+ if (fontColor === "") {
|
|
|
+ fontColor = "rgb(0,0,0)";
|
|
|
+ }
|
|
|
+ const htmlText = obj.innerText;
|
|
|
+ const text = htmlText.trim();
|
|
|
+ const result = getTextInfo(fontName, fontSize, fontBold, htmlText);
|
|
|
+ const textWidth = result.width;
|
|
|
+ const textHeight = result.height;
|
|
|
+ objLine.width += textWidth;
|
|
|
+ if (textHeight > objLine.height) {
|
|
|
+ objLine.height = textHeight;
|
|
|
+ }
|
|
|
+ if (fontName.indexOf("맑은 고딕") !== -1) {
|
|
|
+ objLine.gothic = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ const objText = new Text(fontName, fontSize, fontColor, fontBold, textWidth, textHeight, htmlText, text);
|
|
|
+ objLine.texts.push(objText);
|
|
|
+
|
|
|
+ console.log(
|
|
|
+ `line ${line}, objects ${jj}, font-Name: ${fontName}, bold: ${fontBold}, size: ${fontSize}, color: ${fontColor}, text: ${text}, [${htmlText}], text-height: ${textHeight}, text-width: ${textWidth}`
|
|
|
+ );
|
|
|
+ }
|
|
|
+ console.log(
|
|
|
+ `line ${line}, objects: [${children.length}], text-align: [${textAlign}]${getTextAlignFromCode(textAlign)}, line-width: ${objLine.width}, line-height: ${
|
|
|
+ objLine.height
|
|
|
+ }`
|
|
|
+ );
|
|
|
+ objForm.textHeight += objLine.height;
|
|
|
+ objForm.lines.push(objLine);
|
|
|
+ line++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 텍스트 위치 계산
|
|
|
+ let textTop = objForm.height - objForm.textHeight;
|
|
|
+ if (textTop <= 0) {
|
|
|
+ textTop = 0;
|
|
|
+ } else {
|
|
|
+ textTop /= 2;
|
|
|
+ }
|
|
|
+ objForm.lines.forEach((line, idx) => {
|
|
|
+ let left = 0; // left
|
|
|
+ if (line.align == 1) {
|
|
|
+ // right
|
|
|
+ left = objForm.width - line.width;
|
|
|
+ if (left <= 0) {
|
|
|
+ left = 0;
|
|
|
+ }
|
|
|
+ } else if (line.align == 2) {
|
|
|
+ // center
|
|
|
+ left = objForm.width - line.width;
|
|
|
+ if (left <= 0) {
|
|
|
+ left = 0;
|
|
|
+ } else {
|
|
|
+ left /= 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ line.texts.forEach((text, seq) => {
|
|
|
+ text.x = left;
|
|
|
+ let txtY = textTop;
|
|
|
+ //text.y = textTop + (line.height - text.height);
|
|
|
+ text.y = textTop; // + (line.height - text.height);
|
|
|
+ console.log(line.gothic, text.name);
|
|
|
+ if (line.gothic && text.name.indexOf("맑은 고딕") === -1) {
|
|
|
+ text.y = textTop + 4;
|
|
|
+ }
|
|
|
+ //text.y = textTop + line.height / 2;
|
|
|
+ text.bottom = textTop + line.height;
|
|
|
+ if (text.x >= objForm.width) {
|
|
|
+ text.x = objForm.width - text.width;
|
|
|
+ }
|
|
|
+ if (text.x < 0) {
|
|
|
+ text.x = 0;
|
|
|
+ }
|
|
|
+ if (text.y >= objForm.height - text.height) {
|
|
|
+ text.y = objForm.height - text.height;
|
|
|
+ console.log("ccccccccccccccccccccccccccccccccccccccc");
|
|
|
+ }
|
|
|
+ text.middle = textTop + line.height / 2;
|
|
|
+ left += text.width;
|
|
|
+ });
|
|
|
+ textTop += line.height;
|
|
|
+ });
|
|
|
+ console.log(objForm);
|
|
|
+ // 미리보기 폼을 캔버스에 그린다.
|
|
|
+ drawPreviewForm(objForm);
|
|
|
+
|
|
|
+ $log.append(html);
|
|
|
+ $log.append("<h3>Preview:</h3>");
|
|
|
+
|
|
|
+ function getTextInfo2(fontName, fontSize, fontBold, htmlText) {
|
|
|
+ var text = document.createElement("span");
|
|
|
+ document.body.appendChild(text);
|
|
|
+
|
|
|
+ //text.style.backgroundColor = "#FF0000";
|
|
|
+ text.style.lineHeight = "normal";
|
|
|
+ text.style.border = "none";
|
|
|
+ text.style.margin = "0px";
|
|
|
+ text.style.padding = "0px";
|
|
|
+ text.style.font = fontName;
|
|
|
+ if (fontBold) {
|
|
|
+ text.style.fontWeight = "bold";
|
|
|
+ }
|
|
|
+ text.style.fontFamily = fontName;
|
|
|
+ text.style.fontSize = fontSize + "pt";
|
|
|
+ text.style.height = "auto";
|
|
|
+ text.style.width = "auto";
|
|
|
+ text.style.position = "absolute";
|
|
|
+ text.style.whiteSpace = "pre"; //"nowrap";
|
|
|
+ text.innerHTML = htmlText;
|
|
|
+ //console.log("getTextInfo: ", text.getBoundingClientRect());
|
|
|
+ const width = Math.ceil(text.clientWidth);
|
|
|
+ const height = Math.ceil(text.clientHeight);
|
|
|
+ document.body.removeChild(text);
|
|
|
+ console.log("getTextInfo: ", width, height);
|
|
|
+ return {
|
|
|
+ width: width,
|
|
|
+ height: height,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ function getTextInfo(fontName, fontSize, fontBold, htmlText) {
|
|
|
+ const canvas = document.getElementById("previewCanvas");
|
|
|
+ const ctx = canvas.getContext("2d");
|
|
|
+ ctx.fillStyle = "rgb(0,0,0)";
|
|
|
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
+ const bold = fontBold ? "bold" : "";
|
|
|
+ ctx.font = `${bold} ${fontSize}pt ${fontName}`;
|
|
|
+ ctx.textBaseline = "middle";
|
|
|
+ ctx.fillStyle = "rgb(255,0,0)";
|
|
|
+ ctx.fillText(htmlText, 0, 100);
|
|
|
+ const metrics = ctx.measureText(htmlText);
|
|
|
+ const textWidth = metrics.width;
|
|
|
+ const fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
|
|
|
+ const actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
|
+ console.log(metrics);
|
|
|
+ // console.log(fontHeight, actualHeight);
|
|
|
+ const width = Math.ceil(textWidth);
|
|
|
+ const height = Math.ceil(fontHeight);
|
|
|
+ return {
|
|
|
+ width: width,
|
|
|
+ height: height,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ function drawPreviewForm(form) {
|
|
|
+ const canvas = document.getElementById("previewCanvas");
|
|
|
+ const ctx = canvas.getContext("2d");
|
|
|
+ ctx.fillStyle = form.color;
|
|
|
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
|
+
|
|
|
+ form.lines.forEach((line, idx) => {
|
|
|
+ line.texts.forEach((text, seq) => {
|
|
|
+ const bold = text.bold ? "bold" : "";
|
|
|
+ ctx.font = `${bold} ${text.size}pt ${text.name}`;
|
|
|
+ ctx.fillStyle = text.color;
|
|
|
+ ctx.textBaseline = "middle"; //"middle"; //"top";//"hanging";
|
|
|
+ //ctx.fillText(text.text, text.x, text.y);
|
|
|
+ ctx.fillText(text.text, text.x, text.middle);
|
|
|
+ // const metrics = ctx.measureText(text.text);
|
|
|
+ // console.error(metrics);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ </script>
|
|
|
+ </body>
|
|
|
+</html>
|