www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

mmultiscripts.js (11768B)


      1 /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 
      4 /*************************************************************
      5  *
      6  *  MathJax/jax/output/CommonHTML/autoload/mmultiscripts.js
      7  *  
      8  *  Implements the CommonHTML output for <mmultiscripts> elements.
      9  *
     10  *  ---------------------------------------------------------------------
     11  *  
     12  *  Copyright (c) 2015 The MathJax Consortium
     13  * 
     14  *  Licensed under the Apache License, Version 2.0 (the "License");
     15  *  you may not use this file except in compliance with the License.
     16  *  You may obtain a copy of the License at
     17  * 
     18  *      http://www.apache.org/licenses/LICENSE-2.0
     19  * 
     20  *  Unless required by applicable law or agreed to in writing, software
     21  *  distributed under the License is distributed on an "AS IS" BASIS,
     22  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     23  *  See the License for the specific language governing permissions and
     24  *  limitations under the License.
     25  */
     26 
     27 MathJax.Hub.Register.StartupHook("CommonHTML Jax Ready",function () {
     28   var VERSION = "2.6.0";
     29   var MML = MathJax.ElementJax.mml,
     30       CHTML = MathJax.OutputJax.CommonHTML;
     31 
     32   MML.mmultiscripts.Augment({
     33     toCommonHTML: function (node,stretch) {
     34       if (!stretch) {
     35         node = this.CHTMLcreateNode(node);
     36         this.CHTMLhandleStyle(node);
     37         this.CHTMLhandleScale(node);
     38         this.CHTMLgetVariant();
     39       }
     40       CHTML.BBOX.empty(this.CHTML);
     41 
     42       //
     43       //  Get base node
     44       //
     45       var base, bbox;
     46       if (stretch) {
     47         base = CHTML.getNode(node,"mjx-base");
     48       } else {
     49         this.CHTMLaddChild(node,0,{type:"mjx-base", noBBox:true, forceChild:true});
     50         base = node.firstChild;
     51       }
     52       bbox = this.CHTMLbboxFor(0);
     53       if (bbox.ic) {
     54           bbox.R -= bbox.ic;         // remove IC (added by mo and mi)
     55           if (!stretch) base.style.marginRight = CHTML.Em(-bbox.ic);
     56           delta = 1.3*bbox.ic + .05; // make faked IC be closer to expeted results
     57       }
     58       
     59       //
     60       //  Collect scripts into horizontal boxes and add them into the node
     61       //
     62       var BOX = {}, BBOX = {};
     63       this.CHTMLgetScripts(BOX,BBOX,stretch,node);
     64       var sub = BOX.sub, sup = BOX.sup, presub = BOX.presub, presup = BOX.presup;
     65       var sbox = BBOX.sub, Sbox = BBOX.sup, pbox = BBOX.presub, Pbox = BBOX.presup;
     66       if (!stretch) this.CHTMLaddBoxes(node,base,BOX);
     67       
     68       //
     69       //  Get the initial values for the variables
     70       //
     71       var values = this.getValues("scriptlevel","scriptsizemultiplier");
     72       var sscale = (this.Get("scriptlevel") < 3 ? values.scriptsizemultiplier : 1);
     73       var ex = CHTML.TEX.x_height, s = CHTML.TEX.scriptspace;
     74       var q = CHTML.TEX.sup_drop * sscale, r = CHTML.TEX.sub_drop * sscale;
     75       var u = bbox.h - q, v = bbox.d + r, delta = 0, p;
     76       var bmml = this.data[this.base];
     77       if (bmml && (bmml.type === "mi" || bmml.type === "mo")) {
     78         if (bmml.data.join("").length === 1 && bbox.rscale === 1 && !bbox.sH &&
     79           !bmml.Get("largeop")) {u = v = 0}
     80       }
     81       values = this.getValues("displaystyle","subscriptshift","superscriptshift","texprimestyle");
     82       values.subscriptshift   = (values.subscriptshift === ""   ? 0 : this.CHTMLlength2em(values.subscriptshift));
     83       values.superscriptshift = (values.superscriptshift === "" ? 0 : this.CHTMLlength2em(values.superscriptshift));
     84 
     85       var dx = (presub ? s+pbox.w : presup ? s+Pbox.w-delta : 0);
     86       this.CHTML.combine(bbox,dx,0); var x = this.CHTML.w;
     87 
     88       //
     89       //  Place the scripts as needed
     90       //
     91       if (!sup && !presup) {
     92         v = Math.max(v,CHTML.TEX.sub1,values.subscriptshift);
     93         if (sub)    v = Math.max(v,sbox.h-(4/5)*ex);
     94         if (presub) v = Math.max(v,pbox.h-(4/5)*ex);
     95         if (sub)    this.CHTMLplaceSubOnly(sub,sbox,x,v,s);
     96         if (presub) this.CHTMLplacePresubOnly(presub,pbox,v,s);
     97       } else {
     98         if (!sub && !presub) {
     99           p = CHTML.TEX[(values.displaystyle ? "sup1" : (values.texprimestyle ? "sup3" : "sup2"))];
    100           u = Math.max(u,p,values.superscriptshift);
    101           if (sup)    u = Math.max(u,Sbox.d+(1/4)*ex);
    102           if (presup) u = Math.max(u,Pbox.d+(1/4)*ex);
    103           if (sup)    this.CHTMLplaceSupOnly(sup,Sbox,x,delta,u,s);
    104           if (presup) this.CHTMLplacePresupOnly(presup,Pbox,delta,u,s);
    105         } else {
    106           v = Math.max(v,CHTML.TEX.sub2);
    107           var t = CHTML.TEX.rule_thickness;
    108           var h = (sbox||pbox).h, d = (Sbox||Pbox).d;
    109           if (presub) h = Math.max(h,pbox.h);
    110           if (presup) d = Math.max(d,Pbox.d);
    111           if ((u - d) - (h - v) < 3*t) {
    112             v = 3*t - u + d + h; q = (4/5)*ex - (u - d);
    113             if (q > 0) {u += q; v -= q}
    114           }
    115           u = Math.max(u,values.superscriptshift);
    116           v = Math.max(v,values.subscriptshift);
    117           if (sup) {
    118             if (sub) {this.CHTMLplaceSubSup(sub,sbox,sup,Sbox,x,delta,u,v,s)}
    119                 else {this.CHTMLplaceSupOnly(sup,Sbox,x,delta,u,s)}
    120           } else if (sub) {this.CHTMLplaceSubOnly(sub,sbox,x,v,s)}
    121           if (presup) {
    122             if (presub) {this.CHTMLplacePresubPresup(presub,pbox,presup,Pbox,delta,u,v,s)}
    123                    else {this.CHTMLplacePresupOnly(presup,Pbox,delta,u,s)}
    124           } else if (presub) {this.CHTMLplacePresubOnly(presub,pbox,v,s)}
    125         }
    126       }
    127       this.CHTML.clean();
    128       this.CHTMLhandleSpace(node);
    129       this.CHTMLhandleBBox(node);
    130       this.CHTMLhandleColor(node);
    131       return node;
    132     },
    133     //
    134     //  Get the subscript, superscript, presubscript, and presuperscript
    135     //  boxes, with proper spacing, and computer their bounding boxes.
    136     //
    137     CHTMLgetScripts: function (BOX,BBOX,stretch,node) {
    138       if (stretch) {
    139         BOX.sub = CHTML.getNode(node,"mjx-sub");
    140         BOX.sup = CHTML.getNode(node,"mjx-sup");
    141         BOX.presub = CHTML.getNode(node,"mjx-presub");
    142         BOX.presup = CHTML.getNode(node,"mjx-presup");
    143         BBOX.sub = this.CHTMLbbox.sub;
    144         BBOX.sup = this.CHTMLbbox.sup;
    145         BBOX.presub = this.CHTMLbbox.presub;
    146         BBOX.presup = this.CHTMLbbox.presup;
    147         return;
    148       }
    149       this.CHTMLbbox = BBOX;  // save for when stretched
    150       var state = {i:1, w:0, BOX:BOX, BBOX:BBOX}, m = this.data.length;
    151       var sub = "sub", sup = "sup";
    152       while (state.i < m) {
    153         if ((this.data[state.i]||{}).type === "mprescripts") {
    154           state.i++; state.w = 0;
    155           sub = "presub"; sup = "presup";
    156         } else {
    157           var sbox = this.CHTMLaddScript(sub,state);
    158           var Sbox = this.CHTMLaddScript(sup,state);
    159           var w = Math.max((sbox ? sbox.rscale*sbox.w : 0),(Sbox ? Sbox.rscale*Sbox.w : 0));
    160           this.CHTMLpadScript(sub,w,sbox,state);
    161           this.CHTMLpadScript(sup,w,Sbox,state);
    162           state.w += w;
    163         }
    164       }
    165       if (BBOX.sub) BBOX.sub.clean();
    166       if (BBOX.sup) BBOX.sup.clean();
    167       if (BBOX.presub) BBOX.presub.clean();
    168       if (BBOX.presup) BBOX.presup.clean();
    169     },
    170     //
    171     //  Add a script to the proper box, creating the box if needed,
    172     //  and padding the box to account for any <none/> elements.
    173     //  Return the bounding box for the script for later use.
    174     //
    175     CHTMLaddScript: function (type,state) {
    176       var BOX, BBOX, data = this.data[state.i];
    177       if (data && data.type !== "none" && data.type !== "mprescripts") {
    178         BOX = state.BOX[type];
    179         if (!BOX) {
    180           BOX = state.BOX[type] = CHTML.Element("mjx-"+type);
    181           BBOX = state.BBOX[type] = CHTML.BBOX.empty();
    182           if (state.w) {
    183             BOX.style.paddingLeft = CHTML.Em(state.w);
    184             BBOX.w = BBOX.r = state.w; BBOX.x = state.w;
    185           }
    186         }
    187         data.toCommonHTML(BOX);
    188         BBOX = data.CHTML;
    189       }
    190       if (data && data.type !== "mprescripts") state.i++;
    191       return BBOX;
    192     },
    193     //
    194     //  Add padding to the script box to make match the width of the
    195     //  super- or subscript that is above or below it, and adjust the
    196     //  bounding box for the script row.  If these are pre-scripts,
    197     //  right-justify the scripts, otherwise, left-justify them.
    198     //
    199     CHTMLpadScript: function (type,w,bbox,state) {
    200       if (!bbox) bbox = {w:0, fake:1, rscale:1};
    201       var BBOX = state.BBOX[type], dx = 0, dw = 0;
    202       if (BBOX) {
    203         if (bbox.rscale*bbox.w < w) {
    204           var BOX = state.BOX[type]; dw = w-bbox.rscale*bbox.w;
    205           var space = CHTML.Element("mjx-spacer",{style:{width:CHTML.Em(dw)}});
    206           if (type.substr(0,3) === "pre" && !bbox.fake) {
    207             BOX.insertBefore(space,BOX.lastChild);
    208             dx = dw; dw = 0;
    209           } else {
    210             BOX.appendChild(space);
    211           }
    212         }
    213         if (bbox.fake) {BBOX.w += dx} else {BBOX.combine(bbox,BBOX.w+dx,0)}
    214         BBOX.w += dw;
    215       }
    216     },
    217     //
    218     //  Add the boxes into the main node, creating stacks when needed
    219     //
    220     CHTMLaddBoxes: function (node,base,BOX) {
    221       var sub = BOX.sub, sup = BOX.sup, presub = BOX.presub, presup = BOX.presup;
    222       if (presub && presup) {
    223         var prestack = CHTML.Element("mjx-prestack"); node.insertBefore(prestack,base);
    224         prestack.appendChild(presup); prestack.appendChild(presub);
    225       } else {
    226         if (presub) node.insertBefore(presub,base);
    227         if (presup) node.insertBefore(presup,base);
    228       }
    229       if (sub && sup) {
    230         var stack = CHTML.addElement(node,"mjx-stack");
    231         stack.appendChild(sup); stack.appendChild(sub);
    232       } else {
    233         if (sub) node.appendChild(sub);
    234         if (sup) node.appendChild(sup);
    235       }
    236     },
    237     //
    238     //  Handle positioning the various scripts
    239     //
    240     CHTMLplaceSubOnly: function (sub,sbox,x,v,s) {
    241       sub.style.verticalAlign = CHTML.Em(-v);
    242       sub.style.marginRight = CHTML.Em(s); sbox.w += s;
    243       this.CHTML.combine(sbox,x,-v);
    244     },
    245     CHTMLplaceSupOnly: function (sup,Sbox,x,delta,u,s) {
    246       sup.style.verticalAlign = CHTML.Em(u);
    247       sup.style.paddingLeft = CHTML.Em(delta);
    248       sup.style.paddingRight = CHTML.Em(s); Sbox.w += s;
    249       this.CHTML.combine(Sbox,x+delta,u);
    250     },
    251     CHTMLplaceSubSup: function (sub,sbox,sup,Sbox,x,delta,u,v,s) {
    252       sub.style.paddingRight = CHTML.Em(s); sbox.w += s;
    253       sup.style.paddingBottom = CHTML.Em(u+v-Sbox.d-sbox.h);
    254       sup.style.paddingLeft = CHTML.Em(delta+(Sbox.x||0));
    255       sup.style.paddingRight = CHTML.Em(s); Sbox.w += s;
    256       sup.parentNode.style.verticalAlign = CHTML.Em(-v);
    257       this.CHTML.combine(sbox,x,-v);
    258       this.CHTML.combine(Sbox,x+delta,u);
    259     },
    260     CHTMLplacePresubOnly: function (presub,pbox,v,s) {
    261       presub.style.verticalAlign = CHTML.Em(-v);
    262       presub.style.marginLeft = CHTML.Em(s);
    263       this.CHTML.combine(pbox,s,-v);
    264     },
    265     CHTMLplacePresupOnly: function (presup,Pbox,delta,u,s) {
    266       presup.style.verticalAlign = CHTML.Em(u);
    267       presup.style.paddingLeft = CHTML.Em(s);
    268       presup.style.paddingRight = CHTML.Em(-delta);
    269       this.CHTML.combine(Pbox,s,u);
    270     },
    271     CHTMLplacePresubPresup: function (presub,pbox,presup,Pbox,delta,u,v,s) {
    272       presub.style.paddingLeft = CHTML.Em(s);
    273       presup.style.paddingBottom = CHTML.Em(u+v-Pbox.d-pbox.h);
    274       presup.style.paddingLeft = CHTML.Em(delta+s+(Pbox.x||0));
    275       presup.style.paddingRight = CHTML.Em(-delta);
    276       presup.parentNode.style.verticalAlign = CHTML.Em(-v);
    277       this.CHTML.combine(pbox,s,-v);
    278       this.CHTML.combine(Pbox,s+delta,u);
    279     },
    280     //
    281     //  Handle stretchy bases
    282     //
    283     CHTMLstretchH: MML.mbase.CHTMLstretchH,
    284     CHTMLstretchV: MML.mbase.CHTMLstretchV
    285   });
    286   
    287   MathJax.Hub.Startup.signal.Post("CommonHTML mmultiscripts Ready");
    288   MathJax.Ajax.loadComplete(CHTML.autoloadDir+"/mmultiscripts.js");
    289 });
    290