Commit b414d4c54d956c0a7cdc33af339fd708bc94e640

Authored by 房远帅
1 parent 99c0b4c3

合同:打印模板调整

... ... @@ -1253,13 +1253,41 @@ public class ContractDistributorStandardController extends DefaultBaseController
1253 1253 }
1254 1254 }
1255 1255
  1256 + int contractSpecFontSize = Integer.MAX_VALUE;
  1257 + for (SpecImageCell specCell : specImageCells) {
  1258 + int currentFontSize = LatexFormulaExcelExporterUtil.calculateContractReferenceFontSize(
  1259 + workbook,
  1260 + sheet,
  1261 + specCell.rowIndex,
  1262 + specCell.colIndex
  1263 + );
  1264 + contractSpecFontSize = Math.min(contractSpecFontSize, currentFontSize);
  1265 + }
  1266 + if (contractSpecFontSize == Integer.MAX_VALUE) {
  1267 + contractSpecFontSize = 16;
  1268 + }
  1269 +
  1270 + double contractSpecScale = 1.0;
  1271 + for (SpecImageCell specCell : specImageCells) {
  1272 + double currentScale = LatexFormulaExcelExporterUtil.calculateContractReferenceFitScale(
  1273 + workbook,
  1274 + sheet,
  1275 + specCell.rowIndex,
  1276 + specCell.colIndex,
  1277 + contractSpecFontSize
  1278 + );
  1279 + contractSpecScale = Math.min(contractSpecScale, currentScale);
  1280 + }
  1281 +
1256 1282 for (SpecImageCell specCell : specImageCells) {
1257 1283 LatexFormulaExcelExporterUtil.insertContractLatexImageToCellFillTemplate(
1258 1284 workbook,
1259 1285 sheet,
1260 1286 specCell.latex,
1261 1287 specCell.rowIndex,
1262   - specCell.colIndex
  1288 + specCell.colIndex,
  1289 + contractSpecFontSize,
  1290 + contractSpecScale
1263 1291 );
1264 1292 }
1265 1293
... ...
... ... @@ -24,6 +24,9 @@ import java.util.List;
24 24 @Slf4j
25 25 public class LatexFormulaExcelExporterUtil {
26 26
  27 + private static final String CONTRACT_SPEC_REFERENCE_LATEX =
  28 + "\\mathbf{\\mathrm{22^{+0.2}_{+0.1}\\!\\times\\!22^{+0.2}_{+0.1}\\!\\times\\!22^{+0.2}_{+0.1}}}";
  29 +
27 30 public static String convertToLatex(List<FormulaComponent> componentList) {
28 31 if (CollectionUtils.isEmpty(componentList)) {
29 32 return "";
... ... @@ -97,11 +100,12 @@ public class LatexFormulaExcelExporterUtil {
97 100 return "";
98 101 }
99 102
  103 + String referenceComponentLatex = resolveReferenceComponentLatex(componentList);
100 104 int missing = Math.max(0, 3 - nonNullCount);
101 105 if (missing > 0) {
102 106 StringBuilder phantom = new StringBuilder();
103 107 for (int i = 0; i < missing; i++) {
104   - phantom.append(" \\times 000^{+00}_{+00}");
  108 + phantom.append(" \\times ").append(referenceComponentLatex);
105 109 }
106 110 actual = actual + "\\phantom{" + phantom + "}";
107 111 }
... ... @@ -129,11 +133,12 @@ public class LatexFormulaExcelExporterUtil {
129 133 return "";
130 134 }
131 135
  136 + String referenceComponentLatex = resolveReferenceComponentLatex(componentList);
132 137 int missing = Math.max(0, 3 - nonNullCount);
133 138 if (missing > 0) {
134 139 StringBuilder phantom = new StringBuilder();
135 140 for (int i = 0; i < missing; i++) {
136   - phantom.append("\\!\\times\\!000^{+00}_{+00}");
  141 + phantom.append("\\!\\times\\!").append(referenceComponentLatex);
137 142 }
138 143 actual = actual + "\\phantom{" + phantom + "}";
139 144 }
... ... @@ -158,21 +163,45 @@ public class LatexFormulaExcelExporterUtil {
158 163 latex.append(separator);
159 164 }
160 165 first = false;
  166 + latex.append(buildLatexComponent(comp));
  167 + }
  168 + return latex.toString();
  169 + }
161 170
162   - latex.append(formatScientificNotation(comp.getBase()));
163   - if (comp.getSup() != null && comp.getSup().compareTo(BigDecimal.ZERO) >= 0) {
164   - latex.append("^{+").append(formatScientificNotation(comp.getSup())).append("}");
  171 + private static String resolveReferenceComponentLatex(List<FormulaComponent> componentList) {
  172 + String reference = "000^{+00}_{+00}";
  173 + int maxLength = reference.length();
  174 + for (FormulaComponent comp : componentList) {
  175 + if (comp == null || comp.getBase() == null) {
  176 + continue;
165 177 }
166   - if (comp.getSup() != null && comp.getSup().compareTo(BigDecimal.ZERO) < 0) {
167   - latex.append("^{").append(formatScientificNotation(comp.getSup())).append("}");
  178 + String candidate = buildLatexComponent(comp);
  179 + if (candidate.length() > maxLength) {
  180 + reference = candidate;
  181 + maxLength = candidate.length();
168 182 }
  183 + }
  184 + return reference;
  185 + }
169 186
170   - if (comp.getSub() != null && comp.getSub().compareTo(BigDecimal.ZERO) >= 0) {
171   - latex.append("_{+").append(formatScientificNotation(comp.getSub())).append("}");
172   - }
173   - if (comp.getSub() != null && comp.getSub().compareTo(BigDecimal.ZERO) < 0) {
174   - latex.append("_{").append(formatScientificNotation(comp.getSub())).append("}");
175   - }
  187 + private static String buildLatexComponent(FormulaComponent comp) {
  188 + if (comp == null || comp.getBase() == null) {
  189 + return "";
  190 + }
  191 + StringBuilder latex = new StringBuilder();
  192 + latex.append(formatScientificNotation(comp.getBase()));
  193 + if (comp.getSup() != null && comp.getSup().compareTo(BigDecimal.ZERO) >= 0) {
  194 + latex.append("^{+").append(formatScientificNotation(comp.getSup())).append("}");
  195 + }
  196 + if (comp.getSup() != null && comp.getSup().compareTo(BigDecimal.ZERO) < 0) {
  197 + latex.append("^{").append(formatScientificNotation(comp.getSup())).append("}");
  198 + }
  199 +
  200 + if (comp.getSub() != null && comp.getSub().compareTo(BigDecimal.ZERO) >= 0) {
  201 + latex.append("_{+").append(formatScientificNotation(comp.getSub())).append("}");
  202 + }
  203 + if (comp.getSub() != null && comp.getSub().compareTo(BigDecimal.ZERO) < 0) {
  204 + latex.append("_{").append(formatScientificNotation(comp.getSub())).append("}");
176 205 }
177 206 return latex.toString();
178 207 }
... ... @@ -295,6 +324,17 @@ public class LatexFormulaExcelExporterUtil {
295 324 public static void insertContractLatexImageToCellFillTemplate(Workbook workbook, Sheet sheet, String latex,
296 325 int rowIndex, int colIndex) throws IOException {
297 326 int baseFontSize = Math.max(16, resolveCellFontSize(workbook, sheet, rowIndex, colIndex));
  327 + insertContractLatexImageToCellFillTemplate(workbook, sheet, latex, rowIndex, colIndex, baseFontSize);
  328 + }
  329 +
  330 + public static void insertContractLatexImageToCellFillTemplate(Workbook workbook, Sheet sheet, String latex,
  331 + int rowIndex, int colIndex, int baseFontSize) throws IOException {
  332 + insertContractLatexImageToCellFillTemplate(workbook, sheet, latex, rowIndex, colIndex, baseFontSize, null);
  333 + }
  334 +
  335 + public static void insertContractLatexImageToCellFillTemplate(Workbook workbook, Sheet sheet, String latex,
  336 + int rowIndex, int colIndex, int baseFontSize,
  337 + Double maxScale) throws IOException {
298 338 CellRangeAddress mergedRegion = findMergedRegion(sheet, rowIndex, colIndex);
299 339 if (mergedRegion != null) {
300 340 insertContractLatexImageToRegionFillTemplate(
... ... @@ -305,11 +345,57 @@ public class LatexFormulaExcelExporterUtil {
305 345 mergedRegion.getFirstColumn(),
306 346 mergedRegion.getLastRow() - mergedRegion.getFirstRow() + 1,
307 347 mergedRegion.getLastColumn() - mergedRegion.getFirstColumn() + 1,
308   - baseFontSize
  348 + baseFontSize,
  349 + maxScale
309 350 );
310 351 return;
311 352 }
312   - insertContractLatexImageToRegionFillTemplate(workbook, sheet, latex, rowIndex, colIndex, 1, 1, baseFontSize);
  353 + insertContractLatexImageToRegionFillTemplate(workbook, sheet, latex, rowIndex, colIndex, 1, 1, baseFontSize, maxScale);
  354 + }
  355 +
  356 + public static int calculateContractBestFontSize(Workbook workbook, Sheet sheet, String latex,
  357 + int rowIndex, int colIndex) throws IOException {
  358 + int baseFontSize = Math.max(16, resolveCellFontSize(workbook, sheet, rowIndex, colIndex));
  359 + CellRangeAddress mergedRegion = findMergedRegion(sheet, rowIndex, colIndex);
  360 + if (mergedRegion != null) {
  361 + return calculateContractBestFontSizeForRegion(
  362 + sheet,
  363 + latex,
  364 + mergedRegion.getFirstRow(),
  365 + mergedRegion.getFirstColumn(),
  366 + mergedRegion.getLastRow() - mergedRegion.getFirstRow() + 1,
  367 + mergedRegion.getLastColumn() - mergedRegion.getFirstColumn() + 1,
  368 + baseFontSize
  369 + );
  370 + }
  371 + return calculateContractBestFontSizeForRegion(sheet, latex, rowIndex, colIndex, 1, 1, baseFontSize);
  372 + }
  373 +
  374 + public static int calculateContractReferenceFontSize(Workbook workbook, Sheet sheet,
  375 + int rowIndex, int colIndex) throws IOException {
  376 + return calculateContractBestFontSize(workbook, sheet, CONTRACT_SPEC_REFERENCE_LATEX, rowIndex, colIndex);
  377 + }
  378 +
  379 + public static double calculateContractFitScale(Workbook workbook, Sheet sheet, String latex,
  380 + int rowIndex, int colIndex, int fontSize) throws IOException {
  381 + CellRangeAddress mergedRegion = findMergedRegion(sheet, rowIndex, colIndex);
  382 + if (mergedRegion != null) {
  383 + return calculateContractFitScaleForRegion(
  384 + sheet,
  385 + latex,
  386 + mergedRegion.getFirstRow(),
  387 + mergedRegion.getFirstColumn(),
  388 + mergedRegion.getLastRow() - mergedRegion.getFirstRow() + 1,
  389 + mergedRegion.getLastColumn() - mergedRegion.getFirstColumn() + 1,
  390 + fontSize
  391 + );
  392 + }
  393 + return calculateContractFitScaleForRegion(sheet, latex, rowIndex, colIndex, 1, 1, fontSize);
  394 + }
  395 +
  396 + public static double calculateContractReferenceFitScale(Workbook workbook, Sheet sheet,
  397 + int rowIndex, int colIndex, int fontSize) throws IOException {
  398 + return calculateContractFitScale(workbook, sheet, CONTRACT_SPEC_REFERENCE_LATEX, rowIndex, colIndex, fontSize);
313 399 }
314 400
315 401 private static final int EMU_PER_PX = 9525;
... ... @@ -478,7 +564,7 @@ public class LatexFormulaExcelExporterUtil {
478 564
479 565 private static void insertContractLatexImageToRegionFillTemplate(Workbook workbook, Sheet sheet, String latex,
480 566 int rowIndex, int colIndex, int rowRange, int colRange,
481   - int baseFontSize) throws IOException {
  567 + int baseFontSize, Double maxScale) throws IOException {
482 568 int regionWidthPx = 0;
483 569 for (int c = colIndex; c < colIndex + colRange; c++) {
484 570 regionWidthPx += getColumnWidthPx(sheet, c);
... ... @@ -488,26 +574,29 @@ public class LatexFormulaExcelExporterUtil {
488 574 regionHeightPx += getRowHeightPx(sheet, r);
489 575 }
490 576
491   - int paddingXPx = 4;
492   - int paddingYPx = 2;
  577 + int paddingXPx = 6;
  578 + int paddingYPx = 4;
493 579 int availableWidthPx = Math.max(1, regionWidthPx - paddingXPx * 2);
494 580 int availableHeightPx = Math.max(1, regionHeightPx - paddingYPx * 2);
495   - RenderedLatexImage renderedImage = renderBestFitLatexImageByHeight(
496   - latex,
497   - baseFontSize,
498   - availableHeightPx
499   - );
  581 + RenderedLatexImage renderedImage = renderLatexImage(latex, baseFontSize);
500 582 if (renderedImage.image == null) {
501 583 return;
502 584 }
503 585
504 586 byte[] imageBytes = renderedImage.imageBytes;
505 587 BufferedImage image = renderedImage.image;
506   - int scaledHeightPx = availableHeightPx;
507   - int widthByHeightPx = Math.max(1, (int) Math.round(
508   - (double) image.getWidth() * scaledHeightPx / Math.max(1, image.getHeight())
509   - ));
510   - int scaledWidthPx = Math.min(availableWidthPx, widthByHeightPx);
  588 + double scale = Math.min(
  589 + 1.0,
  590 + Math.min(
  591 + (double) availableWidthPx / Math.max(1, image.getWidth()),
  592 + (double) availableHeightPx / Math.max(1, image.getHeight())
  593 + )
  594 + );
  595 + if (maxScale != null) {
  596 + scale = Math.min(scale, maxScale);
  597 + }
  598 + int scaledWidthPx = Math.max(1, (int) Math.round(image.getWidth() * scale));
  599 + int scaledHeightPx = Math.max(1, (int) Math.round(image.getHeight() * scale));
511 600
512 601 int offsetXPx = Math.max(paddingXPx, (regionWidthPx - scaledWidthPx) / 2);
513 602 int offsetYPx = Math.max(paddingYPx, (regionHeightPx - scaledHeightPx) / 2);
... ... @@ -566,6 +655,55 @@ public class LatexFormulaExcelExporterUtil {
566 655 drawing.createPicture(anchor, pictureIdx);
567 656 }
568 657
  658 + private static int calculateContractBestFontSizeForRegion(Sheet sheet, String latex,
  659 + int rowIndex, int colIndex, int rowRange, int colRange,
  660 + int preferredFontSize) throws IOException {
  661 + int regionWidthPx = 0;
  662 + for (int c = colIndex; c < colIndex + colRange; c++) {
  663 + regionWidthPx += getColumnWidthPx(sheet, c);
  664 + }
  665 + int regionHeightPx = 0;
  666 + for (int r = rowIndex; r < rowIndex + rowRange; r++) {
  667 + regionHeightPx += getRowHeightPx(sheet, r);
  668 + }
  669 +
  670 + int paddingXPx = 3;
  671 + int paddingYPx = 1;
  672 + int availableWidthPx = Math.max(1, regionWidthPx - paddingXPx * 2);
  673 + int availableHeightPx = Math.max(1, regionHeightPx - paddingYPx * 2);
  674 + return renderBestFitLatexFontSize(latex, preferredFontSize, availableWidthPx, availableHeightPx);
  675 + }
  676 +
  677 + private static double calculateContractFitScaleForRegion(Sheet sheet, String latex,
  678 + int rowIndex, int colIndex, int rowRange, int colRange,
  679 + int fontSize) throws IOException {
  680 + int regionWidthPx = 0;
  681 + for (int c = colIndex; c < colIndex + colRange; c++) {
  682 + regionWidthPx += getColumnWidthPx(sheet, c);
  683 + }
  684 + int regionHeightPx = 0;
  685 + for (int r = rowIndex; r < rowIndex + rowRange; r++) {
  686 + regionHeightPx += getRowHeightPx(sheet, r);
  687 + }
  688 +
  689 + int paddingXPx = 6;
  690 + int paddingYPx = 4;
  691 + int availableWidthPx = Math.max(1, regionWidthPx - paddingXPx * 2);
  692 + int availableHeightPx = Math.max(1, regionHeightPx - paddingYPx * 2);
  693 + RenderedLatexImage renderedImage = renderLatexImage(latex, fontSize);
  694 + if (renderedImage.image == null) {
  695 + return 1.0;
  696 + }
  697 +
  698 + return Math.min(
  699 + 1.0,
  700 + Math.min(
  701 + (double) availableWidthPx / Math.max(1, renderedImage.image.getWidth()),
  702 + (double) availableHeightPx / Math.max(1, renderedImage.image.getHeight())
  703 + )
  704 + );
  705 + }
  706 +
569 707 private static int getColumnWidthPx(Sheet sheet, int colIndex) {
570 708 int widthUnits = sheet.getColumnWidth(colIndex);
571 709 return Math.max(1, (int) Math.round(widthUnits / 256.0 * 7.0 + 5));
... ... @@ -577,26 +715,26 @@ public class LatexFormulaExcelExporterUtil {
577 715 return Math.max(1, (int) Math.round(points * 96.0 / 72.0));
578 716 }
579 717
580   - private static RenderedLatexImage renderBestFitLatexImageByHeight(String latex, int preferredFontSize,
581   - int targetHeightPx) throws IOException {
  718 + private static int renderBestFitLatexFontSize(String latex, int preferredFontSize,
  719 + int targetWidthPx, int targetHeightPx) throws IOException {
582 720 int minFontSize = 8;
583 721 int maxFontSize = Math.max(minFontSize, preferredFontSize + 40);
584 722 maxFontSize = Math.min(96, maxFontSize);
585 723 int left = minFontSize;
586 724 int right = maxFontSize;
587   - RenderedLatexImage best = renderLatexImage(latex, minFontSize);
  725 + int bestFontSize = minFontSize;
588 726
589 727 while (left <= right) {
590 728 int mid = (left + right) >>> 1;
591 729 RenderedLatexImage candidate = renderLatexImage(latex, mid);
592   - if (candidate.image != null && candidate.image.getHeight() <= targetHeightPx) {
593   - best = candidate;
  730 + if (fitsWithin(candidate, targetWidthPx, targetHeightPx)) {
  731 + bestFontSize = mid;
594 732 left = mid + 1;
595 733 } else {
596 734 right = mid - 1;
597 735 }
598 736 }
599   - return best;
  737 + return bestFontSize;
600 738 }
601 739
602 740 private static RenderedLatexImage renderLatexImage(String latex, int fontSize) throws IOException {
... ... @@ -659,6 +797,13 @@ public class LatexFormulaExcelExporterUtil {
659 797 }
660 798 }
661 799
  800 + private static boolean fitsWithin(RenderedLatexImage renderedImage, int targetWidthPx, int targetHeightPx) {
  801 + return renderedImage != null
  802 + && renderedImage.image != null
  803 + && renderedImage.image.getWidth() <= targetWidthPx
  804 + && renderedImage.image.getHeight() <= targetHeightPx;
  805 + }
  806 +
662 807 private static BufferedImage trimWhitespace(BufferedImage source, int whiteThreshold, int marginPx) {
663 808 if (source == null || source.getWidth() <= 0 || source.getHeight() <= 0) {
664 809 return source;
... ...