@cj-tech-master/excelts 9.1.0 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +16 -1
  2. package/dist/browser/modules/archive/compression/crc32.js +1 -1
  3. package/dist/browser/modules/archive/crypto/aes.d.ts +0 -8
  4. package/dist/browser/modules/archive/crypto/aes.js +1 -20
  5. package/dist/browser/modules/archive/crypto/index.d.ts +2 -1
  6. package/dist/browser/modules/archive/crypto/index.js +3 -1
  7. package/dist/browser/modules/csv/parse/row-processor.d.ts +1 -1
  8. package/dist/browser/modules/csv/worker/worker-script.generated.js +1 -1
  9. package/dist/browser/modules/excel/utils/cell-matrix.js +1 -0
  10. package/dist/browser/modules/excel/utils/encryptor.browser.d.ts +4 -5
  11. package/dist/browser/modules/excel/utils/encryptor.browser.js +7 -12
  12. package/dist/browser/modules/excel/utils/encryptor.d.ts +1 -1
  13. package/dist/browser/modules/excel/utils/encryptor.js +4 -7
  14. package/dist/browser/modules/pdf/builder/document-builder.d.ts +517 -0
  15. package/dist/browser/modules/pdf/builder/document-builder.js +1493 -0
  16. package/dist/browser/modules/pdf/builder/form-appearance.d.ts +56 -0
  17. package/dist/browser/modules/pdf/builder/form-appearance.js +140 -0
  18. package/dist/browser/modules/pdf/builder/image-utils.d.ts +39 -0
  19. package/dist/browser/modules/pdf/builder/image-utils.js +129 -0
  20. package/dist/browser/modules/pdf/builder/pdf-editor.d.ts +230 -0
  21. package/dist/browser/modules/pdf/builder/pdf-editor.js +1574 -0
  22. package/dist/browser/modules/pdf/builder/resource-merger.d.ts +41 -0
  23. package/dist/browser/modules/pdf/builder/resource-merger.js +258 -0
  24. package/dist/browser/modules/pdf/core/digital-signature.d.ts +109 -0
  25. package/dist/browser/modules/pdf/core/digital-signature.js +659 -0
  26. package/dist/browser/modules/pdf/core/encryption.js +8 -7
  27. package/dist/browser/modules/pdf/core/pdf-object.d.ts +11 -0
  28. package/dist/browser/modules/pdf/core/pdf-object.js +38 -0
  29. package/dist/browser/modules/pdf/core/pdf-stream.d.ts +32 -0
  30. package/dist/browser/modules/pdf/core/pdf-stream.js +66 -0
  31. package/dist/browser/modules/pdf/core/pdf-writer.d.ts +55 -1
  32. package/dist/browser/modules/pdf/core/pdf-writer.js +271 -6
  33. package/dist/browser/modules/pdf/core/pdfa.d.ts +62 -0
  34. package/dist/browser/modules/pdf/core/pdfa.js +261 -0
  35. package/dist/browser/modules/pdf/index.d.ts +11 -0
  36. package/dist/browser/modules/pdf/index.js +9 -0
  37. package/dist/browser/modules/pdf/reader/bookmark-extractor.d.ts +35 -0
  38. package/dist/browser/modules/pdf/reader/bookmark-extractor.js +324 -0
  39. package/dist/browser/modules/pdf/reader/pdf-decrypt.js +6 -5
  40. package/dist/browser/modules/pdf/reader/pdf-reader.d.ts +17 -0
  41. package/dist/browser/modules/pdf/reader/pdf-reader.js +26 -2
  42. package/dist/browser/modules/pdf/reader/table-extractor.d.ts +69 -0
  43. package/dist/browser/modules/pdf/reader/table-extractor.js +365 -0
  44. package/dist/browser/modules/pdf/render/layout-engine.d.ts +21 -1
  45. package/dist/browser/modules/pdf/render/layout-engine.js +112 -5
  46. package/dist/browser/modules/pdf/render/page-renderer.d.ts +2 -9
  47. package/dist/browser/modules/pdf/render/page-renderer.js +62 -103
  48. package/dist/browser/modules/pdf/render/pdf-exporter.js +2 -61
  49. package/dist/browser/modules/pdf/render/style-converter.d.ts +4 -0
  50. package/dist/browser/modules/pdf/render/style-converter.js +1 -1
  51. package/dist/browser/modules/pdf/types.d.ts +14 -1
  52. package/dist/browser/modules/stream/browser/readable.js +8 -2
  53. package/dist/browser/utils/crypto.browser.d.ts +64 -0
  54. package/dist/browser/{modules/pdf/core/crypto.js → utils/crypto.browser.js} +91 -101
  55. package/dist/browser/utils/crypto.d.ts +97 -0
  56. package/dist/browser/utils/crypto.js +209 -0
  57. package/dist/cjs/modules/archive/compression/crc32.js +1 -1
  58. package/dist/cjs/modules/archive/crypto/aes.js +2 -23
  59. package/dist/cjs/modules/archive/crypto/index.js +3 -1
  60. package/dist/cjs/modules/csv/worker/worker-script.generated.js +1 -1
  61. package/dist/cjs/modules/excel/utils/cell-matrix.js +1 -0
  62. package/dist/cjs/modules/excel/utils/encryptor.browser.js +7 -12
  63. package/dist/cjs/modules/excel/utils/encryptor.js +4 -10
  64. package/dist/cjs/modules/pdf/builder/document-builder.js +1532 -0
  65. package/dist/cjs/modules/pdf/builder/form-appearance.js +145 -0
  66. package/dist/cjs/modules/pdf/builder/image-utils.js +135 -0
  67. package/dist/cjs/modules/pdf/builder/pdf-editor.js +1612 -0
  68. package/dist/cjs/modules/pdf/builder/resource-merger.js +263 -0
  69. package/dist/cjs/modules/pdf/core/digital-signature.js +667 -0
  70. package/dist/cjs/modules/pdf/core/encryption.js +8 -7
  71. package/dist/cjs/modules/pdf/core/pdf-object.js +38 -0
  72. package/dist/cjs/modules/pdf/core/pdf-stream.js +66 -0
  73. package/dist/cjs/modules/pdf/core/pdf-writer.js +272 -6
  74. package/dist/cjs/modules/pdf/core/pdfa.js +266 -0
  75. package/dist/cjs/modules/pdf/index.js +19 -1
  76. package/dist/cjs/modules/pdf/reader/bookmark-extractor.js +327 -0
  77. package/dist/cjs/modules/pdf/reader/pdf-decrypt.js +6 -5
  78. package/dist/cjs/modules/pdf/reader/pdf-reader.js +26 -2
  79. package/dist/cjs/modules/pdf/reader/table-extractor.js +368 -0
  80. package/dist/cjs/modules/pdf/render/layout-engine.js +113 -4
  81. package/dist/cjs/modules/pdf/render/page-renderer.js +63 -105
  82. package/dist/cjs/modules/pdf/render/pdf-exporter.js +3 -62
  83. package/dist/cjs/modules/pdf/render/style-converter.js +1 -0
  84. package/dist/cjs/modules/stream/browser/readable.js +8 -2
  85. package/dist/cjs/{modules/pdf/core/crypto.js → utils/crypto.browser.js} +95 -102
  86. package/dist/cjs/utils/crypto.js +228 -0
  87. package/dist/esm/modules/archive/compression/crc32.js +1 -1
  88. package/dist/esm/modules/archive/crypto/aes.js +1 -20
  89. package/dist/esm/modules/archive/crypto/index.js +3 -1
  90. package/dist/esm/modules/csv/worker/worker-script.generated.js +1 -1
  91. package/dist/esm/modules/excel/utils/cell-matrix.js +1 -0
  92. package/dist/esm/modules/excel/utils/encryptor.browser.js +7 -12
  93. package/dist/esm/modules/excel/utils/encryptor.js +4 -7
  94. package/dist/esm/modules/pdf/builder/document-builder.js +1493 -0
  95. package/dist/esm/modules/pdf/builder/form-appearance.js +140 -0
  96. package/dist/esm/modules/pdf/builder/image-utils.js +129 -0
  97. package/dist/esm/modules/pdf/builder/pdf-editor.js +1574 -0
  98. package/dist/esm/modules/pdf/builder/resource-merger.js +258 -0
  99. package/dist/esm/modules/pdf/core/digital-signature.js +659 -0
  100. package/dist/esm/modules/pdf/core/encryption.js +8 -7
  101. package/dist/esm/modules/pdf/core/pdf-object.js +38 -0
  102. package/dist/esm/modules/pdf/core/pdf-stream.js +66 -0
  103. package/dist/esm/modules/pdf/core/pdf-writer.js +271 -6
  104. package/dist/esm/modules/pdf/core/pdfa.js +261 -0
  105. package/dist/esm/modules/pdf/index.js +9 -0
  106. package/dist/esm/modules/pdf/reader/bookmark-extractor.js +324 -0
  107. package/dist/esm/modules/pdf/reader/pdf-decrypt.js +6 -5
  108. package/dist/esm/modules/pdf/reader/pdf-reader.js +26 -2
  109. package/dist/esm/modules/pdf/reader/table-extractor.js +365 -0
  110. package/dist/esm/modules/pdf/render/layout-engine.js +112 -5
  111. package/dist/esm/modules/pdf/render/page-renderer.js +62 -103
  112. package/dist/esm/modules/pdf/render/pdf-exporter.js +2 -61
  113. package/dist/esm/modules/pdf/render/style-converter.js +1 -1
  114. package/dist/esm/modules/stream/browser/readable.js +8 -2
  115. package/dist/esm/{modules/pdf/core/crypto.js → utils/crypto.browser.js} +91 -101
  116. package/dist/esm/utils/crypto.js +209 -0
  117. package/dist/iife/excelts.iife.js +1248 -1074
  118. package/dist/iife/excelts.iife.js.map +1 -1
  119. package/dist/iife/excelts.iife.min.js +53 -54
  120. package/dist/types/modules/archive/crypto/aes.d.ts +0 -8
  121. package/dist/types/modules/archive/crypto/index.d.ts +2 -1
  122. package/dist/types/modules/csv/parse/row-processor.d.ts +1 -1
  123. package/dist/types/modules/excel/utils/encryptor.browser.d.ts +4 -5
  124. package/dist/types/modules/excel/utils/encryptor.d.ts +1 -1
  125. package/dist/types/modules/pdf/builder/document-builder.d.ts +517 -0
  126. package/dist/types/modules/pdf/builder/form-appearance.d.ts +56 -0
  127. package/dist/types/modules/pdf/builder/image-utils.d.ts +39 -0
  128. package/dist/types/modules/pdf/builder/pdf-editor.d.ts +230 -0
  129. package/dist/types/modules/pdf/builder/resource-merger.d.ts +41 -0
  130. package/dist/types/modules/pdf/core/digital-signature.d.ts +109 -0
  131. package/dist/types/modules/pdf/core/pdf-object.d.ts +11 -0
  132. package/dist/types/modules/pdf/core/pdf-stream.d.ts +32 -0
  133. package/dist/types/modules/pdf/core/pdf-writer.d.ts +55 -1
  134. package/dist/types/modules/pdf/core/pdfa.d.ts +62 -0
  135. package/dist/types/modules/pdf/index.d.ts +11 -0
  136. package/dist/types/modules/pdf/reader/bookmark-extractor.d.ts +35 -0
  137. package/dist/types/modules/pdf/reader/pdf-reader.d.ts +17 -0
  138. package/dist/types/modules/pdf/reader/table-extractor.d.ts +69 -0
  139. package/dist/types/modules/pdf/render/layout-engine.d.ts +21 -1
  140. package/dist/types/modules/pdf/render/page-renderer.d.ts +2 -9
  141. package/dist/types/modules/pdf/render/style-converter.d.ts +4 -0
  142. package/dist/types/modules/pdf/types.d.ts +14 -1
  143. package/dist/types/utils/crypto.browser.d.ts +64 -0
  144. package/dist/types/utils/crypto.d.ts +97 -0
  145. package/package.json +110 -111
  146. package/dist/browser/modules/pdf/core/crypto.d.ts +0 -65
  147. package/dist/types/modules/pdf/core/crypto.d.ts +0 -65
@@ -17,10 +17,18 @@ exports.computeTextStartY = computeTextStartY;
17
17
  exports.computeTextX = computeTextX;
18
18
  exports.wrapTextLines = wrapTextLines;
19
19
  exports.renderWatermark = renderWatermark;
20
- exports.parseImageDimensions = parseImageDimensions;
21
20
  const pdf_stream_1 = require("../core/pdf-stream");
22
21
  const font_manager_1 = require("../font/font-manager");
23
22
  const constants_1 = require("./constants");
23
+ const image_utils_1 = require("../builder/image-utils");
24
+ function computeCellPadding(cell, scaleFactor = 1) {
25
+ return {
26
+ left: (constants_1.CELL_PADDING_H + cell.borderInsets.left) * scaleFactor,
27
+ right: (constants_1.CELL_PADDING_H + cell.borderInsets.right) * scaleFactor,
28
+ top: (constants_1.CELL_PADDING_V + cell.borderInsets.top) * scaleFactor,
29
+ bottom: (constants_1.CELL_PADDING_V + cell.borderInsets.bottom) * scaleFactor
30
+ };
31
+ }
24
32
  /**
25
33
  * Render a single page to a PDF content stream.
26
34
  */
@@ -196,10 +204,9 @@ function drawCellText(stream, cell, fontManager, alphaValues, scaleFactor = 1) {
196
204
  if (!text && !cell.richText) {
197
205
  return;
198
206
  }
199
- const padH = constants_1.CELL_PADDING_H * scaleFactor;
200
- const padV = constants_1.CELL_PADDING_V * scaleFactor;
201
- const availWidth = rect.width - padH * 2;
202
- const availHeight = rect.height - padV * 2;
207
+ const pad = computeCellPadding(cell, scaleFactor);
208
+ const availWidth = rect.width - pad.left - pad.right;
209
+ const availHeight = rect.height - pad.top - pad.bottom;
203
210
  if (availWidth <= 0 || availHeight <= 0) {
204
211
  return;
205
212
  }
@@ -257,7 +264,7 @@ function drawCellText(stream, cell, fontManager, alphaValues, scaleFactor = 1) {
257
264
  const lineHeight = fontSize * constants_1.LINE_HEIGHT_FACTOR;
258
265
  const ascent = fontManager.getFontAscent(resourceName, fontSize);
259
266
  const totalTextHeight = lines.length * lineHeight;
260
- const textStartY = computeTextStartY(verticalAlign, rect, totalTextHeight, ascent, padV);
267
+ const textStartY = computeTextStartY(verticalAlign, rect, totalTextHeight, ascent, pad.top, pad.bottom);
261
268
  stream.setFillColor(cell.textColor);
262
269
  stream.beginText();
263
270
  stream.setFont(resourceName, fontSize);
@@ -265,7 +272,7 @@ function drawCellText(stream, cell, fontManager, alphaValues, scaleFactor = 1) {
265
272
  const line = lines[i];
266
273
  const lineY = textStartY - i * lineHeight;
267
274
  const textWidth = measure(line);
268
- const textX = computeTextX(horizontalAlign, rect, textWidth, indentPts, padH);
275
+ const textX = computeTextX(horizontalAlign, rect, textWidth, indentPts, pad.left, pad.right);
269
276
  stream.setTextMatrix(1, 0, 0, 1, textX, lineY);
270
277
  const hexEncoded = fontManager.encodeText(line, resourceName);
271
278
  if (hexEncoded) {
@@ -276,7 +283,7 @@ function drawCellText(stream, cell, fontManager, alphaValues, scaleFactor = 1) {
276
283
  }
277
284
  }
278
285
  stream.endText();
279
- drawTextDecorations(stream, cell, lines, lineHeight, textStartY, measure, resourceName, fontManager, indentPts);
286
+ drawTextDecorations(stream, cell, lines, lineHeight, textStartY, measure, resourceName, fontManager, indentPts, pad);
280
287
  stream.restore();
281
288
  }
282
289
  // =============================================================================
@@ -285,8 +292,7 @@ function drawCellText(stream, cell, fontManager, alphaValues, scaleFactor = 1) {
285
292
  function drawRichText(stream, cell, fontManager, indentPts, scaleFactor = 1) {
286
293
  const { rect, horizontalAlign, verticalAlign, wrapText } = cell;
287
294
  const runs = cell.richText;
288
- const padH = constants_1.CELL_PADDING_H * scaleFactor;
289
- const padV = constants_1.CELL_PADDING_V * scaleFactor;
295
+ const pad = computeCellPadding(cell, scaleFactor);
290
296
  // Use the largest font size across all runs for line height calculation
291
297
  let maxFontSize = cell.fontSize;
292
298
  for (const run of runs) {
@@ -303,7 +309,7 @@ function drawRichText(stream, cell, fontManager, indentPts, scaleFactor = 1) {
303
309
  : fontManager.ensureFont((0, font_manager_1.resolvePdfFontName)(run.fontFamily, run.bold, run.italic));
304
310
  // --- Wrapping path ---
305
311
  if (wrapText) {
306
- const availWidth = rect.width - padH * 2 - indentPts;
312
+ const availWidth = rect.width - pad.left - pad.right - indentPts;
307
313
  if (availWidth <= 0) {
308
314
  return;
309
315
  }
@@ -322,7 +328,7 @@ function drawRichText(stream, cell, fontManager, indentPts, scaleFactor = 1) {
322
328
  const primaryResourceName = runResource(runs[0]);
323
329
  const ascent = fontManager.getFontAscent(primaryResourceName, primaryFontSize);
324
330
  const totalTextHeight = lines.length * lineHeight;
325
- const textStartY = computeTextStartY(verticalAlign, rect, totalTextHeight, ascent, padV);
331
+ const textStartY = computeTextStartY(verticalAlign, rect, totalTextHeight, ascent, pad.top, pad.bottom);
326
332
  let charPos = 0;
327
333
  for (let li = 0; li < lines.length; li++) {
328
334
  const lineY = textStartY - li * lineHeight;
@@ -360,7 +366,7 @@ function drawRichText(stream, cell, fontManager, indentPts, scaleFactor = 1) {
360
366
  for (const seg of segments) {
361
367
  lineWidth += fontManager.measureText(seg.text, seg.resourceName, seg.run.fontSize);
362
368
  }
363
- let textX = computeTextX(horizontalAlign, rect, lineWidth, indentPts, padH);
369
+ let textX = computeTextX(horizontalAlign, rect, lineWidth, indentPts, pad.left, pad.right);
364
370
  for (const seg of segments) {
365
371
  const { run, text, resourceName } = seg;
366
372
  const segWidth = fontManager.measureText(text, resourceName, run.fontSize);
@@ -403,8 +409,8 @@ function drawRichText(stream, cell, fontManager, indentPts, scaleFactor = 1) {
403
409
  }
404
410
  const primaryResourceName = runMetrics[0]?.resourceName ?? "F1";
405
411
  const ascent = fontManager.getFontAscent(primaryResourceName, primaryFontSize);
406
- const textStartY = computeTextStartY(verticalAlign, rect, lineHeight, ascent, padV);
407
- let textX = computeTextX(horizontalAlign, rect, totalWidth, indentPts, padH);
412
+ const textStartY = computeTextStartY(verticalAlign, rect, lineHeight, ascent, pad.top, pad.bottom);
413
+ let textX = computeTextX(horizontalAlign, rect, totalWidth, indentPts, pad.left, pad.right);
408
414
  for (let i = 0; i < runs.length; i++) {
409
415
  const run = runs[i];
410
416
  const { resourceName } = runMetrics[i];
@@ -441,8 +447,7 @@ function drawRichText(stream, cell, fontManager, indentPts, scaleFactor = 1) {
441
447
  function drawRotatedText(stream, cell, fontManager, indentPts, scaleFactor = 1) {
442
448
  const { rect, wrapText } = cell;
443
449
  let { fontSize } = cell;
444
- const padH = constants_1.CELL_PADDING_H * scaleFactor;
445
- const padV = constants_1.CELL_PADDING_V * scaleFactor;
450
+ const pad = computeCellPadding(cell, scaleFactor);
446
451
  const isEmbedded = fontManager.hasEmbeddedFont();
447
452
  const resourceName = isEmbedded
448
453
  ? fontManager.getEmbeddedResourceName()
@@ -454,8 +459,8 @@ function drawRotatedText(stream, cell, fontManager, indentPts, scaleFactor = 1)
454
459
  const sin = Math.sin(radians);
455
460
  const absSin = Math.abs(sin);
456
461
  const absCos = Math.abs(cos);
457
- const maxWidth = rect.width - padH * 2;
458
- const maxHeight = rect.height - padV * 2;
462
+ const maxWidth = rect.width - pad.left - pad.right;
463
+ const maxHeight = rect.height - pad.top - pad.bottom;
459
464
  // Available length along the text flow direction for wrapping
460
465
  let availTextLength;
461
466
  if (absSin > 0.01 && absCos > 0.01) {
@@ -503,11 +508,11 @@ function drawRotatedText(stream, cell, fontManager, indentPts, scaleFactor = 1)
503
508
  stream.setFillColor(cell.textColor);
504
509
  if (is90) {
505
510
  // Text reads bottom-to-top. Each line becomes a column drawn left-to-right.
506
- drawRotated90(stream, cell, lines, fontManager, resourceName, fontSize, scaledLineHeight, ascent, padH, padV);
511
+ drawRotated90(stream, cell, lines, fontManager, resourceName, fontSize, scaledLineHeight, ascent, pad);
507
512
  }
508
513
  else if (isMinus90) {
509
514
  // Text reads top-to-bottom. Each line becomes a column drawn right-to-left.
510
- drawRotatedMinus90(stream, cell, lines, fontManager, resourceName, fontSize, scaledLineHeight, ascent, padH, padV);
515
+ drawRotatedMinus90(stream, cell, lines, fontManager, resourceName, fontSize, scaledLineHeight, ascent, pad);
511
516
  }
512
517
  else {
513
518
  // General rotation — center multi-line text block in cell
@@ -515,7 +520,7 @@ function drawRotatedText(stream, cell, fontManager, indentPts, scaleFactor = 1)
515
520
  }
516
521
  }
517
522
  /** 90° CCW: text reads bottom-to-top, lines stack left-to-right. */
518
- function drawRotated90(stream, cell, lines, fontManager, resourceName, fontSize, lineHeight, ascent, padH, padV) {
523
+ function drawRotated90(stream, cell, lines, fontManager, resourceName, fontSize, lineHeight, ascent, pad) {
519
524
  const { rect, horizontalAlign, verticalAlign } = cell;
520
525
  const totalColumnsWidth = lines.length * lineHeight;
521
526
  // horizontalAlign controls X placement of line columns (same visual axis)
@@ -524,11 +529,11 @@ function drawRotated90(stream, cell, lines, fontManager, resourceName, fontSize,
524
529
  startX = rect.x + rect.width / 2 - totalColumnsWidth / 2 + ascent;
525
530
  }
526
531
  else if (horizontalAlign === "right") {
527
- startX = rect.x + rect.width - padH - totalColumnsWidth + ascent;
532
+ startX = rect.x + rect.width - pad.right - totalColumnsWidth + ascent;
528
533
  }
529
534
  else {
530
535
  // left (default)
531
- startX = rect.x + padH + ascent;
536
+ startX = rect.x + pad.left + ascent;
532
537
  }
533
538
  for (let i = 0; i < lines.length; i++) {
534
539
  const line = lines[i];
@@ -539,16 +544,16 @@ function drawRotated90(stream, cell, lines, fontManager, resourceName, fontSize,
539
544
  let ty;
540
545
  if (verticalAlign === "top") {
541
546
  // text at top → text end near top → ty starts at bottom so text reaches top
542
- ty = rect.y + rect.height - padV - lineWidth;
547
+ ty = rect.y + rect.height - pad.top - lineWidth;
543
548
  }
544
549
  else if (verticalAlign === "middle") {
545
550
  ty = rect.y + (rect.height - lineWidth) / 2;
546
551
  }
547
552
  else {
548
553
  // bottom (default) → text at bottom → ty near bottom
549
- ty = rect.y + padV;
554
+ ty = rect.y + pad.bottom;
550
555
  }
551
- ty = Math.max(ty, rect.y + padV);
556
+ ty = Math.max(ty, rect.y + pad.bottom);
552
557
  stream.beginText();
553
558
  stream.setFont(resourceName, fontSize);
554
559
  stream.setTextMatrix(0, 1, -1, 0, colX, ty);
@@ -557,7 +562,7 @@ function drawRotated90(stream, cell, lines, fontManager, resourceName, fontSize,
557
562
  }
558
563
  }
559
564
  /** -90° (270° CW): text reads top-to-bottom, lines stack right-to-left. */
560
- function drawRotatedMinus90(stream, cell, lines, fontManager, resourceName, fontSize, lineHeight, ascent, padH, padV) {
565
+ function drawRotatedMinus90(stream, cell, lines, fontManager, resourceName, fontSize, lineHeight, ascent, pad) {
561
566
  const { rect, horizontalAlign, verticalAlign } = cell;
562
567
  const totalColumnsWidth = lines.length * lineHeight;
563
568
  // horizontalAlign controls X placement: lines stack right-to-left
@@ -566,11 +571,11 @@ function drawRotatedMinus90(stream, cell, lines, fontManager, resourceName, font
566
571
  startX = rect.x + rect.width / 2 + totalColumnsWidth / 2 - lineHeight + ascent;
567
572
  }
568
573
  else if (horizontalAlign === "right") {
569
- startX = rect.x + rect.width - padH - lineHeight + ascent;
574
+ startX = rect.x + rect.width - pad.right - lineHeight + ascent;
570
575
  }
571
576
  else {
572
577
  // left (default)
573
- startX = rect.x + padH + totalColumnsWidth - lineHeight + ascent;
578
+ startX = rect.x + pad.left + totalColumnsWidth - lineHeight + ascent;
574
579
  }
575
580
  for (let i = 0; i < lines.length; i++) {
576
581
  const line = lines[i];
@@ -581,16 +586,16 @@ function drawRotatedMinus90(stream, cell, lines, fontManager, resourceName, font
581
586
  let ty;
582
587
  if (verticalAlign === "top") {
583
588
  // text at top → ty near top (high PDF y)
584
- ty = rect.y + rect.height - padV;
589
+ ty = rect.y + rect.height - pad.top;
585
590
  }
586
591
  else if (verticalAlign === "middle") {
587
592
  ty = rect.y + (rect.height + lineWidth) / 2;
588
593
  }
589
594
  else {
590
595
  // bottom (default) → text at bottom → ty so text ends at bottom
591
- ty = rect.y + padV + lineWidth;
596
+ ty = rect.y + pad.bottom + lineWidth;
592
597
  }
593
- ty = Math.min(ty, rect.y + rect.height - padV);
598
+ ty = Math.min(ty, rect.y + rect.height - pad.top);
594
599
  stream.beginText();
595
600
  stream.setFont(resourceName, fontSize);
596
601
  stream.setTextMatrix(0, -1, 1, 0, colX, ty);
@@ -601,8 +606,8 @@ function drawRotatedMinus90(stream, cell, lines, fontManager, resourceName, font
601
606
  /** General rotation — center a multi-line text block in the cell. */
602
607
  function drawRotatedGeneral(stream, cell, lines, fontManager, resourceName, fontSize, lineHeight, ascent, cos, sin, indentPts) {
603
608
  const { rect, horizontalAlign, verticalAlign } = cell;
604
- const padH = constants_1.CELL_PADDING_H;
605
- const padV = constants_1.CELL_PADDING_V;
609
+ // Use border-aware padding (no scaleFactor — font size is already scaled by caller)
610
+ const pad = computeCellPadding(cell);
606
611
  // Compute the rotated bounding box of the text block
607
612
  let maxLineWidth = 0;
608
613
  for (const line of lines) {
@@ -622,10 +627,10 @@ function drawRotatedGeneral(stream, cell, lines, fontManager, resourceName, font
622
627
  const indentOffset = horizontalAlign === "left" ? indentPts / 2 : horizontalAlign === "right" ? -indentPts / 2 : 0;
623
628
  let cy;
624
629
  if (verticalAlign === "top") {
625
- cy = rect.y + rect.height - padV - rotatedHeight / 2;
630
+ cy = rect.y + rect.height - pad.top - rotatedHeight / 2;
626
631
  }
627
632
  else if (verticalAlign === "bottom") {
628
- cy = rect.y + padV + rotatedHeight / 2;
633
+ cy = rect.y + pad.bottom + rotatedHeight / 2;
629
634
  }
630
635
  else {
631
636
  // middle (default)
@@ -638,10 +643,10 @@ function drawRotatedGeneral(stream, cell, lines, fontManager, resourceName, font
638
643
  const slantAtCy = slantShift * 2 * verticalRatio; // slantShift*2 = full slantOffset
639
644
  let cx;
640
645
  if (horizontalAlign === "right") {
641
- cx = rect.x + rect.width - padH - rotatedWidth / 2 + indentOffset + slantAtCy;
646
+ cx = rect.x + rect.width - pad.right - rotatedWidth / 2 + indentOffset + slantAtCy;
642
647
  }
643
648
  else if (horizontalAlign === "left") {
644
- cx = rect.x + padH + rotatedWidth / 2 + indentOffset + slantAtCy;
649
+ cx = rect.x + pad.left + rotatedWidth / 2 + indentOffset + slantAtCy;
645
650
  }
646
651
  else {
647
652
  // center (default for rotated)
@@ -678,8 +683,7 @@ function emitText(stream, fontManager, text, resourceName) {
678
683
  */
679
684
  function drawVerticalStackedText(stream, cell, fontManager, _indentPts, scaleFactor = 1) {
680
685
  const { rect, text, fontSize, horizontalAlign, verticalAlign } = cell;
681
- const padH = constants_1.CELL_PADDING_H * scaleFactor;
682
- const padV = constants_1.CELL_PADDING_V * scaleFactor;
686
+ const pad = computeCellPadding(cell, scaleFactor);
683
687
  const isEmbedded = fontManager.hasEmbeddedFont();
684
688
  const resourceName = isEmbedded
685
689
  ? fontManager.getEmbeddedResourceName()
@@ -696,11 +700,11 @@ function drawVerticalStackedText(stream, cell, fontManager, _indentPts, scaleFac
696
700
  startX = rect.x + rect.width / 2 - totalColumnsWidth / 2 + columnWidth / 2;
697
701
  }
698
702
  else if (horizontalAlign === "right") {
699
- startX = rect.x + rect.width - padH - totalColumnsWidth + columnWidth / 2;
703
+ startX = rect.x + rect.width - pad.right - totalColumnsWidth + columnWidth / 2;
700
704
  }
701
705
  else {
702
706
  // left (default)
703
- startX = rect.x + padH + columnWidth / 2;
707
+ startX = rect.x + pad.left + columnWidth / 2;
704
708
  }
705
709
  stream.setFillColor(cell.textColor);
706
710
  for (let colIdx = 0; colIdx < columns.length; colIdx++) {
@@ -713,14 +717,14 @@ function drawVerticalStackedText(stream, cell, fontManager, _indentPts, scaleFac
713
717
  currentY = rect.y + rect.height / 2 + totalTextHeight / 2 - ascent;
714
718
  }
715
719
  else if (verticalAlign === "bottom") {
716
- currentY = rect.y + padV + totalTextHeight - ascent;
720
+ currentY = rect.y + pad.bottom + totalTextHeight - ascent;
717
721
  }
718
722
  else {
719
723
  // top (default)
720
- currentY = rect.y + rect.height - padV - ascent;
724
+ currentY = rect.y + rect.height - pad.top - ascent;
721
725
  }
722
726
  for (const ch of colText) {
723
- if (currentY < rect.y + padV) {
727
+ if (currentY < rect.y + pad.bottom) {
724
728
  break;
725
729
  }
726
730
  const charWidth = fontManager.measureText(ch, resourceName, fontSize);
@@ -747,60 +751,60 @@ function alphaGsName(alpha) {
747
751
  // =============================================================================
748
752
  // Text Layout Helpers
749
753
  // =============================================================================
750
- function computeTextStartY(verticalAlign, rect, totalTextHeight, ascent, padV = constants_1.CELL_PADDING_V) {
754
+ function computeTextStartY(verticalAlign, rect, totalTextHeight, ascent, padVTop = constants_1.CELL_PADDING_V, padVBottom = padVTop) {
751
755
  let y;
752
756
  switch (verticalAlign) {
753
757
  case "top":
754
- y = rect.y + rect.height - padV - ascent;
758
+ y = rect.y + rect.height - padVTop - ascent;
755
759
  break;
756
760
  case "middle":
757
761
  y = rect.y + rect.height / 2 + totalTextHeight / 2 - ascent;
758
762
  break;
759
763
  case "bottom":
760
764
  default:
761
- y = rect.y + padV + (totalTextHeight - ascent);
765
+ y = rect.y + padVBottom + (totalTextHeight - ascent);
762
766
  break;
763
767
  }
764
768
  // Clamp: ensure text ascent doesn't exceed the cell top
765
- const maxY = rect.y + rect.height - padV - ascent;
769
+ const maxY = rect.y + rect.height - padVTop - ascent;
766
770
  if (y > maxY) {
767
771
  y = maxY;
768
772
  }
769
773
  // Clamp: ensure text descent doesn't go below cell bottom
770
- const minY = rect.y + padV;
774
+ const minY = rect.y + padVBottom;
771
775
  if (y < minY) {
772
776
  y = minY;
773
777
  }
774
778
  return y;
775
779
  }
776
- function computeTextX(align, rect, textWidth, indentPts = 0, padH = constants_1.CELL_PADDING_H) {
780
+ function computeTextX(align, rect, textWidth, indentPts = 0, padHLeft = constants_1.CELL_PADDING_H, padHRight = padHLeft) {
777
781
  let x;
778
782
  switch (align) {
779
783
  case "center":
780
784
  x = rect.x + (rect.width - textWidth) / 2;
781
785
  break;
782
786
  case "right":
783
- x = rect.x + rect.width - padH - textWidth;
787
+ x = rect.x + rect.width - padHRight - textWidth;
784
788
  break;
785
789
  default:
786
- x = rect.x + padH + indentPts;
790
+ x = rect.x + padHLeft + indentPts;
787
791
  break;
788
792
  }
789
793
  // Clamp: don't start before cell left edge
790
- const minX = rect.x + padH;
794
+ const minX = rect.x + padHLeft;
791
795
  if (x < minX) {
792
796
  x = minX;
793
797
  }
794
798
  return x;
795
799
  }
796
- function drawTextDecorations(stream, cell, lines, lineHeight, textStartY, measure, resourceName, fontManager, indentPts) {
800
+ function drawTextDecorations(stream, cell, lines, lineHeight, textStartY, measure, resourceName, fontManager, indentPts, pad) {
797
801
  if (cell.strike) {
798
802
  const descent = fontManager.getFontDescent(resourceName, cell.fontSize);
799
803
  const strikeY = textStartY + descent + cell.fontSize * 0.3;
800
804
  for (let i = 0; i < lines.length; i++) {
801
805
  const lineY = strikeY - i * lineHeight;
802
806
  const lw = measure(lines[i]);
803
- const startX = computeTextX(cell.horizontalAlign, cell.rect, lw, indentPts);
807
+ const startX = computeTextX(cell.horizontalAlign, cell.rect, lw, indentPts, pad?.left, pad?.right);
804
808
  stream.drawLine(startX, lineY, startX + lw, lineY, cell.textColor, 0.5);
805
809
  }
806
810
  }
@@ -810,7 +814,7 @@ function drawTextDecorations(stream, cell, lines, lineHeight, textStartY, measur
810
814
  for (let i = 0; i < lines.length; i++) {
811
815
  const lineY = textStartY - i * lineHeight + underlineOffset;
812
816
  const lw = measure(lines[i]);
813
- const startX = computeTextX(cell.horizontalAlign, cell.rect, lw, indentPts);
817
+ const startX = computeTextX(cell.horizontalAlign, cell.rect, lw, indentPts, pad?.left, pad?.right);
814
818
  stream.drawLine(startX, lineY, startX + lw, lineY, cell.textColor, 0.5);
815
819
  }
816
820
  }
@@ -1036,7 +1040,7 @@ function renderImageWatermark(stream, page, watermark) {
1036
1040
  imgHeight = watermark.height;
1037
1041
  }
1038
1042
  else {
1039
- const dims = parseImageDimensions(watermark.data, watermark.format);
1043
+ const dims = (0, image_utils_1.parseImageDimensions)(watermark.data, watermark.format);
1040
1044
  const minDim = Math.min(page.width, page.height);
1041
1045
  const targetSize = minDim * scale;
1042
1046
  const maxDim = Math.max(dims.width, dims.height);
@@ -1079,52 +1083,6 @@ function renderImageWatermark(stream, page, watermark) {
1079
1083
  /**
1080
1084
  * Parse image dimensions from raw JPEG or PNG data without a full decode.
1081
1085
  */
1082
- function parseImageDimensions(data, format) {
1083
- if (format === "png") {
1084
- return parsePngDimensions(data);
1085
- }
1086
- return parseJpegDimensions(data);
1087
- }
1088
- /** Read width/height from a PNG IHDR chunk (bytes 16-23). */
1089
- function parsePngDimensions(data) {
1090
- // PNG header: 8 byte signature, then IHDR chunk: 4 byte length, 4 byte type, 4 byte width, 4 byte height
1091
- if (data.length >= 24 &&
1092
- data[12] === 0x49 &&
1093
- data[13] === 0x48 &&
1094
- data[14] === 0x44 &&
1095
- data[15] === 0x52) {
1096
- const width = (data[16] << 24) | (data[17] << 16) | (data[18] << 8) | data[19];
1097
- const height = (data[20] << 24) | (data[21] << 16) | (data[22] << 8) | data[23];
1098
- return { width, height };
1099
- }
1100
- return { width: 1, height: 1 };
1101
- }
1102
- /** Read width/height from JPEG SOF marker. */
1103
- function parseJpegDimensions(data) {
1104
- let offset = 2; // skip SOI marker
1105
- while (offset < data.length - 1) {
1106
- while (offset < data.length && data[offset] === 0xff && data[offset + 1] === 0xff) {
1107
- offset++;
1108
- }
1109
- if (offset >= data.length - 1 || data[offset] !== 0xff) {
1110
- break;
1111
- }
1112
- const marker = data[offset + 1];
1113
- const isSof = marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;
1114
- if (isSof && offset + 8 < data.length) {
1115
- return {
1116
- width: (data[offset + 7] << 8) | data[offset + 8],
1117
- height: (data[offset + 5] << 8) | data[offset + 6]
1118
- };
1119
- }
1120
- if (offset + 3 >= data.length) {
1121
- break;
1122
- }
1123
- const segLen = (data[offset + 2] << 8) | data[offset + 3];
1124
- offset += 2 + segLen;
1125
- }
1126
- return { width: 1, height: 1 };
1127
- }
1128
1086
  /**
1129
1087
  * Resolve the center position for a watermark on a given page.
1130
1088
  */
@@ -18,7 +18,7 @@ const ttf_parser_1 = require("../font/ttf-parser");
18
18
  const encryption_1 = require("../core/encryption");
19
19
  const layout_engine_1 = require("./layout-engine");
20
20
  const page_renderer_1 = require("./page-renderer");
21
- const png_decoder_1 = require("./png-decoder");
21
+ const image_utils_1 = require("../builder/image-utils");
22
22
  const errors_1 = require("../errors");
23
23
  const types_1 = require("../types");
24
24
  const style_converter_1 = require("./style-converter");
@@ -172,7 +172,7 @@ function renderSinglePage(page, fontManager, writer, fontObjectMap, totalPages,
172
172
  for (let imgIdx = 0; imgIdx < page.images.length; imgIdx++) {
173
173
  const img = page.images[imgIdx];
174
174
  const imgName = `Im${imgIdx + 1}`;
175
- const imgObjNum = writeImageXObject(writer, img.data, img.format);
175
+ const imgObjNum = (0, image_utils_1.writeImageXObject)(writer, img.data, img.format);
176
176
  imageXObjects.set(imgName, imgObjNum);
177
177
  contentStream.drawImage(imgName, img.rect.x, img.rect.y, img.rect.width, img.rect.height);
178
178
  }
@@ -191,7 +191,7 @@ function renderSinglePage(page, fontManager, writer, fontObjectMap, totalPages,
191
191
  }
192
192
  // Register watermark image XObjects
193
193
  for (const wmImg of wmResult.imageXObjects) {
194
- const imgObjNum = writeImageXObject(writer, wmImg.data, wmImg.format);
194
+ const imgObjNum = (0, image_utils_1.writeImageXObject)(writer, wmImg.data, wmImg.format);
195
195
  imageXObjects.set(wmImg.name, imgObjNum);
196
196
  }
197
197
  // Write watermark content stream object
@@ -503,62 +503,3 @@ function isWatermarkApplicable(watermark, page) {
503
503
  }
504
504
  return true;
505
505
  }
506
- // =============================================================================
507
- // Image XObject
508
- // =============================================================================
509
- /**
510
- * Write a JPEG or PNG image as a PDF XObject Image.
511
- */
512
- function writeImageXObject(writer, data, format) {
513
- if (format === "png") {
514
- return writePngImageXObject(writer, data);
515
- }
516
- return writeJpegImageXObject(writer, data);
517
- }
518
- /**
519
- * Write a JPEG image using DCTDecode (raw JPEG data embedded directly).
520
- */
521
- function writeJpegImageXObject(writer, data) {
522
- const objNum = writer.allocObject();
523
- const dims = (0, page_renderer_1.parseImageDimensions)(data, "jpeg");
524
- const dict = new pdf_object_1.PdfDict()
525
- .set("Type", "/XObject")
526
- .set("Subtype", "/Image")
527
- .set("Width", (0, pdf_object_1.pdfNumber)(dims.width))
528
- .set("Height", (0, pdf_object_1.pdfNumber)(dims.height))
529
- .set("ColorSpace", "/DeviceRGB")
530
- .set("BitsPerComponent", "8")
531
- .set("Filter", "/DCTDecode");
532
- writer.addStreamObject(objNum, dict, data);
533
- return objNum;
534
- }
535
- /**
536
- * Write a PNG image: decode to raw RGB, create SMask for alpha if needed.
537
- */
538
- function writePngImageXObject(writer, data) {
539
- const png = (0, png_decoder_1.decodePng)(data);
540
- const objNum = writer.allocObject();
541
- const dict = new pdf_object_1.PdfDict()
542
- .set("Type", "/XObject")
543
- .set("Subtype", "/Image")
544
- .set("Width", (0, pdf_object_1.pdfNumber)(png.width))
545
- .set("Height", (0, pdf_object_1.pdfNumber)(png.height))
546
- .set("ColorSpace", "/DeviceRGB")
547
- .set("BitsPerComponent", (0, pdf_object_1.pdfNumber)(png.bitsPerComponent));
548
- // If the image has an alpha channel, create a soft mask XObject
549
- if (png.alpha) {
550
- const smaskObjNum = writer.allocObject();
551
- const smaskDict = new pdf_object_1.PdfDict()
552
- .set("Type", "/XObject")
553
- .set("Subtype", "/Image")
554
- .set("Width", (0, pdf_object_1.pdfNumber)(png.width))
555
- .set("Height", (0, pdf_object_1.pdfNumber)(png.height))
556
- .set("ColorSpace", "/DeviceGray")
557
- .set("BitsPerComponent", "8");
558
- writer.addStreamObject(smaskObjNum, smaskDict, png.alpha);
559
- dict.set("SMask", (0, pdf_object_1.pdfRef)(smaskObjNum));
560
- }
561
- // RGB pixel data — compression handled by addStreamObject
562
- writer.addStreamObject(objNum, dict, png.pixels);
563
- return objNum;
564
- }
@@ -15,6 +15,7 @@ exports.excelColorToPdf = excelColorToPdf;
15
15
  exports.applyTint = applyTint;
16
16
  exports.extractFontProperties = extractFontProperties;
17
17
  exports.excelFillToPdfColor = excelFillToPdfColor;
18
+ exports.borderStyleToLineWidth = borderStyleToLineWidth;
18
19
  exports.excelBordersToPdf = excelBordersToPdf;
19
20
  exports.excelHAlignToPdf = excelHAlignToPdf;
20
21
  exports.excelVAlignToPdf = excelVAlignToPdf;
@@ -237,7 +237,10 @@ class Readable extends event_emitter_1.EventEmitter {
237
237
  err.code = "ERR_INVALID_ARG_TYPE";
238
238
  throw err;
239
239
  }
240
- const readable = new Readable({ ...options, objectMode: options?.objectMode ?? true });
240
+ const readable = new Readable({
241
+ ...options,
242
+ objectMode: options?.objectMode ?? true
243
+ });
241
244
  const iter = iterable;
242
245
  // Node.js treats strings as a single chunk, not as Iterable<char>.
243
246
  // Match that behavior by wrapping strings in an array.
@@ -1743,7 +1746,10 @@ class Readable extends event_emitter_1.EventEmitter {
1743
1746
  }
1744
1747
  }
1745
1748
  else {
1746
- for await (const item of _mapWithConcurrency(this, async (chunk) => ({ chunk, match: await fn(chunk, { signal: innerSignal }) }), concurrency, signal)) {
1749
+ for await (const item of _mapWithConcurrency(this, async (chunk) => ({
1750
+ chunk,
1751
+ match: await fn(chunk, { signal: innerSignal })
1752
+ }), concurrency, signal)) {
1747
1753
  if (item.match) {
1748
1754
  this.destroy();
1749
1755
  return item.chunk;