Skip to content

Commit

Permalink
Issue #4148: Switch PDF editor to compact model v2
Browse files Browse the repository at this point in the history
- Switch over to the new format
  • Loading branch information
reckart committed Aug 11, 2023
1 parent 6f7d7d6 commit 11789f9
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default abstract class AbstractAnnotation extends EventEmitter {
this.setHoverEvent()
}

this.disabled && this.disable()
if (!this.disabled) this.disable()
}

/**
Expand Down
136 changes: 71 additions & 65 deletions inception/inception-pdf-editor2/src/main/ts/src/pdfanno/pdfanno.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ import AnnotationContainer from './core/src/annotation/container'
import AbstractAnnotation from './core/src/annotation/abstract'
import { installSpanSelection } from './core/src/UI/span'
import { installRelationSelection } from './core/src/UI/relation'
import { CompactAnnotatedText, CompactSpan, DiamAjax, Offsets, VID } from '@inception-project/inception-js-api'
import { unpackCompactAnnotatedTextV2, DiamAjax, Offsets, VID, AnnotatedText, Span, Relation, TextMarker } from '@inception-project/inception-js-api'
import { CompactAnnotatedText } from '@inception-project/inception-js-api/src/model/compact_v2'
import { DiamLoadAnnotationsOptions } from '@inception-project/inception-js-api/src/diam/DiamAjax'
import SpanAnnotation from './core/src/annotation/span'
import { getGlyphAtTextOffset, getGlyphsInRange } from './page/textLayer'
import RelationAnnotation from './core/src/annotation/relation'
import { createRect, mapToDocumentCoordinates, mergeRects } from './core/src/render/renderSpan'
import { transform } from './core/src/render/appendChild'
import { makeMarkerMap } from '@inception-project/inception-js-api/src/model/compact/CompactAnnotatedText'
import { CompactTextMarker } from '@inception-project/inception-js-api/src/model/compact/CompactTextMarker'
import { CompactRelation } from '@inception-project/inception-js-api/src/model/compact/CompactRelation'
import { CompactAnnotationMarker } from '@inception-project/inception-js-api/src/model/compact/CompactAnnotationMarker'
import { Rectangle } from '../vmodel/Rectangle'

// TODO make it a global const.
Expand All @@ -31,6 +28,8 @@ let diamAjax: DiamAjax
let currentFocusPage: number
let pagechangeEventCounter: number

let data: AnnotatedText | undefined

export async function initPdfAnno (ajax: DiamAjax): Promise<void> {
globalThis.globalEvent = new EventEmitter()
globalThis.globalEvent.setMaxListeners(0)
Expand Down Expand Up @@ -198,13 +197,13 @@ function renderAnno () {

dispatchWindowEvent('annotationlayercreated')

renderAnnotations()
rerenderAnnotations()
}

/**
* Render all annotations.
*/
function renderAnnotations () {
function rerenderAnnotations () {
const annotations = annotationContainer.getAllAnnotations()
if (annotations.length === 0) {
return
Expand Down Expand Up @@ -274,42 +273,44 @@ export function getAnnotations () {

const options : DiamLoadAnnotationsOptions = {
range: [extendedBegin, extendedEnd],
includeText: false
includeText: false,
format: 'compact_v2'
}

diamAjax.loadAnnotations(options).then((doc: CompactAnnotatedText) => {
annotationContainer.clear()
data = unpackCompactAnnotatedTextV2(doc)
renderAnnotations(data)
})
}

const annotationMarkers = makeMarkerMap(doc.annotationMarkers)
function renderAnnotations (doc: AnnotatedText): void {
const startTime = new Date().getTime()

console.log(`Loaded ${doc.spans?.length || '0'} spans and ${doc.relations?.length || '0'} relations in range [${doc.window}]`)
annotationContainer.clear()

if (doc.spans) {
for (const s of doc.spans) {
makeSpan(s, doc, annotationMarkers)
}
}
if (doc.spans) {
console.log(`Loaded ${doc.spans.size} span annotations`)
doc.spans.forEach(span => renderSpan(doc, span))
}

if (doc.relations) {
for (const r of doc.relations) {
makeRelation(r, annotationMarkers)
}
}
if (doc.relations) {
console.log(`Loaded ${doc.relations.size} relations annotations`)
doc.relations.forEach(relation => renderRelation(doc, relation))
}

if (doc.textMarkers) {
for (const m of doc.textMarkers) {
makeTextMarker(m, doc)
}
}
if (doc.textMarkers) {
doc.textMarkers.forEach(marker => makeTextMarker(doc, marker))
}

renderAnnotations()
})
rerenderAnnotations()

const endTime = new Date().getTime()
console.log(`Client-side rendering took ${Math.abs(endTime - startTime)}ms`)
}

function makeSpan (s: CompactSpan, doc: CompactAnnotatedText, annotationMarkers: Map<VID, Array<CompactAnnotationMarker>>) {
const offsets = s[1]
const begin = offsets[0][0] + doc.window[0]
const end = offsets[0][1] + doc.window[0]
function renderSpan (doc: AnnotatedText, span: Span) {
const begin = span.offsets[0][0] + doc.window[0]
const end = span.offsets[0][1] + doc.window[0]
const range: Offsets = [begin, end]

const page = textLayer.findPageForTextOffset(begin)?.index
Expand All @@ -323,40 +324,45 @@ function makeSpan (s: CompactSpan, doc: CompactAnnotatedText, annotationMarkers:
return
}

const span = new SpanAnnotation()
span.vid = `${s[0]}`
span.textRange = range
span.page = page
span.color = s[2]?.c || '#FFF'
span.text = s[2]?.l || ''
span.rectangles = rectangles
annotationMarkers.get(s[0])?.forEach(m => span.classList.push(`marker-${m[0]}`))
span.save()
const spanAnnotation = new SpanAnnotation()
spanAnnotation.vid = span.vid
spanAnnotation.textRange = range
spanAnnotation.page = page
spanAnnotation.color = span.color || '#FFF'
spanAnnotation.text = span.label || ''
spanAnnotation.rectangles = rectangles

const ms = doc.annotationMarkers.get(spanAnnotation.vid) || []
ms.forEach(m => spanAnnotation.classList.push(`marker-${m.type}`))

spanAnnotation.save()
}

function makeRelation (r: CompactRelation, annotationMarkers: Map<VID, Array<CompactAnnotationMarker>>) {
const source = annotationContainer.findById(r[1][0][0])
const target = annotationContainer.findById(r[1][1][0])
function renderRelation (doc: AnnotatedText, relation: Relation) {
const source = annotationContainer.findById(relation.arguments[0].targetId)
const target = annotationContainer.findById(relation.arguments[1].targetId)

if (!source || !target) {
console.warn(`Cannot find source or target for relation ${r[0]}`)
console.warn(`Cannot find source or target for relation ${relation[0]}`)
return
}

const rel = new RelationAnnotation()
rel.vid = `${r[0]}`
rel.rel1Annotation = source as SpanAnnotation
rel.rel2Annotation = target as SpanAnnotation
rel.color = r[2]?.c
rel.text = r[2]?.l || null
annotationMarkers.get(r[0])?.forEach(m => rel.classList.push(`marker-${m[0]}`))
rel.save()
const relationAnnotation = new RelationAnnotation()
relationAnnotation.vid = relation.vid
relationAnnotation.rel1Annotation = source as SpanAnnotation
relationAnnotation.rel2Annotation = target as SpanAnnotation
relationAnnotation.color = relation.color || '#FFF'
relationAnnotation.text = relation.label || ''

const ms = doc.annotationMarkers.get(relationAnnotation.vid) || []
ms.forEach(m => relationAnnotation.classList.push(`marker-${m.type}`))

relationAnnotation.save()
}

function makeTextMarker (m: CompactTextMarker, doc: CompactAnnotatedText) {
const offsets = m[1]
const begin = offsets[0][0] + doc.window[0]
const end = offsets[0][1] + doc.window[0]
function makeTextMarker (doc: AnnotatedText, marker: TextMarker) {
const begin = marker.offsets[0][0] + doc.window[0]
const end = marker.offsets[0][1] + doc.window[0]
const range: Offsets = [begin, end]

const page = textLayer.findPageForTextOffset(begin)?.index
Expand All @@ -370,14 +376,14 @@ function makeTextMarker (m: CompactTextMarker, doc: CompactAnnotatedText) {
return
}

const marker = new SpanAnnotation()
marker.textRange = range
marker.page = page
marker.knob = false
marker.border = false
marker.rectangles = rectangles
marker.classList = [`marker-${m[0]}`]
marker.save()
const markerAnnotation = new SpanAnnotation()
markerAnnotation.textRange = range
markerAnnotation.page = page
markerAnnotation.knob = false
markerAnnotation.border = false
markerAnnotation.rectangles = rectangles
markerAnnotation.classList = [`marker-$${marker.type}`]
markerAnnotation.save()
}

function calculateRectangles (range: [number, number]): Rectangle[] | null {
Expand Down

0 comments on commit 11789f9

Please sign in to comment.