@@ -82,8 +82,13 @@ class StructTreeLayerBuilder {
82
82
83
83
#elementAttributes = new Map ( ) ;
84
84
85
- constructor ( pdfPage ) {
85
+ #rawDims;
86
+
87
+ #elementsToAddToTextLayer = null ;
88
+
89
+ constructor ( pdfPage , rawDims ) {
86
90
this . #promise = pdfPage . getStructTree ( ) ;
91
+ this . #rawDims = rawDims ;
87
92
}
88
93
89
94
async render ( ) {
@@ -156,6 +161,50 @@ class StructTreeLayerBuilder {
156
161
}
157
162
}
158
163
164
+ #addImageInTextLayer( node , element ) {
165
+ const { alt, bbox, children } = node ;
166
+ const child = children ?. [ 0 ] ;
167
+ if ( ! this . #rawDims || ! alt || ! bbox || child ?. type !== "content" ) {
168
+ return false ;
169
+ }
170
+
171
+ const { id } = child ;
172
+ if ( ! id ) {
173
+ return false ;
174
+ }
175
+
176
+ // We cannot add the created element to the text layer immediately, as the
177
+ // text layer might not be ready yet. Instead, we store the element and add
178
+ // it later in `addElementsToTextLayer`.
179
+
180
+ element . setAttribute ( "aria-owns" , id ) ;
181
+ const img = document . createElement ( "span" ) ;
182
+ ( this . #elementsToAddToTextLayer ||= new Map ( ) ) . set ( id , img ) ;
183
+ img . setAttribute ( "role" , "img" ) ;
184
+ img . setAttribute ( "aria-label" , removeNullCharacters ( alt ) ) ;
185
+
186
+ const { pageHeight, pageX, pageY } = this . #rawDims;
187
+ const calc = "calc(var(--scale-factor)*" ;
188
+ const { style } = img ;
189
+ style . width = `${ calc } ${ bbox [ 2 ] - bbox [ 0 ] } px)` ;
190
+ style . height = `${ calc } ${ bbox [ 3 ] - bbox [ 1 ] } px)` ;
191
+ style . left = `${ calc } ${ bbox [ 0 ] - pageX } px)` ;
192
+ style . top = `${ calc } ${ pageHeight - bbox [ 3 ] + pageY } px)` ;
193
+
194
+ return true ;
195
+ }
196
+
197
+ addElementsToTextLayer ( ) {
198
+ if ( ! this . #elementsToAddToTextLayer) {
199
+ return ;
200
+ }
201
+ for ( const [ id , img ] of this . #elementsToAddToTextLayer) {
202
+ document . getElementById ( id ) ?. append ( img ) ;
203
+ }
204
+ this . #elementsToAddToTextLayer. clear ( ) ;
205
+ this . #elementsToAddToTextLayer = null ;
206
+ }
207
+
159
208
#walk( node ) {
160
209
if ( ! node ) {
161
210
return null ;
@@ -171,6 +220,9 @@ class StructTreeLayerBuilder {
171
220
} else if ( PDF_ROLE_TO_HTML_ROLE [ role ] ) {
172
221
element . setAttribute ( "role" , PDF_ROLE_TO_HTML_ROLE [ role ] ) ;
173
222
}
223
+ if ( role === "Figure" && this . #addImageInTextLayer( node , element ) ) {
224
+ return element ;
225
+ }
174
226
}
175
227
176
228
this . #setAttributes( node , element ) ;
0 commit comments