Преглед изворни кода

Clamp PDF highlights to the extents of the page container (#25498)

GitOrigin-RevId: cc2e30b04b9c57b2ea6038bee1e06467b785386f
Alf Eaton пре 1 година
родитељ
комит
c942b490ab
1 измењених фајлова са 42 додато и 15 уклоњено
  1. 42 15
      services/web/frontend/js/features/pdf-preview/util/highlights.js

+ 42 - 15
services/web/frontend/js/features/pdf-preview/util/highlights.js

@@ -1,28 +1,55 @@
 import { PDFJS } from '@/features/pdf-preview/util/pdf-js'
 
 export function buildHighlightElement(highlight, viewer) {
-  const pageView = viewer.getPageView(highlight.page - 1)
+  const { viewport, div } = viewer.getPageView(highlight.page - 1)
+
+  // page coordinates from synctex
+  const rectangle = {
+    left: highlight.h,
+    right: highlight.h + highlight.width,
+    top: highlight.v,
+    bottom: highlight.v + highlight.height,
+  }
+
+  // needed because PDF page origin is at the bottom left
+  const viewBoxHeight = viewport.viewBox[3] + 10
+
+  // account for scaling
+  const viewportRectangle = viewport.convertToViewportRectangle([
+    rectangle.left,
+    viewBoxHeight - rectangle.bottom,
+    rectangle.right,
+    viewBoxHeight - rectangle.top,
+  ])
 
-  const viewport = pageView.viewport
+  // flip top/bottom, left/right if needed
+  const normalizedRectangle = PDFJS.Util.normalizeRect(viewportRectangle)
 
-  const height = viewport.viewBox[3]
+  const [left, top, right, bottom] = normalizedRectangle
 
-  const rect = viewport.convertToViewportRectangle([
-    highlight.h, // xMin
-    height - (highlight.v + highlight.height) + 10, // yMin
-    highlight.h + highlight.width, // xMax
-    height - highlight.v + 10, // yMax
-  ])
+  // restrict to within the page container
+  const clampedRectangle = {
+    left: Math.max(left, 0),
+    right: Math.min(right, div.clientWidth),
+    top: Math.max(top, 0),
+    bottom: Math.min(bottom, div.clientHeight),
+  }
 
-  const [left, top, right, bottom] = PDFJS.Util.normalizeRect(rect)
+  // convert to screen positions
+  const positions = {
+    left: div.offsetLeft + clampedRectangle.left,
+    right: div.offsetLeft + clampedRectangle.right,
+    top: div.offsetTop + clampedRectangle.top,
+    bottom: div.offsetTop + clampedRectangle.bottom,
+  }
 
   const element = document.createElement('div')
-  element.style.left = Math.floor(pageView.div.offsetLeft + left) + 'px'
-  element.style.top = Math.floor(pageView.div.offsetTop + top) + 'px'
-  element.style.width = Math.ceil(right - left) + 'px'
-  element.style.height = Math.ceil(bottom - top) + 'px'
-  element.style.backgroundColor = 'rgba(255,255,0)'
   element.style.position = 'absolute'
+  element.style.left = Math.floor(positions.left) + 'px'
+  element.style.top = Math.floor(positions.top) + 'px'
+  element.style.width = Math.floor(positions.right - positions.left) + 'px'
+  element.style.height = Math.floor(positions.bottom - positions.top) + 'px'
+  element.style.backgroundColor = 'rgb(255,255,0)'
   element.style.display = 'inline-block'
   element.style.scrollMargin = '72px'
   element.style.pointerEvents = 'none'