pdf-codec 5.6.1 → 5.7.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/README.md +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/text-group.cjs +75 -2
- package/dist/text-group.d.cts +24 -1
- package/dist/text-group.d.ts +24 -1
- package/dist/text-group.js +74 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -353,7 +353,7 @@ Two runs are on one line when their baselines sit within a fraction of an em of
|
|
|
353
353
|
|
|
354
354
|
A run whose `widthPt` is absent states no advance, so where it ends is unknown and the gap after it is underivable. `runGapPt` reports `undefined` for that, and an undefined gap is **no evidence of a space**. Reading it as zero puts the previous run's end at its own start, turns its whole advance into an apparent gap, and produces "Com plete ly".
|
|
355
355
|
|
|
356
|
-
Gaps that are derivable become a word space at an eighth of an em (the narrowest genuine one: the standard fourteen faces set their space glyph at 250/1000 em, and justified setting compresses to no less than half of that) and a column boundary past a full em (wider than the em space, the widest single space character there is), so a table's row reads as `"North\t4.2m\t11%"` rather than as one sentence. `runsShareBaseline` and `runGapPt` are exported on their own for a consumer with its own pipeline around them, and every threshold is overridable.
|
|
356
|
+
Gaps that are derivable become a word space at an eighth of an em (the narrowest genuine one: the standard fourteen faces set their space glyph at 250/1000 em, and justified setting compresses to no less than half of that) and a column boundary past a full em (wider than the em space, the widest single space character there is), so a table's row reads as `"North\t4.2m\t11%"` rather than as one sentence. `runsShareBaseline` and `runGapPt` are exported on their own for a consumer with its own pipeline around them, and every threshold is overridable. `scriptPositionOf(base, candidate)` says whether a run is a superscript or subscript of the run it touches: set at no more than three quarters of its size, with its baseline moved by more than a twentieth and at most half of its em (fonts declare script sizes about 0.65 em and offsets between 0.07 and 0.48 em), and no further than a word space from it along the baseline. A script raised past the same-baseline tolerance would otherwise be clustered as a line of its own, so `groupPdfTextRuns` returns it to its base's line, and `attachScriptRuns` does the same for a consumer that clusters lines itself. A line's text joins a script to its base like any touching run (`280m2`); `scriptPositionOf` on a word's `runs` is what tells a reader to raise or lower it.
|
|
357
357
|
|
|
358
358
|
Limits, each inherent to what a PDF states rather than to the implementation: grouping is by baseline alone with no page segmentation, so on a multi-column page whose columns sit at different vertical offsets a line of one can fall within tolerance of a line of the next and the two are reported as one line with a column boundary between them, which is the cut a caller needs (`document-outline.js`'s `segmentPdfRegions` finds the gutter first if you want them genuinely apart); text comes out in visual order, so a right-to-left script needs the Unicode Bidi Algorithm applied to the result; a vertically set run groups into a column instead of a line, reported with a `rotationDeg` of 270 and its own `writingMode`, with columns ordered right to left; and a word hyphenated across a line end stays split, hyphen intact, because rejoining it is a paragraph-level judgement this package leaves to its consumers.
|
|
359
359
|
|
package/dist/index.cjs
CHANGED
|
@@ -68,6 +68,7 @@ exports.PdfPasswordRequiredError = require_diagnostics.PdfPasswordRequiredError;
|
|
|
68
68
|
exports.PdfSkippedSurfacesError = require_write_skipped_surfaces.PdfSkippedSurfacesError;
|
|
69
69
|
exports.STANDARD_METRICS = require_afm_widths.STANDARD_METRICS;
|
|
70
70
|
exports.assembleStretchyGlyph = require_math_stretch.assembleStretchyGlyph;
|
|
71
|
+
exports.attachScriptRuns = require_text_group.attachScriptRuns;
|
|
71
72
|
exports.createFontMeasurer = require_measure.createFontMeasurer;
|
|
72
73
|
exports.createFontRegistry = require_font_registry.createFontRegistry;
|
|
73
74
|
exports.createStandardFontMeasurer = require_measure.createStandardFontMeasurer;
|
|
@@ -89,6 +90,7 @@ exports.resolveStandardFont = require_fonts.resolveStandardFont;
|
|
|
89
90
|
exports.runGapPt = require_text_group.runGapPt;
|
|
90
91
|
exports.runsShareBaseline = require_text_group.runsShareBaseline;
|
|
91
92
|
exports.scaleMathStretchConstruction = require_math_stretch.scaleMathStretchConstruction;
|
|
93
|
+
exports.scriptPositionOf = require_text_group.scriptPositionOf;
|
|
92
94
|
exports.sourcePageIndex = require_layout.sourcePageIndex;
|
|
93
95
|
exports.unfilterScanlines = require_image_png_filter.unfilterScanlines;
|
|
94
96
|
exports.writePdf = require_write.writePdf;
|
package/dist/index.d.cts
CHANGED
|
@@ -24,8 +24,8 @@ import { a as MathGlyphPart, c as MathVariants, n as MathGlyphAssembly, o as Mat
|
|
|
24
24
|
import { a as scaleMathStretchConstruction, i as assembleStretchyGlyph, n as MathStretchOptions, r as MathStretchPlacement, t as MathStretchConstruction } from "./math-stretch-C2JanDAz.cjs";
|
|
25
25
|
import { LoadedMathFont, MathFont, MathFontDescriptorMetrics, loadMathFont } from "./math-font.cjs";
|
|
26
26
|
import { DEFAULT_VERTICAL_METRIC_POLICY, FontMeasurerOptions, StandardFontMeasurerOptions, VerticalMetricPolicy, createFontMeasurer, createStandardFontMeasurer } from "./measure.cjs";
|
|
27
|
-
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, groupPdfTextRuns, runGapPt, runsShareBaseline } from "./text-group.cjs";
|
|
27
|
+
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfLineWithScripts, PdfScriptPosition, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf } from "./text-group.cjs";
|
|
28
28
|
import { PageRasteriser, RasterDrawOp, RasterFillRectOp, RasterFillSpec, RasterImageOp, RasterMatrix, RasterPageGeometry, RasterPathOp, RasterPathSegment, RasterRegionPt, RasterStrokeSpec, RasterSubpath, RenderPdfPageOptions, renderPdfPage } from "./raster.cjs";
|
|
29
29
|
import { FontRegistryOptions, FontSubstitution, MathAssembledGlyphs, MathBox, MathColor, MathFontMetrics, MathGlyphMetrics, MathGlyphPlacement, MathGlyphRun, MathLayoutItem, MathRule, MathStretchAxis, MathStretchGlyph, MathStretchResult, MathStroke, Point, PositionedFormula, ProvidedFont, StyledFragment, StyledRun, TextMeasurer, UnderlineMetrics, WrapOptions, WrappedLine } from "document-schema.js";
|
|
30
30
|
export * from "byte-codec";
|
|
31
|
-
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutDocumentSurface, LayoutDocumentSurfaceSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, PdfPageSelectionError, PdfParseError, PdfPartialDocumentError, PdfPasswordRequiredError, PdfSkippedSurfacesError, type PdfTextBox, type PdfTextGroupingOptions, type PdfTextLine, type PdfTextRunGeometry, type PdfTextWord, type PdfWordSeparator, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type ReadPdfSurfaces, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, sourcePageIndex, unfilterScanlines, writePdf };
|
|
31
|
+
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutDocumentSurface, LayoutDocumentSurfaceSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, type PdfLineWithScripts, PdfPageSelectionError, PdfParseError, PdfPartialDocumentError, PdfPasswordRequiredError, type PdfScriptPosition, PdfSkippedSurfacesError, type PdfTextBox, type PdfTextGroupingOptions, type PdfTextLine, type PdfTextRunGeometry, type PdfTextWord, type PdfWordSeparator, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type ReadPdfSurfaces, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, attachScriptRuns, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, scriptPositionOf, sourcePageIndex, unfilterScanlines, writePdf };
|
package/dist/index.d.ts
CHANGED
|
@@ -24,8 +24,8 @@ import { a as MathGlyphPart, c as MathVariants, n as MathGlyphAssembly, o as Mat
|
|
|
24
24
|
import { a as scaleMathStretchConstruction, i as assembleStretchyGlyph, n as MathStretchOptions, r as MathStretchPlacement, t as MathStretchConstruction } from "./math-stretch-BbC2o4Br.js";
|
|
25
25
|
import { LoadedMathFont, MathFont, MathFontDescriptorMetrics, loadMathFont } from "./math-font.js";
|
|
26
26
|
import { DEFAULT_VERTICAL_METRIC_POLICY, FontMeasurerOptions, StandardFontMeasurerOptions, VerticalMetricPolicy, createFontMeasurer, createStandardFontMeasurer } from "./measure.js";
|
|
27
|
-
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, groupPdfTextRuns, runGapPt, runsShareBaseline } from "./text-group.js";
|
|
27
|
+
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfLineWithScripts, PdfScriptPosition, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf } from "./text-group.js";
|
|
28
28
|
import { PageRasteriser, RasterDrawOp, RasterFillRectOp, RasterFillSpec, RasterImageOp, RasterMatrix, RasterPageGeometry, RasterPathOp, RasterPathSegment, RasterRegionPt, RasterStrokeSpec, RasterSubpath, RenderPdfPageOptions, renderPdfPage } from "./raster.js";
|
|
29
29
|
import { FontRegistryOptions, FontSubstitution, MathAssembledGlyphs, MathBox, MathColor, MathFontMetrics, MathGlyphMetrics, MathGlyphPlacement, MathGlyphRun, MathLayoutItem, MathRule, MathStretchAxis, MathStretchGlyph, MathStretchResult, MathStroke, Point, PositionedFormula, ProvidedFont, StyledFragment, StyledRun, TextMeasurer, UnderlineMetrics, WrapOptions, WrappedLine } from "document-schema.js";
|
|
30
30
|
export * from "byte-codec";
|
|
31
|
-
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutDocumentSurface, LayoutDocumentSurfaceSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, PdfPageSelectionError, PdfParseError, PdfPartialDocumentError, PdfPasswordRequiredError, PdfSkippedSurfacesError, type PdfTextBox, type PdfTextGroupingOptions, type PdfTextLine, type PdfTextRunGeometry, type PdfTextWord, type PdfWordSeparator, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type ReadPdfSurfaces, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, sourcePageIndex, unfilterScanlines, writePdf };
|
|
31
|
+
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutDocumentSurface, LayoutDocumentSurfaceSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, type PdfLineWithScripts, PdfPageSelectionError, PdfParseError, PdfPartialDocumentError, PdfPasswordRequiredError, type PdfScriptPosition, PdfSkippedSurfacesError, type PdfTextBox, type PdfTextGroupingOptions, type PdfTextLine, type PdfTextRunGeometry, type PdfTextWord, type PdfWordSeparator, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type ReadPdfSurfaces, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, attachScriptRuns, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, scriptPositionOf, sourcePageIndex, unfilterScanlines, writePdf };
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { decodeJpeg2000, readJpeg2000Metadata } from "./image/jpeg2000.js";
|
|
|
9
9
|
import { LAYOUT_FORMAT_VERSION, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachmentSchema, LayoutDestinationSchema, LayoutDestinationTargetSchema, LayoutDocumentSchema, LayoutDocumentSurfaceSchema, LayoutEllipseSchema, LayoutFormFieldSchema, LayoutFormWidgetSchema, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLinkSchema, LayoutItemSchema, LayoutLayerSchema, LayoutLineSchema, LayoutLinkSchema, LayoutOutlineItemSchema, LayoutPageSchema, LayoutPathSchema, LayoutPathSegmentSchema, LayoutRectSchema, LayoutStructureElementSchema, LayoutSubpathSchema, LayoutTextSchema, sourcePageIndex } from "./layout.js";
|
|
10
10
|
import { NOOP_DIAGNOSTIC_SINK, PdfEncryptedError, PdfPageSelectionError, PdfParseError, PdfPasswordRequiredError } from "./diagnostics.js";
|
|
11
11
|
import { resolveStandardFont } from "./fonts.js";
|
|
12
|
-
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, groupPdfTextRuns, runGapPt, runsShareBaseline } from "./text-group.js";
|
|
12
|
+
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf } from "./text-group.js";
|
|
13
13
|
import { readPdf } from "./read.js";
|
|
14
14
|
import { PdfEncryptionError } from "./encrypt-write.js";
|
|
15
15
|
import { assembleStretchyGlyph, scaleMathStretchConstruction } from "./math-stretch.js";
|
|
@@ -22,4 +22,4 @@ import { PdfBytesSchema, pdfCodec } from "./codec.js";
|
|
|
22
22
|
import { FontFaceParseError, readFontFace } from "./font-face.js";
|
|
23
23
|
import { r as renderPdfPage } from "./raster-CIc6ot36.js";
|
|
24
24
|
export * from "byte-codec";
|
|
25
|
-
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, FontFaceParseError, Jbig2ParseError, Jbig2UnsupportedError, Jpeg2000ParseError, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachmentSchema, LayoutDestinationSchema, LayoutDestinationTargetSchema, LayoutDocumentSchema, LayoutDocumentSurfaceSchema, LayoutEllipseSchema, LayoutFormFieldSchema, LayoutFormWidgetSchema, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLinkSchema, LayoutItemSchema, LayoutLayerSchema, LayoutLineSchema, LayoutLinkSchema, LayoutOutlineItemSchema, LayoutPageSchema, LayoutPathSchema, LayoutPathSegmentSchema, LayoutRectSchema, LayoutStructureElementSchema, LayoutSubpathSchema, LayoutTextSchema, NOOP_DIAGNOSTIC_SINK, PdfBytesSchema, PdfEncryptedError, PdfEncryptionError, PdfPageSelectionError, PdfParseError, PdfPartialDocumentError, PdfPasswordRequiredError, PdfSkippedSurfacesError, STANDARD_METRICS, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, sourcePageIndex, unfilterScanlines, writePdf };
|
|
25
|
+
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, FontFaceParseError, Jbig2ParseError, Jbig2UnsupportedError, Jpeg2000ParseError, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachmentSchema, LayoutDestinationSchema, LayoutDestinationTargetSchema, LayoutDocumentSchema, LayoutDocumentSurfaceSchema, LayoutEllipseSchema, LayoutFormFieldSchema, LayoutFormWidgetSchema, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLinkSchema, LayoutItemSchema, LayoutLayerSchema, LayoutLineSchema, LayoutLinkSchema, LayoutOutlineItemSchema, LayoutPageSchema, LayoutPathSchema, LayoutPathSegmentSchema, LayoutRectSchema, LayoutStructureElementSchema, LayoutSubpathSchema, LayoutTextSchema, NOOP_DIAGNOSTIC_SINK, PdfBytesSchema, PdfEncryptedError, PdfEncryptionError, PdfPageSelectionError, PdfParseError, PdfPartialDocumentError, PdfPasswordRequiredError, PdfSkippedSurfacesError, STANDARD_METRICS, assembleStretchyGlyph, attachScriptRuns, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, scriptPositionOf, sourcePageIndex, unfilterScanlines, writePdf };
|
package/dist/text-group.cjs
CHANGED
|
@@ -63,6 +63,70 @@ function runGapPt(previous, next) {
|
|
|
63
63
|
if (previousWidthPt === void 0) return;
|
|
64
64
|
return project(next, rotationDeg).alongPt - (project(previous, rotationDeg).alongPt + previousWidthPt);
|
|
65
65
|
}
|
|
66
|
+
const SCRIPT_MAX_SIZE_RATIO = .75;
|
|
67
|
+
const SCRIPT_MIN_SHIFT_EM = .05;
|
|
68
|
+
const SCRIPT_MAX_SHIFT_EM = .5;
|
|
69
|
+
/**
|
|
70
|
+
* Whether `candidate` is a superscript or subscript of `base`: a run set smaller than `base`, with its baseline moved off `base`'s by more than positioning noise and by less than half `base`'s em, and touching it along the baseline (no wider than a word space apart, on either side).
|
|
71
|
+
*
|
|
72
|
+
* Runs at different angles or in different writing modes are never scripts of one another, and neither is a pair whose gap cannot be derived because the earlier of the two states no advance width.
|
|
73
|
+
* @param base - the run the candidate might decorate
|
|
74
|
+
* @param candidate - the run that might be its superscript or subscript
|
|
75
|
+
* @returns which side of `base`'s baseline `candidate` is set on, or undefined when it is not a script of `base`
|
|
76
|
+
*/
|
|
77
|
+
function scriptPositionOf(base, candidate) {
|
|
78
|
+
if (candidate.sizePt > SCRIPT_MAX_SIZE_RATIO * base.sizePt) return;
|
|
79
|
+
const rotationDeg = advanceAngleDeg(base);
|
|
80
|
+
if (rotationDeg !== advanceAngleDeg(candidate) || base.writingMode !== candidate.writingMode) return;
|
|
81
|
+
const baseProjected = project(base, rotationDeg);
|
|
82
|
+
const candidateProjected = project(candidate, rotationDeg);
|
|
83
|
+
const shiftPt = candidateProjected.acrossPt - baseProjected.acrossPt;
|
|
84
|
+
const magnitude = Math.abs(shiftPt);
|
|
85
|
+
if (magnitude < SCRIPT_MIN_SHIFT_EM * base.sizePt || magnitude > SCRIPT_MAX_SHIFT_EM * base.sizePt) return;
|
|
86
|
+
const gapPt = candidateProjected.alongPt >= baseProjected.alongPt ? runGapPt(base, candidate) : runGapPt(candidate, base);
|
|
87
|
+
if (gapPt === void 0 || gapPt <= -candidate.sizePt || gapPt >= .125 * candidate.sizePt) return;
|
|
88
|
+
return shiftPt > 0 ? "superscript" : "subscript";
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Moves every run that is a superscript or subscript of a run on another line onto that run's line.
|
|
92
|
+
*
|
|
93
|
+
* A same-baseline tolerance that keeps two lines of type apart cannot also hold every script on its base's line: a script may be raised or lowered by up to half its base's em ({@link scriptPositionOf}), which is more than two thirds of the script's own em once it is set small, so baseline clustering can put a unit's raised exponent on a line of its own. This returns each such run to the line its base is on. Every move is decided against the lines as given, before any is made, so a run that moves is never taken for another run's base and the outcome does not depend on the order of the lines.
|
|
94
|
+
* @param lines - lines already grouped by baseline, of whatever shape the caller keeps them in
|
|
95
|
+
* @param runsOf - the runs on one of those lines, in any order
|
|
96
|
+
* @returns one entry per line, in the order given: the line itself and its runs, less every run that moved off it and followed by every run that moved onto it; a line every run moved off has no runs left, and is kept so that the caller decides what an empty line means
|
|
97
|
+
*/
|
|
98
|
+
function attachScriptRuns(lines, runsOf) {
|
|
99
|
+
const runsByLine = lines.map((line) => runsOf(line));
|
|
100
|
+
const maxSizePt = Math.max(0, ...runsByLine.flatMap((runs) => runs.map((run) => run.sizePt)));
|
|
101
|
+
const reachPt = 1.5 * maxSizePt;
|
|
102
|
+
const placed = runsByLine.flatMap((runs, index) => runs.slice(0, 1).map((first) => {
|
|
103
|
+
const rotationDeg = advanceAngleDeg(first);
|
|
104
|
+
return {
|
|
105
|
+
index,
|
|
106
|
+
runs,
|
|
107
|
+
rotationDeg,
|
|
108
|
+
acrossPt: project(first, rotationDeg).acrossPt
|
|
109
|
+
};
|
|
110
|
+
}));
|
|
111
|
+
const moves = [];
|
|
112
|
+
runsByLine.forEach((runs, lineIndex) => {
|
|
113
|
+
for (const candidate of runs) {
|
|
114
|
+
if (candidate.sizePt > SCRIPT_MAX_SIZE_RATIO * maxSizePt) continue;
|
|
115
|
+
const rotationDeg = advanceAngleDeg(candidate);
|
|
116
|
+
const acrossPt = project(candidate, rotationDeg).acrossPt;
|
|
117
|
+
const target = placed.find((other) => other.index !== lineIndex && other.rotationDeg === rotationDeg && Math.abs(other.acrossPt - acrossPt) <= reachPt && other.runs.some((base) => scriptPositionOf(base, candidate) !== void 0));
|
|
118
|
+
if (target !== void 0) moves.push({
|
|
119
|
+
run: candidate,
|
|
120
|
+
to: target.index
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
const moved = new Set(moves.map((move) => move.run));
|
|
125
|
+
return lines.map((line, index) => ({
|
|
126
|
+
line,
|
|
127
|
+
runs: [...runsOf(line).filter((run) => !moved.has(run)), ...moves.filter((move) => move.to === index).map((move) => move.run)]
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
66
130
|
function clusterIntoLines(entries, toleranceEm) {
|
|
67
131
|
const lines = [];
|
|
68
132
|
for (const entry of entries) {
|
|
@@ -209,8 +273,15 @@ function groupPdfTextRuns(runs, options = {}) {
|
|
|
209
273
|
const result = [];
|
|
210
274
|
const ordered = [...buckets.values()].sort((a, b) => a.rotationDeg - b.rotationDeg || Number(a.vertical) - Number(b.vertical));
|
|
211
275
|
for (const bucket of ordered) {
|
|
212
|
-
const
|
|
213
|
-
for (const line of
|
|
276
|
+
const attached = attachScriptRuns(clusterIntoLines(bucket.runs.map((run) => project(run, bucket.rotationDeg)).sort((a, b) => b.acrossPt - a.acrossPt || a.alongPt - b.alongPt), toleranceEm), (line) => line.entries.map((entry) => entry.run));
|
|
277
|
+
for (const { line: clusteredLine, runs: runsOnLine } of attached) {
|
|
278
|
+
const lineEntries = runsOnLine.map((run) => project(run, bucket.rotationDeg));
|
|
279
|
+
const anchor = runsOnLine.includes(clusteredLine.anchor.run) ? clusteredLine.anchor : lineEntries[0];
|
|
280
|
+
if (anchor === void 0) continue;
|
|
281
|
+
const line = {
|
|
282
|
+
anchor,
|
|
283
|
+
entries: lineEntries
|
|
284
|
+
};
|
|
214
285
|
line.entries.sort((a, b) => a.alongPt - b.alongPt);
|
|
215
286
|
result.push(buildLine(line, bucket.rotationDeg, bucket.vertical, wordGapEm, columnGapEm));
|
|
216
287
|
}
|
|
@@ -221,6 +292,8 @@ function groupPdfTextRuns(runs, options = {}) {
|
|
|
221
292
|
exports.DEFAULT_BASELINE_TOLERANCE_EM = DEFAULT_BASELINE_TOLERANCE_EM;
|
|
222
293
|
exports.DEFAULT_COLUMN_GAP_EM = DEFAULT_COLUMN_GAP_EM;
|
|
223
294
|
exports.DEFAULT_WORD_GAP_EM = DEFAULT_WORD_GAP_EM;
|
|
295
|
+
exports.attachScriptRuns = attachScriptRuns;
|
|
224
296
|
exports.groupPdfTextRuns = groupPdfTextRuns;
|
|
225
297
|
exports.runGapPt = runGapPt;
|
|
226
298
|
exports.runsShareBaseline = runsShareBaseline;
|
|
299
|
+
exports.scriptPositionOf = scriptPositionOf;
|
package/dist/text-group.d.cts
CHANGED
|
@@ -56,6 +56,29 @@ declare function runsShareBaseline(a: PdfTextRunGeometry, b: PdfTextRunGeometry,
|
|
|
56
56
|
* @returns the gap in points, or undefined when it cannot be derived
|
|
57
57
|
*/
|
|
58
58
|
declare function runGapPt(previous: PdfTextRunGeometry, next: PdfTextRunGeometry): number | undefined;
|
|
59
|
+
type PdfScriptPosition = "superscript" | "subscript";
|
|
60
|
+
/**
|
|
61
|
+
* Whether `candidate` is a superscript or subscript of `base`: a run set smaller than `base`, with its baseline moved off `base`'s by more than positioning noise and by less than half `base`'s em, and touching it along the baseline (no wider than a word space apart, on either side).
|
|
62
|
+
*
|
|
63
|
+
* Runs at different angles or in different writing modes are never scripts of one another, and neither is a pair whose gap cannot be derived because the earlier of the two states no advance width.
|
|
64
|
+
* @param base - the run the candidate might decorate
|
|
65
|
+
* @param candidate - the run that might be its superscript or subscript
|
|
66
|
+
* @returns which side of `base`'s baseline `candidate` is set on, or undefined when it is not a script of `base`
|
|
67
|
+
*/
|
|
68
|
+
declare function scriptPositionOf(base: PdfTextRunGeometry, candidate: PdfTextRunGeometry): PdfScriptPosition | undefined;
|
|
69
|
+
interface PdfLineWithScripts<TLine, TRun extends PdfTextRunGeometry> {
|
|
70
|
+
readonly line: TLine;
|
|
71
|
+
readonly runs: TRun[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Moves every run that is a superscript or subscript of a run on another line onto that run's line.
|
|
75
|
+
*
|
|
76
|
+
* A same-baseline tolerance that keeps two lines of type apart cannot also hold every script on its base's line: a script may be raised or lowered by up to half its base's em ({@link scriptPositionOf}), which is more than two thirds of the script's own em once it is set small, so baseline clustering can put a unit's raised exponent on a line of its own. This returns each such run to the line its base is on. Every move is decided against the lines as given, before any is made, so a run that moves is never taken for another run's base and the outcome does not depend on the order of the lines.
|
|
77
|
+
* @param lines - lines already grouped by baseline, of whatever shape the caller keeps them in
|
|
78
|
+
* @param runsOf - the runs on one of those lines, in any order
|
|
79
|
+
* @returns one entry per line, in the order given: the line itself and its runs, less every run that moved off it and followed by every run that moved onto it; a line every run moved off has no runs left, and is kept so that the caller decides what an empty line means
|
|
80
|
+
*/
|
|
81
|
+
declare function attachScriptRuns<TLine, TRun extends PdfTextRunGeometry>(lines: readonly TLine[], runsOf: (line: TLine) => readonly TRun[]): PdfLineWithScripts<TLine, TRun>[];
|
|
59
82
|
/**
|
|
60
83
|
* Groups positioned PDF text runs into lines of words.
|
|
61
84
|
*
|
|
@@ -72,4 +95,4 @@ declare function runGapPt(previous: PdfTextRunGeometry, next: PdfTextRunGeometry
|
|
|
72
95
|
*/
|
|
73
96
|
declare function groupPdfTextRuns<TRun extends PdfTextRunGeometry>(runs: readonly TRun[], options?: PdfTextGroupingOptions): PdfTextLine<TRun>[];
|
|
74
97
|
//#endregion
|
|
75
|
-
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, groupPdfTextRuns, runGapPt, runsShareBaseline };
|
|
98
|
+
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfLineWithScripts, PdfScriptPosition, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf };
|
package/dist/text-group.d.ts
CHANGED
|
@@ -56,6 +56,29 @@ declare function runsShareBaseline(a: PdfTextRunGeometry, b: PdfTextRunGeometry,
|
|
|
56
56
|
* @returns the gap in points, or undefined when it cannot be derived
|
|
57
57
|
*/
|
|
58
58
|
declare function runGapPt(previous: PdfTextRunGeometry, next: PdfTextRunGeometry): number | undefined;
|
|
59
|
+
type PdfScriptPosition = "superscript" | "subscript";
|
|
60
|
+
/**
|
|
61
|
+
* Whether `candidate` is a superscript or subscript of `base`: a run set smaller than `base`, with its baseline moved off `base`'s by more than positioning noise and by less than half `base`'s em, and touching it along the baseline (no wider than a word space apart, on either side).
|
|
62
|
+
*
|
|
63
|
+
* Runs at different angles or in different writing modes are never scripts of one another, and neither is a pair whose gap cannot be derived because the earlier of the two states no advance width.
|
|
64
|
+
* @param base - the run the candidate might decorate
|
|
65
|
+
* @param candidate - the run that might be its superscript or subscript
|
|
66
|
+
* @returns which side of `base`'s baseline `candidate` is set on, or undefined when it is not a script of `base`
|
|
67
|
+
*/
|
|
68
|
+
declare function scriptPositionOf(base: PdfTextRunGeometry, candidate: PdfTextRunGeometry): PdfScriptPosition | undefined;
|
|
69
|
+
interface PdfLineWithScripts<TLine, TRun extends PdfTextRunGeometry> {
|
|
70
|
+
readonly line: TLine;
|
|
71
|
+
readonly runs: TRun[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Moves every run that is a superscript or subscript of a run on another line onto that run's line.
|
|
75
|
+
*
|
|
76
|
+
* A same-baseline tolerance that keeps two lines of type apart cannot also hold every script on its base's line: a script may be raised or lowered by up to half its base's em ({@link scriptPositionOf}), which is more than two thirds of the script's own em once it is set small, so baseline clustering can put a unit's raised exponent on a line of its own. This returns each such run to the line its base is on. Every move is decided against the lines as given, before any is made, so a run that moves is never taken for another run's base and the outcome does not depend on the order of the lines.
|
|
77
|
+
* @param lines - lines already grouped by baseline, of whatever shape the caller keeps them in
|
|
78
|
+
* @param runsOf - the runs on one of those lines, in any order
|
|
79
|
+
* @returns one entry per line, in the order given: the line itself and its runs, less every run that moved off it and followed by every run that moved onto it; a line every run moved off has no runs left, and is kept so that the caller decides what an empty line means
|
|
80
|
+
*/
|
|
81
|
+
declare function attachScriptRuns<TLine, TRun extends PdfTextRunGeometry>(lines: readonly TLine[], runsOf: (line: TLine) => readonly TRun[]): PdfLineWithScripts<TLine, TRun>[];
|
|
59
82
|
/**
|
|
60
83
|
* Groups positioned PDF text runs into lines of words.
|
|
61
84
|
*
|
|
@@ -72,4 +95,4 @@ declare function runGapPt(previous: PdfTextRunGeometry, next: PdfTextRunGeometry
|
|
|
72
95
|
*/
|
|
73
96
|
declare function groupPdfTextRuns<TRun extends PdfTextRunGeometry>(runs: readonly TRun[], options?: PdfTextGroupingOptions): PdfTextLine<TRun>[];
|
|
74
97
|
//#endregion
|
|
75
|
-
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, groupPdfTextRuns, runGapPt, runsShareBaseline };
|
|
98
|
+
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfLineWithScripts, PdfScriptPosition, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf };
|
package/dist/text-group.js
CHANGED
|
@@ -62,6 +62,70 @@ function runGapPt(previous, next) {
|
|
|
62
62
|
if (previousWidthPt === void 0) return;
|
|
63
63
|
return project(next, rotationDeg).alongPt - (project(previous, rotationDeg).alongPt + previousWidthPt);
|
|
64
64
|
}
|
|
65
|
+
const SCRIPT_MAX_SIZE_RATIO = .75;
|
|
66
|
+
const SCRIPT_MIN_SHIFT_EM = .05;
|
|
67
|
+
const SCRIPT_MAX_SHIFT_EM = .5;
|
|
68
|
+
/**
|
|
69
|
+
* Whether `candidate` is a superscript or subscript of `base`: a run set smaller than `base`, with its baseline moved off `base`'s by more than positioning noise and by less than half `base`'s em, and touching it along the baseline (no wider than a word space apart, on either side).
|
|
70
|
+
*
|
|
71
|
+
* Runs at different angles or in different writing modes are never scripts of one another, and neither is a pair whose gap cannot be derived because the earlier of the two states no advance width.
|
|
72
|
+
* @param base - the run the candidate might decorate
|
|
73
|
+
* @param candidate - the run that might be its superscript or subscript
|
|
74
|
+
* @returns which side of `base`'s baseline `candidate` is set on, or undefined when it is not a script of `base`
|
|
75
|
+
*/
|
|
76
|
+
function scriptPositionOf(base, candidate) {
|
|
77
|
+
if (candidate.sizePt > SCRIPT_MAX_SIZE_RATIO * base.sizePt) return;
|
|
78
|
+
const rotationDeg = advanceAngleDeg(base);
|
|
79
|
+
if (rotationDeg !== advanceAngleDeg(candidate) || base.writingMode !== candidate.writingMode) return;
|
|
80
|
+
const baseProjected = project(base, rotationDeg);
|
|
81
|
+
const candidateProjected = project(candidate, rotationDeg);
|
|
82
|
+
const shiftPt = candidateProjected.acrossPt - baseProjected.acrossPt;
|
|
83
|
+
const magnitude = Math.abs(shiftPt);
|
|
84
|
+
if (magnitude < SCRIPT_MIN_SHIFT_EM * base.sizePt || magnitude > SCRIPT_MAX_SHIFT_EM * base.sizePt) return;
|
|
85
|
+
const gapPt = candidateProjected.alongPt >= baseProjected.alongPt ? runGapPt(base, candidate) : runGapPt(candidate, base);
|
|
86
|
+
if (gapPt === void 0 || gapPt <= -candidate.sizePt || gapPt >= .125 * candidate.sizePt) return;
|
|
87
|
+
return shiftPt > 0 ? "superscript" : "subscript";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Moves every run that is a superscript or subscript of a run on another line onto that run's line.
|
|
91
|
+
*
|
|
92
|
+
* A same-baseline tolerance that keeps two lines of type apart cannot also hold every script on its base's line: a script may be raised or lowered by up to half its base's em ({@link scriptPositionOf}), which is more than two thirds of the script's own em once it is set small, so baseline clustering can put a unit's raised exponent on a line of its own. This returns each such run to the line its base is on. Every move is decided against the lines as given, before any is made, so a run that moves is never taken for another run's base and the outcome does not depend on the order of the lines.
|
|
93
|
+
* @param lines - lines already grouped by baseline, of whatever shape the caller keeps them in
|
|
94
|
+
* @param runsOf - the runs on one of those lines, in any order
|
|
95
|
+
* @returns one entry per line, in the order given: the line itself and its runs, less every run that moved off it and followed by every run that moved onto it; a line every run moved off has no runs left, and is kept so that the caller decides what an empty line means
|
|
96
|
+
*/
|
|
97
|
+
function attachScriptRuns(lines, runsOf) {
|
|
98
|
+
const runsByLine = lines.map((line) => runsOf(line));
|
|
99
|
+
const maxSizePt = Math.max(0, ...runsByLine.flatMap((runs) => runs.map((run) => run.sizePt)));
|
|
100
|
+
const reachPt = 1.5 * maxSizePt;
|
|
101
|
+
const placed = runsByLine.flatMap((runs, index) => runs.slice(0, 1).map((first) => {
|
|
102
|
+
const rotationDeg = advanceAngleDeg(first);
|
|
103
|
+
return {
|
|
104
|
+
index,
|
|
105
|
+
runs,
|
|
106
|
+
rotationDeg,
|
|
107
|
+
acrossPt: project(first, rotationDeg).acrossPt
|
|
108
|
+
};
|
|
109
|
+
}));
|
|
110
|
+
const moves = [];
|
|
111
|
+
runsByLine.forEach((runs, lineIndex) => {
|
|
112
|
+
for (const candidate of runs) {
|
|
113
|
+
if (candidate.sizePt > SCRIPT_MAX_SIZE_RATIO * maxSizePt) continue;
|
|
114
|
+
const rotationDeg = advanceAngleDeg(candidate);
|
|
115
|
+
const acrossPt = project(candidate, rotationDeg).acrossPt;
|
|
116
|
+
const target = placed.find((other) => other.index !== lineIndex && other.rotationDeg === rotationDeg && Math.abs(other.acrossPt - acrossPt) <= reachPt && other.runs.some((base) => scriptPositionOf(base, candidate) !== void 0));
|
|
117
|
+
if (target !== void 0) moves.push({
|
|
118
|
+
run: candidate,
|
|
119
|
+
to: target.index
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
const moved = new Set(moves.map((move) => move.run));
|
|
124
|
+
return lines.map((line, index) => ({
|
|
125
|
+
line,
|
|
126
|
+
runs: [...runsOf(line).filter((run) => !moved.has(run)), ...moves.filter((move) => move.to === index).map((move) => move.run)]
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
65
129
|
function clusterIntoLines(entries, toleranceEm) {
|
|
66
130
|
const lines = [];
|
|
67
131
|
for (const entry of entries) {
|
|
@@ -208,8 +272,15 @@ function groupPdfTextRuns(runs, options = {}) {
|
|
|
208
272
|
const result = [];
|
|
209
273
|
const ordered = [...buckets.values()].sort((a, b) => a.rotationDeg - b.rotationDeg || Number(a.vertical) - Number(b.vertical));
|
|
210
274
|
for (const bucket of ordered) {
|
|
211
|
-
const
|
|
212
|
-
for (const line of
|
|
275
|
+
const attached = attachScriptRuns(clusterIntoLines(bucket.runs.map((run) => project(run, bucket.rotationDeg)).sort((a, b) => b.acrossPt - a.acrossPt || a.alongPt - b.alongPt), toleranceEm), (line) => line.entries.map((entry) => entry.run));
|
|
276
|
+
for (const { line: clusteredLine, runs: runsOnLine } of attached) {
|
|
277
|
+
const lineEntries = runsOnLine.map((run) => project(run, bucket.rotationDeg));
|
|
278
|
+
const anchor = runsOnLine.includes(clusteredLine.anchor.run) ? clusteredLine.anchor : lineEntries[0];
|
|
279
|
+
if (anchor === void 0) continue;
|
|
280
|
+
const line = {
|
|
281
|
+
anchor,
|
|
282
|
+
entries: lineEntries
|
|
283
|
+
};
|
|
213
284
|
line.entries.sort((a, b) => a.alongPt - b.alongPt);
|
|
214
285
|
result.push(buildLine(line, bucket.rotationDeg, bucket.vertical, wordGapEm, columnGapEm));
|
|
215
286
|
}
|
|
@@ -217,4 +288,4 @@ function groupPdfTextRuns(runs, options = {}) {
|
|
|
217
288
|
return result;
|
|
218
289
|
}
|
|
219
290
|
//#endregion
|
|
220
|
-
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, groupPdfTextRuns, runGapPt, runsShareBaseline };
|
|
291
|
+
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pdf-codec",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.7.0",
|
|
4
4
|
"description": "Hand-written, dependency-minimal PDF codec: parses arbitrary real-world PDFs and generates new ones, built on its own codec-owned LayoutDocument item model and Zod 4 codecs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|