Commit 3d826b4
fix(search): position match highlights from item geometry (correct at zoom + across text-layer builders) (#299)
* fix(search): position highlights from the matched items, not a visual re-scan
Highlights were positioned by re-scanning the DOM for the match text
and pairing the Nth stream-order result with the Nth visual-order
occurrence; whenever content-stream order differs from reading order
(multi-column pages, tables, headers drawn last) the box lands on the
wrong occurrence, and matches spanning multiple text items were
missed entirely. Build the highlight from the result's own items via
span[data-item-index] and a character Range, which is exact in both
orders and across item boundaries. Also fix the continuous-mode
page selectors (data-page, not data-page-num), which returned null
and silently skipped highlight/scroll there.
* fix(search): scale highlight rects into the text layer's coordinate space
Search highlights are positioned inside .textLayer, which is laid out in
unscaled PDF points and zoomed via a CSS matrix transform. The highlight
rects were measured with getBoundingClientRect() (visual, post-transform
pixels) and applied as-is, so the layer's transform scaled them a second
time — at any zoom other than 100% every highlight drifted away from its
match, proportionally to its distance from the page origin.
Divide the measured offsets and sizes by the layer's effective scale
(bounding-rect width over layout width) before positioning. Works in both
single-page and continuous mode and is a no-op at scale 1.
Also remove findAllMatchPositions(), dead since the switch to
item-based positioning.
* fix(search): position highlights from item geometry, not DOM spans
Highlighting depended on span[data-item-index], which only the custom
single-page PDF.js text layer sets. The Rust-extracted vector-mode layer
and the stock PDF.js TextLayer (continuous mode) carry no such attribute,
so every match on those pages silently produced zero highlights. DOM
measurement also broke on zoom: rects captured at one zoom level went
stale the moment the layer was rebuilt or re-scaled.
Position highlights directly from the matched items' PDF-space geometry
(transform/width/height captured at text extraction), converted to
layer-local coordinates via --total-scale-factor, which every layer
builder sets. Layer-local rects ride the viewport zoom transform, so
zooming no longer displaces them.
Also sort results by visual position (top-to-bottom, left-to-right)
instead of content-stream order, so "1 of N" starts at the top of the
page, and remove the now-unused findDomSpanForItem().
* fix(search): start at the visually-first match on the current page
The initial current match is chosen during the progressive search, from
a page's raw results — which were in content-stream order, so "1 of N"
could land mid-page (e.g. starting at 3/14). Sort each page's results
visually at discovery time so the starting match is the topmost one on
the current page (or the next page with matches).
---------
Co-authored-by: Maarten Vroegindeweij <30430941+DutchSailor@users.noreply.github.com>1 parent 6cdbdf7 commit 3d826b4
2 files changed
Lines changed: 83 additions & 155 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
303 | 303 | | |
304 | 304 | | |
305 | 305 | | |
306 | | - | |
| 306 | + | |
307 | 307 | | |
308 | 308 | | |
309 | 309 | | |
| |||
395 | 395 | | |
396 | 396 | | |
397 | 397 | | |
398 | | - | |
399 | | - | |
400 | | - | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
411 | | - | |
412 | | - | |
413 | | - | |
414 | | - | |
415 | | - | |
416 | | - | |
417 | | - | |
418 | | - | |
419 | | - | |
420 | | - | |
421 | | - | |
422 | | - | |
423 | | - | |
424 | | - | |
425 | | - | |
426 | | - | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
448 | | - | |
449 | | - | |
450 | | - | |
451 | | - | |
452 | | - | |
453 | | - | |
454 | | - | |
455 | | - | |
456 | | - | |
457 | | - | |
458 | | - | |
459 | | - | |
460 | | - | |
461 | | - | |
462 | | - | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
467 | | - | |
468 | | - | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
480 | | - | |
481 | | - | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | | - | |
489 | | - | |
490 | | - | |
491 | | - | |
492 | | - | |
493 | | - | |
494 | | - | |
495 | | - | |
496 | | - | |
497 | | - | |
498 | | - | |
499 | | - | |
500 | | - | |
501 | | - | |
502 | | - | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
503 | 409 | | |
504 | 410 | | |
505 | | - | |
| 411 | + | |
506 | 412 | | |
507 | 413 | | |
| 414 | + | |
508 | 415 | | |
509 | 416 | | |
510 | 417 | | |
511 | | - | |
512 | | - | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
513 | 421 | | |
| 422 | + | |
514 | 423 | | |
515 | 424 | | |
516 | | - | |
517 | 425 | | |
518 | 426 | | |
519 | | - | |
520 | | - | |
521 | | - | |
522 | | - | |
523 | | - | |
524 | | - | |
525 | | - | |
526 | | - | |
527 | | - | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
528 | 455 | | |
529 | 456 | | |
530 | 457 | | |
531 | 458 | | |
532 | | - | |
533 | | - | |
534 | | - | |
535 | | - | |
536 | | - | |
537 | | - | |
538 | | - | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
539 | 463 | | |
540 | 464 | | |
541 | 465 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
128 | 128 | | |
129 | 129 | | |
130 | 130 | | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
131 | 135 | | |
132 | 136 | | |
133 | 137 | | |
134 | 138 | | |
135 | 139 | | |
136 | 140 | | |
| 141 | + | |
| 142 | + | |
137 | 143 | | |
138 | 144 | | |
139 | 145 | | |
140 | 146 | | |
141 | 147 | | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
142 | 153 | | |
143 | 154 | | |
144 | 155 | | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
145 | 173 | | |
146 | 174 | | |
147 | 175 | | |
| |||
167 | 195 | | |
168 | 196 | | |
169 | 197 | | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
| 198 | + | |
175 | 199 | | |
176 | 200 | | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
177 | 204 | | |
178 | 205 | | |
179 | 206 | | |
| |||
251 | 278 | | |
252 | 279 | | |
253 | 280 | | |
254 | | - | |
| 281 | + | |
255 | 282 | | |
256 | 283 | | |
257 | 284 | | |
| |||
386 | 413 | | |
387 | 414 | | |
388 | 415 | | |
389 | | - | |
390 | | - | |
391 | | - | |
392 | | - | |
393 | | - | |
394 | | - | |
395 | | - | |
396 | | - | |
397 | | - | |
398 | | - | |
399 | | - | |
400 | | - | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
411 | | - | |
412 | 416 | | |
413 | 417 | | |
414 | 418 | | |
| |||
0 commit comments