@@ -49,9 +49,15 @@ export class CHTMLmfrac<N, T, D> extends CHTMLWrapper<N, T, D> {
4949 'mjx-frac[type="d"]' : {
5050 'vertical-align' : '.04em' // axis_height - 3.5 * rule_thickness
5151 } ,
52- 'mjx-frac[delims="true" ]' : {
52+ 'mjx-frac[delims]' : {
5353 padding : '0 .1em' // .1 (for line's -.1em margin)
5454 } ,
55+ 'mjx-frac[atop]' : {
56+ padding : '0 .12em' // nulldelimiterspace
57+ } ,
58+ 'mjx-frac[atop][delims]' : {
59+ padding : '0'
60+ } ,
5561 'mjx-dtable' : {
5662 display : 'inline-table' ,
5763 width : '100%'
@@ -120,10 +126,27 @@ export class CHTMLmfrac<N, T, D> extends CHTMLWrapper<N, T, D> {
120126 * @override
121127 */
122128 public toCHTML ( parent : N ) {
123- const chtml = this . standardCHTMLnode ( parent ) ;
124- const { displaystyle, scriptlevel, linethickness, numalign, denomalign} =
125- this . node . attributes . getList ( 'displaystyle' , 'scriptlevel' , 'linethickness' , 'numalign' , 'denomalign' ) ;
126- const withDelims = this . node . getProperty ( 'withDelims' ) ;
129+ this . standardCHTMLnode ( parent ) ;
130+ const { linethickness, bevelled} = this . node . attributes . getList ( 'linethickness' , 'bevelled' ) ;
131+ if ( bevelled ) {
132+ this . makeBevelled ( ) ;
133+ } else {
134+ const thickness = this . length2em ( String ( linethickness ) ) ;
135+ if ( thickness === 0 ) {
136+ this . makeAtop ( ) ;
137+ } else {
138+ this . makeFraction ( thickness ) ;
139+ }
140+ }
141+ }
142+
143+ /*
144+ * @param {number } t The rule line thickness
145+ */
146+ protected makeFraction ( t : number ) {
147+ const { displaystyle, scriptlevel, numalign, denomalign} =
148+ this . node . attributes . getList ( 'displaystyle' , 'scriptlevel' , 'numalign' , 'denomalign' ) ;
149+ const withDelims = this . node . getProperty ( 'texWithDelims' ) ;
127150 const display = ( displaystyle && scriptlevel === 0 ) ;
128151 //
129152 // Attributes to set for the different elements making up the fraction
@@ -136,7 +159,6 @@ export class CHTMLmfrac<N, T, D> extends CHTMLWrapper<N, T, D> {
136159 //
137160 // Set the styles to handle the linethickness, if needed
138161 //
139- const t = this . length2em ( linethickness ) ;
140162 const fparam = this . font . params ;
141163 if ( t !== .06 ) {
142164 const a = fparam . axis_height ;
@@ -152,7 +174,7 @@ export class CHTMLmfrac<N, T, D> extends CHTMLWrapper<N, T, D> {
152174 // Create the DOM tree
153175 //
154176 let num , den ;
155- this . adaptor . append ( chtml , this . html ( 'mjx-frac' , fattr , [
177+ this . adaptor . append ( this . chtml , this . html ( 'mjx-frac' , fattr , [
156178 num = this . html ( 'mjx-num' , nattr , [ this . html ( 'mjx-nstrut' , nsattr ) ] ) ,
157179 this . html ( 'mjx-dbox' , { } , [
158180 this . html ( 'mjx-dtable' , { } , [
@@ -165,28 +187,117 @@ export class CHTMLmfrac<N, T, D> extends CHTMLWrapper<N, T, D> {
165187 ] ) ) ;
166188 this . childNodes [ 0 ] . toCHTML ( num ) ;
167189 this . childNodes [ 1 ] . toCHTML ( den ) ;
190+ }
191+
192+ protected makeAtop ( ) {
193+ const { displaystyle, scriptlevel, numalign, denomalign} =
194+ this . node . attributes . getList ( 'displaystyle' , 'scriptlevel' , 'numalign' , 'denomalign' ) ;
195+ const withDelims = this . node . getProperty ( 'texWithDelims' ) ;
196+ const display = ( displaystyle && scriptlevel === 0 ) ;
197+ //
198+ // Attributes to set for the different elements making up the fraction
199+ //
200+ const attr = ( display ? { type : 'd' , atop : true } : { atop : true } ) as OptionList ;
201+ const fattr = ( withDelims ? { ...attr , delims : true } : { ...attr } ) as OptionList ;
202+ const nattr = ( numalign !== 'center' ? { align : numalign } : { } ) as OptionList ;
203+ const dattr = ( denomalign !== 'center' ? { align : denomalign } : { } ) as OptionList ;
204+ //
205+ // Determine sparation and positioning
206+ //
207+ const { v, q} = this . getUVQ ( display ) ;
208+ nattr . style = { 'padding-bottom' : this . em ( q ) } ;
209+ fattr . style = { 'vertical-align' : this . em ( - v ) } ;
210+ //
211+ // Create the DOM tree
212+ //
213+ let num , den ;
214+ this . adaptor . append ( this . chtml , this . html ( 'mjx-frac' , fattr , [
215+ num = this . html ( 'mjx-num' , nattr ) ,
216+ den = this . html ( 'mjx-den' , dattr )
217+ ] ) ) ;
218+ this . childNodes [ 0 ] . toCHTML ( num ) ;
219+ this . childNodes [ 1 ] . toCHTML ( den ) ;
168220 this . drawBBox ( ) ;
169221 }
170222
223+ /*
224+ * @param {boolean } display True for diplay-mode fractions
225+ * @return {Object }
226+ * The vertical offsets of the numerator (u), the denominator (v),
227+ * the separation between the two, and the bboxes themselves.
228+ */
229+ protected getUVQ ( display : boolean ) {
230+ const nbox = this . childNodes [ 0 ] . getBBox ( ) ;
231+ const dbox = this . childNodes [ 1 ] . getBBox ( ) ;
232+ const fparam = this . font . params ;
233+ //
234+ // Initial offsets (u, v)
235+ // Minimum separation (p)
236+ // Actual separation with initial positions (q)
237+ //
238+ let [ u , v ] = ( display ? [ fparam . num1 , fparam . denom1 ] : [ fparam . num3 , fparam . denom2 ] ) ;
239+ let p = ( display ? 7 : 3 ) * fparam . rule_thickness ;
240+ let q = ( u - nbox . d * nbox . scale ) - ( dbox . h * dbox . scale - v ) ;
241+ //
242+ // If actual separation is less than minimum, move them farther apart
243+ //
244+ if ( q < p ) {
245+ u += ( p - q ) / 2 ;
246+ v += ( p - q ) / 2 ;
247+ q = p ;
248+ }
249+ return { u, v, q, nbox, dbox} ;
250+ }
251+
252+ protected makeBevelled ( ) {
253+ }
254+
255+
171256 /*
172257 * @override
173258 */
174259 public computeBBox ( bbox : BBox ) {
175260 bbox . empty ( ) ;
176- const { displaystyle, scriptlevel, linethickness} =
177- this . node . attributes . getList ( 'displaystyle' , 'scriptlevel' , 'linethickness' ) ;
261+ const { linethickness, bevelled} = this . node . attributes . getList ( 'linethickness' , 'bevelled' ) ;
262+ if ( bevelled ) {
263+ this . getBevelledBBox ( bbox ) ;
264+ } else {
265+ const thickness = this . length2em ( String ( linethickness ) ) ;
266+ if ( thickness === 0 ) {
267+ this . getAtopBBox ( bbox ) ;
268+ } else {
269+ this . getFractionBBox ( bbox , thickness ) ;
270+ }
271+ }
272+ bbox . clean ( ) ;
273+ }
274+
275+ protected getFractionBBox ( bbox : BBox , t : number ) {
276+ const { displaystyle, scriptlevel} = this . node . attributes . getList ( 'displaystyle' , 'scriptlevel' ) ;
178277 const display = displaystyle && scriptlevel === 0 ;
179278 const nbox = this . childNodes [ 0 ] . getBBox ( ) ;
180279 const dbox = this . childNodes [ 1 ] . getBBox ( ) ;
181280 const fparam = this . font . params ;
182- const pad = ( this . node . getProperty ( 'withDelims ' ) as boolean ? 0 : fparam . nulldelimiterspace ) ;
281+ const pad = ( this . node . getProperty ( 'texWithDelims ' ) as boolean ? 0 : fparam . nulldelimiterspace ) ;
183282 const a = fparam . axis_height ;
184- const t = this . length2em ( linethickness ) ;
185283 const T = ( display ? 3.5 : 1.5 ) * t ;
186284 bbox . combine ( nbox , 0 , a + T + Math . max ( nbox . d * nbox . rscale , ( display ? fparam . num1 : fparam . num2 ) - a - T ) ) ;
187285 bbox . combine ( dbox , 0 , a - T - Math . max ( dbox . h * dbox . rscale , ( display ? fparam . denom1 : fparam . denom2 ) + a - T ) ) ;
188286 bbox . w += 2 * pad + .2 ;
189- bbox . clean ( ) ;
287+ }
288+
289+ protected getAtopBBox ( bbox : BBox ) {
290+ const { displaystyle, scriptlevel} = this . node . attributes . getList ( 'displaystyle' , 'scriptlevel' ) ;
291+ const display = displaystyle && scriptlevel === 0 ;
292+ const fparam = this . font . params ;
293+ const pad = ( this . node . getProperty ( 'texWithDelims' ) as boolean ? 0 : fparam . nulldelimiterspace ) ;
294+ const { u, v, nbox, dbox} = this . getUVQ ( display ) ;
295+ bbox . combine ( nbox , 0 , u ) ;
296+ bbox . combine ( dbox , 0 , - v ) ;
297+ bbox . w += 2 * pad ;
298+ }
299+
300+ protected getBevelledBBox ( bbox : BBox ) {
190301 }
191302
192303 /*
0 commit comments