@@ -54,14 +54,80 @@ import {
5454 */
5555const renderTextLayer = ( function renderTextLayerClosure ( ) {
5656 const MAX_TEXT_DIVS_TO_RENDER = 100000 ;
57+ const DEFAULT_FONT_SIZE = 30 ;
58+ const DEFAULT_FONT_ASCENT = 0.8 ;
59+ const ascentCache = new Map ( ) ;
5760
5861 const NonWhitespaceRegexp = / \S / ;
5962
6063 function isAllWhitespace ( str ) {
6164 return ! NonWhitespaceRegexp . test ( str ) ;
6265 }
6366
64- function appendText ( task , geom , styles ) {
67+ function getAscent ( fontFamily , ctx ) {
68+ const cachedAscent = ascentCache . get ( fontFamily ) ;
69+ if ( cachedAscent ) {
70+ return cachedAscent ;
71+ }
72+
73+ ctx . save ( ) ;
74+ ctx . font = `${ DEFAULT_FONT_SIZE } px ${ fontFamily } ` ;
75+ const metrics = ctx . measureText ( "" ) ;
76+
77+ // Both properties aren't available by default in Firefox.
78+ let ascent = metrics . fontBoundingBoxAscent ;
79+ let descent = Math . abs ( metrics . fontBoundingBoxDescent ) ;
80+ if ( ascent ) {
81+ ctx . restore ( ) ;
82+ const ratio = ascent / ( ascent + descent ) ;
83+ ascentCache . set ( fontFamily , ratio ) ;
84+ return ratio ;
85+ }
86+
87+ // Try basic heuristic to guess ascent/descent.
88+ // Draw a g with baseline at 0,0 and then get the line
89+ // number where a pixel has non-null red component (starting
90+ // from bottom).
91+ ctx . strokeStyle = "red" ;
92+ ctx . clearRect ( 0 , 0 , DEFAULT_FONT_SIZE , DEFAULT_FONT_SIZE ) ;
93+ ctx . strokeText ( "g" , 0 , 0 ) ;
94+ let pixels = ctx . getImageData ( 0 , 0 , DEFAULT_FONT_SIZE , DEFAULT_FONT_SIZE )
95+ . data ;
96+ descent = 0 ;
97+ for ( let i = pixels . length - 1 - 3 ; i >= 0 ; i -= 4 ) {
98+ if ( pixels [ i ] > 0 ) {
99+ descent = Math . ceil ( i / 4 / DEFAULT_FONT_SIZE ) ;
100+ break ;
101+ }
102+ }
103+
104+ // Draw an A with baseline at 0,DEFAULT_FONT_SIZE and then get the line
105+ // number where a pixel has non-null red component (starting
106+ // from top).
107+ ctx . clearRect ( 0 , 0 , DEFAULT_FONT_SIZE , DEFAULT_FONT_SIZE ) ;
108+ ctx . strokeText ( "A" , 0 , DEFAULT_FONT_SIZE ) ;
109+ pixels = ctx . getImageData ( 0 , 0 , DEFAULT_FONT_SIZE , DEFAULT_FONT_SIZE ) . data ;
110+ ascent = 0 ;
111+ for ( let i = 0 , ii = pixels . length ; i < ii ; i += 4 ) {
112+ if ( pixels [ i ] > 0 ) {
113+ ascent = DEFAULT_FONT_SIZE - Math . floor ( i / 4 / DEFAULT_FONT_SIZE ) ;
114+ break ;
115+ }
116+ }
117+
118+ ctx . restore ( ) ;
119+
120+ if ( ascent ) {
121+ const ratio = ascent / ( ascent + descent ) ;
122+ ascentCache . set ( fontFamily , ratio ) ;
123+ return ratio ;
124+ }
125+
126+ ascentCache . set ( fontFamily , DEFAULT_FONT_ASCENT ) ;
127+ return DEFAULT_FONT_ASCENT ;
128+ }
129+
130+ function appendText ( task , geom , styles , ctx ) {
65131 // Initialize all used properties to keep the caches monomorphic.
66132 const textDiv = document . createElement ( "span" ) ;
67133 const textDivProperties = {
@@ -90,12 +156,7 @@ const renderTextLayer = (function renderTextLayerClosure() {
90156 angle += Math . PI / 2 ;
91157 }
92158 const fontHeight = Math . hypot ( tx [ 2 ] , tx [ 3 ] ) ;
93- let fontAscent = fontHeight ;
94- if ( style . ascent ) {
95- fontAscent = style . ascent * fontAscent ;
96- } else if ( style . descent ) {
97- fontAscent = ( 1 + style . descent ) * fontAscent ;
98- }
159+ const fontAscent = fontHeight * getAscent ( style . fontFamily , ctx ) ;
99160
100161 let left , top ;
101162 if ( angle === 0 ) {
@@ -578,7 +639,7 @@ const renderTextLayer = (function renderTextLayerClosure() {
578639 _processItems ( items , styleCache ) {
579640 for ( let i = 0 , len = items . length ; i < len ; i ++ ) {
580641 this . _textContentItemsStr . push ( items [ i ] . str ) ;
581- appendText ( this , items [ i ] , styleCache ) ;
642+ appendText ( this , items [ i ] , styleCache , this . _layoutTextCtx ) ;
582643 }
583644 } ,
584645
@@ -628,6 +689,8 @@ const renderTextLayer = (function renderTextLayerClosure() {
628689
629690 // The temporary canvas is used to measure text length in the DOM.
630691 const canvas = this . _document . createElement ( "canvas" ) ;
692+ canvas . height = canvas . width = DEFAULT_FONT_SIZE ;
693+
631694 if (
632695 typeof PDFJSDev === "undefined" ||
633696 PDFJSDev . test ( "MOZCENTRAL || GENERIC" )
0 commit comments