@embedpdf/core-geometry 3.0.0-next.13 → 3.0.0-next.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +182 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +135 -184
- package/dist/index.d.ts +135 -184
- package/dist/index.js +172 -301
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
//#region src/page-space.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Page space: the unrotated page's own frame, origin at the top-left of the
|
|
4
|
+
* visible page, y down, in points (the
|
|
5
|
+
* page's UserUnit is applied by the view, not here). The engine gives and
|
|
6
|
+
* takes every position in this space.
|
|
7
|
+
*/
|
|
8
|
+
type PagePoint = PointIn<'page'>;
|
|
9
|
+
type PageRect = RectIn<'page'>;
|
|
10
|
+
type PageQuad = QuadIn<'page'>;
|
|
11
|
+
//#endregion
|
|
1
12
|
//#region src/index.d.ts
|
|
2
13
|
/**
|
|
3
14
|
* @embedpdf/core-geometry — the viewer's pure 2D coordinate primitives.
|
|
4
15
|
*
|
|
5
16
|
* The bottom of the pyramid: stage-core (layout), plugin-stage (`pageToWorld`),
|
|
6
|
-
* and every framework adapter (`
|
|
17
|
+
* and every framework adapter (`toPagePoint` hit-testing) all sit on these.
|
|
7
18
|
* Zero dependencies, DOM-free, serializable — Rust-portable.
|
|
8
19
|
*
|
|
9
20
|
* The page-rotation transforms are the reason this package exists: the same
|
|
10
|
-
* quarter-turn maps content↔box in
|
|
21
|
+
* quarter-turn maps content↔box in both directions, and that one rule must not
|
|
11
22
|
* be hand-written (and drift, or be bug-fixed in only one of four adapters).
|
|
12
23
|
*/
|
|
13
24
|
interface Point {
|
|
@@ -19,13 +30,9 @@ interface Size {
|
|
|
19
30
|
height: number;
|
|
20
31
|
}
|
|
21
32
|
/**
|
|
22
|
-
* A rectangle in
|
|
23
|
-
*
|
|
24
|
-
* rects, render boxes.
|
|
25
|
-
*
|
|
26
|
-
* The rule: shown on screen → `Rect`; stored in the file → the engine's y-up
|
|
27
|
-
* `PdfRect` (`{left, bottom, right, top}`). The shapes are incompatible on
|
|
28
|
-
* purpose — passing one where the other goes doesn't compile.
|
|
33
|
+
* A rectangle in page space: top-left origin, y-down, in points. What every
|
|
34
|
+
* viewer and engine API speaks — annotation rects, `stage.reveal`, selection
|
|
35
|
+
* and search rects, render boxes.
|
|
29
36
|
*/
|
|
30
37
|
interface Rect {
|
|
31
38
|
x: number;
|
|
@@ -45,10 +52,21 @@ declare function boundsOfRects(rects: readonly Rect[]): Rect | null;
|
|
|
45
52
|
* without a null branch. Space-agnostic like {@link boundsOfRects}: view-px
|
|
46
53
|
* viewport ∩ footprint, page-point visibility ∩ tile footprints, ….
|
|
47
54
|
*/
|
|
48
|
-
declare function intersectRects(
|
|
55
|
+
declare function intersectRects(left: Rect, right: Rect): Rect;
|
|
56
|
+
/** The axis-aligned rect spanned by two corners, in any order — a drag box. */
|
|
57
|
+
declare function rectFromCorners(from: Point, to: Point): Rect;
|
|
58
|
+
/** Whether a rect contains a point, edges inclusive. Space-agnostic. */
|
|
59
|
+
declare function rectContains(rect: Rect, point: Point): boolean;
|
|
60
|
+
/** Positive-area overlap of two rects — touching edges do not count. */
|
|
61
|
+
declare function rectsOverlap(left: Rect, right: Rect): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* The largest rect of `content`'s proportions inside `box`, centred in it:
|
|
64
|
+
* CSS `object-fit: contain`. `box` itself when `content` has no area.
|
|
65
|
+
*/
|
|
66
|
+
declare function containedRect(content: Size, box: Rect): Rect;
|
|
49
67
|
/**
|
|
50
68
|
* Quarter-turn display rotation, degrees clockwise. The viewer-side notion of a
|
|
51
|
-
* page's on-screen rotation — the
|
|
69
|
+
* page's on-screen rotation — the total = (document /Rotate + any view
|
|
52
70
|
* rotation), resolved by the shell. Structurally identical to the engine's
|
|
53
71
|
* `PageRotation`, so the two interoperate without this package depending on the
|
|
54
72
|
* engine.
|
|
@@ -70,118 +88,117 @@ declare const NO_FRAME: PageFrame;
|
|
|
70
88
|
/** True for the quarter-turns that swap a page's width and height. */
|
|
71
89
|
declare function isQuarterTurn(rotation: PageRotation): boolean;
|
|
72
90
|
/**
|
|
73
|
-
* Compose two quarter-turn rotations (mod 360).
|
|
74
|
-
* page's
|
|
91
|
+
* Compose two quarter-turn rotations (mod 360). The way the shell resolves a
|
|
92
|
+
* page's total display rotation — `addRotations(page /Rotate, view rotation)`
|
|
75
93
|
* — so the wrap arithmetic is never hand-written (and drift) per call site.
|
|
76
94
|
*/
|
|
77
|
-
declare function addRotations(
|
|
95
|
+
declare function addRotations(left: PageRotation, right: PageRotation): PageRotation;
|
|
78
96
|
/**
|
|
79
97
|
* Snap a view-px value to the device pixel grid: round to a whole device pixel,
|
|
80
|
-
* back to view px. Used for a page's screen
|
|
98
|
+
* back to view px. Used for a page's screen position so a CSS-rotated page lands
|
|
81
99
|
* on the grid (no sub-pixel anti-aliased fringe). The shell never hand-rounds.
|
|
82
100
|
*/
|
|
83
101
|
declare function snapToDevice(value: number, dpr: number): number;
|
|
84
102
|
/** A page's on-screen footprint: width and height swapped for quarter-turns. */
|
|
85
103
|
declare function displaySize(content: Size, rotation: PageRotation): Size;
|
|
86
104
|
/**
|
|
87
|
-
* The engine's `kind:'width'` height rule, replicated
|
|
105
|
+
* The engine's `kind:'width'` height rule, replicated exactly so the viewer can
|
|
88
106
|
* predict the rendered bitmap's height up front — the page box is sized to it,
|
|
89
107
|
* so the box matches the bitmap with no reflow and no 1px seam.
|
|
90
108
|
*
|
|
91
109
|
* Mirrors `PageRenderReader.resolveDeviceSize` (engine-services): we render the
|
|
92
|
-
* page
|
|
93
|
-
* here — `pageSize` is the page's own points.
|
|
110
|
+
* page un-rotated (CSS applies the rotation), so there is no width/height swap
|
|
111
|
+
* here — `pageSize` is the page's own points. Must stay in lockstep with that
|
|
94
112
|
* function; the round-trip test in the render plugin asserts they agree.
|
|
95
113
|
*/
|
|
96
114
|
declare function deviceHeightForWidth(pageSize: Size, deviceWidth: number): number;
|
|
97
115
|
/**
|
|
98
|
-
* The single per-page bridge between the viewer's three coordinate spaces
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* hop (the y-flip + crop offset) is a separate matrix (`pageGeometry`).
|
|
116
|
+
* The single per-page bridge between the viewer's three coordinate spaces, all
|
|
117
|
+
* top-left origin, y-down. Page space is the engine's own, so engine values
|
|
118
|
+
* need no hop of their own.
|
|
102
119
|
*
|
|
103
|
-
*
|
|
120
|
+
* page space page-local points, top-left, y-down — un-rotated page frame
|
|
104
121
|
* view space platform logical px (web: CSS px) — layout, DOM, pointer events
|
|
105
122
|
* device space physical pixels — the rendered bitmap
|
|
106
123
|
*
|
|
107
|
-
*
|
|
124
|
+
* Page-local by design: it knows this page's own box, not where the page sits in
|
|
108
125
|
* the scene. Placement (camera/layout) stays on `VisiblePage.{x,y}` and positions
|
|
109
|
-
* the page container; the transform converts everything
|
|
126
|
+
* the page container; the transform converts everything inside that container. So
|
|
110
127
|
* it is camera/pan-invariant — it only changes on zoom / rotation / contentScale
|
|
111
128
|
* / dpr, which makes it cheap to memoize.
|
|
112
129
|
*
|
|
113
|
-
* Every plugin and framework adapter consumes
|
|
130
|
+
* Every plugin and framework adapter consumes this — never `x * scale`, never
|
|
114
131
|
* `pageToWorld()∘toScreen()`, never `* dpr`. New plugins (annotations, search,
|
|
115
132
|
* forms) do no coordinate math; new platforms (iOS/Android) inject a different
|
|
116
133
|
* `scale` and reuse all of it.
|
|
117
134
|
*/
|
|
118
135
|
interface PageTransform {
|
|
119
136
|
/**
|
|
120
|
-
* The page's
|
|
137
|
+
* The page's total display rotation (document /Rotate + any view rotation) —
|
|
121
138
|
* the same value the transform's matrices were built from, exposed so
|
|
122
139
|
* consumers that need the quarter-turn itself (an upright-placement rule, a
|
|
123
|
-
* pointer sample) read it
|
|
140
|
+
* pointer sample) read it here instead of re-deriving it from the matrix.
|
|
124
141
|
*/
|
|
125
142
|
readonly rotation: PageRotation;
|
|
126
|
-
/** Display footprint in
|
|
143
|
+
/** Display footprint in view px (device-snapped) — the page container's size.
|
|
127
144
|
* Width↔height already swapped for quarter-turns. */
|
|
128
145
|
readonly viewWidth: number;
|
|
129
146
|
readonly viewHeight: number;
|
|
130
|
-
/** The
|
|
131
|
-
* and
|
|
147
|
+
/** The un-rotated content box in view px — the size of the wrapper the bitmap
|
|
148
|
+
* and page-space overlays live in (before the wrapper's CSS rotation). */
|
|
132
149
|
readonly contentWidth: number;
|
|
133
150
|
readonly contentHeight: number;
|
|
134
|
-
/** Render the (un-rotated) bitmap at
|
|
151
|
+
/** Render the (un-rotated) bitmap at exactly this — `viewport: {kind:'width', width: deviceWidth}`.
|
|
135
152
|
* Integer device px; `deviceHeight` is the engine's exact derived height. */
|
|
136
153
|
readonly deviceWidth: number;
|
|
137
154
|
readonly deviceHeight: number;
|
|
138
155
|
/** Device px per PDF point (uniform). */
|
|
139
156
|
readonly renderScale: number;
|
|
140
|
-
/**
|
|
157
|
+
/** View px per PDF point (uniform, device-snapped) — the one factor for
|
|
141
158
|
* screen-constant chrome: content units = CSS px ÷ `viewScale`. */
|
|
142
159
|
readonly viewScale: number;
|
|
143
160
|
/**
|
|
144
|
-
* View px per PDF point at 100%
|
|
161
|
+
* View px per PDF point at 100% zoom — the page's physical baseline:
|
|
145
162
|
* `viewUnitsPerPoint × userUnit` (web: 96/72 × `/UserUnit`, so 100% maps to
|
|
146
|
-
* inches on screen, Acrobat-style). What "100%"
|
|
163
|
+
* inches on screen, Acrobat-style). What "100%" means for this page.
|
|
147
164
|
*/
|
|
148
165
|
readonly baseScale: number;
|
|
149
166
|
/**
|
|
150
|
-
* The page's zoom
|
|
151
|
-
* dimensionless; exactly 1 at 100% for any `userUnit`).
|
|
167
|
+
* The page's zoom relative to its 100% baseline (`viewScale / baseScale`,
|
|
168
|
+
* dimensionless; exactly 1 at 100% for any `userUnit`). The number
|
|
152
169
|
* zoom-relative policies consume — e.g. the `/F` NoZoom exemption clamps
|
|
153
170
|
* its body to `zoom ≤ 1`. Distinct from `viewScale` (a units conversion).
|
|
154
171
|
*/
|
|
155
172
|
readonly zoom: number;
|
|
156
173
|
/**
|
|
157
174
|
* Content point → this page's pixels (the un-rotated content wrapper's local
|
|
158
|
-
* px).
|
|
159
|
-
* rotation, so they place in
|
|
175
|
+
* px). The overlay author's converter: elements inside the wrapper ride its
|
|
176
|
+
* rotation, so they place in page points and only scale here. Convert at
|
|
160
177
|
* the last moment — pixels are never stored.
|
|
161
178
|
*/
|
|
162
|
-
toPixels(
|
|
163
|
-
/** Inverse of {@link toPixels}: wrapper-local px →
|
|
179
|
+
toPixels(point: Point): Point;
|
|
180
|
+
/** Inverse of {@link toPixels}: wrapper-local px → page point (a pointer
|
|
164
181
|
* event inside the wrapper back to the viewer's coordinates). */
|
|
165
|
-
fromPixels(
|
|
166
|
-
/** Content point → page-local view px in the
|
|
182
|
+
fromPixels(point: Point): Point;
|
|
183
|
+
/** Content point → page-local view px in the display box (rotation applied). For
|
|
167
184
|
* footprint-space layers (outside the wrapper). */
|
|
168
|
-
|
|
185
|
+
pageToView(point: Point): Point;
|
|
169
186
|
/** Content rect → its axis-aligned view-px rect (exact for quarter-turns). */
|
|
170
|
-
|
|
171
|
-
/** Inverse — display-box view px (box-local) →
|
|
172
|
-
|
|
173
|
-
/** Inverse of {@link
|
|
187
|
+
pageToViewRect(rect: Rect): Rect;
|
|
188
|
+
/** Inverse — display-box view px (box-local) → page point. Hit-testing. */
|
|
189
|
+
viewToPage(point: Point): Point;
|
|
190
|
+
/** Inverse of {@link pageToViewRect}: display-box view-px rect → its content
|
|
174
191
|
* AABB (exact for quarter-turns). The visibility primitive — projecting a
|
|
175
|
-
* viewport rect into page points is
|
|
176
|
-
|
|
177
|
-
/** CSS `matrix()` mapping
|
|
192
|
+
* viewport rect into page points is this, never per-adapter corner math. */
|
|
193
|
+
viewToPageRect(rect: Rect): Rect;
|
|
194
|
+
/** CSS `matrix()` mapping page space → this page's display box. Drop it on
|
|
178
195
|
* a footprint-space layer (`transform`, `transform-origin: 0 0`) and place
|
|
179
|
-
* children in
|
|
196
|
+
* children in page points — rotation + scale handled for free. */
|
|
180
197
|
readonly cssMatrix: string;
|
|
181
198
|
}
|
|
182
199
|
/**
|
|
183
200
|
* Build a page's transform from its intrinsic size + the platform/view scale.
|
|
184
|
-
* `scale` is
|
|
201
|
+
* `scale` is view px per PDF point (the shell composes it: `viewUnitsPerPoint ×
|
|
185
202
|
* contentScale × zoom`); `dpr` is device px per view px. Device dimensions snap
|
|
186
203
|
* to the grid (crisp, no rotation fringe) and follow the engine's width rule
|
|
187
204
|
* (box == bitmap, no reflow).
|
|
@@ -203,15 +220,22 @@ declare function pageTransform(input: {
|
|
|
203
220
|
dpr: number;
|
|
204
221
|
}): PageTransform;
|
|
205
222
|
/**
|
|
206
|
-
*
|
|
207
|
-
*
|
|
223
|
+
* Whether two transforms place things on the page the same: the same scale, zoom and turn, and
|
|
224
|
+
* the same content box. A Stage builds a new transform on every frame, also for a plain scroll,
|
|
225
|
+
* which moves the page but changes nothing inside it; a layer that compares with this redraws
|
|
226
|
+
* only when what it draws in the page's pixels moved.
|
|
208
227
|
*/
|
|
209
|
-
|
|
228
|
+
declare function samePagePlacement(left: Pick<PageTransform, 'viewScale' | 'zoom' | 'rotation' | 'contentWidth' | 'contentHeight'>, right: Pick<PageTransform, 'viewScale' | 'zoom' | 'rotation' | 'contentWidth' | 'contentHeight'>): boolean;
|
|
210
229
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
230
|
+
* The coordinate spaces a viewer touches, all y-down. `content` is the
|
|
231
|
+
* engine's page space: points from the top-left of the visible page.
|
|
232
|
+
*/
|
|
233
|
+
type Space = 'page' | 'view' | 'screen';
|
|
234
|
+
/**
|
|
235
|
+
* Phantom space brand. It is optional so plain `{ x, y }` / `{ x, y, w, h }`
|
|
236
|
+
* literals stay assignable day-to-day (terse), but a value explicitly tagged
|
|
213
237
|
* with the wrong space is rejected — and `Mat2D<From, To>` enforces the hop at
|
|
214
|
-
* the matrix, so you cannot `applyRect` a `
|
|
238
|
+
* the matrix, so you cannot `applyRect` a `view` rect with a `content→view`
|
|
215
239
|
* matrix. The brand is type-only; it carries no runtime field.
|
|
216
240
|
*/
|
|
217
241
|
interface SpaceBrand<S extends Space> {
|
|
@@ -222,23 +246,29 @@ type PointIn<S extends Space> = Point & SpaceBrand<S>;
|
|
|
222
246
|
/**
|
|
223
247
|
* An axis-aligned rect tagged with its space, as min-corner + positive extent:
|
|
224
248
|
* `(x, y)` is the corner with the smallest coordinates and `(x+width, y+height)`
|
|
225
|
-
* the largest
|
|
226
|
-
* `y=bottom`); in the y-down viewer spaces it is top-left.
|
|
249
|
+
* the largest: in every space here, the top-left.
|
|
227
250
|
*/
|
|
228
251
|
type RectIn<S extends Space> = Rect & SpaceBrand<S>;
|
|
229
252
|
/**
|
|
230
|
-
*
|
|
231
|
-
* `
|
|
232
|
-
*
|
|
253
|
+
* A quad: four corners named in the text's own upright frame, the viewer twin
|
|
254
|
+
* of the engine's `PageQuad`. `upper` is the ascent side and `lower` the
|
|
255
|
+
* baseline side; `left` to `right` runs along the frame's x axis. The names
|
|
256
|
+
* are neither screen directions nor reading order: text turned 180° has its
|
|
257
|
+
* `upperLeft` at the bottom right, and right-to-left text still runs from
|
|
258
|
+
* `left` to `right`. In y-down page space an upright quad has `upper*` at the
|
|
259
|
+
* smaller y. Use it (via {@link applyQuad}) for text and any content that can
|
|
260
|
+
* turn or skew, where an axis-aligned rect would lie.
|
|
233
261
|
*/
|
|
234
262
|
interface Quad {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
263
|
+
upperLeft: Point;
|
|
264
|
+
upperRight: Point;
|
|
265
|
+
lowerLeft: Point;
|
|
266
|
+
lowerRight: Point;
|
|
239
267
|
}
|
|
240
268
|
/** A quad tagged with its coordinate space. */
|
|
241
269
|
type QuadIn<S extends Space> = Quad & SpaceBrand<S>;
|
|
270
|
+
/** Four points as a polygon ring, for `<polygon>`, fills and hit tests. */
|
|
271
|
+
type QuadRing = [Point, Point, Point, Point];
|
|
242
272
|
/**
|
|
243
273
|
* A 2D affine transform from space `From` to space `To`, stored as the six
|
|
244
274
|
* numbers `[a, b, c, d, e, f]`. The phantom `From`/`To` make the compiler track
|
|
@@ -252,154 +282,75 @@ type Mat2D<From extends Space = Space, To extends Space = Space> = readonly [num
|
|
|
252
282
|
/** The identity transform within a single space. */
|
|
253
283
|
declare function identity<S extends Space>(): Mat2D<S, S>;
|
|
254
284
|
/**
|
|
255
|
-
* Compose two matrices: `compose(
|
|
256
|
-
* product `
|
|
257
|
-
* rejects composing mismatched hops.
|
|
285
|
+
* Compose two matrices: `compose(matrix, inner)` applies `inner` first, then
|
|
286
|
+
* `matrix` (matrix product `matrix · inner`). The shared middle space `B` must
|
|
287
|
+
* line up, so the type system rejects composing mismatched hops.
|
|
258
288
|
*/
|
|
259
|
-
declare function compose<A extends Space, B extends Space, C extends Space>(
|
|
260
|
-
/** Invert a transform — `invert(
|
|
261
|
-
declare function invert<F extends Space, T extends Space>(
|
|
289
|
+
declare function compose<A extends Space, B extends Space, C extends Space>(matrix: Mat2D<B, C>, inner: Mat2D<A, B>): Mat2D<A, C>;
|
|
290
|
+
/** Invert a transform — `invert(pageToView)` is `viewToPage`, i.e. hit-testing for free. */
|
|
291
|
+
declare function invert<F extends Space, T extends Space>(matrix: Mat2D<F, T>): Mat2D<T, F>;
|
|
262
292
|
/** Apply a transform to a point. */
|
|
263
|
-
declare function applyPoint<F extends Space, T extends Space>(
|
|
293
|
+
declare function applyPoint<F extends Space, T extends Space>(matrix: Mat2D<F, T>, point: PointIn<F>): PointIn<T>;
|
|
264
294
|
/**
|
|
265
295
|
* Apply a transform to a rect, returning the axis-aligned bounding box of the
|
|
266
|
-
* four transformed corners.
|
|
296
|
+
* four transformed corners. Exact for translate/scale/quarter-turn (every page
|
|
267
297
|
* transform `pageGeometry` produces); lossy under skew — use {@link applyQuad}
|
|
268
298
|
* for content that can be rotated off-axis.
|
|
269
299
|
*/
|
|
270
|
-
declare function applyRect<F extends Space, T extends Space>(
|
|
271
|
-
/** Apply a transform to a quad
|
|
272
|
-
declare function applyQuad<F extends Space, T extends Space>(
|
|
300
|
+
declare function applyRect<F extends Space, T extends Space>(matrix: Mat2D<F, T>, rect: RectIn<F>): RectIn<T>;
|
|
301
|
+
/** Apply a transform to a quad: each corner moves and keeps its name. */
|
|
302
|
+
declare function applyQuad<F extends Space, T extends Space>(matrix: Mat2D<F, T>, quad: QuadIn<F>): QuadIn<T>;
|
|
273
303
|
/**
|
|
274
|
-
* A `Mat2D`
|
|
304
|
+
* A `Mat2D` is a CSS `matrix()` — the six numbers are identical. Drop the result
|
|
275
305
|
* on a footprint-space layer (`transform`, `transform-origin: 0 0`) and place
|
|
276
306
|
* children in the source space; the rotation + scale are handled for free.
|
|
277
307
|
*/
|
|
278
|
-
declare function matrixToCss(
|
|
308
|
+
declare function matrixToCss(matrix: Mat2D): string;
|
|
279
309
|
/** Translate within a space. */
|
|
280
310
|
declare function translate<S extends Space>(tx: number, ty: number): Mat2D<S, S>;
|
|
281
311
|
/** Scale about the space origin. */
|
|
282
312
|
declare function scale<S extends Space>(sx: number, sy: number): Mat2D<S, S>;
|
|
283
|
-
/** Rotate about the space origin (radians; clockwise in y-down
|
|
313
|
+
/** Rotate about the space origin (radians; clockwise in y-down page space). */
|
|
284
314
|
declare function rotate<S extends Space>(rad: number): Mat2D<S, S>;
|
|
285
315
|
/** Rotate about an arbitrary pivot: `T(c) · R(rad) · T(-c)`. */
|
|
286
|
-
declare function rotateAbout<S extends Space>(
|
|
316
|
+
declare function rotateAbout<S extends Space>(point: PointIn<S>, rad: number): Mat2D<S, S>;
|
|
287
317
|
/** Scale about an arbitrary anchor: `T(a) · S(sx, sy) · T(-a)`. */
|
|
288
|
-
declare function scaleAbout<S extends Space>(
|
|
318
|
+
declare function scaleAbout<S extends Space>(point: PointIn<S>, sx: number, sy: number): Mat2D<S, S>;
|
|
289
319
|
/** The rotation angle (radians) encoded in a matrix — `atan2(b, a)`. Positive is
|
|
290
|
-
* clockwise in y-down
|
|
291
|
-
declare function angleOf(
|
|
320
|
+
* clockwise in y-down page space (the inverse of {@link rotate}). */
|
|
321
|
+
declare function angleOf(matrix: Mat2D): number;
|
|
292
322
|
/**
|
|
293
|
-
* The page's scale + integer quarter-turn as a `Mat2D`: a
|
|
294
|
-
* its place in the rotated
|
|
295
|
-
* point; `boxW`/`boxH` are the
|
|
323
|
+
* The page's scale + integer quarter-turn as a `Mat2D`: a page point maps to
|
|
324
|
+
* its place in the rotated display box. `scale` is output units per content
|
|
325
|
+
* point; `boxW`/`boxH` are the un-rotated content's extents in those same output
|
|
296
326
|
* units, and the offsets keep the footprint in the box's positive quadrant
|
|
297
327
|
* (origin at the box top-left).
|
|
298
328
|
*
|
|
299
|
-
*
|
|
329
|
+
* The single encoding of the quarter-turn — `pageTransform` (view px),
|
|
300
330
|
* `pageGeometry` (the `content→view` hop), and `pageToWorld` (world units) all
|
|
301
331
|
* build on this one function, so the rotation can never drift between them.
|
|
302
332
|
*/
|
|
303
333
|
declare function rotateScaleMatrix(scale: number, boxW: number, boxH: number, rotation: PageRotation): Mat2D;
|
|
334
|
+
/** An upright quad over a rect (y-down: upper = smaller y). */
|
|
335
|
+
declare function quadFromRect(rect: Rect): Quad;
|
|
336
|
+
/** The four corners: upper-left, upper-right, lower-left, lower-right. */
|
|
337
|
+
declare function quadCorners(quad: Quad): [Point, Point, Point, Point];
|
|
338
|
+
/** The corners as a polygon ring: upper-left, upper-right, lower-right, lower-left. */
|
|
339
|
+
declare function quadRing(quad: Quad): QuadRing;
|
|
304
340
|
/**
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
* this package dependency-free — the same reason {@link PageRotation} is a
|
|
308
|
-
* structural twin of the engine's rotation.
|
|
309
|
-
*/
|
|
310
|
-
interface PageGeometryInput {
|
|
311
|
-
/** Effective crop box in PDF user space (y-up edges); origin preserved, so
|
|
312
|
-
* `left`/`bottom` may be non-zero or negative. */
|
|
313
|
-
crop: {
|
|
314
|
-
left: number;
|
|
315
|
-
bottom: number;
|
|
316
|
-
right: number;
|
|
317
|
-
top: number;
|
|
318
|
-
};
|
|
319
|
-
/** Persistent page rotation (the document's `/Rotate`). */
|
|
320
|
-
rotation: PageRotation;
|
|
321
|
-
/** PDF `userUnit` (§14.11.6): scales PDF points into the layout. 1 for most docs. */
|
|
322
|
-
userUnit: number;
|
|
323
|
-
}
|
|
324
|
-
/** The matrices bridging one page's spaces — every other matrix composes from these. */
|
|
325
|
-
interface PageGeometry {
|
|
326
|
-
/** PDF user space (y-up, crop-relative) → content space (y-down, crop top-left, unscaled points). */
|
|
327
|
-
readonly pdfToContent: Mat2D<'pdf', 'content'>;
|
|
328
|
-
/** Content → view: scale (zoom × userUnit) + the page's quarter-turn rotation. */
|
|
329
|
-
readonly contentToView: Mat2D<'content', 'view'>;
|
|
330
|
-
/** PDF → view, precomposed. */
|
|
331
|
-
readonly pdfToView: Mat2D<'pdf', 'view'>;
|
|
332
|
-
/** View → PDF, the inverse — hit-testing for free. */
|
|
333
|
-
readonly viewToPdf: Mat2D<'view', 'pdf'>;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* PDF user space (y-up, origin = crop bottom-left) → content space (y-down,
|
|
337
|
-
* origin = crop top-left, unscaled points). THE single encoding of the engine→
|
|
338
|
-
* content y-flip + crop offset: `pageGeometry` composes its `pdfToContent` from
|
|
339
|
-
* this, and pure annotation geometry (content-space editing) reuses it too, so
|
|
340
|
-
* the rule can never be hand-written twice and drift.
|
|
341
|
-
*/
|
|
342
|
-
declare function pdfToContentMatrix(crop: {
|
|
343
|
-
left: number;
|
|
344
|
-
top: number;
|
|
345
|
-
}): Mat2D<'pdf', 'content'>;
|
|
346
|
-
/**
|
|
347
|
-
* Build a page's space matrices from its crop box, rotation, and `userUnit` plus
|
|
348
|
-
* the viewer `zoom`. This is the ONE function that knows the y-flip, crop origin,
|
|
349
|
-
* `userUnit`, and rotation; everything else composes from its output. The engine
|
|
350
|
-
* never emits these — they bake in viewer state (zoom, later scroll/dpr) — so the
|
|
351
|
-
* boundary stays clean: engine owns `Pdf*` truth, the viewer composes the rest.
|
|
352
|
-
*/
|
|
353
|
-
declare function pageGeometry(input: PageGeometryInput, zoom: number): PageGeometry;
|
|
354
|
-
interface TextQuad {
|
|
355
|
-
upperStart: Point;
|
|
356
|
-
upperEnd: Point;
|
|
357
|
-
lowerStart: Point;
|
|
358
|
-
lowerEnd: Point;
|
|
359
|
-
}
|
|
360
|
-
/** A TextQuad tagged with its coordinate space. */
|
|
361
|
-
type TextQuadIn<S extends Space> = TextQuad & SpaceBrand<S>;
|
|
362
|
-
/** Axis-aligned TextQuad over a rect (y-down: upper = smaller y). */
|
|
363
|
-
declare function textQuadFromRect(r: Rect): TextQuad;
|
|
364
|
-
/** The four corners in slot order: upper-start, upper-end, lower-start, lower-end. */
|
|
365
|
-
declare function textQuadPoints(t: TextQuad): [Point, Point, Point, Point];
|
|
366
|
-
/** The corners as a polygon RING (US → UE → LE → LS) — for `<polygon>`/fills. */
|
|
367
|
-
declare function textQuadRing(t: TextQuad): [Point, Point, Point, Point];
|
|
368
|
-
/**
|
|
369
|
-
* One SIDE edge of the cell — the start (`US → LS`) or end (`UE → LE`) edge,
|
|
370
|
-
* ASCENT CORNER FIRST. This is the segment a caret or a selection handle
|
|
341
|
+
* One side edge of the cell, the left (`UL → LL`) or right (`UR → LR`) one,
|
|
342
|
+
* ascent corner first. This is the segment a caret or a selection handle
|
|
371
343
|
* occupies: its length is the glyph's ink height in the text's own frame (not
|
|
372
344
|
* the AABB height, which grows with tilt), and its direction carries the
|
|
373
|
-
* text's rotation. Which side is the selection's
|
|
345
|
+
* text's rotation. Which side is the selection's leading edge is a reading
|
|
374
346
|
* -order question — decide it with `advance`, not with geometry.
|
|
375
347
|
*/
|
|
376
|
-
declare function
|
|
377
|
-
/** Corner-wise equality — an AABB comparison would call a quad that
|
|
348
|
+
declare function quadEdge(quad: Quad, side: 'left' | 'right'): [Point, Point];
|
|
349
|
+
/** Corner-wise equality — an AABB comparison would call a quad that rotated
|
|
378
350
|
* in place "unchanged"; corners cannot. (Change-detection for quad consumers.) */
|
|
379
|
-
declare function
|
|
380
|
-
/** Axis-aligned bounds of a
|
|
381
|
-
declare function
|
|
382
|
-
/** Map a TextQuad through an affine transform (corner semantics ride along). */
|
|
383
|
-
declare function applyTextQuad<F extends Space, T extends Space>(m: Mat2D<F, T>, t: TextQuadIn<F>): TextQuadIn<T>;
|
|
384
|
-
/** Serialize to the positional zigzag convention (`p1..p4` = US, UE, LS, LE). */
|
|
385
|
-
declare function positionalQuad(t: TextQuad): Quad;
|
|
386
|
-
/**
|
|
387
|
-
* Interpret an arbitrary positional quad (an imported `/QuadPoints` entry,
|
|
388
|
-
* already in content space) as a TextQuad — a NORMALIZER, not a cast:
|
|
389
|
-
*
|
|
390
|
-
* 1. the de-facto zigzag order (US, UE, LS, LE) passes through untouched —
|
|
391
|
-
* this covers every well-formed writer, rotated quads included;
|
|
392
|
-
* 2. the common ring order (US, UE, LE, LS) is recognized and repaired;
|
|
393
|
-
* 3. anything else gets a deterministic geometric labeling: corners sorted
|
|
394
|
-
* into a ring around their centroid, "upper" = the edge whose midpoint
|
|
395
|
-
* sits highest on screen (smallest y). The 180° "which side is up"
|
|
396
|
-
* ambiguity is unresolvable from geometry alone — convention decides.
|
|
397
|
-
*
|
|
398
|
-
* Drawing code downstream (`markupScene`) reads corner SEMANTICS, so a
|
|
399
|
-
* mislabeled import can shift an underline to the wrong edge but can never
|
|
400
|
-
* crash or self-intersect.
|
|
401
|
-
*/
|
|
402
|
-
declare function normalizeQuad(q: Quad): TextQuad;
|
|
351
|
+
declare function quadEquals(left: Quad, right: Quad): boolean;
|
|
352
|
+
/** Axis-aligned bounds of a quad. */
|
|
353
|
+
declare function quadBounds(quad: Quad): Rect;
|
|
403
354
|
//#endregion
|
|
404
|
-
export { Mat2D, NO_FRAME, PageFrame,
|
|
355
|
+
export { Mat2D, NO_FRAME, PageFrame, PagePoint, PageQuad, PageRect, PageRotation, PageTransform, Point, PointIn, Quad, QuadIn, QuadRing, Rect, RectIn, Size, Space, addRotations, angleOf, applyPoint, applyQuad, applyRect, boundsOfRects, compose, containedRect, deviceHeightForWidth, displaySize, identity, intersectRects, invert, isQuarterTurn, matrixToCss, pageTransform, quadBounds, quadCorners, quadEdge, quadEquals, quadFromRect, quadRing, rectContains, rectFromCorners, rectsOverlap, rotate, rotateAbout, rotateScaleMatrix, samePagePlacement, scale, scaleAbout, snapToDevice, translate };
|
|
405
356
|
//# sourceMappingURL=index.d.ts.map
|