diff --git a/src/main/java/cokr/xit/base/file/pdf/PDFWriter.java b/src/main/java/cokr/xit/base/file/pdf/PDFWriter.java index 0dddeff8..b90212f2 100644 --- a/src/main/java/cokr/xit/base/file/pdf/PDFWriter.java +++ b/src/main/java/cokr/xit/base/file/pdf/PDFWriter.java @@ -1,835 +1,8 @@ package cokr.xit.base.file.pdf; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.pdmodel.PDPage; -import org.apache.pdfbox.pdmodel.PDPageContentStream; -import org.apache.pdfbox.pdmodel.common.PDRectangle; -import org.apache.pdfbox.pdmodel.font.PDType0Font; -import org.apache.pdfbox.pdmodel.graphics.color.PDColor; -import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; -import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode; -import org.egovframe.rte.fdl.string.EgovStringUtil; -import org.springframework.core.io.ClassPathResource; - -import cokr.xit.fims.cmmn.CmmnUtil; -import cokr.xit.fims.cmmn.Print; -import cokr.xit.fims.cmmn.PrintOption; -import cokr.xit.fims.cmmn.Pstn; -import cokr.xit.fims.cmmn.PstnAndSize; -import cokr.xit.fims.cmmn.Size; -import cokr.xit.fims.cmmn.pdf.print.DefaultOtptArtclStng; -import cokr.xit.fims.cmmn.pdf.print.PDFColors; -import cokr.xit.fims.cmmn.pdf.print.PDFCoordinate; -import cokr.xit.fims.cmmn.pdf.print.format.PDFPrintFormat; -import cokr.xit.fims.sprt.MediaUtil; -import cokr.xit.foundation.data.DataObject; - public class PDFWriter { - protected String paper; - protected Print print; - protected PDFPrintFormat format; - - protected DataObject otptBscStng; - protected List otptArtclStngList; - - protected float[] paperMilimeter = new float[2]; - - public void setPaper(String paperType) { - this.paper = paperType; - if(paperType.equals("01")) { - this.paperMilimeter = new float[] {210.0f , 297.0f}; - } else if(paperType.equals("02")){ - this.paperMilimeter = new float[] {216.0f , 279.0f}; - } - } - - public void setPrint(Print print) { - this.print = print; - }; - - public void setFormat(PDFPrintFormat format) { - this.format = format; - } - public PDFPrintFormat getFormat() { - return this.format; - } - - public void setOtptBscStng(DataObject otptBscStng) { - this.otptBscStng = otptBscStng; - } - - public void setOtptArtclStngList(List otptArtclStngList) { - this.otptArtclStngList = otptArtclStngList; - } - - public List getOtptArtclStngList() { - return this.otptArtclStngList; - } - - /** - * 서식에서 사용하는 출력항목 중 사용하는 항목만 추출한다. - */ - public List filterUsedArtcls() { - List otptArtclNmList = this.otptArtclStngList.stream().map((item) -> { return item.string("OTPT_ARTCL_NM"); }).toList(); - - List result = this.getFormat().getPrototypeStngs().stream() - .filter((item) -> { - return otptArtclNmList.contains(item.getArtclNm()); - }).toList(); - - return result; - } - - /** - * 다운로드 이력에 남길 항목명을 추출한다. - */ - public List filterDownloadDataNames() { - - List result = this.filterUsedArtcls().stream() - .filter((item) -> { - return item.isDownloadData(); - }) - .map(DefaultOtptArtclStng::getArtclDscrp).toList(); - - return result; - } - - public Map makePdfFile(String formatType, String formatName, PrintOption printOption, List dataObjectList) { - Map result = new HashMap<>(); - - - - String resultFilePath = this.filePathForNewFile(); - PDDocument doc = new PDDocument();//pdf문서 생성 - - //폰트 로드 - Map fontMap = this.getFontMap(doc); - - //용지 크기 설정 - PDRectangle paper = null; - if(this.paper.equals("01")) { - paper = PDRectangle.A4; - } else { - paper = PDRectangle.LETTER; - } - - - List prototypeStngList = this.format.getPrototypeStngs(); - - try { - - - //출력요소별 속성 정보 추가 - this.format.appendOtptAttribute(this.otptArtclStngList); - - //출력 요소 정렬 - Comparator comparator1 = (item1, item2) -> { - int int1 = item1.string("UNIQUE_YN").equals("Y") ? 0 : 1; - int int2 = item2.string("UNIQUE_YN").equals("Y") ? 0 : 1; - return Integer.compare(int1, int2); - }; - Comparator comparator2 = (item1, item2) -> { - int int1 = item1.number("OTPT_ARTCL_ORDR").intValue(); - int int2 = item2.number("OTPT_ARTCL_ORDR").intValue(); - return Integer.compare(int1, int2); - }; - otptArtclStngList = otptArtclStngList.stream() - .sorted(comparator1.thenComparing(comparator2)).collect(Collectors.toList()); - - - //대표단속사진 설정 여부 확인 - boolean rprsCrdnPhotoYn = false; - if(otptArtclStngList.stream().filter(item -> item.string("OTPT_ARTCL_NM").equals("rprsCrdnPhoto")).count() > 0) { - rprsCrdnPhotoYn = true; - } - - for(DataObject dataObject : dataObjectList) { - //페이지생성(건별) - PDPage blankPage = new PDPage(paper); - doc.addPage(blankPage); - - // 작업 페이지 설정 - PDPage page = doc.getPage(doc.getNumberOfPages()-1); - // 컨텐츠 스트림 열기 - PDPageContentStream contentStream = new PDPageContentStream(doc, page); - - boolean completeFoldLine = false; - - for(DataObject otptArtclStng : otptArtclStngList) { - String otptArtclNm = otptArtclStng.string("OTPT_ARTCL_NM"); - - if(!otptArtclNm.equals("background") && !completeFoldLine) { - //접는곳 점선 그리기 - if(!otptBscStng.string("FOLD_LINE_PSTN_SE_CD").equals("")) { - this.renderFoldLine(contentStream, paper, otptBscStng.string("FOLD_LINE_PSTN_SE_CD")); - } - completeFoldLine = true; - } - - DefaultOtptArtclStng prototypeStng = prototypeStngList.stream() - .filter(item -> item.getArtclNm().equals(otptArtclNm)).toList().get(0); - - float[] pstn = this.getPstnStng(prototypeStng, otptArtclStng, this.paper); - float[] size = this.getSize(prototypeStng, otptArtclStng); - - boolean forPost = prototypeStng.isForPost(); - String defaultValue = prototypeStng.getOtptBscVl(); - - if(prototypeStng.getComponentType().equals("text")) { - String align = this.getAlign(prototypeStng, otptArtclStng); - String lineChgYn = this.getLineChgYn(prototypeStng, otptArtclStng); - PDType0Font font = this.getFontType(prototypeStng, otptArtclStng, fontMap); - int fontSz = this.getFontSize(prototypeStng, otptArtclStng); - RenderingMode fontStyle = this.getFontStyle(prototypeStng, otptArtclStng); - PDColor fontColor = this.getFontColor(prototypeStng, otptArtclStng); - - String textValue = this.format.getMappingValue(otptArtclNm,defaultValue,forPost,dataObject,printOption,print); - - this.writeText(contentStream, textValue, pstn, size[0], align, lineChgYn - , font, fontSz, fontStyle, fontColor); - - } else if(prototypeStng.getComponentType().equals("image")) { - - String imagePath = this.format.getMappingValue(otptArtclNm,defaultValue,forPost,dataObject,printOption,print); - - if(EgovStringUtil.null2void(imagePath).equals("")) { - continue; - } - - if(!imagePath.startsWith("files")) { - imagePath = CmmnUtil.copyStaticResource(imagePath, false); - } - - File imageFile = new File(imagePath); - InputStream is = new FileInputStream(imageFile); - - String imageKey = ""; - List mosSet = null; - if(otptArtclNm.equals("rprsCrdnPhoto")) { - imageKey = this.format.getMappingValue(otptArtclNm+"Key",defaultValue,forPost,dataObject,printOption,print); - mosSet = this.format.getMosSet(imageKey, dataObject); - } - this.insertImage(doc, contentStream, is, pstn, size); - - if(otptArtclNm.equals("rprsCrdnPhoto") && !imageKey.equals("") && mosSet != null) { - - File imageFile0 = new File(imagePath); - InputStream is0 = new FileInputStream(imageFile0); - - List transformedMosaicInfos = MediaUtil.getTransformedMosaic( - mosSet, is0, new PstnAndSize(pstn[0],pstn[1], size[0], size[1]) - ); - - for(int k=0; k < transformedMosaicInfos.size(); k++) { - PstnAndSize mosaicInfo = transformedMosaicInfos.get(k); - - InputStream blackImageStream = new ClassPathResource("samplefiles/black.png").getInputStream(); - this.insertImage(doc, contentStream, blackImageStream, - mosaicInfo.getPstn().to2Float(), mosaicInfo.getSize().to2Float()); - } - - } - - - } else if(prototypeStng.getComponentType().equals("images")) { - - List imagePaths = this.format.getMappingValues(otptArtclNm,defaultValue,forPost,dataObject,printOption,print); - - List imageKeys = new ArrayList(); - List> mosSets = new ArrayList>(); - if(otptArtclNm.equals("crdnPhoto")) { - imageKeys = this.format.getMappingValues(otptArtclNm+"Key",defaultValue,forPost,dataObject,printOption,print); - if(rprsCrdnPhotoYn && imagePaths.size() > 0) { - imageKeys.remove(0); - } - for(String imageKey : imageKeys) { - mosSets.add(this.format.getMosSet(imageKey, dataObject)); - } - - } - - if(otptArtclNm.equals("crdnPhoto")) { - if(rprsCrdnPhotoYn && imagePaths.size() > 0) { - imagePaths.remove(0); - } - } - - int printCntSetting = otptBscStng.number("OTPT_PHOTO_CNT").intValue(); - int dataImageCnt = imagePaths.size(); - - if(printCntSetting != 0 && dataImageCnt != 0) { - - List devideInfos = this.devideImageArea(pstn, size, printCntSetting, dataImageCnt); - - for (int i=0; i< devideInfos.size(); i++){ - PstnAndSize devideInfo = devideInfos.get(i); - - if(EgovStringUtil.null2void(imagePaths.get(i)).equals("")) { - continue; - } - - if(!imagePaths.get(i).startsWith("files")) { - imagePaths.set(i, CmmnUtil.copyStaticResource(imagePaths.get(i), false)); - } - - String imagePath = imagePaths.get(i); - - File imageFile = new File(imagePath); - InputStream is = new FileInputStream(imageFile); - - this.insertImage(doc, contentStream, is, - devideInfo.getPstn().to2Float(), devideInfo.getSize().to2Float()); - - - if(otptArtclNm.equals("crdnPhoto") && !imageKeys.isEmpty() && !mosSets.isEmpty()) { - - if(mosSets.get(i) != null) { - String imagePath0 = imagePaths.get(i); - - File imageFile0 = new File(imagePath0); - InputStream is0 = new FileInputStream(imageFile0); - - List transformedMosaicInfos = MediaUtil.getTransformedMosaic( - mosSets.get(i), is0, devideInfo - ); - - for(int k=0; k < transformedMosaicInfos.size(); k++) { - PstnAndSize mosaicInfo = transformedMosaicInfos.get(k); - InputStream blackImageStream = new ClassPathResource("samplefiles/black.png").getInputStream(); - this.insertImage(doc, contentStream, blackImageStream, - mosaicInfo.getPstn().to2Float(), mosaicInfo.getSize().to2Float()); - } - } - - - - } - - } - - } - - } - - }//출력항목 loop 끝 - - if(!completeFoldLine) { - if(!otptBscStng.string("FOLD_LINE_PSTN_SE_CD").equals("")) { - this.renderFoldLine(contentStream, paper, otptBscStng.string("FOLD_LINE_PSTN_SE_CD")); - } - } - - contentStream.close(); - - } //출력자료건수 loop 끝 - - - doc.save(resultFilePath); - doc.close(); - - String downloadFileName = print.getFormatKorName()+"_"+print.getPrintRequestDt()+".pdf"; - result.put("filename", downloadFileName); - result.put("filePath", resultFilePath); - result.put("file", new File(resultFilePath)); - - } catch (Exception e) { - throw new RuntimeException("출력오류."+e); - } - - return result; - } - - - - - - - - - public String filePathForNewFile() { - - SimpleDateFormat ymdhmsFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - String currentTime = ymdhmsFormat.format(new Date()); - String year = currentTime.substring(0, 4); - String month = currentTime.substring(4, 6); - String day = currentTime.substring(6, 8); - - String fileResultRootPath = "files" + File.separator + "result" + File.separator + "print"; - - String fileResultFolderPath = fileResultRootPath - + File.separator + year + File.separator + month + File.separator + day; - File formatFileResultFolder = new File(fileResultFolderPath); - if(!formatFileResultFolder.exists()) { - formatFileResultFolder.mkdirs(); - } - String resultPdfPath = fileResultFolderPath - + File.separator + currentTime + "_" + (print.getFileNameIndex()) + ".pdf"; - - print.setFileNameIndex(print.getFileNameIndex()+1); - - return resultPdfPath; - - } - - /** - * mm단위로 입력된 값을 pdf좌표계 형식으로 변환한다. - */ - public PDFCoordinate toPDFCoordinate(float[] XYmm) { - float Xmm = XYmm[0]; - float Ymm = XYmm[1]; - - float Xpt = CmmnUtil.mmToPt(Xmm); - float Ypt = CmmnUtil.mmToPt(Ymm); - - float YptMax = CmmnUtil.mmToPt(this.paperMilimeter[1]); - - return new PDFCoordinate(Xpt, Ypt, YptMax); - } - - /** - * 텍스트를 pdf에 입력한다. - */ - public void writeText(PDPageContentStream contentStream, String allText, - float[] XYmm, float textAreaWidth_mm, String align, String newLineYn, - PDType0Font font, int fontSize, RenderingMode fontStyle, PDColor fontColor) { - try { - if(allText == null) { - allText = ""; - } - if(newLineYn == null || newLineYn.equals("")) { - newLineYn = "N"; - } - - float[] xyAbsolute = this.toPDFCoordinate(XYmm).absolute(); - - float textAreaWidth_pt = CmmnUtil.mmToPt(textAreaWidth_mm); - - float allTextWidth = calcTextWidth(font, fontSize, allText); - - String textArr[]; - if(allText.equals("") || allText.length() == 1 || textAreaWidth_pt == 0 - || (allTextWidth <= textAreaWidth_pt) - || newLineYn.equals("N")) { - - textArr = new String[] { allText }; - - } else { - - textArr = splitByLineForLargeText(font, fontSize, allText, textAreaWidth_pt); - - } - - String firstLine = textArr[0]; - float firstLineWidth = calcTextWidth(font, fontSize, firstLine); - - contentStream.beginText(); - contentStream.setFont(font, fontSize); - contentStream.setRenderingMode(fontStyle); - contentStream.setNonStrokingColor(fontColor); - - float resultY = xyAbsolute[1] - fontSize; - - float firstLineAlignCorrection = 0; - if(align.equals("right")) { - firstLineAlignCorrection = textAreaWidth_pt - firstLineWidth; - } else if(align.equals("center")) { - firstLineAlignCorrection = (textAreaWidth_pt - firstLineWidth)/2.0f; - } - - float resultX = xyAbsolute[0] + firstLineAlignCorrection; - - contentStream.newLineAtOffset(resultX, resultY); - contentStream.showText(textArr[0]); - - if(textArr.length > 1) { - float beforeLineWidth = firstLineWidth; - - for(int i = 1; i < textArr.length; i++) { - String thisLine = textArr[i]; - float thisLineWidth = this.calcTextWidth(font, fontSize, thisLine); - float alignCorrection = 0; - - if(align.equals("right")) { - alignCorrection = beforeLineWidth - thisLineWidth; - } if(align.equals("center")) { - alignCorrection = (beforeLineWidth - thisLineWidth)/2.0f; - } - - contentStream.newLineAtOffset(alignCorrection, -(fontSize + 1)); - contentStream.showText(thisLine); - - beforeLineWidth = thisLineWidth; - } - - - } - - contentStream.endText(); - - } catch (IOException e) { - throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."+e); - } - - } - - /** - * 글꼴모양,폰트크기 등에 따른 텍스트의 가로 길이(pt)를 계산한다. - */ - public float calcTextWidth(PDType0Font font, int fontSize, String text) { - try { - return (font.getStringWidth(text) / 1000.0f) * fontSize; - } catch (IOException e) { - throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."); - } - } - - /** - * 출력할 텍스트가 지정한 영역 안에 들어가지 않을 경우 줄바꿈 처리를 위해 텍스트를 나누어 배열로 반환한다. - */ - public String[] splitByLineForLargeText(PDType0Font font, int fontSize, String allText, float textAreaWidth_pt) { - - float allTextWidth = calcTextWidth(font, fontSize, allText); - - if(allText.equals("") || allText.length() == 1 || textAreaWidth_pt == 0 - || (allTextWidth <= textAreaWidth_pt) - ) { - return new String[] { allText }; - } - - ArrayList textList = new ArrayList(); - - while(!allText.equals("")) { - int lengthForLine = this.getLengthForLine(font, fontSize, allText, textAreaWidth_pt); - String newLine = allText.substring(0,lengthForLine); - textList.add(newLine); - allText = allText.substring(lengthForLine); - } - - return textList.toArray(new String[textList.size()]); - } - - /** - * 텍스트를 줄바꿈 처리할 경우 첫 라인에 출력될 글자 수를 반환한다. - */ - private int getLengthForLine(PDType0Font font, int fontSize, String allText, float textAreaWidth_pt) { - int forLine = allText.length(); - if(forLine <= 1) { - return forLine; - }; - - for( ; ; forLine--) { - if(forLine == 1) { - break; - } - - boolean hit = ( this.calcTextWidth(font, fontSize, allText.substring(0, forLine)) <= textAreaWidth_pt ); - if(hit) { - break; - } - } - - return forLine; - } - - /** - * pdf에 이미지를 삽입한다. - */ - public void insertImage(PDDocument doc, PDPageContentStream contentStream, InputStream imageStream, float[] XYmm, - float[] SIZEmm) { - - float[] xyAbsolute = this.toPDFCoordinate(XYmm).absolute(); - - float[] size = new float[] { - CmmnUtil.mmToPt(SIZEmm[0]),CmmnUtil.mmToPt(SIZEmm[1]) - }; - try { - - PDImageXObject image = PDImageXObject.createFromByteArray(doc, imageStream.readAllBytes(), "temp"); - contentStream.drawImage(image, xyAbsolute[0], xyAbsolute[1]-size[1], size[0], size[1]); - - } catch (IOException e) { - throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."+e); - } - } - - public List devideImageArea(float[] totAreaPstn, float[] totAreaSize, int imageCntSetting, int dataImageCnt) { - List result = new ArrayList(); - - int printable = imageCntSetting <= dataImageCnt ? imageCntSetting : dataImageCnt; - - if(printable <= 1) { - result.add(new PstnAndSize(totAreaPstn[0], totAreaPstn[1], totAreaSize[0], totAreaSize[1])); - return result; - } - - boolean longerThenWidth = totAreaSize[1] > totAreaSize[0]; - - int xLengthOfD2 = 0; - int yLengthOfD2 = 0; - - if(printable == 2){ - if(longerThenWidth) { - xLengthOfD2 = 1; - yLengthOfD2 = 2; - } else { - xLengthOfD2 = 2; - yLengthOfD2 = 1; - } - } else if(printable == 3 || printable == 4){ - xLengthOfD2 = 2; - yLengthOfD2 = 2; - } else if(printable == 5 || printable == 6){ - if(longerThenWidth) { - xLengthOfD2 = 2; - yLengthOfD2 = 3; - } else { - xLengthOfD2 = 3; - yLengthOfD2 = 2; - } - } else { - throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."); - } - - PstnAndSize[][] d2Array = new PstnAndSize[xLengthOfD2][yLengthOfD2]; - Size cellSize = new Size(totAreaSize[0] / (xLengthOfD2 * 1.0f), totAreaSize[1] / (yLengthOfD2 * 1.0f)); - - d2Array[0][0] = new PstnAndSize(totAreaPstn[0], totAreaPstn[1], cellSize.getWidth(), cellSize.getHeight()); - d2Array = this.fillImageCells(d2Array); - - //출력영역 크기 병합 - if(printable == 3 || printable == 5) { - - boolean longerThenWidth_cell = cellSize.getHeight() > cellSize.getWidth(); - if(longerThenWidth_cell) { - d2Array = this.mergeLastImageCell(d2Array, "left"); - } else { - d2Array = this.mergeLastImageCell(d2Array, "up"); - } - - } - for(int y=0; y < yLengthOfD2; y++) { - for(int x=0; x < xLengthOfD2; x++) { - if(d2Array[x][y] != null) { - result.add(d2Array[x][y]); - } - } - } - - return result; - } - - private PstnAndSize[][] fillImageCells(PstnAndSize[][] d2) { - int xLengthOfD2 = d2.length; - int yLengthOfD2 = d2[0].length; - - PstnAndSize firstCell = d2[0][0]; - - Size cellSize = firstCell.getSize(); - float cellWidth = cellSize.getWidth(); - float cellHeight = cellSize.getHeight(); - - Pstn startPoint = firstCell.getPstn(); - float spX = startPoint.getLeft(); - float spY = startPoint.getTop(); - - for(int x=0; x < xLengthOfD2; x++) { - for(int y=0; y < yLengthOfD2; y++) { - if(x != 0 || y != 0) { - d2[x][y] = new PstnAndSize(spX + (cellWidth * (x * 1.0f)), spY + (cellHeight * (y * 1.0f)), cellSize); - } - } - } - - return d2; - } - - public PstnAndSize[][] mergeLastImageCell(PstnAndSize[][] d2, String mergeDirection) { - if(!mergeDirection.equals("up") && !mergeDirection.equals("left")) { - throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."); - } - - int xLengthOfD2 = d2.length; - int yLengthOfD2 = d2[0].length; - - int lastCellIndexX = xLengthOfD2-1; - int lastCellIndexY = yLengthOfD2-1; - - int mergeTargetCellIndexX = 0; - int mergeTargetCellIndexY = 0; - - if(mergeDirection.equals("up")) { - mergeTargetCellIndexX = lastCellIndexX; - mergeTargetCellIndexY = lastCellIndexY-1; - } - if(mergeDirection.equals("left")) { - mergeTargetCellIndexX = lastCellIndexX-1; - mergeTargetCellIndexY = lastCellIndexY; - } - - //병합대상셀 - if(mergeDirection.equals("up")) { - d2[mergeTargetCellIndexX][mergeTargetCellIndexY] = (d2[mergeTargetCellIndexX][mergeTargetCellIndexY]).x2Height(); - } - if(mergeDirection.equals("left")) { - d2[mergeTargetCellIndexX][mergeTargetCellIndexY] = (d2[mergeTargetCellIndexX][mergeTargetCellIndexY]).x2Width(); - } - - //마지막셀 - d2[lastCellIndexX][lastCellIndexY] = null; - - return d2; - } - - /** - * pdf에 봉합선을 넣는다. - */ - public void renderFoldLine(PDPageContentStream contentStream, PDRectangle paper, String foldCode) { - if(foldCode.equals("") && !foldCode.equals("01") && !foldCode.equals("02")) { - return; - } - - float paperWidth = paper.getWidth(); - - float partHeight; - if(foldCode.equals("01")) { - if(PDRectangle.A4.equals(paper)) { - partHeight = 99; - } else { - partHeight = 93; - } - } else { - partHeight = 93; - } - - float margin = 0; - if(foldCode.equals("02")) { - margin = 18; - } - - float bottomFold = margin + partHeight; //하단접는곳 - float topFold = margin + (partHeight * 2); //상단접는곳 - - float bottomFold_pt = CmmnUtil.mmToPt(bottomFold); - float topFold_pt = CmmnUtil.mmToPt(topFold); - - try { - contentStream.setLineDashPattern(new float[]{3,1}, 0); - contentStream.moveTo(0, topFold_pt); - contentStream.lineTo(paperWidth, topFold_pt); - contentStream.stroke(); - contentStream.moveTo(0, bottomFold_pt); - contentStream.lineTo(paperWidth, bottomFold_pt); - contentStream.stroke(); - contentStream.setLineDashPattern(new float[]{}, 0); - } catch (IOException e) { - throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."+e); - } - } - - public float[] getPstnStng(DefaultOtptArtclStng prototypeStng, DataObject sggStng, String paperSeCd) { - if(!sggStng.string("LEFT_PSTN").equals("") && !sggStng.string("TOP_PSTN").equals("")) { - return new float[] { - sggStng.number("LEFT_PSTN").floatValue(), - sggStng.number("TOP_PSTN").floatValue() - }; - } else { - return new float[] { - prototypeStng.getLeftPstn(paperSeCd), - prototypeStng.getTopPstn(paperSeCd) - }; - } - } - - public PDType0Font getFontType(DefaultOtptArtclStng prototypeStng, DataObject sggStng, Map fontMap) { - if(sggStng != null && !sggStng.isEmpty() && !sggStng.string("FONT_NM").equals("")) { - return fontMap.get(sggStng.string("FONT_NM")); - } else { - return fontMap.get(prototypeStng.getFontNm()); - } - } - - public int getFontSize(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { - if(!sggStng.string("FONT_SZ").equals("")) { - return sggStng.number("FONT_SZ").intValue(); - } else { - return prototypeStng.getFontSz(); - } - } - - public RenderingMode getFontStyle(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { - if(!sggStng.string("FONT_STYLE").equals("")) { - return RenderingMode.valueOf(sggStng.string("FONT_STYLE")); - } else { - return RenderingMode.valueOf(prototypeStng.getFontStyle()); - } - } - - public PDColor getFontColor(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { - if(!sggStng.string("FONT_COLOR").equals("")) { - return PDFColors.getColor(sggStng.string("FONT_COLOR")); - } else { - return PDFColors.getColor(prototypeStng.getFontColor()); - } - } - public float[] getSize(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { - if(!sggStng.string("WIDTH_SZ").equals("")) { - return new float[] { - sggStng.number("WIDTH_SZ").floatValue(), - sggStng.number("HEIGHT_SZ").floatValue() - }; - } else { - return new float[] { - prototypeStng.getWidthSz(), - prototypeStng.getHeightSz() - }; - } - } - public String getAlign(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { - if(!sggStng.string("TEXT_SORT").equals("")) { - return sggStng.string("TEXT_SORT"); - } else { - return prototypeStng.getTextSort(); - } - } - public String getLineChgYn(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { - if(!sggStng.string("LINE_CHG_YN").equals("")) { - return sggStng.string("LINE_CHG_YN"); - } else { - return prototypeStng.getLineChgYn(); - } - } - public Map getFontMap(PDDocument doc) { - try { - Map fontMap = Map.of( - "gulim", PDType0Font.load(doc, new ClassPathResource("fonts/gulim.ttf").getInputStream()), - "gulimche", PDType0Font.load(doc, new ClassPathResource("fonts/gulimche.ttf").getInputStream()), - "batang", PDType0Font.load(doc, new ClassPathResource("fonts/batang.ttf").getInputStream()), - "batangche", PDType0Font.load(doc, new ClassPathResource("fonts/batangche.ttf").getInputStream()), - "dotum", PDType0Font.load(doc, new ClassPathResource("fonts/dotum.ttf").getInputStream()), - "dotumche", PDType0Font.load(doc, new ClassPathResource("fonts/dotumche.ttf").getInputStream()), - "gungsuh", PDType0Font.load(doc, new ClassPathResource("fonts/gungsuh.ttf").getInputStream()), - "gungsuhche", PDType0Font.load(doc, new ClassPathResource("fonts/gungsuhche.ttf").getInputStream()) - ); - return fontMap; - } catch (IOException e) { - throw new RuntimeException("글꼴 로드 오류"+e); - } - } } diff --git a/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Advntce.java b/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Advntce.java index eb2997f7..ba3d530a 100644 --- a/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Advntce.java +++ b/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Advntce.java @@ -14,16 +14,8 @@ import cokr.xit.foundation.data.DataObject; * 사전통지서 */ public class Advntce extends PDFPrintFormat { - - - @Override - public void setting(Print print) { - print.setFormatKorName("사전통지서"); - this.sndngSeCd = "02"; - } - - public Advntce(){ + public void initDefaultStng() { addForPost( image("postSenderLogo","우편물송신자로고","").a4(10, 0).letter(10, 0).size(0, 0), text("postSenderInst","우편물송신자기관","").a4(10, 5).letter(10, 5), @@ -89,6 +81,15 @@ public class Advntce extends PDFPrintFormat { text("undefined","(미정)","미정항목").offLog() ); } + public Advntce() { + super(); + } + public Advntce(Print print, PrintOption printOption, + DataObject otptBscStng, List otptArtclStngList, String paperSeCd){ + super(print,printOption,otptBscStng,otptArtclStngList,paperSeCd); + this.print.setFormatKorName("사전통지서"); + this.sndngSeCd = "02"; + } /** * 출력요소에 매핑될 값을 반환한다. diff --git a/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Nht.java b/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Nht.java index a6a5f4fd..cf9d5149 100644 --- a/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Nht.java +++ b/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/Nht.java @@ -12,14 +12,8 @@ import cokr.xit.foundation.data.DataFormat; import cokr.xit.foundation.data.DataObject; public class Nht extends PDFPrintFormat { - @Override - public void setting(Print print) { - print.setFormatKorName("고지서"); - sndngSeCd = "03"; - } - - public Nht() { + public void initDefaultStng() { addForPost( image("postSenderLogo","우편물송신자로고","").a4(10, 0).letter(10, 0).size(0, 0), text("postSenderInst","우편물송신자기관","").a4(10, 5).letter(10, 5), @@ -96,6 +90,19 @@ public class Nht extends PDFPrintFormat { ); } + public Nht() { + super(); + } + + public Nht(Print print, PrintOption printOption, + DataObject otptBscStng, List otptArtclStngList, String paperSeCd) { + super(print,printOption,otptBscStng,otptArtclStngList,paperSeCd); + this.print.setFormatKorName("고지서"); + this.sndngSeCd = "03"; + } + + + /** * 출력요소에 매핑될 값을 반환한다. */ diff --git a/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/PDFPrintFormat.java b/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/PDFPrintFormat.java index 30a889b0..af6651b8 100644 --- a/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/PDFPrintFormat.java +++ b/src/main/java/cokr/xit/fims/cmmn/pdf/print/format/PDFPrintFormat.java @@ -1,19 +1,95 @@ package cokr.xit.fims.cmmn.pdf.print.format; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.font.PDType0Font; +import org.apache.pdfbox.pdmodel.graphics.color.PDColor; +import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode; +import org.egovframe.rte.fdl.string.EgovStringUtil; +import org.springframework.core.io.ClassPathResource; import cokr.xit.fims.cmmn.CmmnUtil; import cokr.xit.fims.cmmn.Print; import cokr.xit.fims.cmmn.PrintOption; +import cokr.xit.fims.cmmn.Pstn; +import cokr.xit.fims.cmmn.PstnAndSize; +import cokr.xit.fims.cmmn.Size; import cokr.xit.fims.cmmn.pdf.print.DefaultOtptArtclStng; +import cokr.xit.fims.cmmn.pdf.print.PDFColors; +import cokr.xit.fims.cmmn.pdf.print.PDFCoordinate; +import cokr.xit.fims.sprt.MediaUtil; import cokr.xit.foundation.data.DataObject; public abstract class PDFPrintFormat { protected String sndngSeCd; + protected Print print; + protected PrintOption printOption; + protected DataObject otptBscStng; + protected List otptArtclStngList; + protected String paperSeCd; + protected float[] paperMilimeter = new float[2]; + + public abstract void initDefaultStng(); + + public PDFPrintFormat() { + initDefaultStng(); + } + + public PDFPrintFormat(Print print, PrintOption printOption, + DataObject otptBscStng, List otptArtclStngList, String paperSeCd) { + initDefaultStng(); + + this.print = print; + this.printOption = printOption; + this.otptBscStng = otptBscStng; + this.otptArtclStngList = otptArtclStngList; + this.paperSeCd = paperSeCd; + if(paperSeCd.equals("01")) { + this.paperMilimeter = new float[] {210.0f , 297.0f}; + } else if(paperSeCd.equals("02")){ + this.paperMilimeter = new float[] {216.0f , 279.0f}; + } + } + + public void setOtptBscStng(DataObject otptBscStng) { + this.otptBscStng = otptBscStng; + } + + public void setOtptArtclStngList(List otptArtclStngList) { + this.otptArtclStngList = otptArtclStngList; + } + + public List getOtptArtclStngList() { + return this.otptArtclStngList; + } + + + public void setPaperSeCd(String paperSeCd) { + this.paperSeCd = paperSeCd; + + } + + public void setPrint(Print print) { + this.print = print; + }; - public abstract void setting(Print print); protected List prototypeStngs = new ArrayList(); @@ -125,5 +201,758 @@ public abstract class PDFPrintFormat { + /** + * 서식에서 사용하는 출력항목 중 사용하는 항목만 추출한다. + */ + public List filterUsedArtcls() { + List otptArtclNmList = this.otptArtclStngList.stream().map((item) -> { return item.string("OTPT_ARTCL_NM"); }).toList(); + + List result = this.getPrototypeStngs().stream() + .filter((item) -> { + return otptArtclNmList.contains(item.getArtclNm()); + }).toList(); + + return result; + } + + /** + * 다운로드 이력에 남길 항목명을 추출한다. + */ + public List filterDownloadDataNames() { + + List result = this.filterUsedArtcls().stream() + .filter((item) -> { + return item.isDownloadData(); + }) + .map(DefaultOtptArtclStng::getArtclDscrp).toList(); + + return result; + } + + public Map makePdfFile(List dataObjectList) { + Map result = new HashMap<>(); + + + + String resultFilePath = this.filePathForNewFile(); + PDDocument doc = new PDDocument();//pdf문서 생성 + + //폰트 로드 + Map fontMap = this.getFontMap(doc); + + //용지 크기 설정 + PDRectangle paper = null; + if(this.paperSeCd.equals("01")) { + paper = PDRectangle.A4; + } else { + paper = PDRectangle.LETTER; + } + + + List prototypeStngList = this.getPrototypeStngs(); + + try { + + + //출력요소별 속성 정보 추가 + this.appendOtptAttribute(this.otptArtclStngList); + + //출력 요소 정렬 + Comparator comparator1 = (item1, item2) -> { + int int1 = item1.string("UNIQUE_YN").equals("Y") ? 0 : 1; + int int2 = item2.string("UNIQUE_YN").equals("Y") ? 0 : 1; + return Integer.compare(int1, int2); + }; + Comparator comparator2 = (item1, item2) -> { + int int1 = item1.number("OTPT_ARTCL_ORDR").intValue(); + int int2 = item2.number("OTPT_ARTCL_ORDR").intValue(); + return Integer.compare(int1, int2); + }; + otptArtclStngList = otptArtclStngList.stream() + .sorted(comparator1.thenComparing(comparator2)).collect(Collectors.toList()); + + + //대표단속사진 설정 여부 확인 + boolean rprsCrdnPhotoYn = false; + if(otptArtclStngList.stream().filter(item -> item.string("OTPT_ARTCL_NM").equals("rprsCrdnPhoto")).count() > 0) { + rprsCrdnPhotoYn = true; + } + + for(DataObject dataObject : dataObjectList) { + //페이지생성(건별) + PDPage blankPage = new PDPage(paper); + doc.addPage(blankPage); + + // 작업 페이지 설정 + PDPage page = doc.getPage(doc.getNumberOfPages()-1); + // 컨텐츠 스트림 열기 + PDPageContentStream contentStream = new PDPageContentStream(doc, page); + + boolean completeFoldLine = false; + + for(DataObject otptArtclStng : otptArtclStngList) { + String otptArtclNm = otptArtclStng.string("OTPT_ARTCL_NM"); + + if(!otptArtclNm.equals("background") && !completeFoldLine) { + //접는곳 점선 그리기 + if(!otptBscStng.string("FOLD_LINE_PSTN_SE_CD").equals("")) { + this.renderFoldLine(contentStream, paper, otptBscStng.string("FOLD_LINE_PSTN_SE_CD")); + } + completeFoldLine = true; + } + + DefaultOtptArtclStng prototypeStng = prototypeStngList.stream() + .filter(item -> item.getArtclNm().equals(otptArtclNm)).toList().get(0); + + float[] pstn = this.getPstnStng(prototypeStng, otptArtclStng, this.paperSeCd); + float[] size = this.getSize(prototypeStng, otptArtclStng); + + boolean forPost = prototypeStng.isForPost(); + String defaultValue = prototypeStng.getOtptBscVl(); + + if(prototypeStng.getComponentType().equals("text")) { + String align = this.getAlign(prototypeStng, otptArtclStng); + String lineChgYn = this.getLineChgYn(prototypeStng, otptArtclStng); + PDType0Font font = this.getFontType(prototypeStng, otptArtclStng, fontMap); + int fontSz = this.getFontSize(prototypeStng, otptArtclStng); + RenderingMode fontStyle = this.getFontStyle(prototypeStng, otptArtclStng); + PDColor fontColor = this.getFontColor(prototypeStng, otptArtclStng); + + String textValue = this.getMappingValue(otptArtclNm,defaultValue,forPost,dataObject,printOption, this.print); + + this.writeText(contentStream, textValue, pstn, size[0], align, lineChgYn + , font, fontSz, fontStyle, fontColor); + + } else if(prototypeStng.getComponentType().equals("image")) { + + String imagePath = this.getMappingValue(otptArtclNm,defaultValue,forPost,dataObject,printOption,this.print); + + if(EgovStringUtil.null2void(imagePath).equals("")) { + continue; + } + + if(!imagePath.startsWith("files")) { + imagePath = CmmnUtil.copyStaticResource(imagePath, false); + } + + File imageFile = new File(imagePath); + InputStream is = new FileInputStream(imageFile); + + String imageKey = ""; + List mosSet = null; + if(otptArtclNm.equals("rprsCrdnPhoto")) { + imageKey = this.getMappingValue(otptArtclNm+"Key",defaultValue,forPost,dataObject,printOption,this.print); + mosSet = this.getMosSet(imageKey, dataObject); + } + this.insertImage(doc, contentStream, is, pstn, size); + + if(otptArtclNm.equals("rprsCrdnPhoto") && !imageKey.equals("") && mosSet != null) { + + File imageFile0 = new File(imagePath); + InputStream is0 = new FileInputStream(imageFile0); + + List transformedMosaicInfos = MediaUtil.getTransformedMosaic( + mosSet, is0, new PstnAndSize(pstn[0],pstn[1], size[0], size[1]) + ); + + for(int k=0; k < transformedMosaicInfos.size(); k++) { + PstnAndSize mosaicInfo = transformedMosaicInfos.get(k); + + InputStream blackImageStream = new ClassPathResource("samplefiles/black.png").getInputStream(); + this.insertImage(doc, contentStream, blackImageStream, + mosaicInfo.getPstn().to2Float(), mosaicInfo.getSize().to2Float()); + } + + } + + + } else if(prototypeStng.getComponentType().equals("images")) { + + List imagePaths = this.getMappingValues(otptArtclNm,defaultValue,forPost,dataObject,printOption,this.print); + + List imageKeys = new ArrayList(); + List> mosSets = new ArrayList>(); + if(otptArtclNm.equals("crdnPhoto")) { + imageKeys = this.getMappingValues(otptArtclNm+"Key",defaultValue,forPost,dataObject,printOption,this.print); + if(rprsCrdnPhotoYn && imagePaths.size() > 0) { + imageKeys.remove(0); + } + for(String imageKey : imageKeys) { + mosSets.add(this.getMosSet(imageKey, dataObject)); + } + + } + + if(otptArtclNm.equals("crdnPhoto")) { + if(rprsCrdnPhotoYn && imagePaths.size() > 0) { + imagePaths.remove(0); + } + } + + int printCntSetting = otptBscStng.number("OTPT_PHOTO_CNT").intValue(); + int dataImageCnt = imagePaths.size(); + + if(printCntSetting != 0 && dataImageCnt != 0) { + + List devideInfos = this.devideImageArea(pstn, size, printCntSetting, dataImageCnt); + + for (int i=0; i< devideInfos.size(); i++){ + PstnAndSize devideInfo = devideInfos.get(i); + + if(EgovStringUtil.null2void(imagePaths.get(i)).equals("")) { + continue; + } + + if(!imagePaths.get(i).startsWith("files")) { + imagePaths.set(i, CmmnUtil.copyStaticResource(imagePaths.get(i), false)); + } + + String imagePath = imagePaths.get(i); + + File imageFile = new File(imagePath); + InputStream is = new FileInputStream(imageFile); + + this.insertImage(doc, contentStream, is, + devideInfo.getPstn().to2Float(), devideInfo.getSize().to2Float()); + + + if(otptArtclNm.equals("crdnPhoto") && !imageKeys.isEmpty() && !mosSets.isEmpty()) { + + if(mosSets.get(i) != null) { + String imagePath0 = imagePaths.get(i); + + File imageFile0 = new File(imagePath0); + InputStream is0 = new FileInputStream(imageFile0); + + List transformedMosaicInfos = MediaUtil.getTransformedMosaic( + mosSets.get(i), is0, devideInfo + ); + + for(int k=0; k < transformedMosaicInfos.size(); k++) { + PstnAndSize mosaicInfo = transformedMosaicInfos.get(k); + InputStream blackImageStream = new ClassPathResource("samplefiles/black.png").getInputStream(); + this.insertImage(doc, contentStream, blackImageStream, + mosaicInfo.getPstn().to2Float(), mosaicInfo.getSize().to2Float()); + } + } + + + + } + + } + + } + + } + + }//출력항목 loop 끝 + + if(!completeFoldLine) { + if(!otptBscStng.string("FOLD_LINE_PSTN_SE_CD").equals("")) { + this.renderFoldLine(contentStream, paper, otptBscStng.string("FOLD_LINE_PSTN_SE_CD")); + } + } + + contentStream.close(); + + } //출력자료건수 loop 끝 + + + doc.save(resultFilePath); + doc.close(); + + String downloadFileName = this.print.getFormatKorName()+"_"+this.print.getPrintRequestDt()+".pdf"; + result.put("filename", downloadFileName); + result.put("filePath", resultFilePath); + result.put("file", new File(resultFilePath)); + + } catch (Exception e) { + throw new RuntimeException("출력오류."+e); + } + + return result; + } + + + + + + + + + public String filePathForNewFile() { + + SimpleDateFormat ymdhmsFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + String currentTime = ymdhmsFormat.format(new Date()); + String year = currentTime.substring(0, 4); + String month = currentTime.substring(4, 6); + String day = currentTime.substring(6, 8); + + String fileResultRootPath = "files" + File.separator + "result" + File.separator + "print"; + + String fileResultFolderPath = fileResultRootPath + + File.separator + year + File.separator + month + File.separator + day; + File formatFileResultFolder = new File(fileResultFolderPath); + if(!formatFileResultFolder.exists()) { + formatFileResultFolder.mkdirs(); + } + String resultPdfPath = fileResultFolderPath + + File.separator + currentTime + "_" + (print.getFileNameIndex()) + ".pdf"; + + this.print.setFileNameIndex(this.print.getFileNameIndex()+1); + + return resultPdfPath; + + } + + /** + * mm단위로 입력된 값을 pdf좌표계 형식으로 변환한다. + */ + public PDFCoordinate toPDFCoordinate(float[] XYmm) { + float Xmm = XYmm[0]; + float Ymm = XYmm[1]; + + float Xpt = CmmnUtil.mmToPt(Xmm); + float Ypt = CmmnUtil.mmToPt(Ymm); + + float YptMax = CmmnUtil.mmToPt(this.paperMilimeter[1]); + + return new PDFCoordinate(Xpt, Ypt, YptMax); + } + + /** + * 텍스트를 pdf에 입력한다. + */ + public void writeText(PDPageContentStream contentStream, String allText, + float[] XYmm, float textAreaWidth_mm, String align, String newLineYn, + PDType0Font font, int fontSize, RenderingMode fontStyle, PDColor fontColor) { + try { + if(allText == null) { + allText = ""; + } + if(newLineYn == null || newLineYn.equals("")) { + newLineYn = "N"; + } + + float[] xyAbsolute = this.toPDFCoordinate(XYmm).absolute(); + + float textAreaWidth_pt = CmmnUtil.mmToPt(textAreaWidth_mm); + + float allTextWidth = calcTextWidth(font, fontSize, allText); + + String textArr[]; + if(allText.equals("") || allText.length() == 1 || textAreaWidth_pt == 0 + || (allTextWidth <= textAreaWidth_pt) + || newLineYn.equals("N")) { + + textArr = new String[] { allText }; + + } else { + + textArr = splitByLineForLargeText(font, fontSize, allText, textAreaWidth_pt); + + } + + String firstLine = textArr[0]; + float firstLineWidth = calcTextWidth(font, fontSize, firstLine); + + contentStream.beginText(); + contentStream.setFont(font, fontSize); + contentStream.setRenderingMode(fontStyle); + contentStream.setNonStrokingColor(fontColor); + + float resultY = xyAbsolute[1] - fontSize; + + float firstLineAlignCorrection = 0; + if(align.equals("right")) { + firstLineAlignCorrection = textAreaWidth_pt - firstLineWidth; + } else if(align.equals("center")) { + firstLineAlignCorrection = (textAreaWidth_pt - firstLineWidth)/2.0f; + } + + float resultX = xyAbsolute[0] + firstLineAlignCorrection; + + contentStream.newLineAtOffset(resultX, resultY); + contentStream.showText(textArr[0]); + + if(textArr.length > 1) { + float beforeLineWidth = firstLineWidth; + + for(int i = 1; i < textArr.length; i++) { + String thisLine = textArr[i]; + float thisLineWidth = this.calcTextWidth(font, fontSize, thisLine); + float alignCorrection = 0; + + if(align.equals("right")) { + alignCorrection = beforeLineWidth - thisLineWidth; + } if(align.equals("center")) { + alignCorrection = (beforeLineWidth - thisLineWidth)/2.0f; + } + + contentStream.newLineAtOffset(alignCorrection, -(fontSize + 1)); + contentStream.showText(thisLine); + + beforeLineWidth = thisLineWidth; + } + + + } + + contentStream.endText(); + + } catch (IOException e) { + throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."+e); + } + + } + + /** + * 글꼴모양,폰트크기 등에 따른 텍스트의 가로 길이(pt)를 계산한다. + */ + public float calcTextWidth(PDType0Font font, int fontSize, String text) { + try { + return (font.getStringWidth(text) / 1000.0f) * fontSize; + } catch (IOException e) { + throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."); + } + } + + /** + * 출력할 텍스트가 지정한 영역 안에 들어가지 않을 경우 줄바꿈 처리를 위해 텍스트를 나누어 배열로 반환한다. + */ + public String[] splitByLineForLargeText(PDType0Font font, int fontSize, String allText, float textAreaWidth_pt) { + + float allTextWidth = calcTextWidth(font, fontSize, allText); + + if(allText.equals("") || allText.length() == 1 || textAreaWidth_pt == 0 + || (allTextWidth <= textAreaWidth_pt) + ) { + return new String[] { allText }; + } + + ArrayList textList = new ArrayList(); + + while(!allText.equals("")) { + int lengthForLine = this.getLengthForLine(font, fontSize, allText, textAreaWidth_pt); + String newLine = allText.substring(0,lengthForLine); + textList.add(newLine); + allText = allText.substring(lengthForLine); + } + + return textList.toArray(new String[textList.size()]); + } + + /** + * 텍스트를 줄바꿈 처리할 경우 첫 라인에 출력될 글자 수를 반환한다. + */ + private int getLengthForLine(PDType0Font font, int fontSize, String allText, float textAreaWidth_pt) { + int forLine = allText.length(); + if(forLine <= 1) { + return forLine; + }; + + for( ; ; forLine--) { + if(forLine == 1) { + break; + } + + boolean hit = ( this.calcTextWidth(font, fontSize, allText.substring(0, forLine)) <= textAreaWidth_pt ); + if(hit) { + break; + } + } + + return forLine; + } + + /** + * pdf에 이미지를 삽입한다. + */ + public void insertImage(PDDocument doc, PDPageContentStream contentStream, InputStream imageStream, float[] XYmm, + float[] SIZEmm) { + + float[] xyAbsolute = this.toPDFCoordinate(XYmm).absolute(); + + float[] size = new float[] { + CmmnUtil.mmToPt(SIZEmm[0]),CmmnUtil.mmToPt(SIZEmm[1]) + }; + try { + + PDImageXObject image = PDImageXObject.createFromByteArray(doc, imageStream.readAllBytes(), "temp"); + contentStream.drawImage(image, xyAbsolute[0], xyAbsolute[1]-size[1], size[0], size[1]); + + } catch (IOException e) { + throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."+e); + } + } + + public List devideImageArea(float[] totAreaPstn, float[] totAreaSize, int imageCntSetting, int dataImageCnt) { + List result = new ArrayList(); + + int printable = imageCntSetting <= dataImageCnt ? imageCntSetting : dataImageCnt; + + if(printable <= 1) { + result.add(new PstnAndSize(totAreaPstn[0], totAreaPstn[1], totAreaSize[0], totAreaSize[1])); + return result; + } + + boolean longerThenWidth = totAreaSize[1] > totAreaSize[0]; + + int xLengthOfD2 = 0; + int yLengthOfD2 = 0; + + if(printable == 2){ + if(longerThenWidth) { + xLengthOfD2 = 1; + yLengthOfD2 = 2; + } else { + xLengthOfD2 = 2; + yLengthOfD2 = 1; + } + } else if(printable == 3 || printable == 4){ + xLengthOfD2 = 2; + yLengthOfD2 = 2; + } else if(printable == 5 || printable == 6){ + if(longerThenWidth) { + xLengthOfD2 = 2; + yLengthOfD2 = 3; + } else { + xLengthOfD2 = 3; + yLengthOfD2 = 2; + } + } else { + throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."); + } + + PstnAndSize[][] d2Array = new PstnAndSize[xLengthOfD2][yLengthOfD2]; + Size cellSize = new Size(totAreaSize[0] / (xLengthOfD2 * 1.0f), totAreaSize[1] / (yLengthOfD2 * 1.0f)); + + d2Array[0][0] = new PstnAndSize(totAreaPstn[0], totAreaPstn[1], cellSize.getWidth(), cellSize.getHeight()); + d2Array = this.fillImageCells(d2Array); + + //출력영역 크기 병합 + if(printable == 3 || printable == 5) { + + boolean longerThenWidth_cell = cellSize.getHeight() > cellSize.getWidth(); + if(longerThenWidth_cell) { + d2Array = this.mergeLastImageCell(d2Array, "left"); + } else { + d2Array = this.mergeLastImageCell(d2Array, "up"); + } + + } + for(int y=0; y < yLengthOfD2; y++) { + for(int x=0; x < xLengthOfD2; x++) { + if(d2Array[x][y] != null) { + result.add(d2Array[x][y]); + } + } + } + + return result; + } + + private PstnAndSize[][] fillImageCells(PstnAndSize[][] d2) { + int xLengthOfD2 = d2.length; + int yLengthOfD2 = d2[0].length; + + PstnAndSize firstCell = d2[0][0]; + + Size cellSize = firstCell.getSize(); + float cellWidth = cellSize.getWidth(); + float cellHeight = cellSize.getHeight(); + + Pstn startPoint = firstCell.getPstn(); + float spX = startPoint.getLeft(); + float spY = startPoint.getTop(); + + for(int x=0; x < xLengthOfD2; x++) { + for(int y=0; y < yLengthOfD2; y++) { + if(x != 0 || y != 0) { + d2[x][y] = new PstnAndSize(spX + (cellWidth * (x * 1.0f)), spY + (cellHeight * (y * 1.0f)), cellSize); + } + } + } + + return d2; + } + + public PstnAndSize[][] mergeLastImageCell(PstnAndSize[][] d2, String mergeDirection) { + if(!mergeDirection.equals("up") && !mergeDirection.equals("left")) { + throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."); + } + + int xLengthOfD2 = d2.length; + int yLengthOfD2 = d2[0].length; + + int lastCellIndexX = xLengthOfD2-1; + int lastCellIndexY = yLengthOfD2-1; + + int mergeTargetCellIndexX = 0; + int mergeTargetCellIndexY = 0; + + if(mergeDirection.equals("up")) { + mergeTargetCellIndexX = lastCellIndexX; + mergeTargetCellIndexY = lastCellIndexY-1; + } + if(mergeDirection.equals("left")) { + mergeTargetCellIndexX = lastCellIndexX-1; + mergeTargetCellIndexY = lastCellIndexY; + } + + //병합대상셀 + if(mergeDirection.equals("up")) { + d2[mergeTargetCellIndexX][mergeTargetCellIndexY] = (d2[mergeTargetCellIndexX][mergeTargetCellIndexY]).x2Height(); + } + if(mergeDirection.equals("left")) { + d2[mergeTargetCellIndexX][mergeTargetCellIndexY] = (d2[mergeTargetCellIndexX][mergeTargetCellIndexY]).x2Width(); + } + + //마지막셀 + d2[lastCellIndexX][lastCellIndexY] = null; + + return d2; + } + + /** + * pdf에 봉합선을 넣는다. + */ + public void renderFoldLine(PDPageContentStream contentStream, PDRectangle paper, String foldCode) { + if(foldCode.equals("") && !foldCode.equals("01") && !foldCode.equals("02")) { + return; + } + + float paperWidth = paper.getWidth(); + + float partHeight; + if(foldCode.equals("01")) { + if(PDRectangle.A4.equals(paper)) { + partHeight = 99; + } else { + partHeight = 93; + } + } else { + partHeight = 93; + } + + float margin = 0; + if(foldCode.equals("02")) { + margin = 18; + } + + float bottomFold = margin + partHeight; //하단접는곳 + float topFold = margin + (partHeight * 2); //상단접는곳 + + float bottomFold_pt = CmmnUtil.mmToPt(bottomFold); + float topFold_pt = CmmnUtil.mmToPt(topFold); + + try { + contentStream.setLineDashPattern(new float[]{3,1}, 0); + contentStream.moveTo(0, topFold_pt); + contentStream.lineTo(paperWidth, topFold_pt); + contentStream.stroke(); + contentStream.moveTo(0, bottomFold_pt); + contentStream.lineTo(paperWidth, bottomFold_pt); + contentStream.stroke(); + contentStream.setLineDashPattern(new float[]{}, 0); + } catch (IOException e) { + throw new RuntimeException("PDF 파일 출력 중 오류가 발생하였습니다."+e); + } + } + + public float[] getPstnStng(DefaultOtptArtclStng prototypeStng, DataObject sggStng, String paperSeCd) { + if(!sggStng.string("LEFT_PSTN").equals("") && !sggStng.string("TOP_PSTN").equals("")) { + return new float[] { + sggStng.number("LEFT_PSTN").floatValue(), + sggStng.number("TOP_PSTN").floatValue() + }; + } else { + return new float[] { + prototypeStng.getLeftPstn(paperSeCd), + prototypeStng.getTopPstn(paperSeCd) + }; + } + } + + public PDType0Font getFontType(DefaultOtptArtclStng prototypeStng, DataObject sggStng, Map fontMap) { + if(sggStng != null && !sggStng.isEmpty() && !sggStng.string("FONT_NM").equals("")) { + return fontMap.get(sggStng.string("FONT_NM")); + } else { + return fontMap.get(prototypeStng.getFontNm()); + } + } + + public int getFontSize(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { + if(!sggStng.string("FONT_SZ").equals("")) { + return sggStng.number("FONT_SZ").intValue(); + } else { + return prototypeStng.getFontSz(); + } + } + + public RenderingMode getFontStyle(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { + if(!sggStng.string("FONT_STYLE").equals("")) { + return RenderingMode.valueOf(sggStng.string("FONT_STYLE")); + } else { + return RenderingMode.valueOf(prototypeStng.getFontStyle()); + } + } + + public PDColor getFontColor(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { + if(!sggStng.string("FONT_COLOR").equals("")) { + return PDFColors.getColor(sggStng.string("FONT_COLOR")); + } else { + return PDFColors.getColor(prototypeStng.getFontColor()); + } + } + + public float[] getSize(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { + if(!sggStng.string("WIDTH_SZ").equals("")) { + return new float[] { + sggStng.number("WIDTH_SZ").floatValue(), + sggStng.number("HEIGHT_SZ").floatValue() + }; + } else { + return new float[] { + prototypeStng.getWidthSz(), + prototypeStng.getHeightSz() + }; + } + } + + public String getAlign(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { + if(!sggStng.string("TEXT_SORT").equals("")) { + return sggStng.string("TEXT_SORT"); + } else { + return prototypeStng.getTextSort(); + } + } + + public String getLineChgYn(DefaultOtptArtclStng prototypeStng, DataObject sggStng) { + if(!sggStng.string("LINE_CHG_YN").equals("")) { + return sggStng.string("LINE_CHG_YN"); + } else { + return prototypeStng.getLineChgYn(); + } + } + + public Map getFontMap(PDDocument doc) { + try { + Map fontMap = Map.of( + "gulim", PDType0Font.load(doc, new ClassPathResource("fonts/gulim.ttf").getInputStream()), + "gulimche", PDType0Font.load(doc, new ClassPathResource("fonts/gulimche.ttf").getInputStream()), + "batang", PDType0Font.load(doc, new ClassPathResource("fonts/batang.ttf").getInputStream()), + "batangche", PDType0Font.load(doc, new ClassPathResource("fonts/batangche.ttf").getInputStream()), + "dotum", PDType0Font.load(doc, new ClassPathResource("fonts/dotum.ttf").getInputStream()), + "dotumche", PDType0Font.load(doc, new ClassPathResource("fonts/dotumche.ttf").getInputStream()), + "gungsuh", PDType0Font.load(doc, new ClassPathResource("fonts/gungsuh.ttf").getInputStream()), + "gungsuhche", PDType0Font.load(doc, new ClassPathResource("fonts/gungsuhche.ttf").getInputStream()) + ); + return fontMap; + } catch (IOException e) { + throw new RuntimeException("글꼴 로드 오류"+e); + } + } } diff --git a/src/main/java/cokr/xit/fims/sndb/web/Sndb01Controller.java b/src/main/java/cokr/xit/fims/sndb/web/Sndb01Controller.java index 9c3e89da..f5bafcdd 100644 --- a/src/main/java/cokr/xit/fims/sndb/web/Sndb01Controller.java +++ b/src/main/java/cokr/xit/fims/sndb/web/Sndb01Controller.java @@ -20,7 +20,6 @@ import cokr.xit.base.docs.xls.Format; import cokr.xit.base.docs.xls.Style; import cokr.xit.base.docs.xls.XLSWriter; import cokr.xit.base.file.etc.OutsourcingFileWriter; -import cokr.xit.base.file.pdf.PDFWriter; import cokr.xit.base.file.service.FileQuery; import cokr.xit.base.file.service.bean.FileBean; import cokr.xit.base.user.ManagedUser; @@ -1742,14 +1741,11 @@ public class Sndb01Controller extends ApplicationController { } } - PDFWriter pdfWriter = new PDFWriter(); Print print = new Print(); UserInfo userInfo = currentUser(); factionBean.initUserInfo(userInfo); print.setPrintRequestUserInfo(userInfo); - pdfWriter.setPrint(print); - pdfWriter.setFormat(new Advntce()); //출력물 기본 설정 OtptStngQuery otptStngQuery = new OtptStngQuery(); @@ -1764,12 +1760,9 @@ public class Sndb01Controller extends ApplicationController { if(otptBscStng == null) { otptBscStng = new DataObject(); } - pdfWriter.setOtptBscStng(otptBscStng); //출력 요소별 설정 List otptArtclStngList = otptStngMapper.selectOtptArtclStngList(otptStngQuery); - pdfWriter.setOtptArtclStngList(otptArtclStngList); - pdfWriter.setPaper(paperSeCd); DataObject sggStngInfo = stngBean.getStng("sgg"); DataObject deptStngInfo = stngBean.getStng("dept"); @@ -1790,11 +1783,12 @@ public class Sndb01Controller extends ApplicationController { } printOption.setGlobalVariable(globalVariable); - Map result = pdfWriter.makePdfFile("info", "advntce", printOption, dataObjectList); + Advntce advntce = new Advntce(print,printOption,otptBscStng,otptArtclStngList,paperSeCd); + Map result = advntce.makePdfFile(dataObjectList); mav.addAllObjects(result); mav.addObject("downloadData", dataObjectList); - mav.addObject("dataNames", pdfWriter.filterDownloadDataNames()); + mav.addObject("dataNames", advntce.filterDownloadDataNames()); return mav; } diff --git a/src/main/java/cokr/xit/fims/sprt/web/Sprt01Controller.java b/src/main/java/cokr/xit/fims/sprt/web/Sprt01Controller.java index ba7572df..7c334752 100644 --- a/src/main/java/cokr/xit/fims/sprt/web/Sprt01Controller.java +++ b/src/main/java/cokr/xit/fims/sprt/web/Sprt01Controller.java @@ -25,7 +25,6 @@ import cokr.xit.base.docs.xls.Format; import cokr.xit.base.docs.xls.Style; import cokr.xit.base.docs.xls.XLSWriter; import cokr.xit.base.file.etc.OutsourcingFileWriter; -import cokr.xit.base.file.pdf.PDFWriter; import cokr.xit.base.file.service.FileQuery; import cokr.xit.base.file.service.bean.FileBean; import cokr.xit.base.user.ManagedUser; @@ -734,13 +733,11 @@ public class Sprt01Controller extends ApplicationController { } } - PDFWriter pdfWriter = new PDFWriter(); + Print print = new Print(); UserInfo userInfo = currentUser(); factionBean.initUserInfo(userInfo); print.setPrintRequestUserInfo(userInfo); - pdfWriter.setPrint(print); - pdfWriter.setFormat(new Advntce()); //출력물 기본 설정 OtptStngQuery otptStngQuery = new OtptStngQuery(); @@ -754,12 +751,8 @@ public class Sprt01Controller extends ApplicationController { if(otptBscStng == null) { otptBscStng = new DataObject(); } - pdfWriter.setOtptBscStng(otptBscStng); //출력 요소별 설정 List otptArtclStngList = otptStngMapper.selectOtptArtclStngList(otptStngQuery); - pdfWriter.setOtptArtclStngList(otptArtclStngList); - pdfWriter.setPaper(paperSeCd); - DataObject sggStngInfo = stngBean.getStng("sgg"); DataObject deptStngInfo = stngBean.getStng("dept"); @@ -780,11 +773,12 @@ public class Sprt01Controller extends ApplicationController { } printOption.setGlobalVariable(globalVariable); + Advntce advntce = new Advntce(print,printOption,otptBscStng,otptArtclStngList,paperSeCd); - Map result = pdfWriter.makePdfFile("info", "advntce", printOption, dataObjectList); + Map result = advntce.makePdfFile(dataObjectList); mav.addAllObjects(result); mav.addObject("downloadData", dataObjectList); - mav.addObject("dataNames", pdfWriter.filterDownloadDataNames()); + mav.addObject("dataNames", advntce.filterDownloadDataNames()); return mav; } @@ -913,7 +907,7 @@ public class Sprt01Controller extends ApplicationController { List dataObjectList = new ArrayList(); if(crdnIds.length == 1 && crdnIds[0].equals("sample")) { - DataObject sample = new Advntce().createSampleData(); + DataObject sample = new Nht().createSampleData(); dataObjectList.add(sample); } else { @@ -972,14 +966,12 @@ public class Sprt01Controller extends ApplicationController { } } - PDFWriter pdfWriter = new PDFWriter(); + Print print = new Print(); UserInfo userInfo = currentUser(); factionBean.initUserInfo(userInfo); print.setPrintRequestUserInfo(userInfo); - pdfWriter.setPrint(print); - pdfWriter.setFormat(new Nht()); //출력물 기본 설정 OtptStngQuery otptStngQuery = new OtptStngQuery(); @@ -993,13 +985,8 @@ public class Sprt01Controller extends ApplicationController { if(otptBscStng == null) { otptBscStng = new DataObject(); } - pdfWriter.setOtptBscStng(otptBscStng); //출력 요소별 설정 List otptArtclStngList = otptStngMapper.selectOtptArtclStngList(otptStngQuery); - pdfWriter.setOtptArtclStngList(otptArtclStngList); - - pdfWriter.setPaper(paperSeCd); - DataObject sggStngInfo = stngBean.getStng("sgg"); DataObject deptStngInfo = stngBean.getStng("dept"); @@ -1020,10 +1007,12 @@ public class Sprt01Controller extends ApplicationController { } printOption.setGlobalVariable(globalVariable); - Map result = pdfWriter.makePdfFile("info", "nht", printOption, dataObjectList); + Nht nht = new Nht(print,printOption,otptBscStng,otptArtclStngList,paperSeCd); + + Map result = nht.makePdfFile(dataObjectList); mav.addAllObjects(result); mav.addObject("downloadData", dataObjectList); - mav.addObject("dataNames", pdfWriter.filterDownloadDataNames()); + mav.addObject("dataNames", nht.filterDownloadDataNames()); return mav; }