menclose.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* -*- Mode: Javascript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
  2. /* vim: set ts=2 et sw=2 tw=80: */
  3. /*************************************************************
  4. *
  5. * MathJax/jax/output/HTML-CSS/autoload/menclose.js
  6. *
  7. * Implements the HTML-CSS output for <menclose> elements.
  8. *
  9. * ---------------------------------------------------------------------
  10. *
  11. * Copyright (c) 2010-2013 The MathJax Consortium
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License");
  14. * you may not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS,
  21. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. */
  25. MathJax.Hub.Register.StartupHook("HTML-CSS Jax Ready",function () {
  26. var VERSION = "2.2";
  27. var MML = MathJax.ElementJax.mml,
  28. HTMLCSS = MathJax.OutputJax["HTML-CSS"];
  29. var SVGNS = "http://www.w3.org/2000/svg";
  30. var VMLNS = "urn:schemas-microsoft-com:vml";
  31. var vmlns = "mjxvml";
  32. MML.menclose.Augment({
  33. toHTML: function (span) {
  34. var values = this.getValues("notation","thickness","padding","mathcolor","color");
  35. if (values.color && !this.mathcolor) {values.mathcolor = values.color}
  36. if (values.thickness == null) {values.thickness = ".075em"}
  37. if (values.padding == null) {values.padding = ".2em"}
  38. span = this.HTMLcreateSpan(span);
  39. var mu = this.HTMLgetMu(span), scale = this.HTMLgetScale();
  40. var p = HTMLCSS.length2em(values.padding,mu,1/HTMLCSS.em) * scale; // padding for enclosure
  41. var t = HTMLCSS.length2em(values.thickness,mu,1/HTMLCSS.em); // thickness of lines (not scaled, see issue #414)
  42. var SOLID = HTMLCSS.Em(t)+" solid";
  43. var stack = HTMLCSS.createStack(span);
  44. var base = HTMLCSS.createBox(stack);
  45. this.HTMLmeasureChild(0,base);
  46. var H = base.bbox.h+p+t, D = base.bbox.d+p+t, W = base.bbox.w+2*(p+t);
  47. var frame = HTMLCSS.createFrame(stack,H+D,0,W,t,"none");
  48. frame.id = "MathJax-frame-"+this.spanID;
  49. HTMLCSS.addBox(stack,frame); stack.insertBefore(frame,base); // move base to above background
  50. var notation = MathJax.Hub.SplitList(values.notation);
  51. var T = 0, B = 0, R = 0, L = 0, dx = 0, dy = 0; var svg, vml;
  52. var w, h, r;
  53. if (!values.mathcolor) {values.mathcolor = "black"} else {span.style.color = values.mathcolor}
  54. for (var i = 0, m = notation.length; i < m; i++) {
  55. switch (notation[i]) {
  56. case MML.NOTATION.BOX:
  57. frame.style.border = SOLID; if (!HTMLCSS.msieBorderWidthBug) {T = B = L = R = t}
  58. break;
  59. case MML.NOTATION.ROUNDEDBOX:
  60. if (HTMLCSS.useVML) {
  61. if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)}
  62. // roundrect.arcsize can't be set in IE8 standards mode, so use a path
  63. r = Math.floor(1000*Math.min(W,H+D)-2*t);
  64. w = Math.floor(4000*(W-2*t)), h = Math.floor(4000*(H+D-2*t));
  65. this.HTMLvmlElement(vml,"shape",{
  66. style: {width:this.HTMLpx(W-2*t),height:this.HTMLpx(H+D-2*t),
  67. left:this.HTMLpx(t,.5),top:this.HTMLpx(t,.5)},
  68. path: "m "+r+",0 qx 0,"+r+" l 0,"+(h-r)+" qy "+r+","+h+" "+
  69. "l "+(w-r)+","+h+" qx "+w+","+(h-r)+" l "+w+","+r+" qy "+(w-r)+",0 x e",
  70. coordsize: w+","+h
  71. });
  72. } else {
  73. if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)}
  74. this.HTMLsvgElement(svg.firstChild,"rect",{
  75. x:1, y:1, width:this.HTMLpx(W-t)-1,
  76. height:this.HTMLpx(H+D-t)-1, rx:this.HTMLpx(Math.min(H+D,W)/4)
  77. });
  78. }
  79. break;
  80. case MML.NOTATION.CIRCLE:
  81. if (HTMLCSS.useVML) {
  82. if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)}
  83. this.HTMLvmlElement(vml,"oval",{
  84. style: {width:this.HTMLpx(W-2*t),height:this.HTMLpx(H+D-2*t),
  85. left:this.HTMLpx(t,.5),top:this.HTMLpx(t,.5)}
  86. });
  87. } else {
  88. if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)}
  89. this.HTMLsvgElement(svg.firstChild,"ellipse",{
  90. rx:this.HTMLpx(W/2-t), ry:this.HTMLpx((H+D)/2-t),
  91. cx:this.HTMLpx(W/2), cy:this.HTMLpx((H+D)/2)
  92. });
  93. }
  94. break;
  95. case MML.NOTATION.LEFT:
  96. frame.style.borderLeft = SOLID; if (!HTMLCSS.msieBorderWidthBug) {L = t}
  97. break;
  98. case MML.NOTATION.ACTUARIAL:
  99. frame.style.borderTop = SOLID; if (!HTMLCSS.msieBorderWidthBug) {T = t; frame.bbox.w += p-t}
  100. case MML.NOTATION.RIGHT:
  101. frame.style.borderRight = SOLID; if (!HTMLCSS.msieBorderWidthBug) {R = t}
  102. break;
  103. case MML.NOTATION.VERTICALSTRIKE:
  104. var vline = HTMLCSS.createRule(stack,H+D-t/2,0,t);
  105. HTMLCSS.addBox(stack,vline); HTMLCSS.placeBox(vline,p+t+base.bbox.w/2,-D,true);
  106. break;
  107. case MML.NOTATION.TOP:
  108. frame.style.borderTop = SOLID; if (!HTMLCSS.msieBorderWidthBug) {T = t}
  109. break;
  110. case MML.NOTATION.BOTTOM:
  111. frame.style.borderBottom = SOLID; if (!HTMLCSS.msieBorderWidthBug) {B = t}
  112. break;
  113. case MML.NOTATION.HORIZONTALSTRIKE:
  114. var hline = HTMLCSS.createRule(stack,t,0,W-t/2);
  115. HTMLCSS.addBox(stack,hline); HTMLCSS.placeBox(hline,0,(H+D)/2-D,true);
  116. break;
  117. case MML.NOTATION.UPDIAGONALSTRIKE:
  118. if (HTMLCSS.useVML) {
  119. if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)}
  120. var line = this.HTMLvmlElement(vml,"line",{from: "0,"+this.HTMLpx(H+D-t), to: this.HTMLpx(W)+",0"});
  121. if (this.arrow) {
  122. this.HTMLvmlElement(line,"stroke",{endarrow:"classic"});
  123. line.to = this.HTMLpx(W)+","+this.HTMLpx(t);
  124. }
  125. } else {
  126. if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)}
  127. if (this.arrow) {
  128. var l = Math.sqrt(W*W + (H+D)*(H+D)), f = 1/l * 10*scale/HTMLCSS.em * t/.075;
  129. w = W * f; h = (H+D) * f; var x = W - t/2, y = t/2;
  130. if (y+h-.4*w < 0) {y = .4*w-h}
  131. this.HTMLsvgElement(svg.firstChild,"line",{
  132. x1:1, y1:this.HTMLpx(H+D-t), x2:this.HTMLpx(x-.7*w), y2:this.HTMLpx(y+.7*h)
  133. });
  134. this.HTMLsvgElement(svg.firstChild,"polygon",{
  135. points: this.HTMLpx(x)+","+this.HTMLpx(y)+" "
  136. +this.HTMLpx(x-w-.4*h)+","+this.HTMLpx(y+h-.4*w)+" "
  137. +this.HTMLpx(x-.7*w)+","+this.HTMLpx(y+.7*h)+" "
  138. +this.HTMLpx(x-w+.4*h)+","+this.HTMLpx(y+h+.4*w)+" "
  139. +this.HTMLpx(x)+","+this.HTMLpx(y),
  140. fill:values.mathcolor, stroke:"none"
  141. });
  142. } else {
  143. this.HTMLsvgElement(svg.firstChild,"line",{
  144. x1:1, y1:this.HTMLpx(H+D-t), x2:this.HTMLpx(W-t), y2:this.HTMLpx(t)
  145. });
  146. }
  147. }
  148. break;
  149. case MML.NOTATION.DOWNDIAGONALSTRIKE:
  150. if (HTMLCSS.useVML) {
  151. if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)}
  152. this.HTMLvmlElement(vml,"line",{from: "0,0", to: this.HTMLpx(W)+","+this.HTMLpx(H+D-t)});
  153. } else {
  154. if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)}
  155. this.HTMLsvgElement(svg.firstChild,"line",{
  156. x1:1, y1:this.HTMLpx(t), x2:this.HTMLpx(W-t), y2:this.HTMLpx(H+D-t)
  157. });
  158. }
  159. break;
  160. case MML.NOTATION.MADRUWB:
  161. frame.style.borderBottom = SOLID;
  162. frame.style.borderRight = SOLID; if (!HTMLCSS.msieBorderWidthBug) {B = R = t}
  163. break;
  164. case MML.NOTATION.RADICAL:
  165. if (HTMLCSS.useVML) {
  166. if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)}
  167. this.HTMLvmlElement(vml,"shape",{
  168. style: {width:this.HTMLpx(W), height:this.HTMLpx(H+D)},
  169. path: "m "+this.HTMLpt(t/2,.6*(H+D))+" l "+this.HTMLpt(p,H+D-t)+" "+
  170. this.HTMLpt(2*p,t/2)+" "+this.HTMLpt(W,t/2)+" e",
  171. coordsize: this.HTMLpt(W,H+D)
  172. });
  173. dx = p;
  174. } else {
  175. if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)}
  176. this.HTMLsvgElement(svg.firstChild,"path",{
  177. d: "M 1,"+this.HTMLpx(.6*(H+D)) +
  178. " L "+this.HTMLpx(p)+","+this.HTMLpx(H+D) +
  179. " L "+this.HTMLpx(2*p)+",1 L "+this.HTMLpx(W)+",1"
  180. });
  181. HTMLCSS.placeBox(svg.parentNode,0,p/2-D,true);
  182. dx = p; dy = t;
  183. }
  184. break;
  185. case MML.NOTATION.LONGDIV:
  186. if (HTMLCSS.useVML) {
  187. if (!vml) {vml = this.HTMLvml(stack,H,D,W,t,values.mathcolor)}
  188. this.HTMLvmlElement(vml,"line",{from: "0,"+this.HTMLpx(t/2), to: this.HTMLpx(W-t)+","+this.HTMLpx(t/2)});
  189. this.HTMLvmlElement(vml,"arc",{
  190. style: {width:this.HTMLpx(2*p),height:this.HTMLpx(H+D-2*t),
  191. left:this.HTMLpx(-p),top:this.HTMLpx(t)},
  192. startangle:"10", endangle:"170"
  193. });
  194. dx = p;
  195. } else {
  196. if (!svg) {svg = this.HTMLsvg(stack,H,D,W,t,values.mathcolor)}
  197. this.HTMLsvgElement(svg.firstChild,"path",{
  198. d: "M "+this.HTMLpx(W)+",1 L 1,1 "+
  199. "a"+this.HTMLpx(p)+","+this.HTMLpx((H+D)/2-t)+" 0 0,1 1,"+this.HTMLpx(H+D-2*t)
  200. });
  201. HTMLCSS.placeBox(svg.parentNode,0,t-D,true);
  202. dx = p; dy = t;
  203. }
  204. break;
  205. }
  206. }
  207. frame.style.width = HTMLCSS.Em(W-L-R); frame.style.height = HTMLCSS.Em(H+D-T-B);
  208. HTMLCSS.placeBox(frame,0,dy-D,true);
  209. HTMLCSS.placeBox(base,dx+p+t,0);
  210. this.HTMLhandleSpace(span);
  211. this.HTMLhandleColor(span);
  212. return span;
  213. },
  214. HTMLpx: function (n) {return (n*HTMLCSS.em)},
  215. HTMLpt: function (x,y) {return Math.floor(1000*x)+','+Math.floor(1000*y)},
  216. HTMLhandleColor: function (span) {
  217. var frame = document.getElementById("MathJax-frame-"+this.spanID);
  218. if (frame) {
  219. // mathcolor is handled in toHTML above
  220. var values = this.getValues("mathbackground","background");
  221. if (this.style && span.style.backgroundColor) {
  222. values.mathbackground = span.style.backgroundColor;
  223. span.style.backgroundColor = "";
  224. }
  225. if (values.background && !this.mathbackground) {values.mathbackground = values.background}
  226. if (values.mathbackground && values.mathbackground !== MML.COLOR.TRANSPARENT)
  227. {frame.style.backgroundColor = values.mathbackground}
  228. } else {this.SUPER(arguments).HTMLhandleColor.call(this,span)}
  229. },
  230. HTMLsvg: function (stack,H,D,W,t,color) {
  231. var svg = document.createElementNS(SVGNS,"svg");
  232. if (svg.style) {svg.style.width = HTMLCSS.Em(W); svg.style.height = HTMLCSS.Em(H+D)}
  233. var scale = HTMLCSS.createBox(stack); scale.appendChild(svg);
  234. HTMLCSS.placeBox(scale,0,-D,true);
  235. this.HTMLsvgElement(svg,"g",{fill:"none", stroke:color, "stroke-width":t*HTMLCSS.em});
  236. return svg;
  237. },
  238. HTMLsvgElement: function (svg,type,def) {
  239. var obj = document.createElementNS(SVGNS,type); obj.isMathJax = true;
  240. if (def) {for (var id in def) {if (def.hasOwnProperty(id)) {obj.setAttributeNS(null,id,def[id].toString())}}}
  241. svg.appendChild(obj);
  242. return obj;
  243. },
  244. HTMLvml: function (stack,H,D,W,t,color) {
  245. var vml = HTMLCSS.createFrame(stack,H+D,0,W,0,"none");
  246. HTMLCSS.addBox(stack,vml); HTMLCSS.placeBox(vml,0,-D,true);
  247. this.constructor.VMLcolor = color; this.constructor.VMLthickness = this.HTMLpx(t);
  248. return vml;
  249. },
  250. HTMLvmlElement: function (vml,type,def) {
  251. var obj = HTMLCSS.addElement(vml,vmlns+":"+type,{isMathJax:true});
  252. obj.style.position = "absolute"; obj.style.left = obj.style.top = 0;
  253. MathJax.Hub.Insert(obj,def); // IE8 needs to do this after obj is added to the page
  254. if (!def.fillcolor) {obj.fillcolor = "none"}
  255. if (!def.strokecolor) {obj.strokecolor = this.constructor.VMLcolor}
  256. if (!def.strokeweight) {obj.strokeweight =this.constructor.VMLthickness}
  257. return obj;
  258. }
  259. });
  260. MathJax.Hub.Browser.Select({
  261. MSIE: function (browser) {
  262. //
  263. // IE8 and below doesn't have SVG, so use VML
  264. //
  265. if ((document.documentMode||0) < 9) {
  266. MML.menclose.Augment({HTMLpx: function (n,d) {return (n*HTMLCSS.em+(d||0))+"px"}});
  267. HTMLCSS.useVML = true;
  268. if (!document.namespaces[vmlns]) {
  269. if (document.documentMode && document.documentMode === 8) {
  270. document.namespaces.add(vmlns,VMLNS,"#default#VML");
  271. } else {
  272. document.namespaces.add(vmlns,VMLNS);
  273. document.createStyleSheet().addRule(vmlns+"\\: *","{behavior: url(#default#VML)}");
  274. }
  275. }
  276. }
  277. }
  278. });
  279. MathJax.Hub.Startup.signal.Post("HTML-CSS menclose Ready");
  280. MathJax.Ajax.loadComplete(HTMLCSS.autoloadDir+"/menclose.js");
  281. });