@@ -3075,11 +3075,14 @@ class PartialEvaluator {
30753075 scaledDim = 0 ;
30763076 }
30773077
3078- let prevWidth = textChunk . width ;
3078+ // Keep a signed copy of the advance we will apply for rect construction
3079+ let appliedAdvance ;
3080+
30793081 let m = Util . transform ( textState . ctm , textState . textMatrix ) ;
30803082
30813083 if ( ! font . vertical ) {
30823084 scaledDim *= textState . textHScale ;
3085+ appliedAdvance = scaledDim ; // signed
30833086 intersector ?. addGlyph (
30843087 getCurrentTextTransform ( ) ,
30853088 scaledDim ,
@@ -3089,15 +3092,17 @@ class PartialEvaluator {
30893092 textState . translateTextMatrix ( scaledDim , 0 ) ;
30903093 textChunk . width += scaledDim ;
30913094 } else {
3095+ // Vertical: advance along Y, keep signed value for rect
3096+ appliedAdvance = scaledDim ; // signed
30923097 intersector ?. addGlyph (
30933098 getCurrentTextTransform ( ) ,
30943099 0 ,
30953100 scaledDim ,
30963101 glyph . unicode
30973102 ) ;
30983103 textState . translateTextMatrix ( 0 , scaledDim ) ;
3099- scaledDim = Math . abs ( scaledDim ) ;
3100- textChunk . height += scaledDim ;
3104+ // Accumulate height with absolute value for total chunk size
3105+ textChunk . height += Math . abs ( scaledDim ) ;
31013106 }
31023107
31033108 if ( scaledDim ) {
@@ -3175,8 +3180,18 @@ class PartialEvaluator {
31753180 ascent = font . capHeight ;
31763181 }
31773182
3178- let charWidth = textChunk . width - prevWidth ;
3179- let rect = [ 0 , textState . fontSize * descent , charWidth , textState . fontSize * ascent ]
3183+ // Build the untransformed rect using signed advance on the proper axis
3184+ let rect ;
3185+ if ( ! font . vertical ) {
3186+ // Horizontal: X-advance is appliedAdvance
3187+ rect = [ 0 , textState . fontSize * descent , appliedAdvance , textState . fontSize * ascent ] ;
3188+ } else {
3189+ // Vertical: Y-advance is appliedAdvance (signed).
3190+ // Use min/max so rect covers correct direction
3191+ let y0 = Math . min ( 0 , appliedAdvance ) ;
3192+ let y1 = Math . max ( 0 , appliedAdvance ) ;
3193+ rect = [ textState . fontSize * descent , y0 , textState . fontSize * ascent , y1 ] ;
3194+ }
31803195
31813196 if (
31823197 font . isType3Font &&
@@ -3185,8 +3200,13 @@ class PartialEvaluator {
31853200 ) {
31863201 const glyphHeight = font . bbox [ 3 ] - font . bbox [ 1 ] ;
31873202 if ( glyphHeight > 0 ) {
3188- rect [ 1 ] = font . bbox [ 1 ] * textState . fontMatrix [ 3 ] ;
3189- rect [ 3 ] = font . bbox [ 3 ] * textState . fontMatrix [ 3 ] ;
3203+ if ( ! font . vertical ) {
3204+ rect [ 1 ] = font . bbox [ 1 ] * textState . fontMatrix [ 3 ] ;
3205+ rect [ 3 ] = font . bbox [ 3 ] * textState . fontMatrix [ 3 ] ;
3206+ } else {
3207+ rect [ 0 ] = font . bbox [ 1 ] * textState . fontMatrix [ 3 ] ;
3208+ rect [ 2 ] = font . bbox [ 3 ] * textState . fontMatrix [ 3 ] ;
3209+ }
31903210 }
31913211 }
31923212
@@ -3216,6 +3236,10 @@ class PartialEvaluator {
32163236 let fontSize = Math . hypot ( x1 - x2 , y1 - y2 ) ;
32173237
32183238 let diagonal = rotation % 90 !== 0 ;
3239+ // This is a bit hacky but it fixes text selection for vertical text
3240+ if ( rotation === 0 && font . vertical ) {
3241+ rotation = 270 ;
3242+ }
32193243
32203244 function normalizeChar ( char ) {
32213245 // Normalize the character to NFKD form to decompose ligatures and combined characters
0 commit comments