menclose.js (15341B)
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/HTML-CSS/autoload/menclose.js 7 * 8 * Implements the HTML-CSS output for <menclose> elements. 9 * 10 * --------------------------------------------------------------------- 11 * 12 * Copyright (c) 2010-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("HTML-CSS Jax Ready",function () { 28 var VERSION = "2.6.0"; 29 var MML = MathJax.ElementJax.mml, 30 HTMLCSS = MathJax.OutputJax["HTML-CSS"]; 31 32 var SVGNS = "http://www.w3.org/2000/svg"; 33 var VMLNS = "urn:schemas-microsoft-com:vml"; 34 var vmlns = "mjxvml"; 35 36 MML.menclose.Augment({ 37 toHTML: function (span) { 38 var values = this.getValues("notation","thickness","padding","mathcolor","color"); 39 if (values.color && !this.mathcolor) {values.mathcolor = values.color} 40 if (values.thickness == null) {values.thickness = ".075em"} 41 if (values.padding == null) {values.padding = ".2em"} 42 span = this.HTMLcreateSpan(span); 43 var mu = this.HTMLgetMu(span), scale = this.HTMLgetScale(); 44 var p = HTMLCSS.length2em(values.padding,mu,1/HTMLCSS.em) * scale; // padding for enclosure 45 var t = HTMLCSS.length2em(values.thickness,mu,1/HTMLCSS.em) * scale; // thickness of lines 46 t = Math.max(1/HTMLCSS.em,t); // see issue #414 47 var SOLID = HTMLCSS.Em(t)+" solid"; 48 49 var stack = HTMLCSS.createStack(span); 50 var base = HTMLCSS.createBox(stack); 51 this.HTMLmeasureChild(0,base); 52 var H = base.bbox.h+p+t, D = base.bbox.d+p+t, W = base.bbox.w+2*(p+t); 53 var frame = HTMLCSS.createFrame(stack,H+D,0,W,t,"none"); 54 frame.id = "MathJax-frame-"+this.spanID; 55 HTMLCSS.addBox(stack,frame); stack.insertBefore(frame,base); // move base to above background 56 var T = 0, B = 0, R = 0, L = 0, dx = 0, dy = 0; var svg, vml; 57 var w, h, r; 58 if (!values.mathcolor) {values.mathcolor = "black"} else {span.style.color = values.mathcolor} 59 60 // perform some reduction e.g. eliminate duplicate notations. 61 var nl = MathJax.Hub.SplitList(values.notation), notation = {}; 62 for (var i = 0, m = nl.length; i < m; i++) notation[nl[i]] = true; 63 if (notation[MML.NOTATION.UPDIAGONALARROW]) notation[MML.NOTATION.UPDIAGONALSTRIKE] = false; 64 65 var line; 66 for (var n in notation) { 67 if (!notation.hasOwnProperty(n) || !notation[n]) continue; 68 switch (n) { 69 case MML.NOTATION.BOX: 70 frame.style.border = SOLID; if (!HTMLCSS.msieBorderWidthBug) {T = B = L = R = t} 71 break; 72 73 case MML.NOTATION.ROUNDEDBOX: 74 if (HTMLCSS.useVML) { 75 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 76 // roundrect.arcsize can't be set in IE8 standards mode, so use a path 77 r = Math.floor(1000*Math.min(W,H+D)-2*t); 78 w = Math.floor(4000*(W-2*t)), h = Math.floor(4000*(H+D-2*t)); 79 this.HTMLvmlElement(vml,"shape",{ 80 style: {width:this.HTMLpx(W-2*t),height:this.HTMLpx(H+D-2*t), 81 left:this.HTMLpx(t,.5),top:this.HTMLpx(t,.5)}, 82 path: "m "+r+",0 qx 0,"+r+" l 0,"+(h-r)+" qy "+r+","+h+" "+ 83 "l "+(w-r)+","+h+" qx "+w+","+(h-r)+" l "+w+","+r+" qy "+(w-r)+",0 x e", 84 coordsize: w+","+h 85 }); 86 } else { 87 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 88 this.HTMLsvgElement(svg.firstChild,"rect",{ 89 x:1, y:1, width:this.HTMLpx(W-t)-1, 90 height:this.HTMLpx(H+D-t)-1, rx:this.HTMLpx(Math.min(H+D,W)/4) 91 }); 92 } 93 break; 94 95 case MML.NOTATION.CIRCLE: 96 if (HTMLCSS.useVML) { 97 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 98 this.HTMLvmlElement(vml,"oval",{ 99 style: {width:this.HTMLpx(W-2*t),height:this.HTMLpx(H+D-2*t), 100 left:this.HTMLpx(t,.5),top:this.HTMLpx(t,.5)} 101 }); 102 } else { 103 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 104 this.HTMLsvgElement(svg.firstChild,"ellipse",{ 105 rx:this.HTMLpx(W/2-t), ry:this.HTMLpx((H+D)/2-t), 106 cx:this.HTMLpx(W/2), cy:this.HTMLpx((H+D)/2) 107 }); 108 } 109 break; 110 111 case MML.NOTATION.LEFT: 112 frame.style.borderLeft = SOLID; if (!HTMLCSS.msieBorderWidthBug) {L = t} 113 break; 114 115 case MML.NOTATION.ACTUARIAL: 116 frame.style.borderTop = SOLID; if (!HTMLCSS.msieBorderWidthBug) {T = t; frame.bbox.w += p-t} 117 case MML.NOTATION.RIGHT: 118 frame.style.borderRight = SOLID; if (!HTMLCSS.msieBorderWidthBug) {R = t} 119 break; 120 121 case MML.NOTATION.VERTICALSTRIKE: 122 line = HTMLCSS.createRule(stack,H+D-t/2,0,t); 123 HTMLCSS.addBox(stack,line); HTMLCSS.placeBox(line,p+t+base.bbox.w/2,-D,true); 124 break; 125 126 case MML.NOTATION.TOP: 127 frame.style.borderTop = SOLID; if (!HTMLCSS.msieBorderWidthBug) {T = t} 128 break; 129 130 case MML.NOTATION.BOTTOM: 131 frame.style.borderBottom = SOLID; if (!HTMLCSS.msieBorderWidthBug) {B = t} 132 break; 133 134 case MML.NOTATION.HORIZONTALSTRIKE: 135 line = HTMLCSS.createRule(stack,t,0,W-t/2); 136 HTMLCSS.addBox(stack,line); HTMLCSS.placeBox(line,0,(H+D)/2-D,true); 137 break; 138 139 case MML.NOTATION.UPDIAGONALSTRIKE: 140 if (HTMLCSS.useVML) { 141 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 142 line = this.HTMLvmlElement(vml,"line",{from: "0,"+this.HTMLpx(H+D-t), to: this.HTMLpx(W)+",0"}); 143 } else { 144 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 145 this.HTMLsvgElement(svg.firstChild,"line",{ 146 x1:1, y1:this.HTMLpx(H+D-t), x2:this.HTMLpx(W-t), y2:this.HTMLpx(t) 147 }); 148 } 149 break; 150 151 case MML.NOTATION.UPDIAGONALARROW: 152 if (HTMLCSS.useVML) { 153 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 154 line = this.HTMLvmlElement(vml,"line",{from: "0,"+this.HTMLpx(H+D-t), to: this.HTMLpx(W)+","+this.HTMLpx(t)}); 155 this.HTMLvmlElement(line,"stroke",{endarrow:"classic"}); 156 } else { 157 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 158 var l = Math.sqrt(W*W + (H+D)*(H+D)), f = 1/l * 10*this.scale/HTMLCSS.em * t/.075; 159 w = W * f; h = (H+D) * f; var x = W - t/2, y = t/2; 160 if (y+h-.4*w < 0) {y = .4*w-h} 161 this.HTMLsvgElement(svg.firstChild,"line",{ 162 x1:1, y1:this.HTMLpx(H+D-t), x2:this.HTMLpx(x-.7*w), y2:this.HTMLpx(y+.7*h) 163 }); 164 this.HTMLsvgElement(svg.firstChild,"polygon",{ 165 points: this.HTMLpx(x)+","+this.HTMLpx(y)+" " 166 +this.HTMLpx(x-w-.4*h)+","+this.HTMLpx(y+h-.4*w)+" " 167 +this.HTMLpx(x-.7*w)+","+this.HTMLpx(y+.7*h)+" " 168 +this.HTMLpx(x-w+.4*h)+","+this.HTMLpx(y+h+.4*w)+" " 169 +this.HTMLpx(x)+","+this.HTMLpx(y), 170 fill:values.mathcolor, stroke:"none" 171 }); 172 } 173 break; 174 175 case MML.NOTATION.DOWNDIAGONALSTRIKE: 176 if (HTMLCSS.useVML) { 177 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 178 this.HTMLvmlElement(vml,"line",{from: "0,0", to: this.HTMLpx(W)+","+this.HTMLpx(H+D-t)}); 179 } else { 180 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 181 this.HTMLsvgElement(svg.firstChild,"line",{ 182 x1:1, y1:this.HTMLpx(t), x2:this.HTMLpx(W-t), y2:this.HTMLpx(H+D-t) 183 }); 184 } 185 break; 186 187 case MML.NOTATION.PHASORANGLE: 188 W -= 2*p; p = (H+D)/2; W += p; 189 if (HTMLCSS.useVML) { 190 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 191 this.HTMLvmlElement(vml,"shape",{ 192 style: {width:this.HTMLpx(W), height:this.HTMLpx(H+D)}, 193 path: "m "+this.HTMLpt(p+t/2,t/2)+ 194 " l "+this.HTMLpt(t/2,H+D-t)+" "+this.HTMLpt(W-t/2,H+D-t)+" e", 195 coordsize: this.HTMLpt(W,H+D) 196 }); 197 198 } else { 199 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 200 this.HTMLsvgElement(svg.firstChild,"path",{ 201 d: "M "+this.HTMLpx(p)+",1" + 202 "L 1,"+this.HTMLpx(H+D-t)+" L "+this.HTMLpx(W)+","+this.HTMLpx(H+D-t) 203 }); 204 HTMLCSS.placeBox(svg.parentNode,0,-D,true); 205 } 206 break; 207 208 case MML.NOTATION.MADRUWB: 209 frame.style.borderBottom = SOLID; 210 frame.style.borderRight = SOLID; if (!HTMLCSS.msieBorderWidthBug) {B = R = t} 211 break; 212 213 case MML.NOTATION.RADICAL: 214 if (HTMLCSS.useVML) { 215 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 216 this.HTMLvmlElement(vml,"shape",{ 217 style: {width:this.HTMLpx(W), height:this.HTMLpx(H+D)}, 218 path: "m "+this.HTMLpt(t/2,.6*(H+D))+" l "+this.HTMLpt(p,H+D-t)+" "+ 219 this.HTMLpt(2*p,t/2)+" "+this.HTMLpt(W,t/2)+" e", 220 coordsize: this.HTMLpt(W,H+D) 221 }); 222 dx = p; 223 } else { 224 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 225 this.HTMLsvgElement(svg.firstChild,"path",{ 226 d: "M 1,"+this.HTMLpx(.6*(H+D)) + 227 " L "+this.HTMLpx(p)+","+this.HTMLpx(H+D) + 228 " L "+this.HTMLpx(2*p)+",1 L "+this.HTMLpx(W)+",1" 229 }); 230 HTMLCSS.placeBox(svg.parentNode,0,p/2-D,true); 231 dx = p; dy = t; 232 } 233 break; 234 235 case MML.NOTATION.LONGDIV: 236 if (HTMLCSS.useVML) { 237 if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)} 238 this.HTMLvmlElement(vml,"line",{from: "0,"+this.HTMLpx(t/2), to: this.HTMLpx(W-t)+","+this.HTMLpx(t/2)}); 239 this.HTMLvmlElement(vml,"arc",{ 240 style: {width:this.HTMLpx(2*p),height:this.HTMLpx(H+D-2*t), 241 left:this.HTMLpx(-p),top:this.HTMLpx(t)}, 242 startangle:"10", endangle:"170" 243 }); 244 dx = p; 245 } else { 246 if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)} 247 this.HTMLsvgElement(svg.firstChild,"path",{ 248 d: "M "+this.HTMLpx(W)+",1 L 1,1 "+ 249 "a"+this.HTMLpx(p)+","+this.HTMLpx((H+D)/2-t)+" 0 0,1 1,"+this.HTMLpx(H+D-2*t) 250 }); 251 HTMLCSS.placeBox(svg.parentNode,0,t-D,true); 252 dx = p; dy = t; 253 } 254 break; 255 } 256 } 257 frame.style.width = HTMLCSS.Em(W-L-R); frame.style.height = HTMLCSS.Em(H+D-T-B); 258 HTMLCSS.placeBox(frame,0,dy-D,true); 259 HTMLCSS.placeBox(base,dx+p+t,0); 260 this.HTMLhandleSpace(span); 261 this.HTMLhandleColor(span); 262 return span; 263 }, 264 265 HTMLpx: function (n) {return (n*HTMLCSS.em)}, 266 HTMLpt: function (x,y) {return Math.floor(1000*x)+','+Math.floor(1000*y)}, 267 268 HTMLhandleColor: function (span) { 269 var frame = document.getElementById("MathJax-frame-"+this.spanID); 270 if (frame) { 271 // mathcolor is handled in toHTML above 272 var values = this.getValues("mathbackground","background"); 273 if (this.style && span.style.backgroundColor) { 274 values.mathbackground = span.style.backgroundColor; 275 span.style.backgroundColor = ""; 276 } 277 if (values.background && !this.mathbackground) {values.mathbackground = values.background} 278 if (values.mathbackground && values.mathbackground !== MML.COLOR.TRANSPARENT) 279 {frame.style.backgroundColor = values.mathbackground} 280 } else {this.SUPER(arguments).HTMLhandleColor.call(this,span)} 281 }, 282 283 HTMLsvg: function (stack,H,D,W,t,color) { 284 var svg = document.createElementNS(SVGNS,"svg"); 285 if (svg.style) {svg.style.width = HTMLCSS.Em(W); svg.style.height = HTMLCSS.Em(H+D)} 286 var scale = HTMLCSS.createBox(stack); scale.appendChild(svg); 287 HTMLCSS.placeBox(scale,0,-D,true); 288 this.HTMLsvgElement(svg,"g",{fill:"none", stroke:color, "stroke-width":t*HTMLCSS.em}); 289 return svg; 290 }, 291 HTMLsvgElement: function (svg,type,def) { 292 var obj = document.createElementNS(SVGNS,type); obj.isMathJax = true; 293 if (def) {for (var id in def) {if (def.hasOwnProperty(id)) {obj.setAttributeNS(null,id,def[id].toString())}}} 294 svg.appendChild(obj); 295 return obj; 296 }, 297 HTMLvml: function (stack,H,D,W,t,color) { 298 var vml = HTMLCSS.createFrame(stack,H+D,0,W,0,"none"); 299 HTMLCSS.addBox(stack,vml); HTMLCSS.placeBox(vml,0,-D,true); 300 this.constructor.VMLcolor = color; this.constructor.VMLthickness = this.HTMLpx(t); 301 return vml; 302 }, 303 HTMLvmlElement: function (vml,type,def) { 304 var obj = HTMLCSS.addElement(vml,vmlns+":"+type,{isMathJax:true}); 305 obj.style.position = "absolute"; obj.style.left = obj.style.top = 0; 306 MathJax.Hub.Insert(obj,def); // IE8 needs to do this after obj is added to the page 307 if (!def.fillcolor) {obj.fillcolor = "none"} 308 if (!def.strokecolor) {obj.strokecolor = this.constructor.VMLcolor} 309 if (!def.strokeweight) {obj.strokeweight =this.constructor.VMLthickness} 310 return obj; 311 } 312 }); 313 314 MathJax.Hub.Browser.Select({ 315 MSIE: function (browser) { 316 // 317 // IE8 and below doesn't have SVG, so use VML 318 // 319 if ((document.documentMode||0) < 9) { 320 MML.menclose.Augment({HTMLpx: function (n,d) {return (n*HTMLCSS.em+(d||0))+"px"}}); 321 HTMLCSS.useVML = true; 322 if (!document.namespaces[vmlns]) { 323 if (document.documentMode && document.documentMode === 8) { 324 document.namespaces.add(vmlns,VMLNS,"#default#VML"); 325 } else { 326 document.namespaces.add(vmlns,VMLNS); 327 document.createStyleSheet().addRule(vmlns+"\\: *","{behavior: url(#default#VML)}"); 328 } 329 } 330 } 331 } 332 }); 333 334 335 MathJax.Hub.Startup.signal.Post("HTML-CSS menclose Ready"); 336 MathJax.Ajax.loadComplete(HTMLCSS.autoloadDir+"/menclose.js"); 337 338 }); 339