Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/purple-clowns-wash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/react-pdf": patch
---

[react-pdf] text layer와 canvas 위치 불일치 수정

PR: [[react-pdf] text layer와 canvas 위치 불일치 수정](https://github.com/NaverPayDev/pie/pull/221)
6 changes: 5 additions & 1 deletion packages/react-pdf/src/components/layer/Text.module.scss
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
.text-layer {
pointer-events: none;
line-height: 1;
-webkit-text-size-adjust: none;
-moz-text-size-adjust: none;
text-size-adjust: none;
}

.text-layer-item {
height: 1em;
font-family: sans-serif;
position: absolute;
transform-origin: left bottom;
transform-origin: 0% 0%;
white-space: pre;
pointer-events: all;
}
37 changes: 24 additions & 13 deletions packages/react-pdf/src/utils/text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,27 @@ import type {TextItem, TextMarkedContent} from 'pdfjs-dist/types/src/display/api
function tokenizeTextItems(texts: TextItem[]) {
return texts.reduce((result, textItem) => {
const {str, width, transform, ...rest} = textItem
const splittedStr = str.split(' ')
const strLength = str.length
const tokenizedStr = splittedStr.reduce((calculatedStr, s) => {
const currentStrWidth = s.trim().length === 0 ? 4.5 : Math.ceil((width / strLength) * s.length) + 5
const reducedStrsLength = calculatedStr.length
const {width: lastWidth, transform: lastTransform} =
reducedStrsLength === 0 ? {width: 0, transform: [...transform]} : calculatedStr[reducedStrsLength - 1]
const newTransform = [...lastTransform]
newTransform[4] += lastWidth + (reducedStrsLength === 0 ? 0 : 3.5)
calculatedStr.push({str: s, width: currentStrWidth, transform: newTransform, ...rest})
return calculatedStr
const words = str.split(' ')
const totalChars = str.length

if (totalChars === 0) {
return result
}

const charWidth = width / totalChars
let charOffset = 0

const tokenized = words.reduce((acc, word, wordIndex) => {
if (word.length > 0) {
const newTransform = [...transform]
newTransform[4] += charWidth * charOffset
acc.push({str: word, width: charWidth * word.length, transform: newTransform, ...rest})
}
charOffset += word.length + (wordIndex < words.length - 1 ? 1 : 0)
return acc
}, [] as TextItem[])
return [...result, ...tokenizedStr]

return [...result, ...tokenized]
}, [] as TextItem[])
}

Expand All @@ -31,8 +39,11 @@ export function mergeTextItems(texts: (TextItem | TextMarkedContent)[], options?
const prev = result[result.length - 1]
// y 값을 비교하여, 같은 줄인지 확인
if (prev.transform[5] === token.transform[5]) {
// item 간 gap을 포함한 전체 visual span 계산
const prevEndX = prev.transform[4] + prev.width
const gap = token.transform[4] - prevEndX
prev.str = prev.str + token.str
prev.width = prev.width + token.width
prev.width = prev.width + Math.max(0, gap) + token.width
} else {
result.push(token)
}
Expand Down
Loading