pagyra-js 0.0.20 → 0.0.21
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/README.md +55 -0
- package/dist/assets/fonts/licenses/selawik/SIL Open Font License.txt +43 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-BoldItalic.ttf +0 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-Italic.ttf +0 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Black.ttf +0 -0
- package/dist/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/dejavu/DejaVuSans.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Light.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Medium.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-SemiBold.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Light.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Medium.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-SemiBold.ttf +0 -0
- package/dist/assets/fonts/ttf/notosans/NotoSans-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-BoldItalic.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-Italic.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawk.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawkb.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawkl.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawksb.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawksl.ttf +0 -0
- package/dist/assets/fonts/ttf/stixtwomath/STIXTwoMath-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-BoldItalic.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-Italic.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-Regular.ttf +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-400-italic.woff +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-400-normal.woff +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-700-italic.woff +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-700-normal.woff +0 -0
- package/dist/assets/fonts/woff2/caveat/Caveat-Bold.woff2 +0 -0
- package/dist/assets/fonts/woff2/caveat/Caveat-Regular.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-400-italic.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-400-normal.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-700-italic.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-700-normal.woff2 +0 -0
- package/dist/browser/pagyra.min.js +34 -34
- package/dist/browser/pagyra.min.js.map +4 -4
- package/dist/playground/server.js +2 -0
- package/dist/src/css/compute-style/base-options.d.ts +7 -0
- package/dist/src/css/compute-style/base-options.js +24 -0
- package/dist/src/css/compute-style/declarations.d.ts +10 -0
- package/dist/src/css/compute-style/declarations.js +77 -0
- package/dist/src/css/compute-style/decoration.d.ts +8 -0
- package/dist/src/css/compute-style/decoration.js +55 -0
- package/dist/src/css/compute-style/defaults.d.ts +3 -0
- package/dist/src/css/compute-style/defaults.js +34 -0
- package/dist/src/css/compute-style/display.d.ts +3 -0
- package/dist/src/css/compute-style/display.js +85 -0
- package/dist/src/css/compute-style/float.d.ts +2 -0
- package/dist/src/css/compute-style/float.js +13 -0
- package/dist/src/css/compute-style/font.d.ts +12 -0
- package/dist/src/css/compute-style/font.js +57 -0
- package/dist/src/css/compute-style/overrides.d.ts +3 -0
- package/dist/src/css/compute-style/overrides.js +241 -0
- package/dist/src/css/compute-style.d.ts +2 -0
- package/dist/src/css/compute-style.js +34 -487
- package/dist/src/css/enums.d.ts +4 -0
- package/dist/src/css/enums.js +5 -0
- package/dist/src/css/layout-property-resolver.js +30 -18
- package/dist/src/css/length.d.ts +26 -2
- package/dist/src/css/length.js +48 -0
- package/dist/src/css/parsers/background-parser.js +1 -1
- package/dist/src/css/parsers/calc-parser.d.ts +2 -0
- package/dist/src/css/parsers/calc-parser.js +310 -0
- package/dist/src/css/parsers/content-parser.d.ts +2 -1
- package/dist/src/css/parsers/content-parser.js +7 -2
- package/dist/src/css/parsers/dimension-parser.js +37 -18
- package/dist/src/css/parsers/display-flex-parser.d.ts +4 -0
- package/dist/src/css/parsers/display-flex-parser.js +97 -0
- package/dist/src/css/parsers/filter-parser.d.ts +14 -0
- package/dist/src/css/parsers/filter-parser.js +255 -0
- package/dist/src/css/parsers/grid-parser-extended.d.ts +1 -0
- package/dist/src/css/parsers/grid-parser-extended.js +40 -1
- package/dist/src/css/parsers/grid-parser.d.ts +5 -2
- package/dist/src/css/parsers/grid-parser.js +71 -7
- package/dist/src/css/parsers/length-parser.d.ts +8 -3
- package/dist/src/css/parsers/length-parser.js +45 -2
- package/dist/src/css/parsers/margin-block-parser.js +3 -3
- package/dist/src/css/parsers/margin-parser.js +3 -3
- package/dist/src/css/parsers/padding-block-parser.js +3 -3
- package/dist/src/css/parsers/padding-inline-parser.js +3 -3
- package/dist/src/css/parsers/padding-parser.js +6 -6
- package/dist/src/css/parsers/position-parser.js +2 -22
- package/dist/src/css/parsers/register-parsers.js +29 -2
- package/dist/src/css/parsers/word-break-parser.d.ts +2 -0
- package/dist/src/css/parsers/word-break-parser.js +23 -0
- package/dist/src/css/properties/grid.d.ts +16 -2
- package/dist/src/css/properties/layout.d.ts +3 -1
- package/dist/src/css/properties/layout.js +1 -1
- package/dist/src/css/properties/misc.d.ts +5 -0
- package/dist/src/css/properties/typography.d.ts +3 -0
- package/dist/src/css/properties/visual.d.ts +36 -0
- package/dist/src/css/shorthands/box-shorthand.d.ts +2 -2
- package/dist/src/css/style-inheritance.d.ts +2 -1
- package/dist/src/css/style-inheritance.js +1 -0
- package/dist/src/css/style.d.ts +30 -10
- package/dist/src/css/style.js +8 -1
- package/dist/src/css/ua-defaults/base-defaults.d.ts +1 -0
- package/dist/src/css/ua-defaults/base-defaults.js +10 -1
- package/dist/src/css/ua-defaults/element-defaults.js +0 -2
- package/dist/src/html/css/parse-css.d.ts +2 -0
- package/dist/src/html/css/parse-css.js +32 -3
- package/dist/src/html/dom-converter/background-images.d.ts +3 -0
- package/dist/src/html/dom-converter/background-images.js +88 -0
- package/dist/src/html/dom-converter/convert-dom-node.d.ts +5 -0
- package/dist/src/html/dom-converter/convert-dom-node.js +81 -0
- package/dist/src/html/dom-converter/handlers/br-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/br-handler.js +20 -0
- package/dist/src/html/dom-converter/handlers/form-control-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/form-control-handler.js +28 -0
- package/dist/src/html/dom-converter/handlers/img-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/img-handler.js +4 -0
- package/dist/src/html/dom-converter/handlers/index.d.ts +4 -0
- package/dist/src/html/dom-converter/handlers/index.js +19 -0
- package/dist/src/html/dom-converter/handlers/svg-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/svg-handler.js +32 -0
- package/dist/src/html/dom-converter/handlers/types.d.ts +12 -0
- package/dist/src/html/dom-converter/handlers/types.js +2 -0
- package/dist/src/html/dom-converter/helpers.d.ts +7 -0
- package/dist/src/html/dom-converter/helpers.js +35 -0
- package/dist/src/html/dom-converter/index.d.ts +1 -0
- package/dist/src/html/dom-converter/index.js +1 -0
- package/dist/src/html/dom-converter/pseudo-elements.d.ts +6 -0
- package/dist/src/html/dom-converter/pseudo-elements.js +48 -0
- package/dist/src/html/dom-converter/text.d.ts +15 -0
- package/dist/src/html/dom-converter/text.js +170 -0
- package/dist/src/html/dom-converter.d.ts +1 -5
- package/dist/src/html/dom-converter.js +1 -417
- package/dist/src/html/image-converter.d.ts +5 -0
- package/dist/src/html-to-pdf/document-css.d.ts +14 -0
- package/dist/src/html-to-pdf/document-css.js +45 -0
- package/dist/src/html-to-pdf/fonts.d.ts +16 -0
- package/dist/src/html-to-pdf/fonts.js +74 -0
- package/dist/src/html-to-pdf/header-footer.d.ts +14 -0
- package/dist/src/html-to-pdf/header-footer.js +101 -0
- package/dist/src/html-to-pdf/html-parser.d.ts +6 -0
- package/dist/src/html-to-pdf/html-parser.js +81 -0
- package/dist/src/html-to-pdf/index.d.ts +3 -0
- package/dist/src/html-to-pdf/index.js +2 -0
- package/dist/src/html-to-pdf/layout-build.d.ts +37 -0
- package/dist/src/html-to-pdf/layout-build.js +73 -0
- package/dist/src/html-to-pdf/prepare-html-render.d.ts +2 -0
- package/dist/src/html-to-pdf/prepare-html-render.js +121 -0
- package/dist/src/html-to-pdf/render-finalize.d.ts +15 -0
- package/dist/src/html-to-pdf/render-finalize.js +27 -0
- package/dist/src/html-to-pdf/render-html-to-pdf.d.ts +3 -0
- package/dist/src/html-to-pdf/render-html-to-pdf.js +25 -0
- package/dist/src/html-to-pdf/resource-loader.d.ts +6 -0
- package/dist/src/html-to-pdf/resource-loader.js +120 -0
- package/dist/src/html-to-pdf/types.d.ts +38 -0
- package/dist/src/html-to-pdf/types.js +2 -0
- package/dist/src/html-to-pdf.d.ts +1 -37
- package/dist/src/html-to-pdf.js +1 -537
- package/dist/src/image/js-png-backend.d.ts +7 -0
- package/dist/src/image/js-png-backend.js +9 -0
- package/dist/src/image/png-backend.d.ts +5 -0
- package/dist/src/image/png-backend.js +1 -0
- package/dist/src/image/png-wasm-loader.d.ts +5 -0
- package/dist/src/image/png-wasm-loader.js +59 -0
- package/dist/src/image/wasm/png_decoder_wasm.d.ts +8 -0
- package/dist/src/image/wasm/png_decoder_wasm.js +24 -0
- package/dist/src/image/wasm/png_decoder_wasm_bg.js +16 -0
- package/dist/src/image/wasm-png-backend.d.ts +6 -0
- package/dist/src/image/wasm-png-backend.js +17 -0
- package/dist/src/layout/counter.d.ts +1 -2
- package/dist/src/layout/counter.js +18 -18
- package/dist/src/layout/inline/inline-utils.d.ts +1 -1
- package/dist/src/layout/inline/inline-utils.js +8 -7
- package/dist/src/layout/inline/layout.js +16 -3
- package/dist/src/layout/inline/run-placer.d.ts +1 -0
- package/dist/src/layout/inline/run-placer.js +2 -10
- package/dist/src/layout/pipeline/out-of-flow-manager.js +25 -1
- package/dist/src/layout/strategies/block.js +35 -24
- package/dist/src/layout/strategies/flex.js +305 -61
- package/dist/src/layout/strategies/form.d.ts +2 -0
- package/dist/src/layout/strategies/form.js +38 -13
- package/dist/src/layout/strategies/grid.js +166 -29
- package/dist/src/layout/strategies/image.js +53 -27
- package/dist/src/layout/strategies/inline.js +26 -21
- package/dist/src/layout/strategies/table.js +26 -18
- package/dist/src/layout/utils/content-measurer.d.ts +1 -1
- package/dist/src/layout/utils/content-measurer.js +8 -7
- package/dist/src/layout/utils/floats.d.ts +1 -0
- package/dist/src/layout/utils/floats.js +14 -12
- package/dist/src/layout/utils/margin.d.ts +4 -4
- package/dist/src/layout/utils/margin.js +20 -16
- package/dist/src/layout/utils/node-math.d.ts +12 -6
- package/dist/src/layout/utils/node-math.js +71 -41
- package/dist/src/layout/utils/sizing.js +2 -1
- package/dist/src/pdf/font-subset/font-registry.d.ts +6 -0
- package/dist/src/pdf/font-subset/font-registry.js +30 -2
- package/dist/src/pdf/header-footer-renderer.js +12 -1
- package/dist/src/pdf/layout-tree-builder.js +5 -1
- package/dist/src/pdf/page-painter.js +13 -0
- package/dist/src/pdf/pagination.js +2 -2
- package/dist/src/pdf/renderer/box-painter.js +28 -3
- package/dist/src/pdf/renderer/page-paint.js +11 -3
- package/dist/src/pdf/renderers/radius-utils.js +31 -38
- package/dist/src/pdf/renderers/shape-renderer.js +1 -1
- package/dist/src/pdf/renderers/shape-utils.js +1 -1
- package/dist/src/pdf/renderers/text-renderer.d.ts +9 -1
- package/dist/src/pdf/renderers/text-renderer.js +36 -2
- package/dist/src/pdf/stacking/build-stacking-contexts.js +1 -2
- package/dist/src/pdf/stacking/resolve-paint-order.d.ts +5 -6
- package/dist/src/pdf/stacking/resolve-paint-order.js +29 -9
- package/dist/src/pdf/stacking/types.d.ts +14 -0
- package/dist/src/pdf/svg/shape-renderer.js +47 -20
- package/dist/src/pdf/types.d.ts +7 -1
- package/dist/src/pdf/utils/border-radius-utils.js +31 -38
- package/dist/src/pdf/utils/color-utils.js +17 -2
- package/dist/src/pdf/utils/filter-utils.d.ts +29 -0
- package/dist/src/pdf/utils/filter-utils.js +85 -0
- package/dist/src/pdf/utils/node-text-run-factory.js +1 -1
- package/dist/src/pdf/utils/text-layout-adjuster.d.ts +0 -8
- package/dist/src/pdf/utils/text-layout-adjuster.js +12 -9
- package/dist/src/units/units.d.ts +1 -1
- package/dist/tests/css/box-sizing.spec.d.ts +1 -0
- package/dist/tests/css/box-sizing.spec.js +46 -0
- package/dist/tests/css/calc-parser.spec.d.ts +1 -0
- package/dist/tests/css/calc-parser.spec.js +68 -0
- package/dist/tests/css/container-query-units.spec.d.ts +1 -0
- package/dist/tests/css/container-query-units.spec.js +64 -0
- package/dist/tests/css/content-parser.spec.js +13 -0
- package/dist/tests/css/filter-parser.spec.d.ts +1 -0
- package/dist/tests/css/filter-parser.spec.js +116 -0
- package/dist/tests/css/flex-shorthand.spec.d.ts +1 -0
- package/dist/tests/css/flex-shorthand.spec.js +45 -0
- package/dist/tests/css/grid-clamp.spec.d.ts +1 -0
- package/dist/tests/css/grid-clamp.spec.js +82 -0
- package/dist/tests/css/parse-css-pseudo.spec.d.ts +1 -0
- package/dist/tests/css/parse-css-pseudo.spec.js +26 -0
- package/dist/tests/helpers/render-utils.d.ts +18 -2
- package/dist/tests/helpers/render-utils.js +25 -12
- package/dist/tests/html/dom-converter-pseudo-elements.spec.d.ts +1 -0
- package/dist/tests/html/dom-converter-pseudo-elements.spec.js +33 -0
- package/dist/tests/html/dom-converter-text.spec.d.ts +1 -0
- package/dist/tests/html/dom-converter-text.spec.js +67 -0
- package/dist/tests/image/png-backend.spec.d.ts +1 -0
- package/dist/tests/image/png-backend.spec.js +34 -0
- package/dist/tests/layout/box-sizing.spec.d.ts +1 -0
- package/dist/tests/layout/box-sizing.spec.js +75 -0
- package/dist/tests/layout/calc-padding.spec.d.ts +1 -0
- package/dist/tests/layout/calc-padding.spec.js +19 -0
- package/dist/tests/layout/container-query-units.spec.d.ts +1 -0
- package/dist/tests/layout/container-query-units.spec.js +24 -0
- package/dist/tests/layout/flex-auto-height.spec.d.ts +1 -0
- package/dist/tests/layout/flex-auto-height.spec.js +35 -0
- package/dist/tests/layout/flex-wrap-cards.spec.d.ts +1 -0
- package/dist/tests/layout/flex-wrap-cards.spec.js +16 -0
- package/dist/tests/layout/flex-wrap-grow-align-content.spec.d.ts +1 -0
- package/dist/tests/layout/flex-wrap-grow-align-content.spec.js +20 -0
- package/dist/tests/layout/grid-clamp-gap.spec.d.ts +1 -0
- package/dist/tests/layout/grid-clamp-gap.spec.js +22 -0
- package/dist/tests/layout/inline-fragments.spec.js +38 -0
- package/dist/tests/layout/paged-body-margin.spec.d.ts +1 -0
- package/dist/tests/layout/paged-body-margin.spec.js +92 -0
- package/dist/tests/layout/pseudo-counters-generated-content.spec.d.ts +1 -0
- package/dist/tests/layout/pseudo-counters-generated-content.spec.js +51 -0
- package/dist/tests/layout/responsive-clamp-grid-parity.spec.d.ts +1 -0
- package/dist/tests/layout/responsive-clamp-grid-parity.spec.js +75 -0
- package/dist/tests/layout/run-placer-baseline.spec.js +13 -11
- package/dist/tests/pdf/backdrop-filter-noop.spec.d.ts +1 -0
- package/dist/tests/pdf/backdrop-filter-noop.spec.js +140 -0
- package/dist/tests/pdf/filter-drop-shadow.spec.d.ts +1 -0
- package/dist/tests/pdf/filter-drop-shadow.spec.js +74 -0
- package/dist/tests/pdf/filter-opacity.spec.d.ts +1 -0
- package/dist/tests/pdf/filter-opacity.spec.js +30 -0
- package/dist/tests/pdf/font-subset-registry-key.spec.d.ts +1 -0
- package/dist/tests/pdf/font-subset-registry-key.spec.js +66 -0
- package/dist/tests/pdf/selawik-opt-in.spec.d.ts +1 -0
- package/dist/tests/pdf/selawik-opt-in.spec.js +106 -0
- package/dist/tests/pdf/system-ui-fallback-subset-regression.spec.d.ts +1 -0
- package/dist/tests/pdf/system-ui-fallback-subset-regression.spec.js +39 -0
- package/dist/tests/pdf/text-renderer-fallback.spec.js +55 -0
- package/dist/tests/pdf/text-transform-matrix.spec.js +8 -7
- package/package.json +2 -2
|
@@ -25,9 +25,17 @@ export async function paintLayoutPage({ pageTree, pageNumber, totalPages, pageSi
|
|
|
25
25
|
if (headerFooterLayout.layerMode === LayerMode.Under) {
|
|
26
26
|
await paintHeaderFooter(painter, headerVariant, footerVariant, tokens, pageNumber, totalPages, headerFooterTextOptions, true, hfContext);
|
|
27
27
|
}
|
|
28
|
-
// Paint each
|
|
29
|
-
for (const
|
|
30
|
-
|
|
28
|
+
// Paint each instruction in the resolved paint order.
|
|
29
|
+
for (const instruction of pageTree.paintOrder) {
|
|
30
|
+
if (instruction.type === 'beginOpacity') {
|
|
31
|
+
painter.beginOpacityScope(instruction.opacity);
|
|
32
|
+
}
|
|
33
|
+
else if (instruction.type === 'endOpacity') {
|
|
34
|
+
painter.endOpacityScope(0);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
await paintBoxAtomic(painter, instruction.box);
|
|
38
|
+
}
|
|
31
39
|
}
|
|
32
40
|
if (headerFooterLayout.layerMode === LayerMode.Over) {
|
|
33
41
|
await paintHeaderFooter(painter, headerVariant, footerVariant, tokens, pageNumber, totalPages, headerFooterTextOptions, false, hfContext);
|
|
@@ -15,45 +15,38 @@ export function normalizeRadiiForRect(width, height, radii) {
|
|
|
15
15
|
};
|
|
16
16
|
const safeWidth = Math.max(width, 0);
|
|
17
17
|
const safeHeight = Math.max(height, 0);
|
|
18
|
-
if (safeWidth <= 0) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
if (safeWidth <= 0 || safeHeight <= 0) {
|
|
19
|
+
return {
|
|
20
|
+
topLeft: { x: 0, y: 0 },
|
|
21
|
+
topRight: { x: 0, y: 0 },
|
|
22
|
+
bottomRight: { x: 0, y: 0 },
|
|
23
|
+
bottomLeft: { x: 0, y: 0 },
|
|
24
|
+
};
|
|
23
25
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
result.
|
|
41
|
-
result.
|
|
42
|
-
result.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
result.topLeft.y *= scale;
|
|
49
|
-
result.bottomLeft.y *= scale;
|
|
50
|
-
}
|
|
51
|
-
const rightSum = result.topRight.y + result.bottomRight.y;
|
|
52
|
-
if (rightSum > safeHeight && rightSum > 0) {
|
|
53
|
-
const scale = safeHeight / rightSum;
|
|
54
|
-
result.topRight.y *= scale;
|
|
55
|
-
result.bottomRight.y *= scale;
|
|
56
|
-
}
|
|
26
|
+
// CSS Backgrounds § 5.5: compute a single scale factor f = min(Li/Si)
|
|
27
|
+
// across all four sides, then multiply ALL radii by f if f < 1.
|
|
28
|
+
let f = 1;
|
|
29
|
+
const topSumX = result.topLeft.x + result.topRight.x;
|
|
30
|
+
if (topSumX > 0)
|
|
31
|
+
f = Math.min(f, safeWidth / topSumX);
|
|
32
|
+
const bottomSumX = result.bottomLeft.x + result.bottomRight.x;
|
|
33
|
+
if (bottomSumX > 0)
|
|
34
|
+
f = Math.min(f, safeWidth / bottomSumX);
|
|
35
|
+
const leftSumY = result.topLeft.y + result.bottomLeft.y;
|
|
36
|
+
if (leftSumY > 0)
|
|
37
|
+
f = Math.min(f, safeHeight / leftSumY);
|
|
38
|
+
const rightSumY = result.topRight.y + result.bottomRight.y;
|
|
39
|
+
if (rightSumY > 0)
|
|
40
|
+
f = Math.min(f, safeHeight / rightSumY);
|
|
41
|
+
if (f < 1) {
|
|
42
|
+
result.topLeft.x *= f;
|
|
43
|
+
result.topLeft.y *= f;
|
|
44
|
+
result.topRight.x *= f;
|
|
45
|
+
result.topRight.y *= f;
|
|
46
|
+
result.bottomRight.x *= f;
|
|
47
|
+
result.bottomRight.y *= f;
|
|
48
|
+
result.bottomLeft.x *= f;
|
|
49
|
+
result.bottomLeft.y *= f;
|
|
57
50
|
}
|
|
58
51
|
return result;
|
|
59
52
|
}
|
|
@@ -431,7 +431,7 @@ export class ShapeRenderer {
|
|
|
431
431
|
const scaleY = this.coordinateTransformer.convertPxToPt(1);
|
|
432
432
|
const translateX = this.coordinateTransformer.convertPxToPt(relX);
|
|
433
433
|
const translateY = this.coordinateTransformer.convertPxToPt(-relY); // Negative because PDF y-axis is flipped
|
|
434
|
-
return `${formatNumber(scaleX)} 0 0 ${formatNumber(scaleY)} ${formatNumber(translateX)} ${formatNumber(translateY)} cm`;
|
|
434
|
+
return `${formatNumber(scaleX)} 0 0 ${formatNumber(-scaleY)} ${formatNumber(translateX)} ${formatNumber(translateY)} cm`;
|
|
435
435
|
}
|
|
436
436
|
// Normal absolute positioning
|
|
437
437
|
const scaleX = this.coordinateTransformer.convertPxToPt(1);
|
|
@@ -133,7 +133,7 @@ export function transformForRect(rect, coordinateTransformer, transformContext)
|
|
|
133
133
|
const scaleY = coordinateTransformer.convertPxToPt(1);
|
|
134
134
|
const translateX = coordinateTransformer.convertPxToPt(relX);
|
|
135
135
|
const translateY = coordinateTransformer.convertPxToPt(-relY); // Negative because PDF y-axis is flipped
|
|
136
|
-
return `${formatNumber(scaleX)} 0 0 ${formatNumber(scaleY)} ${formatNumber(translateX)} ${formatNumber(translateY)} cm`;
|
|
136
|
+
return `${formatNumber(scaleX)} 0 0 ${formatNumber(-scaleY)} ${formatNumber(translateX)} ${formatNumber(translateY)} cm`;
|
|
137
137
|
}
|
|
138
138
|
// Normal absolute positioning
|
|
139
139
|
const scaleX = coordinateTransformer.convertPxToPt(1);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Run, TextPaintOptions } from "../types.js";
|
|
1
|
+
import type { Run, TextPaintOptions, Rect } from "../types.js";
|
|
2
2
|
import type { FontRegistry } from "../font/font-registry.js";
|
|
3
3
|
import type { PdfObjectRef } from "../primitives/pdf-document.js";
|
|
4
4
|
import { CoordinateTransformer } from "../utils/coordinate-transformer.js";
|
|
@@ -21,6 +21,7 @@ export declare class TextRenderer {
|
|
|
21
21
|
private readonly fontResolver;
|
|
22
22
|
private readonly gradientService;
|
|
23
23
|
private readonly patterns;
|
|
24
|
+
private transformContext;
|
|
24
25
|
constructor(coordinateTransformer: CoordinateTransformer, fontRegistry: FontRegistry, imageRenderer?: ImageRenderer, graphicsStateManager?: GraphicsStateManager);
|
|
25
26
|
drawText(text: string, xPx: number, yPx: number, options?: TextPaintOptions): Promise<void>;
|
|
26
27
|
drawTextRun(run: Run): Promise<void>;
|
|
@@ -29,5 +30,12 @@ export declare class TextRenderer {
|
|
|
29
30
|
private registerSubsetFont;
|
|
30
31
|
private fillGradientRect;
|
|
31
32
|
private fillPatternRect;
|
|
33
|
+
/**
|
|
34
|
+
* Drain (return and clear) all buffered commands so they can be pushed
|
|
35
|
+
* into the unified shape command stream, preserving paint order.
|
|
36
|
+
*/
|
|
37
|
+
flushCommands(): string[];
|
|
38
|
+
setTransformContext(rect: Rect): void;
|
|
39
|
+
clearTransformContext(): void;
|
|
32
40
|
getResult(): TextRendererResult;
|
|
33
41
|
}
|
|
@@ -19,6 +19,7 @@ export class TextRenderer {
|
|
|
19
19
|
this.commands = [];
|
|
20
20
|
this.fonts = new Map();
|
|
21
21
|
this.patterns = new Map();
|
|
22
|
+
this.transformContext = null;
|
|
22
23
|
this.graphicsStateManager = graphicsStateManager;
|
|
23
24
|
this.fontResolver = new TextFontResolver(fontRegistry);
|
|
24
25
|
this.shadowRenderer = new TextShadowRenderer(coordinateTransformer, fontRegistry, imageRenderer, graphicsStateManager);
|
|
@@ -87,7 +88,7 @@ export class TextRenderer {
|
|
|
87
88
|
text: run.text.slice(0, 64),
|
|
88
89
|
glyphCount: glyphRun.glyphIds.length,
|
|
89
90
|
});
|
|
90
|
-
const textMatrix = buildPdfTextMatrix(run, this.coordinateTransformer);
|
|
91
|
+
const textMatrix = buildPdfTextMatrix(run, this.coordinateTransformer, this.transformContext);
|
|
91
92
|
log("paint", "debug", "drawing text run with glyphs", {
|
|
92
93
|
text: run.text.slice(0, 32),
|
|
93
94
|
glyphIds: glyphRun.glyphIds.slice(0, 10),
|
|
@@ -198,6 +199,20 @@ export class TextRenderer {
|
|
|
198
199
|
"f",
|
|
199
200
|
];
|
|
200
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Drain (return and clear) all buffered commands so they can be pushed
|
|
204
|
+
* into the unified shape command stream, preserving paint order.
|
|
205
|
+
*/
|
|
206
|
+
flushCommands() {
|
|
207
|
+
const cmds = this.commands.splice(0, this.commands.length);
|
|
208
|
+
return cmds;
|
|
209
|
+
}
|
|
210
|
+
setTransformContext(rect) {
|
|
211
|
+
this.transformContext = rect;
|
|
212
|
+
}
|
|
213
|
+
clearTransformContext() {
|
|
214
|
+
this.transformContext = null;
|
|
215
|
+
}
|
|
201
216
|
getResult() {
|
|
202
217
|
return {
|
|
203
218
|
commands: [...this.commands],
|
|
@@ -207,7 +222,7 @@ export class TextRenderer {
|
|
|
207
222
|
};
|
|
208
223
|
}
|
|
209
224
|
}
|
|
210
|
-
function buildPdfTextMatrix(run, transformer) {
|
|
225
|
+
function buildPdfTextMatrix(run, transformer, transformContext = null) {
|
|
211
226
|
const base = run.lineMatrix ?? { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
|
|
212
227
|
if (!run.lineMatrix) {
|
|
213
228
|
log("paint", "debug", "Run provided without lineMatrix, using identity fallback", {
|
|
@@ -215,6 +230,25 @@ function buildPdfTextMatrix(run, transformer) {
|
|
|
215
230
|
fontFamily: run.fontFamily,
|
|
216
231
|
});
|
|
217
232
|
}
|
|
233
|
+
if (transformContext) {
|
|
234
|
+
const relMatrix = {
|
|
235
|
+
a: base.a,
|
|
236
|
+
b: base.b,
|
|
237
|
+
c: base.c,
|
|
238
|
+
d: base.d,
|
|
239
|
+
e: base.e - transformContext.x,
|
|
240
|
+
f: base.f - transformContext.y,
|
|
241
|
+
};
|
|
242
|
+
const pdfPx = svgMatrixToPdf(relMatrix) ?? { a: 1, b: 0, c: 0, d: 1, e: relMatrix.e, f: relMatrix.f };
|
|
243
|
+
return {
|
|
244
|
+
a: pdfPx.a,
|
|
245
|
+
b: pdfPx.b,
|
|
246
|
+
c: pdfPx.c,
|
|
247
|
+
d: pdfPx.d,
|
|
248
|
+
e: transformer.convertPxToPt(pdfPx.e),
|
|
249
|
+
f: transformer.convertPxToPt(pdfPx.f),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
218
252
|
const offsetPx = transformer.pageOffsetPx;
|
|
219
253
|
// Normalize to page origin (top-left), removing any page offset.
|
|
220
254
|
const local = {
|
|
@@ -7,8 +7,7 @@ export function getStackingFlags(box) {
|
|
|
7
7
|
const raw = box.zIndexComputed;
|
|
8
8
|
const hasNumericZ = typeof raw === "number" && Number.isFinite(raw);
|
|
9
9
|
const zIndex = hasNumericZ ? raw : "auto";
|
|
10
|
-
|
|
11
|
-
const establishesContext = isPositioned && hasNumericZ;
|
|
10
|
+
const establishesContext = box.establishesStackingContext || (isPositioned && hasNumericZ);
|
|
12
11
|
return { isPositioned, zIndex, establishesContext };
|
|
13
12
|
}
|
|
14
13
|
/**
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { RenderBox } from "../types.js";
|
|
2
|
+
import type { PaintInstruction } from "./types.js";
|
|
2
3
|
/**
|
|
3
4
|
* Resolve a global paint order from the RenderBox tree using stacking contexts.
|
|
4
5
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - Treat each box as an atomic paint unit (background+border+content together).
|
|
9
|
-
* - Keep API simple: return ordered RenderBox list.
|
|
6
|
+
* Returns an ordered list of PaintInstructions that includes opacity scope
|
|
7
|
+
* markers (beginOpacity/endOpacity) around stacking contexts whose root box
|
|
8
|
+
* has effective opacity < 1 (from CSS opacity or filter: opacity()).
|
|
10
9
|
*/
|
|
11
|
-
export declare function resolvePaintOrder(root: RenderBox):
|
|
10
|
+
export declare function resolvePaintOrder(root: RenderBox): PaintInstruction[];
|
|
@@ -2,20 +2,32 @@ import { buildStackingContexts, getStackingFlags } from "./build-stacking-contex
|
|
|
2
2
|
/**
|
|
3
3
|
* Resolve a global paint order from the RenderBox tree using stacking contexts.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - Treat each box as an atomic paint unit (background+border+content together).
|
|
9
|
-
* - Keep API simple: return ordered RenderBox list.
|
|
5
|
+
* Returns an ordered list of PaintInstructions that includes opacity scope
|
|
6
|
+
* markers (beginOpacity/endOpacity) around stacking contexts whose root box
|
|
7
|
+
* has effective opacity < 1 (from CSS opacity or filter: opacity()).
|
|
10
8
|
*/
|
|
11
9
|
export function resolvePaintOrder(root) {
|
|
12
10
|
const { rootContextId, contexts } = buildStackingContexts(root);
|
|
13
11
|
const steps = [];
|
|
14
12
|
resolveContextPaintOrder(rootContextId, contexts, steps);
|
|
15
|
-
return steps
|
|
13
|
+
return steps;
|
|
16
14
|
}
|
|
17
15
|
/**
|
|
18
|
-
* Compute
|
|
16
|
+
* Compute effective opacity for a box, combining CSS opacity and filter opacity().
|
|
17
|
+
*/
|
|
18
|
+
function computeEffectiveOpacity(box) {
|
|
19
|
+
let opacity = box.opacity;
|
|
20
|
+
if (box.filter) {
|
|
21
|
+
for (const fn of box.filter) {
|
|
22
|
+
if (fn.kind === 'opacity') {
|
|
23
|
+
opacity *= fn.value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return Math.max(0, Math.min(1, opacity));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Compute paint order within a stacking context and append PaintInstructions.
|
|
19
31
|
*
|
|
20
32
|
* Simplified rules (sufficient for our current constraints):
|
|
21
33
|
* For a given context:
|
|
@@ -33,7 +45,7 @@ function resolveContextPaintOrder(contextId, contexts, out) {
|
|
|
33
45
|
return;
|
|
34
46
|
const rootBox = context.box;
|
|
35
47
|
// 1. Paint the context root box as an atomic unit.
|
|
36
|
-
out.push({ box: rootBox });
|
|
48
|
+
out.push({ type: 'box', box: rootBox });
|
|
37
49
|
// Collect direct descendants belonging to this context (non-root boxes).
|
|
38
50
|
const descendants = [];
|
|
39
51
|
collectDescendantsInContext(rootBox, contextId, contexts, descendants);
|
|
@@ -86,14 +98,22 @@ function resolveContextPaintOrder(contextId, contexts, out) {
|
|
|
86
98
|
/**
|
|
87
99
|
* Append either a nested stacking context or a regular box.
|
|
88
100
|
* Nested contexts are treated as atomic units: we delegate to resolveContextPaintOrder.
|
|
101
|
+
* When a nested context root has effective opacity < 1, wrap with begin/endOpacity markers.
|
|
89
102
|
*/
|
|
90
103
|
function appendBoxOrContext(box, parentContextId, contexts, out) {
|
|
91
104
|
const nested = findContextByBox(box, parentContextId, contexts);
|
|
92
105
|
if (nested) {
|
|
106
|
+
const effectiveOpacity = computeEffectiveOpacity(nested.box);
|
|
107
|
+
if (effectiveOpacity < 1) {
|
|
108
|
+
out.push({ type: 'beginOpacity', opacity: effectiveOpacity });
|
|
109
|
+
}
|
|
93
110
|
resolveContextPaintOrder(nested.id, contexts, out);
|
|
111
|
+
if (effectiveOpacity < 1) {
|
|
112
|
+
out.push({ type: 'endOpacity' });
|
|
113
|
+
}
|
|
94
114
|
}
|
|
95
115
|
else {
|
|
96
|
-
out.push({ box });
|
|
116
|
+
out.push({ type: 'box', box });
|
|
97
117
|
}
|
|
98
118
|
}
|
|
99
119
|
/**
|
|
@@ -34,3 +34,17 @@ export interface StackingFlags {
|
|
|
34
34
|
export interface PaintStep {
|
|
35
35
|
box: RenderBox;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* A paint instruction in the resolved paint order.
|
|
39
|
+
* - `box`: paint a single RenderBox atomically.
|
|
40
|
+
* - `beginOpacity` / `endOpacity`: wrap a stacking context group in an opacity scope.
|
|
41
|
+
*/
|
|
42
|
+
export type PaintInstruction = {
|
|
43
|
+
type: 'box';
|
|
44
|
+
box: RenderBox;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'beginOpacity';
|
|
47
|
+
opacity: number;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'endOpacity';
|
|
50
|
+
};
|
|
@@ -309,10 +309,24 @@ function svgLinearNodeToLinearGradient(node, context) {
|
|
|
309
309
|
const stops = (node.stops ?? []).map((s) => ({ color: s.color, position: s.offset }));
|
|
310
310
|
// Default: objectBoundingBox coordinates (ratio 0..1)
|
|
311
311
|
const units = node.gradientUnits === "userSpaceOnUse" ? "userSpace" : "ratio";
|
|
312
|
+
const rawTransform = (node.attributes && (node.attributes["gradientTransform"] ?? node.attributes["gradienttransform"]));
|
|
313
|
+
const transform = rawTransform ? parseTransform(rawTransform) || undefined : undefined;
|
|
312
314
|
// If userSpaceOnUse, map points to page pixels using the SVG render context
|
|
313
315
|
if (units === "userSpace" && context) {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
+
let ux1 = x1;
|
|
317
|
+
let uy1 = y1;
|
|
318
|
+
let ux2 = x2;
|
|
319
|
+
let uy2 = y2;
|
|
320
|
+
if (transform) {
|
|
321
|
+
const tp1 = applyMatrixToPoint(transform, ux1, uy1);
|
|
322
|
+
const tp2 = applyMatrixToPoint(transform, ux2, uy2);
|
|
323
|
+
ux1 = tp1.x;
|
|
324
|
+
uy1 = tp1.y;
|
|
325
|
+
ux2 = tp2.x;
|
|
326
|
+
uy2 = tp2.y;
|
|
327
|
+
}
|
|
328
|
+
const p1 = mapSvgPoint(ux1, uy1, context);
|
|
329
|
+
const p2 = mapSvgPoint(ux2, uy2, context);
|
|
316
330
|
if (p1 && p2) {
|
|
317
331
|
// coords in absolute page pixels; gradient-service will convert to rectangle-local points
|
|
318
332
|
return { type: "linear", direction: "to right", stops, coords: { x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y, units: "userSpace" } };
|
|
@@ -323,13 +337,9 @@ function svgLinearNodeToLinearGradient(node, context) {
|
|
|
323
337
|
// Apply gradientTransform if present — treat it as operating in gradient coordinate space
|
|
324
338
|
let rp1 = { x: x1, y: y1 };
|
|
325
339
|
let rp2 = { x: x2, y: y2 };
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if (t) {
|
|
330
|
-
rp1 = applyMatrixToPoint(t, rp1.x, rp1.y);
|
|
331
|
-
rp2 = applyMatrixToPoint(t, rp2.x, rp2.y);
|
|
332
|
-
}
|
|
340
|
+
if (transform) {
|
|
341
|
+
rp1 = applyMatrixToPoint(transform, rp1.x, rp1.y);
|
|
342
|
+
rp2 = applyMatrixToPoint(transform, rp2.x, rp2.y);
|
|
333
343
|
}
|
|
334
344
|
// compute direction angle from ratio coords (useful when no explicit coords provided)
|
|
335
345
|
const dx = rp2.x - rp1.x;
|
|
@@ -346,12 +356,33 @@ function svgRadialNodeToRadialGradient(node, context) {
|
|
|
346
356
|
const fy = node.fy;
|
|
347
357
|
const stops = (node.stops ?? []).map((s) => ({ color: s.color, position: s.offset }));
|
|
348
358
|
const units = node.gradientUnits === "userSpaceOnUse" ? "userSpace" : "ratio";
|
|
359
|
+
const rawTransform = (node.attributes && (node.attributes["gradientTransform"] ?? node.attributes["gradienttransform"]));
|
|
360
|
+
const transform = rawTransform ? parseTransform(rawTransform) || undefined : undefined;
|
|
349
361
|
if (units === "userSpace" && context) {
|
|
350
|
-
|
|
351
|
-
|
|
362
|
+
let ucx = cx;
|
|
363
|
+
let ucy = cy;
|
|
364
|
+
let ufx = fx;
|
|
365
|
+
let ufy = fy;
|
|
366
|
+
let edgeX = cx + r;
|
|
367
|
+
let edgeY = cy;
|
|
368
|
+
if (transform) {
|
|
369
|
+
const tc = applyMatrixToPoint(transform, ucx, ucy);
|
|
370
|
+
ucx = tc.x;
|
|
371
|
+
ucy = tc.y;
|
|
372
|
+
const te = applyMatrixToPoint(transform, edgeX, edgeY);
|
|
373
|
+
edgeX = te.x;
|
|
374
|
+
edgeY = te.y;
|
|
375
|
+
if (ufx !== undefined && ufy !== undefined) {
|
|
376
|
+
const tf = applyMatrixToPoint(transform, ufx, ufy);
|
|
377
|
+
ufx = tf.x;
|
|
378
|
+
ufy = tf.y;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const center = mapSvgPoint(ucx, ucy, context);
|
|
382
|
+
const focal = ufx !== undefined && ufy !== undefined ? mapSvgPoint(ufx, ufy, context) : undefined;
|
|
352
383
|
const radiusPt = (() => {
|
|
353
384
|
// map a point at cx + r, cy to user space and compute distance
|
|
354
|
-
const edge = mapSvgPoint(
|
|
385
|
+
const edge = mapSvgPoint(edgeX, edgeY, context);
|
|
355
386
|
if (center && edge) {
|
|
356
387
|
const dx = edge.x - center.x;
|
|
357
388
|
const dy = edge.y - center.y;
|
|
@@ -392,14 +423,10 @@ function svgRadialNodeToRadialGradient(node, context) {
|
|
|
392
423
|
radRatio.fx = fx;
|
|
393
424
|
radRatio.fy = fy;
|
|
394
425
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
// Preserve the parsed transform matrix on the RadialGradient for use by the
|
|
400
|
-
// gradient service when building the PDF shading dictionary.
|
|
401
|
-
radRatio.transform = { a: t.a, b: t.b, c: t.c, d: t.d, e: t.e, f: t.f };
|
|
402
|
-
}
|
|
426
|
+
if (transform) {
|
|
427
|
+
// Preserve the parsed transform matrix on the RadialGradient for use by the
|
|
428
|
+
// gradient service when building the PDF shading dictionary.
|
|
429
|
+
radRatio.transform = { a: transform.a, b: transform.b, c: transform.c, d: transform.d, e: transform.e, f: transform.f };
|
|
403
430
|
}
|
|
404
431
|
return radRatio;
|
|
405
432
|
}
|
package/dist/src/pdf/types.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { BackgroundRepeat, Gradient } from "../css/background-types.js";
|
|
2
2
|
import type { GlyphRun } from "../layout/text-run.js";
|
|
3
|
+
import type { FilterFunction } from "../css/properties/visual.js";
|
|
4
|
+
import type { PaintInstruction } from "./stacking/types.js";
|
|
3
5
|
export declare enum NodeKind {
|
|
4
6
|
Container = "container",
|
|
5
7
|
TextRuns = "text-runs",
|
|
@@ -198,7 +200,7 @@ export interface Positioning {
|
|
|
198
200
|
type: "normal" | "float" | "absolute" | "fixed" | "sticky";
|
|
199
201
|
}
|
|
200
202
|
export interface LayoutPageTree {
|
|
201
|
-
paintOrder:
|
|
203
|
+
paintOrder: PaintInstruction[];
|
|
202
204
|
floatLayerOrder: RenderBox[];
|
|
203
205
|
flowContentOrder: RenderBox[];
|
|
204
206
|
positionedLayersSortedByZ: PositionedLayer[];
|
|
@@ -255,6 +257,10 @@ export interface RenderBox {
|
|
|
255
257
|
borderStyle?: BorderStyles;
|
|
256
258
|
color?: RGBA;
|
|
257
259
|
transform?: TextMatrix;
|
|
260
|
+
/** Parsed CSS filter functions carried from ComputedStyle */
|
|
261
|
+
filter?: FilterFunction[];
|
|
262
|
+
/** Parsed CSS backdrop-filter functions carried from ComputedStyle */
|
|
263
|
+
backdropFilter?: FilterFunction[];
|
|
258
264
|
/**
|
|
259
265
|
* Normalized text alignment of this box (from CSS text-align).
|
|
260
266
|
* Only the visual modes are captured here.
|
|
@@ -35,45 +35,38 @@ export function normalizeBorderRadius(input, width, height) {
|
|
|
35
35
|
};
|
|
36
36
|
const safeWidth = Math.max(width, 0);
|
|
37
37
|
const safeHeight = Math.max(height, 0);
|
|
38
|
-
if (safeWidth <= 0) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
if (safeWidth <= 0 || safeHeight <= 0) {
|
|
39
|
+
return {
|
|
40
|
+
topLeft: { x: 0, y: 0 },
|
|
41
|
+
topRight: { x: 0, y: 0 },
|
|
42
|
+
bottomRight: { x: 0, y: 0 },
|
|
43
|
+
bottomLeft: { x: 0, y: 0 },
|
|
44
|
+
};
|
|
43
45
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
result.
|
|
61
|
-
result.
|
|
62
|
-
result.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
result.topLeft.y *= scale;
|
|
69
|
-
result.bottomLeft.y *= scale;
|
|
70
|
-
}
|
|
71
|
-
const rightSum = result.topRight.y + result.bottomRight.y;
|
|
72
|
-
if (rightSum > safeHeight && rightSum > 0) {
|
|
73
|
-
const scale = safeHeight / rightSum;
|
|
74
|
-
result.topRight.y *= scale;
|
|
75
|
-
result.bottomRight.y *= scale;
|
|
76
|
-
}
|
|
46
|
+
// CSS Backgrounds § 5.5: compute a single scale factor f = min(Li/Si)
|
|
47
|
+
// across all four sides, then multiply ALL radii by f if f < 1.
|
|
48
|
+
let f = 1;
|
|
49
|
+
const topSumX = result.topLeft.x + result.topRight.x;
|
|
50
|
+
if (topSumX > 0)
|
|
51
|
+
f = Math.min(f, safeWidth / topSumX);
|
|
52
|
+
const bottomSumX = result.bottomLeft.x + result.bottomRight.x;
|
|
53
|
+
if (bottomSumX > 0)
|
|
54
|
+
f = Math.min(f, safeWidth / bottomSumX);
|
|
55
|
+
const leftSumY = result.topLeft.y + result.bottomLeft.y;
|
|
56
|
+
if (leftSumY > 0)
|
|
57
|
+
f = Math.min(f, safeHeight / leftSumY);
|
|
58
|
+
const rightSumY = result.topRight.y + result.bottomRight.y;
|
|
59
|
+
if (rightSumY > 0)
|
|
60
|
+
f = Math.min(f, safeHeight / rightSumY);
|
|
61
|
+
if (f < 1) {
|
|
62
|
+
result.topLeft.x *= f;
|
|
63
|
+
result.topLeft.y *= f;
|
|
64
|
+
result.topRight.x *= f;
|
|
65
|
+
result.topRight.y *= f;
|
|
66
|
+
result.bottomRight.x *= f;
|
|
67
|
+
result.bottomRight.y *= f;
|
|
68
|
+
result.bottomLeft.x *= f;
|
|
69
|
+
result.bottomLeft.y *= f;
|
|
77
70
|
}
|
|
78
71
|
return result;
|
|
79
72
|
}
|
|
@@ -10,7 +10,7 @@ export function parseColor(value) {
|
|
|
10
10
|
if (normalized === "transparent") {
|
|
11
11
|
return undefined;
|
|
12
12
|
}
|
|
13
|
-
const hexMatch = normalized.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
|
|
13
|
+
const hexMatch = normalized.match(/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i);
|
|
14
14
|
if (hexMatch) {
|
|
15
15
|
const digits = hexMatch[1];
|
|
16
16
|
if (digits.length === 3) {
|
|
@@ -19,10 +19,25 @@ export function parseColor(value) {
|
|
|
19
19
|
const b = parseHex(digits[2] + digits[2]);
|
|
20
20
|
return { r, g, b, a: 1 };
|
|
21
21
|
}
|
|
22
|
+
if (digits.length === 4) {
|
|
23
|
+
const r = parseHex(digits[0] + digits[0]);
|
|
24
|
+
const g = parseHex(digits[1] + digits[1]);
|
|
25
|
+
const b = parseHex(digits[2] + digits[2]);
|
|
26
|
+
const a = parseHex(digits[3] + digits[3]) / 255;
|
|
27
|
+
return { r, g, b, a };
|
|
28
|
+
}
|
|
29
|
+
if (digits.length === 6) {
|
|
30
|
+
const r = parseHex(digits.slice(0, 2));
|
|
31
|
+
const g = parseHex(digits.slice(2, 4));
|
|
32
|
+
const b = parseHex(digits.slice(4, 6));
|
|
33
|
+
return { r, g, b, a: 1 };
|
|
34
|
+
}
|
|
35
|
+
// 8 digits
|
|
22
36
|
const r = parseHex(digits.slice(0, 2));
|
|
23
37
|
const g = parseHex(digits.slice(2, 4));
|
|
24
38
|
const b = parseHex(digits.slice(4, 6));
|
|
25
|
-
|
|
39
|
+
const a = parseHex(digits.slice(6, 8)) / 255;
|
|
40
|
+
return { r, g, b, a };
|
|
26
41
|
}
|
|
27
42
|
const rgbMatch = normalized.match(/^rgba?\((.+)\)$/);
|
|
28
43
|
if (rgbMatch) {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { FilterFunction } from "../../css/properties/visual.js";
|
|
2
|
+
import type { RGBA, ShadowLayer } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Extrai o multiplicador de opacity de uma lista de filter functions.
|
|
5
|
+
* Múltiplos `opacity()` são multiplicados entre si (composição sequencial).
|
|
6
|
+
* Retorna 1.0 se não houver `opacity()` na lista.
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractOpacityMultiplier(filters: FilterFunction[]): number;
|
|
9
|
+
/**
|
|
10
|
+
* Converte `drop-shadow()` do filter em ShadowLayer[] compatível
|
|
11
|
+
* com o pipeline de box-shadow existente.
|
|
12
|
+
*
|
|
13
|
+
* Diferenças em relação a box-shadow real:
|
|
14
|
+
* - Sem `inset` (sempre false).
|
|
15
|
+
* - Sem `spread-radius` (sempre 0).
|
|
16
|
+
* - Na prática do CSS, drop-shadow segue a forma alpha do conteúdo,
|
|
17
|
+
* mas no MVP aproximamos como sombra retangular (box-shadow).
|
|
18
|
+
*/
|
|
19
|
+
export declare function extractDropShadowLayers(filters: FilterFunction[], fallbackColor: RGBA): ShadowLayer[];
|
|
20
|
+
/**
|
|
21
|
+
* Lista nomes de funções de filtro que não são renderizáveis no MVP.
|
|
22
|
+
* Usado para emitir warnings durante a fase de pintura.
|
|
23
|
+
*/
|
|
24
|
+
export declare function listUnsupportedFilters(filters: FilterFunction[] | undefined): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Emite warnings para filtros não suportados.
|
|
27
|
+
* Chamado uma vez por box durante a fase de pintura.
|
|
28
|
+
*/
|
|
29
|
+
export declare function warnUnsupportedFilters(filters: FilterFunction[] | undefined, label: "filter" | "backdrop-filter", boxId: string): void;
|