documonster 0.7.0 → 0.8.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.
- package/dist/browser/modules/pdf/builder/image-utils.d.ts +1 -1
- package/dist/browser/modules/pdf/builder/image-utils.js +58 -9
- package/dist/browser/modules/pdf/core/pdf-writer.d.ts +8 -0
- package/dist/browser/modules/pdf/core/pdf-writer.js +3 -0
- package/dist/browser/modules/pdf/excel-bridge.js +126 -19
- package/dist/browser/modules/pdf/index.d.ts +1 -1
- package/dist/browser/modules/pdf/render/chart-surface.d.ts +6 -1
- package/dist/browser/modules/pdf/render/chart-surface.js +86 -47
- package/dist/browser/modules/pdf/render/constants.d.ts +69 -0
- package/dist/browser/modules/pdf/render/constants.js +45 -0
- package/dist/browser/modules/pdf/render/layout-engine.d.ts +5 -1
- package/dist/browser/modules/pdf/render/layout-engine.js +586 -205
- package/dist/browser/modules/pdf/render/page-renderer.js +180 -3
- package/dist/browser/modules/pdf/render/pdf-exporter.js +176 -35
- package/dist/browser/modules/pdf/render/style-converter.d.ts +11 -0
- package/dist/browser/modules/pdf/render/style-converter.js +24 -0
- package/dist/browser/modules/pdf/types.d.ts +284 -5
- package/dist/cjs/modules/pdf/builder/image-utils.js +58 -9
- package/dist/cjs/modules/pdf/core/pdf-writer.js +3 -0
- package/dist/cjs/modules/pdf/excel-bridge.js +125 -18
- package/dist/cjs/modules/pdf/render/chart-surface.js +86 -47
- package/dist/cjs/modules/pdf/render/constants.js +46 -1
- package/dist/cjs/modules/pdf/render/layout-engine.js +583 -202
- package/dist/cjs/modules/pdf/render/page-renderer.js +179 -2
- package/dist/cjs/modules/pdf/render/pdf-exporter.js +175 -34
- package/dist/cjs/modules/pdf/render/style-converter.js +26 -0
- package/dist/esm/modules/pdf/builder/image-utils.js +58 -9
- package/dist/esm/modules/pdf/core/pdf-writer.js +3 -0
- package/dist/esm/modules/pdf/excel-bridge.js +126 -19
- package/dist/esm/modules/pdf/render/chart-surface.js +86 -47
- package/dist/esm/modules/pdf/render/constants.js +45 -0
- package/dist/esm/modules/pdf/render/layout-engine.js +586 -205
- package/dist/esm/modules/pdf/render/page-renderer.js +180 -3
- package/dist/esm/modules/pdf/render/pdf-exporter.js +176 -35
- package/dist/esm/modules/pdf/render/style-converter.js +24 -0
- package/dist/iife/documonster.archive.iife.js +1 -1
- package/dist/iife/documonster.archive.iife.min.js +1 -1
- package/dist/iife/documonster.csv.iife.js +1 -1
- package/dist/iife/documonster.csv.iife.min.js +1 -1
- package/dist/iife/documonster.excel.iife.js +1 -1
- package/dist/iife/documonster.excel.iife.min.js +1 -1
- package/dist/iife/documonster.formula.iife.js +1 -1
- package/dist/iife/documonster.formula.iife.min.js +1 -1
- package/dist/iife/documonster.markdown.iife.js +1 -1
- package/dist/iife/documonster.markdown.iife.min.js +1 -1
- package/dist/iife/documonster.pdf.iife.js +1457 -664
- package/dist/iife/documonster.pdf.iife.js.map +1 -1
- package/dist/iife/documonster.pdf.iife.min.js +33 -32
- package/dist/iife/documonster.stream.iife.js +1 -1
- package/dist/iife/documonster.stream.iife.min.js +1 -1
- package/dist/iife/documonster.word.iife.js +1 -1
- package/dist/iife/documonster.word.iife.min.js +1 -1
- package/dist/iife/documonster.xml.iife.js +1 -1
- package/dist/iife/documonster.xml.iife.min.js +1 -1
- package/dist/types/modules/pdf/builder/image-utils.d.ts +1 -1
- package/dist/types/modules/pdf/core/pdf-writer.d.ts +8 -0
- package/dist/types/modules/pdf/index.d.ts +1 -1
- package/dist/types/modules/pdf/render/chart-surface.d.ts +6 -1
- package/dist/types/modules/pdf/render/constants.d.ts +69 -0
- package/dist/types/modules/pdf/render/layout-engine.d.ts +5 -1
- package/dist/types/modules/pdf/render/style-converter.d.ts +11 -0
- package/dist/types/modules/pdf/types.d.ts +284 -5
- package/package.json +1 -1
|
@@ -122,11 +122,52 @@ export interface PdfPageSetupData {
|
|
|
122
122
|
header?: number;
|
|
123
123
|
footer?: number;
|
|
124
124
|
};
|
|
125
|
+
/** Excel's scaling percentage (10–400, where 100 = actual size). */
|
|
125
126
|
scale?: number;
|
|
127
|
+
/**
|
|
128
|
+
* Whether Excel's "Fit to N page(s) wide by M tall" scaling mode is active
|
|
129
|
+
* (`<sheetPr><pageSetUpPr fitToPage="1"/></sheetPr>`). When true,
|
|
130
|
+
* {@link fitToWidth} / {@link fitToHeight} drive the scale and
|
|
131
|
+
* {@link scale} is ignored — the two are mutually exclusive in Excel's UI.
|
|
132
|
+
*/
|
|
133
|
+
fitToPage?: boolean;
|
|
134
|
+
/** Pages wide to fit into. `0` means "unlimited" (no width constraint). */
|
|
135
|
+
fitToWidth?: number;
|
|
136
|
+
/** Pages tall to fit into. `0` means "unlimited" (no height constraint). */
|
|
137
|
+
fitToHeight?: number;
|
|
126
138
|
printTitlesRow?: string;
|
|
139
|
+
/** Repeated columns, e.g. `"A:B"` or `"A"` (Excel's "Columns to repeat at left"). */
|
|
140
|
+
printTitlesColumn?: string;
|
|
127
141
|
showGridLines?: boolean;
|
|
142
|
+
/** Print row numbers and column letters (`<printOptions headings="1"/>`). */
|
|
143
|
+
showRowColHeaders?: boolean;
|
|
128
144
|
printArea?: string;
|
|
129
145
|
firstPageNumber?: number;
|
|
146
|
+
/**
|
|
147
|
+
* Order in which pages of a multi-page sheet are emitted.
|
|
148
|
+
* Excel's default is `"downThenOver"`.
|
|
149
|
+
*/
|
|
150
|
+
pageOrder?: string;
|
|
151
|
+
/** Render the sheet without color (Excel's "Black and white" print option). */
|
|
152
|
+
blackAndWhite?: boolean;
|
|
153
|
+
/** Draft quality — skips graphics (images and charts). */
|
|
154
|
+
draft?: boolean;
|
|
155
|
+
/** How error values are printed: `displayed` | `blank` | `dash` | `NA`. */
|
|
156
|
+
errors?: string;
|
|
157
|
+
/** How comments print: `None` | `asDisplayed` | `atEnd`. */
|
|
158
|
+
cellComments?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Excel's "Center on page → Horizontally" print option
|
|
161
|
+
* (`<printOptions horizontalCentered="1"/>`). When false/absent the
|
|
162
|
+
* printed grid starts at the left margin.
|
|
163
|
+
*/
|
|
164
|
+
horizontalCentered?: boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Excel's "Center on page → Vertically" print option
|
|
167
|
+
* (`<printOptions verticalCentered="1"/>`). When false/absent the
|
|
168
|
+
* printed grid starts at the top margin.
|
|
169
|
+
*/
|
|
170
|
+
verticalCentered?: boolean;
|
|
130
171
|
}
|
|
131
172
|
export type PdfHeaderFooterField = "pageNumber" | "pageCount" | "sheetName" | "fileName" | "filePath" | "date" | "time" | "image";
|
|
132
173
|
export interface PdfHeaderFooterRun {
|
|
@@ -359,6 +400,8 @@ export interface PdfSheetData {
|
|
|
359
400
|
images?: PdfSheetImage[];
|
|
360
401
|
/** Embedded charts (classic + ChartEx) */
|
|
361
402
|
charts?: PdfSheetChart[];
|
|
403
|
+
/** Cell comments and notes, in row-major order. */
|
|
404
|
+
comments?: PdfSheetComment[];
|
|
362
405
|
}
|
|
363
406
|
/**
|
|
364
407
|
* A chartsheet — a single-chart "sheet" with no cell grid.
|
|
@@ -440,6 +483,68 @@ export declare const PageSizes: Record<PageSizeName, PdfPageSize>;
|
|
|
440
483
|
* Page orientation for PDF export.
|
|
441
484
|
*/
|
|
442
485
|
export type PdfOrientation = "portrait" | "landscape";
|
|
486
|
+
/**
|
|
487
|
+
* Order in which the pages of a multi-page sheet are emitted, mirroring
|
|
488
|
+
* Excel's "Page order" setting.
|
|
489
|
+
*/
|
|
490
|
+
export type PdfPageOrder = "downThenOver" | "overThenDown";
|
|
491
|
+
/**
|
|
492
|
+
* How cells holding an error value are printed, mirroring Excel's
|
|
493
|
+
* "Cell errors as" setting.
|
|
494
|
+
*/
|
|
495
|
+
export type PdfCellErrorMode = "displayed" | "blank" | "dash" | "NA";
|
|
496
|
+
/**
|
|
497
|
+
* How cell comments are printed, mirroring Excel's "Comments and notes"
|
|
498
|
+
* print option.
|
|
499
|
+
*/
|
|
500
|
+
export type PdfCellCommentMode = "none" | "atEnd" | "asDisplayed";
|
|
501
|
+
/**
|
|
502
|
+
* Comment box placement, in fractional sheet coordinates.
|
|
503
|
+
*
|
|
504
|
+
* Excel stores this as a VML anchor: eight integers giving a column/row plus an
|
|
505
|
+
* offset in 1/68 of a column and 1/18 of a row. Those are pre-divided here so
|
|
506
|
+
* the layout engine only has to interpolate against its own track geometry.
|
|
507
|
+
* All values are 0-based, matching the VML convention.
|
|
508
|
+
*/
|
|
509
|
+
export interface PdfCommentAnchor {
|
|
510
|
+
/** Left edge, in columns. `2.5` is halfway across the third column. */
|
|
511
|
+
left: number;
|
|
512
|
+
/** Top edge, in rows. */
|
|
513
|
+
top: number;
|
|
514
|
+
/** Right edge, in columns. */
|
|
515
|
+
right: number;
|
|
516
|
+
/** Bottom edge, in rows. */
|
|
517
|
+
bottom: number;
|
|
518
|
+
}
|
|
519
|
+
/** A single printed cell comment. */
|
|
520
|
+
export interface PdfSheetComment {
|
|
521
|
+
/** Cell address the comment is attached to, e.g. `"B7"`. */
|
|
522
|
+
ref: string;
|
|
523
|
+
/** Plain-text body. */
|
|
524
|
+
text: string;
|
|
525
|
+
/** Author, when the source recorded one. */
|
|
526
|
+
author?: string;
|
|
527
|
+
/**
|
|
528
|
+
* Where the comment box sits on the sheet, when the source recorded a VML
|
|
529
|
+
* anchor. Consumed by `cellComments: "asDisplayed"`; absent comments fall back
|
|
530
|
+
* to Excel's default offset from their cell.
|
|
531
|
+
*/
|
|
532
|
+
anchor?: PdfCommentAnchor;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* An inclusive band of repeated title rows or columns, in absolute 1-based
|
|
536
|
+
* sheet coordinates.
|
|
537
|
+
*
|
|
538
|
+
* Absolute rather than a count, because Excel's "Rows/Columns to repeat" are
|
|
539
|
+
* independent of the print area: a sheet printing `C5:H50` can still repeat
|
|
540
|
+
* `A:B` at the left of every page.
|
|
541
|
+
*/
|
|
542
|
+
export interface PdfRepeatBand {
|
|
543
|
+
/** First row/column of the band (1-based, inclusive). */
|
|
544
|
+
first: number;
|
|
545
|
+
/** Last row/column of the band (1-based, inclusive). */
|
|
546
|
+
last: number;
|
|
547
|
+
}
|
|
443
548
|
/**
|
|
444
549
|
* Excel header/footer rendering options.
|
|
445
550
|
*
|
|
@@ -497,16 +602,116 @@ export interface PdfExportOptions {
|
|
|
497
602
|
*/
|
|
498
603
|
ignorePrintArea?: boolean;
|
|
499
604
|
/**
|
|
500
|
-
* Whether to
|
|
501
|
-
*
|
|
605
|
+
* Whether to shrink column widths so the grid fits the page width.
|
|
606
|
+
* Never enlarges — content narrower than the page is left at actual size,
|
|
607
|
+
* matching Excel's fit-to-page behaviour.
|
|
608
|
+
*
|
|
609
|
+
* This is the fallback used when neither the caller nor the sheet expresses a
|
|
610
|
+
* fit-to-N or percentage scaling intent, so a sheet asking for 80% is not
|
|
611
|
+
* shrunk twice. Passing it explicitly always wins, including over the sheet's
|
|
612
|
+
* own fit-to-N mode.
|
|
613
|
+
*
|
|
614
|
+
* Note that {@link scale} is a *multiplier applied on top* of this and does
|
|
615
|
+
* not disable it: `{ scale: 0.8 }` on an over-wide grid yields
|
|
616
|
+
* `0.8 × fit-to-width`. Pass `fitToPage: false` alongside it for a plain 80%.
|
|
502
617
|
* @default true
|
|
503
618
|
*/
|
|
504
619
|
fitToPage?: boolean;
|
|
505
620
|
/**
|
|
506
|
-
* Scale factor (0.1 to
|
|
507
|
-
* @
|
|
621
|
+
* Scale factor (0.1 to 4.0), where `1.0` is actual size, multiplied with any
|
|
622
|
+
* fit-to-page shrinking (see {@link fitToPage}). Overrides the sheet's
|
|
623
|
+
* `pageSetup.scale`, which Excel stores as a 10–400 percentage.
|
|
624
|
+
*
|
|
625
|
+
* When omitted, the sheet's own scaling is used; see {@link fitToPage}.
|
|
508
626
|
*/
|
|
509
627
|
scale?: number;
|
|
628
|
+
/**
|
|
629
|
+
* Shrink the grid so it spans at most this many pages horizontally,
|
|
630
|
+
* mirroring Excel's "Fit to N page(s) wide". `0` removes the constraint.
|
|
631
|
+
*
|
|
632
|
+
* Like Excel, this only ever shrinks. When omitted, the sheet's
|
|
633
|
+
* `pageSetup.fitToWidth` is used if its `fitToPage` mode is on.
|
|
634
|
+
*/
|
|
635
|
+
fitToWidth?: number;
|
|
636
|
+
/**
|
|
637
|
+
* Shrink the grid so it spans at most this many pages vertically,
|
|
638
|
+
* mirroring Excel's "Fit to M page(s) tall". `0` removes the constraint.
|
|
639
|
+
*
|
|
640
|
+
* Like Excel, this only ever shrinks. When omitted, the sheet's
|
|
641
|
+
* `pageSetup.fitToHeight` is used if its `fitToPage` mode is on.
|
|
642
|
+
*/
|
|
643
|
+
fitToHeight?: number;
|
|
644
|
+
/**
|
|
645
|
+
* Number of leading columns to repeat on every horizontal page, the
|
|
646
|
+
* counterpart of {@link repeatRows}.
|
|
647
|
+
*
|
|
648
|
+
* When omitted, the sheet's `pageSetup.printTitlesColumn` ("Columns to
|
|
649
|
+
* repeat at left", e.g. `"A:B"`) is used.
|
|
650
|
+
* @default false
|
|
651
|
+
*/
|
|
652
|
+
repeatCols?: number | false;
|
|
653
|
+
/**
|
|
654
|
+
* Print row numbers and column letters around the grid, mirroring Excel's
|
|
655
|
+
* "Row and column headings" print option.
|
|
656
|
+
*
|
|
657
|
+
* When omitted, the sheet's `pageSetup.showRowColHeaders` is used.
|
|
658
|
+
* @default false
|
|
659
|
+
*/
|
|
660
|
+
showRowColHeaders?: boolean;
|
|
661
|
+
/**
|
|
662
|
+
* Order in which the pages of a multi-page sheet are emitted, mirroring
|
|
663
|
+
* Excel's "Page order". `"downThenOver"` finishes each column band top to
|
|
664
|
+
* bottom before moving right; `"overThenDown"` finishes each row band left
|
|
665
|
+
* to right before moving down.
|
|
666
|
+
*
|
|
667
|
+
* When omitted, the sheet's `pageSetup.pageOrder` is used.
|
|
668
|
+
* @default "downThenOver"
|
|
669
|
+
*/
|
|
670
|
+
pageOrder?: PdfPageOrder;
|
|
671
|
+
/**
|
|
672
|
+
* Render vector content without color, mirroring Excel's "Black and white"
|
|
673
|
+
* print option. Colors are converted to their luminance-preserving grayscale
|
|
674
|
+
* equivalent, preserving opacity.
|
|
675
|
+
*
|
|
676
|
+
* Covers vector content (cell text, fills and borders, gridlines, the
|
|
677
|
+
* row/column heading bands, chart vectors, `&K`-colored header/footer runs and
|
|
678
|
+
* text watermarks) as well as raster content: PNG samples are converted to a
|
|
679
|
+
* single luma component, and JPEG keeps its DCTDecode data but is reinterpreted
|
|
680
|
+
* through a `/DeviceN` luma color space, so neither needs an overlay and
|
|
681
|
+
* transparency is preserved.
|
|
682
|
+
*
|
|
683
|
+
* When omitted, the sheet's `pageSetup.blackAndWhite` is used.
|
|
684
|
+
* @default false
|
|
685
|
+
*/
|
|
686
|
+
blackAndWhite?: boolean;
|
|
687
|
+
/**
|
|
688
|
+
* Draft quality — omit images and charts, mirroring Excel's "Draft quality"
|
|
689
|
+
* print option.
|
|
690
|
+
*
|
|
691
|
+
* When omitted, the sheet's `pageSetup.draft` is used.
|
|
692
|
+
* @default false
|
|
693
|
+
*/
|
|
694
|
+
draft?: boolean;
|
|
695
|
+
/**
|
|
696
|
+
* How cells holding an error value are printed, mirroring Excel's
|
|
697
|
+
* "Cell errors as" print option.
|
|
698
|
+
*
|
|
699
|
+
* When omitted, the sheet's `pageSetup.errors` is used.
|
|
700
|
+
* @default "displayed"
|
|
701
|
+
*/
|
|
702
|
+
errors?: PdfCellErrorMode;
|
|
703
|
+
/**
|
|
704
|
+
* Whether cell comments and notes are printed, mirroring Excel's
|
|
705
|
+
* "Comments and notes" print option.
|
|
706
|
+
*
|
|
707
|
+
* `"atEnd"` appends a list of every comment after the sheet's pages.
|
|
708
|
+
* `"asDisplayed"` draws each comment as a box where it sits on the sheet,
|
|
709
|
+
* plus the red corner marker Excel puts on the commented cell.
|
|
710
|
+
*
|
|
711
|
+
* When omitted, the sheet's `pageSetup.cellComments` is used.
|
|
712
|
+
* @default "none"
|
|
713
|
+
*/
|
|
714
|
+
cellComments?: PdfCellCommentMode;
|
|
510
715
|
/**
|
|
511
716
|
* Whether to show grid lines on the page.
|
|
512
717
|
* @default false
|
|
@@ -517,6 +722,24 @@ export interface PdfExportOptions {
|
|
|
517
722
|
* @default "FFD0D0D0"
|
|
518
723
|
*/
|
|
519
724
|
gridLineColor?: string;
|
|
725
|
+
/**
|
|
726
|
+
* Center the printed grid horizontally within the page's content area,
|
|
727
|
+
* mirroring Excel's "Page Setup → Margins → Center on page → Horizontally".
|
|
728
|
+
*
|
|
729
|
+
* When omitted, the source sheet's `pageSetup.horizontalCentered` is used;
|
|
730
|
+
* if that is unset too, content starts at the left margin.
|
|
731
|
+
* @default false
|
|
732
|
+
*/
|
|
733
|
+
horizontalCentered?: boolean;
|
|
734
|
+
/**
|
|
735
|
+
* Center the printed grid vertically within the page's content area,
|
|
736
|
+
* mirroring Excel's "Page Setup → Margins → Center on page → Vertically".
|
|
737
|
+
*
|
|
738
|
+
* When omitted, the source sheet's `pageSetup.verticalCentered` is used;
|
|
739
|
+
* if that is unset too, content starts at the top margin.
|
|
740
|
+
* @default false
|
|
741
|
+
*/
|
|
742
|
+
verticalCentered?: boolean;
|
|
520
743
|
/**
|
|
521
744
|
* Whether to repeat row headers on each page.
|
|
522
745
|
* Can be a number (row count from top) or false to disable.
|
|
@@ -863,9 +1086,22 @@ export interface ResolvedPdfOptions {
|
|
|
863
1086
|
ignorePrintArea: boolean;
|
|
864
1087
|
fitToPage: boolean;
|
|
865
1088
|
scale: number;
|
|
1089
|
+
/** Pages wide to shrink into; `0` means unconstrained. */
|
|
1090
|
+
fitToWidth: number;
|
|
1091
|
+
/** Pages tall to shrink into; `0` means unconstrained. */
|
|
1092
|
+
fitToHeight: number;
|
|
866
1093
|
showGridLines: boolean;
|
|
867
1094
|
gridLineColor: PdfColor;
|
|
868
|
-
|
|
1095
|
+
showRowColHeaders: boolean;
|
|
1096
|
+
horizontalCentered: boolean;
|
|
1097
|
+
verticalCentered: boolean;
|
|
1098
|
+
pageOrder: PdfPageOrder;
|
|
1099
|
+
blackAndWhite: boolean;
|
|
1100
|
+
draft: boolean;
|
|
1101
|
+
errors: PdfCellErrorMode;
|
|
1102
|
+
cellComments: PdfCellCommentMode;
|
|
1103
|
+
repeatRows: PdfRepeatBand | false;
|
|
1104
|
+
repeatCols: PdfRepeatBand | false;
|
|
869
1105
|
defaultFontFamily: string;
|
|
870
1106
|
defaultFontSize: number;
|
|
871
1107
|
showSheetNames: boolean;
|
|
@@ -1040,8 +1276,51 @@ export interface LayoutPage {
|
|
|
1040
1276
|
charts: LayoutChart[];
|
|
1041
1277
|
/** Scale factor applied to this page (for fitToPage) */
|
|
1042
1278
|
scaleFactor: number;
|
|
1279
|
+
/**
|
|
1280
|
+
* Geometry of the printed row/column heading bands, when
|
|
1281
|
+
* {@link ResolvedPdfOptions.showRowColHeaders} is on. Absent otherwise.
|
|
1282
|
+
*/
|
|
1283
|
+
headings?: LayoutHeadings;
|
|
1284
|
+
/**
|
|
1285
|
+
* Comment boxes to draw on this page, for
|
|
1286
|
+
* `cellComments: "asDisplayed"`. Empty otherwise.
|
|
1287
|
+
*/
|
|
1288
|
+
commentBoxes?: LayoutCommentBox[];
|
|
1043
1289
|
headerFooter?: PdfHeaderFooterData;
|
|
1044
1290
|
}
|
|
1291
|
+
/**
|
|
1292
|
+
* A comment box positioned on the sheet, as Excel's "Comments: as displayed"
|
|
1293
|
+
* prints it, together with the corner marker on the commented cell.
|
|
1294
|
+
*/
|
|
1295
|
+
export interface LayoutCommentBox {
|
|
1296
|
+
/** Box outline in page coordinates. */
|
|
1297
|
+
rect: PdfRect;
|
|
1298
|
+
/** Comment body, already prefixed with the author when one is known. */
|
|
1299
|
+
text: string;
|
|
1300
|
+
/** Font size in points. */
|
|
1301
|
+
fontSize: number;
|
|
1302
|
+
/**
|
|
1303
|
+
* Corner marker on the commented cell, when that cell is on this page. Excel
|
|
1304
|
+
* draws a small red triangle in its top-right corner.
|
|
1305
|
+
*/
|
|
1306
|
+
marker?: {
|
|
1307
|
+
x: number;
|
|
1308
|
+
y: number;
|
|
1309
|
+
size: number;
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Row-number gutter and column-letter band geometry for a page printed with
|
|
1314
|
+
* Excel's "Row and column headings" option.
|
|
1315
|
+
*/
|
|
1316
|
+
export interface LayoutHeadings {
|
|
1317
|
+
/** Width of the row-number gutter to the left of the grid, in points. */
|
|
1318
|
+
gutterWidth: number;
|
|
1319
|
+
/** Height of the column-letter band above the grid, in points. */
|
|
1320
|
+
bandHeight: number;
|
|
1321
|
+
/** Font size used for the heading labels, in points. */
|
|
1322
|
+
fontSize: number;
|
|
1323
|
+
}
|
|
1045
1324
|
/**
|
|
1046
1325
|
* A positioned image on a PDF page.
|
|
1047
1326
|
*/
|
|
@@ -82,41 +82,90 @@ function parseJpegDimensions(data) {
|
|
|
82
82
|
* Write an image XObject (JPEG or PNG) to the writer.
|
|
83
83
|
* Returns the allocated object number.
|
|
84
84
|
*/
|
|
85
|
-
function writeImageXObject(writer, data, format) {
|
|
85
|
+
function writeImageXObject(writer, data, format, grayscale = false) {
|
|
86
86
|
if (format === "png") {
|
|
87
|
-
return writePngImageXObject(writer, data);
|
|
87
|
+
return writePngImageXObject(writer, data, grayscale);
|
|
88
88
|
}
|
|
89
|
-
return writeJpegImageXObject(writer, data);
|
|
89
|
+
return writeJpegImageXObject(writer, data, grayscale);
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
* Write
|
|
92
|
+
* Write the PostScript calculator function that converts an RGB triple to its
|
|
93
|
+
* Rec. 601 luma, and return its object number.
|
|
94
|
+
*
|
|
95
|
+
* Used as the tint transform of a `/DeviceN` space so a JPEG can be recoloured
|
|
96
|
+
* without decoding it: the samples stay untouched and the consumer applies the
|
|
97
|
+
* transform per pixel. Unlike painting a blend on top, this cannot darken
|
|
98
|
+
* transparent areas, because it *is* the color space rather than an overlay.
|
|
93
99
|
*/
|
|
94
|
-
function
|
|
100
|
+
function writeLumaTintTransform(writer) {
|
|
95
101
|
const objNum = writer.allocObject();
|
|
102
|
+
const dict = new pdf_object_1.PdfDict()
|
|
103
|
+
.set("FunctionType", "4")
|
|
104
|
+
.set("Domain", "[0 1 0 1 0 1]")
|
|
105
|
+
.set("Range", "[0 1]");
|
|
106
|
+
// Stack on entry is R G B (B on top):
|
|
107
|
+
// 0.114 mul -> R G 0.114B
|
|
108
|
+
// exch -> R 0.114B G
|
|
109
|
+
// 0.587 mul -> R 0.114B 0.587G
|
|
110
|
+
// add -> R (0.114B + 0.587G)
|
|
111
|
+
// exch -> (0.114B + 0.587G) R
|
|
112
|
+
// 0.299 mul -> (0.114B + 0.587G) 0.299R
|
|
113
|
+
// add -> luma
|
|
114
|
+
const program = "{ 0.114 mul exch 0.587 mul add exch 0.299 mul add }";
|
|
115
|
+
writer.addStreamObject(objNum, dict, new TextEncoder().encode(program));
|
|
116
|
+
return objNum;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Write a JPEG image using DCTDecode (raw JPEG data embedded directly).
|
|
120
|
+
*/
|
|
121
|
+
function writeJpegImageXObject(writer, data, grayscale = false) {
|
|
96
122
|
const dims = parseJpegDimensions(data);
|
|
123
|
+
// Grayscale without a JPEG decoder: keep the DCTDecode samples and reinterpret
|
|
124
|
+
// the three components through a `/DeviceN` space whose tint transform is the
|
|
125
|
+
// luma formula. Component count still matches the JPEG, as PDF requires.
|
|
126
|
+
const tintRef = grayscale ? writeLumaTintTransform(writer) : undefined;
|
|
127
|
+
const objNum = writer.allocObject();
|
|
97
128
|
const dict = new pdf_object_1.PdfDict()
|
|
98
129
|
.set("Type", "/XObject")
|
|
99
130
|
.set("Subtype", "/Image")
|
|
100
131
|
.set("Width", (0, pdf_object_1.pdfNumber)(dims.width))
|
|
101
132
|
.set("Height", (0, pdf_object_1.pdfNumber)(dims.height))
|
|
102
|
-
.set("ColorSpace",
|
|
133
|
+
.set("ColorSpace", tintRef === undefined
|
|
134
|
+
? "/DeviceRGB"
|
|
135
|
+
: `[/DeviceN [/C1 /C2 /C3] /DeviceGray ${(0, pdf_object_1.pdfRef)(tintRef)}]`)
|
|
103
136
|
.set("BitsPerComponent", "8")
|
|
104
137
|
.set("Filter", "/DCTDecode");
|
|
105
138
|
writer.addStreamObject(objNum, dict, data);
|
|
106
139
|
return objNum;
|
|
107
140
|
}
|
|
141
|
+
/** Rec. 601 luma of an 8-bit RGB triple. */
|
|
142
|
+
function lumaByte(r, g, b) {
|
|
143
|
+
return Math.round(0.299 * r + 0.587 * g + 0.114 * b);
|
|
144
|
+
}
|
|
108
145
|
/**
|
|
109
146
|
* Write a PNG image: decode to raw RGB, create SMask for alpha if needed.
|
|
110
147
|
*/
|
|
111
|
-
function writePngImageXObject(writer, data) {
|
|
148
|
+
function writePngImageXObject(writer, data, grayscale = false) {
|
|
112
149
|
const png = (0, png_decoder_1.decodePng)(data);
|
|
113
150
|
const objNum = writer.allocObject();
|
|
151
|
+
// PNG is already decoded to raw samples here, so grayscale is a real pixel
|
|
152
|
+
// conversion: collapse RGB to one luma component and switch to DeviceGray.
|
|
153
|
+
// The alpha channel lives in a separate SMask and is untouched, so transparent
|
|
154
|
+
// regions stay transparent.
|
|
155
|
+
let pixels = png.pixels;
|
|
156
|
+
if (grayscale) {
|
|
157
|
+
const gray = new Uint8Array(png.width * png.height);
|
|
158
|
+
for (let i = 0, p = 0; i < gray.length; i++, p += 3) {
|
|
159
|
+
gray[i] = lumaByte(pixels[p], pixels[p + 1], pixels[p + 2]);
|
|
160
|
+
}
|
|
161
|
+
pixels = gray;
|
|
162
|
+
}
|
|
114
163
|
const dict = new pdf_object_1.PdfDict()
|
|
115
164
|
.set("Type", "/XObject")
|
|
116
165
|
.set("Subtype", "/Image")
|
|
117
166
|
.set("Width", (0, pdf_object_1.pdfNumber)(png.width))
|
|
118
167
|
.set("Height", (0, pdf_object_1.pdfNumber)(png.height))
|
|
119
|
-
.set("ColorSpace", "/DeviceRGB")
|
|
168
|
+
.set("ColorSpace", grayscale ? "/DeviceGray" : "/DeviceRGB")
|
|
120
169
|
.set("BitsPerComponent", (0, pdf_object_1.pdfNumber)(png.bitsPerComponent));
|
|
121
170
|
if (png.alpha) {
|
|
122
171
|
const smaskObjNum = writer.allocObject();
|
|
@@ -130,6 +179,6 @@ function writePngImageXObject(writer, data) {
|
|
|
130
179
|
writer.addStreamObject(smaskObjNum, smaskDict, png.alpha);
|
|
131
180
|
dict.set("SMask", (0, pdf_object_1.pdfRef)(smaskObjNum));
|
|
132
181
|
}
|
|
133
|
-
writer.addStreamObject(objNum, dict,
|
|
182
|
+
writer.addStreamObject(objNum, dict, pixels);
|
|
134
183
|
return objNum;
|
|
135
184
|
}
|
|
@@ -168,6 +168,9 @@ class PdfWriter {
|
|
|
168
168
|
.set("MediaBox", mediaBox)
|
|
169
169
|
.set("Contents", contentsValue)
|
|
170
170
|
.set("Resources", (0, pdf_object_1.pdfRef)(options.resourcesRef));
|
|
171
|
+
if (options.transparencyGroup) {
|
|
172
|
+
dict.set("Group", "<< /S /Transparency /CS /DeviceRGB /I false /K false >>");
|
|
173
|
+
}
|
|
171
174
|
if (options.annotRefs && options.annotRefs.length > 0) {
|
|
172
175
|
dict.set("Annots", "[" + options.annotRefs.map(r => (0, pdf_object_1.pdfRef)(r)).join(" ") + "]");
|
|
173
176
|
}
|