Skip to content

Commit f636e64

Browse files
committed
feat: add polyline annotation
1 parent 871f0a7 commit f636e64

File tree

12 files changed

+13897
-36
lines changed

12 files changed

+13897
-36
lines changed

examples/pdfjs-4.3.136-dist/web/pdfjs-annotation-extension/pdfjs-annotation-extension.js

Lines changed: 12950 additions & 2 deletions
Large diffs are not rendered by default.

src/annot/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { formatPDFDate, getPDFDateTimestamp, getTimestampString } from '../utils
1515
import { FreeTextParser } from './parse_freetext'
1616
import { StampParser } from './parse_stamp'
1717
import { LineParser } from './parse_line'
18-
import { PolylineParser } from './parse_polyline'
18+
import { ActualPolylineParser } from './parse_actual_polyline'
1919
import { t } from 'i18next'
2020

2121
// import { HighlightParser } from './parse_highlight' // future
@@ -32,7 +32,7 @@ const parserMap: {
3232
[PdfjsAnnotationType.SQUARE]: SquareParser,
3333
[PdfjsAnnotationType.CIRCLE]: CircleParser,
3434
[PdfjsAnnotationType.INK]: InkParser,
35-
[PdfjsAnnotationType.POLYLINE]: PolylineParser,
35+
[PdfjsAnnotationType.POLYLINE]: ActualPolylineParser,
3636
[PdfjsAnnotationType.FREETEXT]: FreeTextParser,
3737
[PdfjsAnnotationType.STAMP]: StampParser,
3838
[PdfjsAnnotationType.LINE]: LineParser
@@ -48,6 +48,7 @@ const parserMap: {
4848
*/
4949
async function parseAnnotationToPdf(annotation: IAnnotationStore, page: PDFPage, pdfDoc: PDFDocument): Promise<void> {
5050
const ParserClass = parserMap[annotation.pdfjsType]
51+
// Use ActualPolylineParser for all polyline annotations since decoder_polyline now handles both vertices and ink types
5152
if (ParserClass) {
5253
const parser = new ParserClass(pdfDoc, page, annotation)
5354
await parser.parse()
@@ -92,7 +93,7 @@ function clearAllAnnotations(pdfDoc: PDFDocument) {
9293
}
9394

9495
// 动态加载字体文件,返回 ArrayBuffer
95-
async function loadFontBuffer(url: string): Promise<ArrayBuffer> {
96+
export async function loadFontBuffer(url: string): Promise<ArrayBuffer> {
9697
const response = await fetch(url)
9798
if (!response.ok) throw new Error(`Failed to load font at ${url}`)
9899
return await response.arrayBuffer()

src/annot/parse_actual_polyline.ts

Lines changed: 362 additions & 0 deletions
Large diffs are not rendered by default.

src/components/comment/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import {
1919
NoteIcon,
2020
ExportIcon,
2121
ArrowIcon,
22-
CloudIcon
22+
CloudIcon,
23+
PolylineIcon
2324
} from '../../const/icon'
2425
import Paragraph from 'antd/es/typography/Paragraph'
2526

src/const/definitions.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {
1212
UnderlineIcon,
1313
NoteIcon,
1414
ArrowIcon,
15-
CloudIcon
15+
CloudIcon,
16+
PolylineIcon
1617
} from './icon'
1718
import { IRect } from 'konva/lib/types'
1819
import { defaultOptions } from './default_options'
@@ -99,7 +100,8 @@ export enum AnnotationType {
99100
STAMP = 10, // 盖章批注
100101
NOTE = 11, // 注释
101102
ARROW = 12, // 箭头批注
102-
CLOUD = 13 // 云线
103+
CLOUD = 13, // 云线
104+
POLYLINE = 14 // 折线批注
103105
}
104106

105107
// 定义批注类型的接口
@@ -153,6 +155,8 @@ export enum CommentStatus {
153155
export interface IAnnotationContentsObj {
154156
text: string; // 文本内容
155157
image?: string; // 可选的图片属性
158+
points?: number[]; // 可选的点数组,用于描述形状或路径
159+
pathData?: string; // 可选的SVG路径数据,用于云线等复杂形状
156160
}
157161

158162
// 批注存储接口
@@ -299,6 +303,28 @@ export const annotationDefinitions: IAnnotationType[] = [
299303
draggable: true,
300304
icon: <NoteIcon />
301305
},
306+
{
307+
name: 'polyLine',
308+
type: AnnotationType.POLYLINE,
309+
pdfjsEditorType: PdfjsAnnotationEditorType.INK,
310+
pdfjsAnnotationType: PdfjsAnnotationType.POLYLINE,
311+
subtype: 'PolyLine',
312+
isOnce: false,
313+
resizable: true,
314+
draggable: true,
315+
icon: <PolylineIcon />,
316+
style: {
317+
color: defaultOptions.setting.COLOR, // Default polyline color
318+
strokeWidth: defaultOptions.setting.STROKE_WIDTH, // Default line width
319+
opacity: defaultOptions.setting.OPACITY // Default opacity
320+
},
321+
styleEditable: {
322+
color: true,
323+
opacity: true,
324+
strokeWidth: true
325+
} // Add this to enable style editing
326+
},
327+
302328
{
303329
name: 'arrow',
304330
type: AnnotationType.ARROW,

src/const/icon.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,16 @@ const NoteSvg = () => (
136136
</svg>
137137
)
138138

139+
const PolylineSvg = () => (
140+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="22" stroke="white" fill="none" strokeWidth="2">
141+
<polyline points="4,18 8,10 13,14 20,6" stroke="white" fill="none" />
142+
<circle cx="4" cy="18" r="1.5" fill="white" />
143+
<circle cx="8" cy="10" r="1.5" fill="white" />
144+
<circle cx="13" cy="14" r="1.5" fill="white" />
145+
<circle cx="20" cy="6" r="1.5" fill="white" />
146+
</svg>
147+
);
148+
139149
const AnnoSvg = () => (
140150
<svg height="1em" viewBox="0 0 1024 1024">
141151
<path d="M658.02666667 432.85333333H347.30666667c-18.77333333 0-34.13333333 15.36-34.13333334 34.13333334s15.36 34.13333333 34.13333334 34.13333333h310.72c18.77333333 0 34.13333333-15.36 34.13333333-34.13333333s-15.36-34.13333333-34.13333333-34.13333334zM571.30666667 557.22666667h-224c-18.77333333 0-34.13333333 15.36-34.13333334 34.13333333s15.36 34.13333333 34.13333334 34.13333333h224c18.77333333 0 34.13333333-15.36 34.13333333-34.13333333s-15.36-34.13333333-34.13333333-34.13333333zM894.29333333 61.12l-621.76-0.10666667c-18.88 0-34.13333333 15.25333333-34.13333333 34.13333334s15.25333333 34.13333333 34.13333333 34.13333333l621.76 0.10666667c15.25333333 0 27.73333333 12.48 27.73333334 27.73333333v431.36c0 18.88 15.25333333 34.13333333 34.13333333 34.13333333s34.13333333-15.25333333 34.13333333-34.13333333V157.12c0-52.8-43.2-96-96-96z" fill="currentColor"></path><path d="M734.4 229.54666667H157.54666667c-67.52 0-122.66666667 55.25333333-122.66666667 122.66666666v368.74666667c0 66.77333333 54.08 121.49333333 120.53333333 122.66666667l0.42666667 66.98666666c8.64 38.4 50.98666667 84.37333333 121.81333333 36.05333334L389.54666667 843.73333333h344.64c67.52 0 122.66666667-55.25333333 122.66666666-122.66666666V352.21333333c0.21333333-67.52-55.04-122.66666667-122.45333333-122.66666666z m54.4 491.30666666c0 14.4-5.65333333 28.05333333-16 38.4s-24 16-38.4 16h-340.26666667v0.10666667H373.33333333l-72.85333333 68.05333333-60.37333333 56.32c-26.88 17.6-24.96-26.66666667-24.96-26.66666666l-0.10666667-29.76v-68.05333334h-58.45333333v-0.21333333c-14.08-0.21333333-27.30666667-5.86666667-37.44-16-10.34666667-10.34666667-16-24-16-38.4V352.21333333c0-14.4 5.65333333-28.05333333 16-38.4s24-16 38.4-16h576.85333333c14.4 0 28.05333333 5.65333333 38.4 16s16 24 16 38.4v368.64z" fill="currentColor"></path><path d="M249.06666667 432.42666667c-18.77333333 0-34.13333333 15.36-34.13333334 34.13333333s15.36 34.13333333 34.13333334 34.13333333 34.13333333-15.36 34.13333333-34.13333333-15.36-34.13333333-34.13333333-34.13333333zM249.06666667 557.22666667c-18.77333333 0-34.13333333 15.36-34.13333334 34.13333333s15.36 34.13333333 34.13333334 34.13333333 34.13333333-15.36 34.13333333-34.13333333-15.36-34.13333333-34.13333333-34.13333333z" fill="currentColor"></path>
@@ -187,6 +197,8 @@ const ExportIcon = (props: Partial<CustomIconComponentProps>) => <Icon component
187197

188198
const NoteIcon = (props: Partial<CustomIconComponentProps>) => <Icon component={NoteSvg} {...props} />
189199

200+
const PolylineIcon = (props: Partial<CustomIconComponentProps>) => <Icon component={PolylineSvg} {...props} />
201+
190202
const AnnoIcon = (props: Partial<CustomIconComponentProps>) => <Icon component={AnnoSvg} {...props} />
191203

192204
const ArrowIcon = (props: Partial<CustomIconComponentProps>) => <Icon component={ArrowSvg} {...props} />
@@ -215,5 +227,6 @@ export {
215227
AnnoIcon,
216228
ArrowIcon,
217229
CloudIcon,
218-
DeleteIcon
230+
DeleteIcon,
231+
PolylineIcon
219232
}

src/locale/de-de.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
"freeHighlight": "Hervorheben",
1212
"freeText": "Text",
1313
"signature": "Unterschrift",
14-
"stamp": "Stempel",
14+
"stamp": "Stempe",
1515
"note": "Notiz",
1616
"arrow": "Pfeil",
17-
"cloud": "Wolke"
17+
"cloud": "Wolke",
18+
"polyLine": "Polylinie"
1819
},
1920
"toolbar": {
2021
"buttons": {

src/locale/en-us.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"stamp": "Stamp",
1515
"note": "Note",
1616
"arrow": "Arrow",
17-
"cloud": "Cloud"
17+
"cloud": "Cloud",
18+
"polyLine": "Polyline"
1819
},
1920
"toolbar": {
2021
"buttons": {

src/locale/zh-cn.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"stamp": "盖章",
1515
"note": "注解",
1616
"arrow": "箭头",
17-
"cloud": "云线"
17+
"cloud": "云线",
18+
"polyLine": "折线"
1819
},
1920
"toolbar": {
2021
"buttons": {

0 commit comments

Comments
 (0)