소스정리
parent
c956c7e462
commit
ebf533d8a8
@ -1,835 +1,8 @@
|
|||||||
package cokr.xit.base.file.pdf;
|
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 {
|
public class PDFWriter {
|
||||||
protected String paper;
|
|
||||||
protected Print print;
|
|
||||||
protected PDFPrintFormat format;
|
|
||||||
|
|
||||||
protected DataObject otptBscStng;
|
|
||||||
protected List<DataObject> 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<DataObject> otptArtclStngList) {
|
|
||||||
this.otptArtclStngList = otptArtclStngList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DataObject> getOtptArtclStngList() {
|
|
||||||
return this.otptArtclStngList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 서식에서 사용하는 출력항목 중 사용하는 항목만 추출한다.
|
|
||||||
*/
|
|
||||||
public List<DefaultOtptArtclStng> filterUsedArtcls() {
|
|
||||||
List<String> otptArtclNmList = this.otptArtclStngList.stream().map((item) -> { return item.string("OTPT_ARTCL_NM"); }).toList();
|
|
||||||
|
|
||||||
List<DefaultOtptArtclStng> result = this.getFormat().getPrototypeStngs().stream()
|
|
||||||
.filter((item) -> {
|
|
||||||
return otptArtclNmList.contains(item.getArtclNm());
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 다운로드 이력에 남길 항목명을 추출한다.
|
|
||||||
*/
|
|
||||||
public List<String> filterDownloadDataNames() {
|
|
||||||
|
|
||||||
List<String> result = this.filterUsedArtcls().stream()
|
|
||||||
.filter((item) -> {
|
|
||||||
return item.isDownloadData();
|
|
||||||
})
|
|
||||||
.map(DefaultOtptArtclStng::getArtclDscrp).toList();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> makePdfFile(String formatType, String formatName, PrintOption printOption, List<DataObject> dataObjectList) {
|
|
||||||
Map<String, Object> result = new HashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
String resultFilePath = this.filePathForNewFile();
|
|
||||||
PDDocument doc = new PDDocument();//pdf문서 생성
|
|
||||||
|
|
||||||
//폰트 로드
|
|
||||||
Map<String, PDType0Font> fontMap = this.getFontMap(doc);
|
|
||||||
|
|
||||||
//용지 크기 설정
|
|
||||||
PDRectangle paper = null;
|
|
||||||
if(this.paper.equals("01")) {
|
|
||||||
paper = PDRectangle.A4;
|
|
||||||
} else {
|
|
||||||
paper = PDRectangle.LETTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<DefaultOtptArtclStng> prototypeStngList = this.format.getPrototypeStngs();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
|
|
||||||
//출력요소별 속성 정보 추가
|
|
||||||
this.format.appendOtptAttribute(this.otptArtclStngList);
|
|
||||||
|
|
||||||
//출력 요소 정렬
|
|
||||||
Comparator<DataObject> 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<DataObject> 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<DataObject> 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<PstnAndSize> 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<String> imagePaths = this.format.getMappingValues(otptArtclNm,defaultValue,forPost,dataObject,printOption,print);
|
|
||||||
|
|
||||||
List<String> imageKeys = new ArrayList<String>();
|
|
||||||
List<List<DataObject>> mosSets = new ArrayList<List<DataObject>>();
|
|
||||||
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<PstnAndSize> 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<PstnAndSize> 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<String> textList = new ArrayList<String>();
|
|
||||||
|
|
||||||
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<PstnAndSize> devideImageArea(float[] totAreaPstn, float[] totAreaSize, int imageCntSetting, int dataImageCnt) {
|
|
||||||
List<PstnAndSize> result = new ArrayList<PstnAndSize>();
|
|
||||||
|
|
||||||
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<String, PDType0Font> 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<String, PDType0Font> getFontMap(PDDocument doc) {
|
|
||||||
try {
|
|
||||||
Map<String, PDType0Font> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue