@@ -445,16 +445,15 @@ export class ChtmlFontData extends FontData<
445445 const m = this . em ( Hm / 2 - 0.03 ) ;
446446 styles [ `mjx-stretchy-v${ c } > mjx-ext:first-of-type` ] = {
447447 height : '50%' ,
448- 'border-width' : `${ this . em0 ( Hb - 0.03 ) } 0 ${ m } ` ,
448+ 'border-width' : `${ this . em1 ( Hb - 0.03 ) } 0 ${ m } ` ,
449449 } ;
450450 styles [ `mjx-stretchy-v${ c } > mjx-ext:last-of-type` ] = {
451451 height : '50%' ,
452- 'border-width' : `${ m } 0 ${ this . em0 ( He - 0.03 ) } ` ,
452+ 'border-width' : `${ m } 0 ${ this . em1 ( He - 0.03 ) } ` ,
453453 } ;
454454 } else if ( He || Hb ) {
455- styles [ 'mjx-stretchy-v' + c + ' > mjx-ext' ] = {
456- 'border-width' : `${ this . em0 ( Hb - 0.03 ) } 0 ${ this . em0 ( He - 0.03 ) } ` ,
457- } ;
455+ styles [ `mjx-stretchy-v${ c } > mjx-ext` ] [ 'border-width' ] =
456+ `${ this . em1 ( Hb - 0.03 ) } 0 ${ this . em1 ( He - 0.03 ) } ` ;
458457 }
459458 }
460459
@@ -483,28 +482,25 @@ export class ChtmlFontData extends FontData<
483482 // If the non-extender is wider than the assembly,
484483 // use negative margins to center over the assembly
485484 //
486- if ( w > HDW [ 2 ] ) {
487- css . margin = `0 ${ this . em ( ( HDW [ 2 ] - w ) / 2 ) } ` ;
488- }
485+ const dw = w > HDW [ 2 ] ? this . em ( ( HDW [ 2 ] - w ) / 2 ) : 'auto' ;
489486 //
490487 // Non-extenders are 0 height, so place properly
491488 //
492489 const y = part === 'beg' ? h : part === 'end' ? - d : ( h - d ) / 2 ;
493- if ( y > 0 ) {
494- css [ 'padding-top' ] = this . em ( y ) ;
495- } else if ( y < 0 ) {
496- css . transform = `translateY(${ this . em ( y ) } )` ;
497- }
490+ css . margin = `${ this . em ( y ) } ${ dw } ${ this . em ( - y ) } ` ;
498491 } else {
499492 //
500- // Put one fifth above the top of the extender (to avoid ragged ends)
501- // and then scale with origin at the top of the extender (so most extends down)
493+ // Set the line-height to have the extenders touch,
494+ // (plus a little extra for Safari, whose line-height is
495+ // not accurate), and shift the extender stack to overlap
496+ // the ends.
502497 //
503- const y = h - ( h + d ) / 5 ;
504- css . transform = `translateY(${ this . em ( y ) } ) scaleY(500)` ;
505- css [ 'transform-origin' ] = `center ${ this . em ( 0.03 - y ) } ` ;
498+ css [ 'line-height' ] = this . em0 ( h + d + .005 ) ;
499+ styles [ `mjx-stretchy-v${ c } > mjx-${ part } > mjx-spacer` ] = {
500+ 'margin-top' : this . em ( - d ) ,
501+ } ;
506502 }
507- styles [ `mjx-stretchy-v${ c } mjx-${ part } mjx-c ` ] = css ;
503+ styles [ `mjx-stretchy-v${ c } > mjx-${ part } ` ] = css ;
508504 return h + d ;
509505 }
510506
@@ -551,9 +547,12 @@ export class ChtmlFontData extends FontData<
551547 'border-width' : `0 ${ this . em0 ( We - 0.03 ) } 0 ${ m } ` ,
552548 } ;
553549 } else if ( Wb || We ) {
554- styles [ `mjx-stretchy-h${ c } > mjx-ext` ] = {
555- 'border-width' : `0 ${ this . em0 ( We - 0.03 ) } 0 ${ this . em0 ( Wb - 0.03 ) } ` ,
556- } ;
550+ styles [ `mjx-stretchy-h${ c } > mjx-ext` ] [ 'border-width' ] =
551+ `0 ${ this . em0 ( We - 0.06 ) } 0 ${ this . em0 ( Wb - 0.06 ) } ` ;
552+ }
553+ if ( data . ext ) {
554+ styles [ `mjx-stretchy-h${ c } > mjx-ext > mjx-spacer` ] [ 'letter-spacing' ] =
555+ this . em ( - data . ext ) ;
557556 }
558557 }
559558
@@ -575,17 +574,32 @@ export class ChtmlFontData extends FontData<
575574 HDW : ChtmlCharData
576575 ) : number {
577576 if ( ! n ) return 0 ;
578- const [ , , w , options ] = this . getChar ( v , n ) ;
577+ let [ , , w , options ] = this . getChar ( v , n ) ;
579578 const css : StyleData = {
580579 padding : this . padding ( HDW as ChtmlCharData , w - HDW [ 2 ] ) ,
581580 } ;
582- if ( part === 'end' ) {
583- css [ 'margin-left' ] = this . em ( - w ) ;
584- } else if ( part === 'mid' ) {
585- css [ 'margin-left' ] = this . em ( - w / 2 ) ;
581+ if ( part === 'ext' ) {
582+ if ( ! w && options . dx ) {
583+ w = 2 * options . dx - 0.06 ;
584+ }
585+ styles [ `mjx-stretchy-h${ c } > mjx-${ part } > mjx-spacer` ] = {
586+ 'margin-left' : this . em ( - w / 2 ) ,
587+ } ;
588+ if ( options . cmb ) {
589+ styles [ `mjx-stretchy-h${ c } > mjx-${ part } > mjx-c` ] = {
590+ width : this . em ( w ) ,
591+ 'text-align' : 'right' ,
592+ } ;
593+ }
594+ } else {
595+ if ( part === 'mid' ) {
596+ css [ 'margin' ] = `0 ${ this . em ( - w / 2 ) } ` ;
597+ } else {
598+ css [ part == 'end' ? 'margin-left' : 'margin-right' ] = this . em ( - w ) ;
599+ }
600+ this . checkCombiningChar ( options , css ) ;
586601 }
587- this . checkCombiningChar ( options , css ) ;
588- styles [ `mjx-stretchy-h${ c } mjx-${ part } mjx-c` ] = css ;
602+ styles [ `mjx-stretchy-h${ c } > mjx-${ part } ` ] = css ;
589603 return w ;
590604 }
591605
@@ -653,6 +667,15 @@ export class ChtmlFontData extends FontData<
653667 return em ( Math . max ( 0 , n ) ) ;
654668 }
655669
670+ /**
671+ * @param {number } n The number of ems (will be restricted to non-negative values, with .1px rather than 0em)
672+ * @returns {string } The string representing the number with units of "em"
673+ */
674+ public em1 ( n : number ) : string {
675+ const m = em ( Math . max ( 0 , n ) ) ;
676+ return m === '0' ? '.1px' : m ;
677+ }
678+
656679 /**
657680 * @param {ChtmlCharData } data The [h, d, w] data for the character
658681 * @param {number } ic The (optional) italic correction value
0 commit comments