From f68533455b5d9fbc6973cba89d183b04cc9cf757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AA=20Th=C3=A0nh=20=C4=90=E1=BA=A1t?= <91755733+lds217@users.noreply.github.com> Date: Mon, 7 Jul 2025 17:18:40 +0700 Subject: [PATCH] [update] Integrate ultrasound report generation with JasperReports in CheckUpPage. Add functionality to scale RTF font sizes for improved printing quality. Update UltrasoundResult class to display reports directly and enhance launch configuration for testing ultrasound print functionality. --- .vscode/launch.json | 7 + .../ui/component/CheckUpPage/CheckUpPage.java | 6 +- .../PrintDialog/UltrasoundResult.java | 74 ++++++ .../print_forms/test_ultrasound_print.java | 115 +++++++++ .../print_forms/ultrasoundresult.jrxml | 244 ++++++++++++++++++ .../java/BsK/common/util/text/TextUtils.java | 54 +++- 6 files changed, 495 insertions(+), 5 deletions(-) create mode 100644 src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_ultrasound_print.java create mode 100644 src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml diff --git a/.vscode/launch.json b/.vscode/launch.json index 3d256b9..843411f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,13 @@ { "version": "0.2.0", "configurations": [ + { + "type": "java", + "name": "test_ultrasound_print", + "request": "launch", + "mainClass": "BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms.test_ultrasound_print", + "projectName": "ldS_BsK" + }, { "type": "java", "name": "test_print", diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java index 3a951e3..4b7a24c 100644 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/CheckUpPage.java @@ -1373,7 +1373,7 @@ public class CheckUpPage extends JPanel { return; } - UltrasoundResult ultrasoundDialog = new UltrasoundResult( + UltrasoundResult ultrasoundResult = new UltrasoundResult( checkupIdField.getText(), customerLastNameField.getText() + " " + customerFirstNameField.getText(), dobPicker.getJFormattedTextField().getText(), @@ -1381,14 +1381,14 @@ public class CheckUpPage extends JPanel { customerAddressField.getText() + ", " + (wardComboBox.getSelectedItem() != null ? wardComboBox.getSelectedItem().toString() : "") + ", " + (districtComboBox.getSelectedItem() != null ? districtComboBox.getSelectedItem().toString() : "") + ", " + (provinceComboBox.getSelectedItem() != null ? provinceComboBox.getSelectedItem().toString() : ""), (String) doctorComboBox.getSelectedItem(), datePicker.getJFormattedTextField().getText(), - getRtfContentAsString(), + TextUtils.scaleRtfFontSize(getRtfContentAsString()), conclusionField.getText(), suggestionField.getText(), selectedImagesForPrint, printType, templateTitle ); - ultrasoundDialog.createDialog(mainFrame); + ultrasoundResult.showDirectJasperViewer(); break; } } diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java index aaeda0d..1c7c003 100644 --- a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/UltrasoundResult.java @@ -26,6 +26,17 @@ import lombok.extern.slf4j.Slf4j; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; +// --- JasperReports Imports --- +import net.sf.jasperreports.engine.JREmptyDataSource; +import net.sf.jasperreports.engine.JasperCompileManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import net.sf.jasperreports.engine.design.JasperDesign; +import net.sf.jasperreports.engine.xml.JRXmlLoader; +import net.sf.jasperreports.view.JasperViewer; +// --- End JasperReports Imports --- + import javax.imageio.ImageIO; import javax.swing.*; import javax.swing.text.rtf.RTFEditorKit; @@ -39,6 +50,10 @@ import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.*; import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Locale; +import net.sf.jasperreports.engine.JRParameter; @Slf4j public class UltrasoundResult { @@ -79,6 +94,65 @@ public class UltrasoundResult { this.templateTitle = templateTitle; } + public void showDirectJasperViewer() { + try { + Map parameters = new HashMap<>(); + + // Set locale for date/number formatting + parameters.put(JRParameter.REPORT_LOCALE, new Locale("vi", "VN")); + + // Populate all the string parameters + parameters.put("clinicName", LocalStorage.ClinicName != null ? LocalStorage.ClinicName : "Phòng khám BSK"); + parameters.put("clinicAddress", LocalStorage.ClinicAddress != null ? LocalStorage.ClinicAddress : "Địa chỉ phòng khám"); + parameters.put("clinicPhone", LocalStorage.ClinicPhone != null ? LocalStorage.ClinicPhone : "SĐT phòng khám"); + parameters.put("patientName", this.patientName); + parameters.put("patientDOB", this.patientDOB); + parameters.put("patientGender", this.patientGender); + parameters.put("patientAddress", this.patientAddress); + parameters.put("doctorName", this.doctorName); + parameters.put("checkupDate", this.checkupDate); + parameters.put("barcodeNumber", this.checkupId); + + // RTF and plain text content + parameters.put("checkupNote", this.rtfContent); + parameters.put("checkupConclusion", this.conclusion); + parameters.put("checkupSuggestion", this.suggestion); + parameters.put("reCheckupDate", "Tái khám theo lịch hẹn"); // Placeholder, adjust as needed + + // Handle images + int numberOfImages = this.selectedImages.size(); + parameters.put("numberImage", numberOfImages); + + String projectDir = System.getProperty("user.dir"); + parameters.put("logoImage", projectDir + "/src/main/java/BsK/client/ui/assets/icon/logo.jpg"); + + for (int i = 0; i < 6; i++) { + if (i < numberOfImages) { + parameters.put("image" + (i + 1), this.selectedImages.get(i).getAbsolutePath()); + } else { + parameters.put("image" + (i + 1), null); // Pass null for unused image slots + } + } + + // Load and compile the report + String jrxmlPath = projectDir + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml"; + InputStream inputStream = new FileInputStream(new File(jrxmlPath)); + + JasperDesign jasperDesign = JRXmlLoader.load(inputStream); + JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign); + + // Fill the report + JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource()); + + // View the report + JasperViewer.viewReport(jasperPrint, false); + + } catch (Exception e) { + log.error("Error generating or showing JasperReport for Ultrasound", e); + JOptionPane.showMessageDialog(null, "Lỗi khi tạo báo cáo siêu âm: " + e.getMessage(), "Lỗi JasperReport", JOptionPane.ERROR_MESSAGE); + } + } + public void createDialog(JFrame parent) { dialog = new JDialog(parent, "Kết quả siêu âm", true); dialog.setSize(800, 700); diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_ultrasound_print.java b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_ultrasound_print.java new file mode 100644 index 0000000..4405d24 --- /dev/null +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/test_ultrasound_print.java @@ -0,0 +1,115 @@ +package BsK.client.ui.component.CheckUpPage.PrintDialog.print_forms; + +import net.sf.jasperreports.engine.JREmptyDataSource; +import net.sf.jasperreports.engine.JasperReport; +import net.sf.jasperreports.engine.xml.JRXmlLoader; +import net.sf.jasperreports.engine.design.JasperDesign; +import net.sf.jasperreports.engine.JasperCompileManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.view.JasperViewer; +import net.sf.jasperreports.engine.JRParameter; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + + +public class test_ultrasound_print { + public static void main(String[] args) { + try { + // 1. Put the data sources into the parameters map + Map parameters = new HashMap<>(); + + // Set locale to Vietnamese for number formatting and dates + parameters.put(JRParameter.REPORT_LOCALE, new Locale("vi", "VN")); + + // 2. Sample data parameters + parameters.put("clinicName", "BSK CLINIC"); + parameters.put("clinicAddress", "123 Main Street, City, Country"); + parameters.put("clinicPhone", "0123-456-789"); + + parameters.put("patientName", "Nguyễn Thị B"); + parameters.put("patientDOB", "20/07/1985"); + parameters.put("patientGender", "Nữ"); + parameters.put("patientAddress", "456 Đường DEF, Phường UVW, Quận 2, TP.HCM"); + parameters.put("patientDiagnos", "Theo dõi thai kỳ tuần 12"); + + parameters.put("doctorName", "BS. Trần Văn C"); + parameters.put("checkupDate", "22/12/2024"); + + // 3. Add the RTF content for the notes, with corrected font sizes. + // RTF font sizes are in "half-points", so \fs24 = 12pt. + String rtfContent = "{\\rtf1\\ansi\n" + + "{\\fonttbl\\f0\\fnil Monospaced;\\f1\\fnil Times New Roman;}\n" + + "{\\colortbl\\red0\\green0\\blue0;\\red51\\green51\\blue51;\\red0\\green0\\blue255;}\n" + + "\n" + + "\\li0\\ri0\\fi0\\f1\\fs28\\i0\\b\\ul0\\cf2 Test\\fs24\\cf1\\par\n" + // Heading at 14pt, main text at 12pt + "\\par\n" + + "dawdawd\\par\n" + + "ad\\par\n" + + " aw\\par\n" + + "daw da\\b0 daw dad aw\\ul d awd awd \\par\n" + + "\\ul0\\tab\\tab\\ul awdawd\\ul0\\par\n" + + "\\li0\\ri0\\fi0\\ul0\\par\n" + + "}"; + parameters.put("checkupNote", rtfContent); + parameters.put("checkupConclusion", "Thai nhi phát triển bình thường, dự kiến sinh trong 3 tháng tới."); // Normal string + parameters.put("checkupSuggestion", "Bổ sung sắt và canxi, tái khám sau 4 tuần."); // Normal string + + + // 4. Add the re-checkup date + parameters.put("reCheckupDate", "ngày 29 tháng 12 năm 2024"); + + // 5. Add barcode number + parameters.put("barcodeNumber", "2024001235"); + + // 6. Set the number of images to display + int numberOfImages = 4; + parameters.put("numberImage", numberOfImages); + + // 7. Add logo image path + String projectDir = System.getProperty("user.dir"); + String logoPath = projectDir + "/src/main/java/BsK/client/ui/assets/icon/logo.jpg"; + parameters.put("logoImage", logoPath); + + // 8. Add paths for the 6 ultrasound images + String imageDir = projectDir + "/img_db/8/"; + String[] imageFiles = { + "IMG_8_20250619_033320.jpg", + "IMG_8_20250619_033621.jpg", + "IMG_8_20250619_033622.jpg", + "IMG_8_20250619_033623.jpg", + "IMG_8_20250628_220921.jpg", + "IMG_9_20250619_034013.jpg" + }; + + for (int i = 0; i < 6; i++) { + if (i < numberOfImages) { + parameters.put("image" + (i + 1), imageDir + imageFiles[i]); + } else { + parameters.put("image" + (i + 1), null); // Pass null for unused image slots + } + } + + // 9. Load and compile the report + String jrxmlPath = projectDir + "/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml"; + InputStream inputStream = new FileInputStream(new File(jrxmlPath)); + + JasperDesign jasperDesign = JRXmlLoader.load(inputStream); + JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign); + + // 10. Fill the report. Since there's no table, we use an JREmptyDataSource. + JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JREmptyDataSource()); + + // 11. View the report + JasperViewer.viewReport(jasperPrint, false); // `false` to prevent app exit on close + + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml new file mode 100644 index 0000000..97d14de --- /dev/null +++ b/src/main/java/BsK/client/ui/component/CheckUpPage/PrintDialog/print_forms/ultrasoundresult.jrxml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <pageHeader splitType="Stretch"/> + <columnHeader splitType="Stretch"/> + <detail> + <band height="527" splitType="Stretch"> + <element kind="frame" uuid="2b7ec588-953c-4145-87b7-1d861c272fe0" x="0" y="0" width="400" height="525"> + <element kind="image" uuid="fd80ab38-4cae-409b-84b9-356220d2b1e5" x="0" y="-5" width="70" height="64"> + <expression><![CDATA[$P{logoImage}]]></expression> + </element> + <element kind="textField" uuid="eb56d4c8-2a0d-45fa-89a2-ad6528f9a99b" x="70" y="0" width="300" height="20" fontName="Arial" fontSize="14.0" bold="true"> + <expression><![CDATA["PHÒNG KHÁM " + $P{clinicName}]]></expression> + </element> + <element kind="staticText" uuid="2677daaf-d0fb-40ad-afaa-513efa16055c" x="70" y="20" width="150" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Địa chỉ: ]]></text> + </element> + <element kind="textField" uuid="796d9ffd-6d2e-4ae3-bdfb-b08183d7d9c0" x="100" y="20" width="270" height="15" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{clinicAddress}]]></expression> + </element> + <element kind="staticText" uuid="1a1405ee-b3e4-4e98-ac08-6818bc29e902" x="70" y="36" width="150" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[SĐT:]]></text> + </element> + <element kind="textField" uuid="260bb33d-1d11-4178-aceb-3fbf8fcb4b45" x="100" y="36" width="270" height="15" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{clinicPhone}]]></expression> + </element> + <element kind="staticText" uuid="6f89a93f-2d10-4506-baa5-226bdd047b17" x="0" y="59" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true"> + <text><![CDATA[I.Thông tin]]></text> + </element> + <element kind="staticText" uuid="b8dfca43-cf97-49e5-b58d-4667143dba62" x="0" y="79" width="50" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Họ và tên:]]></text> + </element> + <element kind="staticText" uuid="0a9ca0c8-f2bd-4ade-a025-a6d79c13613f" x="1" y="94" width="80" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Ngày sinh:]]></text> + </element> + <element kind="staticText" uuid="21917ab8-ae07-44c8-ba4e-bc6c4c54b440" x="148" y="94" width="80" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Giới tính:]]></text> + </element> + <element kind="staticText" uuid="bcbb614e-7a4d-48a3-83c2-198e4fb62c5f" x="1" y="109" width="80" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Địa chỉ:]]></text> + </element> + <element kind="staticText" uuid="45fe4be1-9e21-459b-aeee-2efc8354f372" x="221" y="80" width="50" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Bác sĩ:]]></text> + </element> + <element kind="staticText" uuid="f2ff4b17-63cc-4e8c-a3b0-2523f534f21a" x="221" y="94" width="60" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Ngày khám:]]></text> + </element> + <element kind="textField" uuid="1511f53a-b282-41b1-b233-612b6106c07a" x="50" y="79" width="180" height="15" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{patientName}]]></expression> + </element> + <element kind="textField" uuid="5bdac267-523d-4931-926b-76233ce9b84d" x="50" y="94" width="98" height="15" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{patientDOB}]]></expression> + </element> + <element kind="textField" uuid="f4df20b4-920c-491e-882b-6e0733cb4866" x="186" y="94" width="44" height="15" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{patientGender}]]></expression> + </element> + <element kind="textField" uuid="3b8ac40e-85aa-4ab8-8445-64bcddb8b267" x="50" y="110" width="200" height="20" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{patientAddress}]]></expression> + </element> + <element kind="textField" uuid="db40cdb0-2850-4d66-8430-addc54f90321" x="266" y="80" width="134" height="15" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{doctorName}]]></expression> + </element> + <element kind="textField" uuid="eb9cf54a-3b50-43c5-8696-cfc1e21bddfe" x="266" y="94" width="134" height="15" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{checkupDate}]]></expression> + </element> + <element kind="staticText" uuid="9f7de81c-4c38-41a2-9fea-a165eff19431" x="1" y="130" width="49" height="15" fontName="Arial" fontSize="8.0" bold="true" hTextAlign="Left"> + <text><![CDATA[Chuẩn đoán:]]></text> + </element> + <element kind="textField" uuid="5ae67e13-7a79-437f-bfb8-c720d896720d" x="51" y="130" width="349" height="26" fontName="Arial" fontSize="8.0"> + <expression><![CDATA[$P{patientDiagnos}]]></expression> + </element> + <element kind="staticText" uuid="b1fa845a-48da-4e45-82b8-8b9d972650f6" x="0" y="156" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true"> + <text><![CDATA[II.Nội dung]]></text> + </element> + <element kind="textField" uuid="6d652a25-b701-45bd-91ba-750842650004" x="0" y="176" width="400" height="348" markup="rtf" fontName="Times New Roman" fontSize="10.0"> + <expression><![CDATA[$P{checkupNote}]]></expression> + </element> + </element> + <element kind="frame" uuid="a72ffc70-007e-43af-a566-b34e6e07b312" x="400" y="0" width="400" height="526"> + <element kind="staticText" uuid="246a04b0-2565-4987-b7f3-dd369703035c" x="0" y="340" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true"> + <text><![CDATA[III.Kết luận]]></text> + </element> + <element kind="staticText" uuid="c53ef0ab-a702-47fc-9b7c-24307a495b30" x="0" y="430" width="100" height="30" forecolor="#FF0905" fontName="Times New Roman" fontSize="15.0" bold="true"> + <text><![CDATA[Đề nghị:]]></text> + </element> + <element kind="staticText" uuid="a38b1187-ddb8-4410-9b52-dc041f894b7b" x="247" y="430" width="96" height="15" fontName="Arial" fontSize="10.0" bold="true" hTextAlign="Center"> + <text><![CDATA[Bác sĩ siêu âm]]></text> + </element> + <element kind="textField" uuid="b548d99d-bedf-4e90-b13b-bdbc763aa974" x="230" y="496" width="132" height="15" fontName="Arial" hTextAlign="Center"> + <expression><![CDATA[$P{doctorName}]]></expression> + </element> + <element kind="textField" uuid="8bca58ab-0958-40fe-8e51-2a39a9d379a5" x="200" y="506" width="200" height="19" pattern="MMMMM dd, yyyy" hTextAlign="Center" vTextAlign="Bottom"> + <expression><![CDATA[new java.text.SimpleDateFormat("'Đức Hoà, ngày ' dd ' tháng ' MM ' năm ' yyyy", new java.util.Locale("vi", "VN")).format(new java.util.Date())]]></expression> + </element> + <element kind="staticText" uuid="c062ce0e-80cb-4e67-a5d9-d85e769c6c4e" x="0" y="511" width="110" height="14" forecolor="#FF0905" fontName="Times New Roman" fontSize="10.0" bold="true"> + <text><![CDATA[Tái khám:]]></text> + </element> + <element kind="textField" uuid="e90ad772-4425-482d-9e75-f2bc66b9084d" x="0" y="358" width="400" height="70" fontName="Times New Roman" fontSize="10.0"> + <expression><![CDATA[$P{checkupConclusion}]]></expression> + </element> + <element kind="component" uuid="cb28d811-1328-45dc-9461-cfbb88b7eeae" x="-59" y="12" width="60" height="40"> + <component kind="barcode4j:Code128"> + <codeExpression><![CDATA[$P{barcodeNumber}]]></codeExpression> + </component> + </element> + <element kind="staticText" uuid="6a7d5f66-d7cc-481f-9fff-8ece0789b3b4" x="-60" y="2" width="61" height="17" fontName="Arial" fontSize="10.0" bold="false" hTextAlign="Center"> + <text><![CDATA[Mã khám bệnh]]></text> + </element> + <element kind="textField" uuid="d63165c2-19e2-43ad-8a3f-004e00bffdfe" x="0" y="450" width="230" height="55" fontName="Times New Roman" fontSize="10.0"> + <expression><![CDATA[$P{checkupSuggestion}]]></expression> + </element> + <element kind="textField" uuid="cece8e5b-67db-4019-b52a-bf73abae535e" x="46" y="514" width="150" height="15" fontName="Times New Roman" fontSize="8.0"> + <expression><![CDATA[$P{reCheckupDate}]]></expression> + </element> + <element kind="frame" uuid="2f301804-acfa-4b6f-9f52-236c04fd1197" x="0" y="0" width="400" height="344"> + <printWhenExpression><![CDATA[$P{numberImage}.intValue() == 6]]></printWhenExpression> + <element kind="image" uuid="fe4e4fa7-8b26-4817-ae86-4c147a25abbe" x="83" y="3" width="111" height="113"> + <expression><![CDATA[$P{image1}]]></expression> + </element> + <element kind="image" uuid="9c6302ea-8b4a-48d6-8c42-68313154be77" x="83" y="117" width="111" height="113"> + <expression><![CDATA[$P{image3}]]></expression> + </element> + <element kind="image" uuid="d7d6a47e-a129-4726-80b1-701113d0d9c2" x="83" y="231" width="111" height="113"> + <expression><![CDATA[$P{image5}]]></expression> + </element> + <element kind="image" uuid="7cd3d01b-f3ac-48d1-9749-ab5787497ab9" x="198" y="232" width="111" height="113"> + <expression><![CDATA[$P{image6}]]></expression> + </element> + <element kind="image" uuid="65610203-a91f-4b55-9a33-d6bfb7ffa7a6" x="199" y="117" width="111" height="113"> + <expression><![CDATA[$P{image4}]]></expression> + </element> + <element kind="image" uuid="127b0f54-33e9-43a5-af62-64152d74958f" x="199" y="3" width="111" height="113"> + <expression><![CDATA[$P{image2}]]></expression> + </element> + </element> + <element kind="frame" uuid="58523878-7ef9-46fe-aad7-ee5bd65115aa" x="0" y="1" width="400" height="344"> + <printWhenExpression><![CDATA[$P{numberImage}.intValue() == 5]]></printWhenExpression> + <element kind="image" uuid="6870ae02-5ee4-40e8-9787-1ad084dc3b7f" x="83" y="3" width="111" height="113"> + <expression><![CDATA[$P{image1}]]></expression> + </element> + <element kind="image" uuid="4216a22f-f20f-4bf1-9e93-79ccc3bbd5c6" x="83" y="117" width="111" height="113"> + <expression><![CDATA[$P{image3}]]></expression> + </element> + <element kind="image" uuid="3069d087-6d97-455c-bb0d-211b0698b54c" x="142" y="231" width="111" height="113"> + <expression><![CDATA[$P{image5}]]></expression> + </element> + <element kind="image" uuid="34187787-d55d-495a-be82-9ff67702211f" x="199" y="117" width="111" height="113"> + <expression><![CDATA[$P{image4}]]></expression> + </element> + <element kind="image" uuid="7b2d4efb-1f35-4c37-80a1-685195e1218e" x="199" y="3" width="111" height="113"> + <expression><![CDATA[$P{image2}]]></expression> + </element> + </element> + <element kind="frame" uuid="33b6f6ef-93e4-4488-a421-08de09b5458c" x="0" y="0" width="400" height="344"> + <printWhenExpression><![CDATA[$P{numberImage}.intValue() == 4]]></printWhenExpression> + <element kind="image" uuid="1378905c-276f-42ba-9101-18b27ba14e0b" x="28" y="3" width="161" height="165"> + <expression><![CDATA[$P{image1}]]></expression> + </element> + <element kind="image" uuid="58917767-70d5-4822-bb6f-7f5aba6f660e" x="29" y="173" width="161" height="165"> + <expression><![CDATA[$P{image3}]]></expression> + </element> + <element kind="image" uuid="6026efa4-cfd7-4b1d-90be-fe8912eb43c3" x="210" y="3" width="161" height="165"> + <expression><![CDATA[$P{image2}]]></expression> + </element> + <element kind="image" uuid="6c5adc41-f3d7-4e32-997a-e1845d7170c5" x="211" y="173" width="161" height="165"> + <expression><![CDATA[$P{image4}]]></expression> + </element> + </element> + <element kind="frame" uuid="94e66ae9-8863-45e0-9b9d-1a5fb7df84f5" x="0" y="0" width="400" height="344"> + <printWhenExpression><![CDATA[$P{numberImage}.intValue() == 3]]></printWhenExpression> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <property name="com.jaspersoft.studio.unit.x" value="px"/> + <element kind="image" uuid="3ab88449-e282-41cd-898e-ab91aeef70b9" x="28" y="3" width="161" height="165"> + <expression><![CDATA[$P{image1}]]></expression> + </element> + <element kind="image" uuid="119378b1-674d-457a-bc69-a9823f2160b7" x="121" y="173" width="161" height="165"> + <expression><![CDATA[$P{image3}]]></expression> + </element> + <element kind="image" uuid="8ac7bc19-5ae6-4569-87fb-c9cf72936b50" x="210" y="3" width="161" height="165"> + <expression><![CDATA[$P{image2}]]></expression> + </element> + </element> + <element kind="frame" uuid="935efa61-0cd7-47ab-b7d8-6508a1726537" x="0" y="0" width="400" height="344"> + <printWhenExpression><![CDATA[$P{numberImage}.intValue() == 2]]></printWhenExpression> + <element kind="image" uuid="8f2957f9-fb76-49d1-94ce-08c723aec7ce" x="121" y="3" width="161" height="165"> + <expression><![CDATA[$P{image1}]]></expression> + </element> + <element kind="image" uuid="f5585019-40b7-4b1b-9c7a-8b10386cf210" x="121" y="173" width="161" height="165"> + <expression><![CDATA[$P{image2}]]></expression> + </element> + </element> + <element kind="frame" uuid="dfa0c283-dbfc-40de-97e0-d1d04db85c96" x="0" y="0" width="400" height="344"> + <printWhenExpression><![CDATA[$P{numberImage}.intValue() == 1]]></printWhenExpression> + <property name="com.jaspersoft.studio.unit.y" value="px"/> + <element kind="image" uuid="a7cef70f-1dbe-4d6f-a007-7543bbc2b9b8" x="51" y="30" width="300" height="289"> + <expression><![CDATA[$P{image1}]]></expression> + </element> + </element> + </element> + </band> + </detail> +</jasperReport> diff --git a/src/main/java/BsK/common/util/text/TextUtils.java b/src/main/java/BsK/common/util/text/TextUtils.java index 96d15e6..2507f24 100644 --- a/src/main/java/BsK/common/util/text/TextUtils.java +++ b/src/main/java/BsK/common/util/text/TextUtils.java @@ -1,6 +1,8 @@ package BsK.common.util.text; import java.text.Normalizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public final class TextUtils { @@ -28,16 +30,64 @@ public final class TextUtils { return normalizedText; } + /** + * Scales down the font size definitions in an RTF string by half. + * Finds all occurrences of \fsXX and replaces them with \fs(XX/2). + * This is useful when JTextPane generates RTF with large font sizes + * that need to be normalized for printing with JasperReports. + * + * @param rtfContent The input RTF string. + * @return A new RTF string with font sizes scaled down. + */ + public static String scaleRtfFontSize(String rtfContent) { + if (rtfContent == null) { + return null; + } + + // Regex to find \fs followed by one or more digits. + // The double backslash is needed to create a literal backslash in the regex string. + Pattern pattern = Pattern.compile("\\\\fs(\\d+)"); + Matcher matcher = pattern.matcher(rtfContent); + + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + try { + // Get the number string from the first capturing group. + String sizeStr = matcher.group(1); + int originalSize = Integer.parseInt(sizeStr); + + // The font size in RTF is in half-points. JTextPane seems to generate + // sizes that are double what is visually represented. Dividing by 2 + // brings it to the expected point size for JasperReports. + int newSize = originalSize / 2; + + // Append the replacement string. We need to escape the backslash for appendReplacement. + matcher.appendReplacement(sb, "\\\\fs" + newSize); + } catch (NumberFormatException e) { + // This should not happen with the given regex, but it's safe to handle. + // In case of an error, just append the original matched string. + matcher.appendReplacement(sb, matcher.group(0)); + } + } + matcher.appendTail(sb); + + return sb.toString(); + } + public static void main(String[] args) { String[] testWords = { "Đạt", "đạt", "Ân", "Ấn", "Lê", "Hồ", "Trần", "Hoàng", "Quốc", "Phạm", "Dũng", "Bạch", "Hạnh", "Cường", "Vỹ" }; - - for (String word : testWords) { System.out.println("Original: " + word + " → Without Accents: " + TextUtils.removeAccents(word)); } + + // Test the new RTF scaling function + System.out.println("\n--- Testing RTF Font Scaling ---"); + String rtfTestString = "{\\rtf1\\ansi{\\fonttbl{\\f0\\fnil Monospaced;}}{\\colortbl;\\red0\\green0\\blue0;}\\pard\\sa200\\sl276\\slmult1\\cf1\\b\\f0\\fs48 Hello World\\fs24 now small\\par}"; + System.out.println("Original RTF: " + rtfTestString); + System.out.println("Scaled RTF: " + scaleRtfFontSize(rtfTestString)); } }