menclose.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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/SVG/autoload/menclose.js
  6. *
  7. * Implements the SVG output for <menclose> elements.
  8. *
  9. * ---------------------------------------------------------------------
  10. *
  11. * Copyright (c) 2011-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("SVG Jax Ready",function () {
  26. var VERSION = "2.2";
  27. var MML = MathJax.ElementJax.mml,
  28. SVG = MathJax.OutputJax.SVG,
  29. BBOX = SVG.BBOX;
  30. BBOX.ELLIPSE = BBOX.Subclass({
  31. type: "ellipse", removeable: false,
  32. Init: function (h,d,w,t,color,def) {
  33. if (def == null) {def = {}}; def.fill = "none";
  34. if (color) {def.stroke = color}
  35. def["stroke-width"] = t.toFixed(2).replace(/\.?0+$/,"");
  36. def.cx = Math.floor(w/2); def.cy = Math.floor((h+d)/2-d);
  37. def.rx = Math.floor((w-t)/2); def.ry = Math.floor((h+d-t)/2);
  38. this.SUPER(arguments).Init.call(this,def);
  39. this.w = this.r = w; this.h = this.H = h;
  40. this.d = this.D = d; this.l = 0;
  41. }
  42. });
  43. BBOX.DLINE = BBOX.Subclass({
  44. type: "line", removeable: false,
  45. Init: function (h,d,w,t,color,updown,def) {
  46. if (def == null) {def = {}}; def.fill = "none";
  47. if (color) {def.stroke = color}
  48. def["stroke-width"] = t.toFixed(2).replace(/\.?0+$/,"");
  49. if (updown == "up") {
  50. def.x1 = Math.floor(t/2); def.y1 = Math.floor(t/2-d);
  51. def.x2 = Math.floor(w-t/2); def.y2 = Math.floor(h-t/2);
  52. } else {
  53. def.x1 = Math.floor(t/2); def.y1 = Math.floor(h-t/2);
  54. def.x2 = Math.floor(w-t/2); def.y2 = Math.floor(t/2-d);
  55. }
  56. this.SUPER(arguments).Init.call(this,def);
  57. this.w = this.r = w; this.h = this.H = h;
  58. this.d = this.D = d; this.l = 0;
  59. }
  60. });
  61. BBOX.FPOLY = BBOX.Subclass({
  62. type: "polygon", removeable: false,
  63. Init: function (points,color,def) {
  64. if (def == null) {def = {}}
  65. if (color) {def.fill = color}
  66. var P = [], mx = 100000000, my = mx, Mx = -mx, My = Mx;
  67. for (var i = 0, m = points.length; i < m; i++) {
  68. var x = points[i][0], y = points[i][1];
  69. if (x > Mx) {Mx = x}; if (x < mx) {mx = x}
  70. if (y > My) {My = y}; if (y < my) {my = y}
  71. P.push(Math.floor(x)+","+Math.floor(y));
  72. }
  73. def.points = P.join(" ");
  74. this.SUPER(arguments).Init.call(this,def);
  75. this.w = this.r = Mx; this.h = this.H = My;
  76. this.d = this.D = -my; this.l = -mx;
  77. }
  78. });
  79. BBOX.PPATH = BBOX.Subclass({
  80. type: "path", removeable: false,
  81. Init: function (h,d,w,p,t,color,def) {
  82. if (def == null) {def = {}}; def.fill = "none";
  83. if (color) {def.stroke = color}
  84. def["stroke-width"] = t.toFixed(2).replace(/\.?0+$/,"");
  85. def.d = p;
  86. this.SUPER(arguments).Init.call(this,def);
  87. this.w = this.r = w; this.h = this.H = h+d;
  88. this.d = this.D = this.l = 0; this.y = -d;
  89. }
  90. });
  91. MML.menclose.Augment({
  92. toSVG: function (HW,DD) {
  93. this.SVGgetStyles();
  94. var svg = this.SVG();
  95. this.SVGhandleSpace(svg);
  96. var base = this.SVGdataStretched(0,HW,DD);
  97. var values = this.getValues("notation","thickness","padding","mathcolor","color");
  98. if (values.color && !this.mathcolor) {values.mathcolor = values.color}
  99. if (values.thickness == null) {values.thickness = ".075em"}
  100. if (values.padding == null) {values.padding = ".2em"}
  101. var mu = this.SVGgetMu(svg), scale = this.SVGgetScale();
  102. var p = SVG.length2em(values.padding,mu,1/SVG.em) * scale; // padding for enclosure
  103. var t = SVG.length2em(values.thickness,mu,1/SVG.em); // thickness of lines (not scaled, see issue #414)
  104. var H = base.h+p+t, D = base.d+p+t, W = base.w+2*(p+t);
  105. var notation = MathJax.Hub.SplitList(values.notation);
  106. var dx = 0, w, h, i, m, borders = [false,false,false,false];
  107. if (!values.mathcolor) {values.mathcolor = "black"}
  108. for (i = 0, m = notation.length; i < m; i++) {
  109. switch (notation[i]) {
  110. case MML.NOTATION.BOX:
  111. borders = [true,true,true,true];
  112. break;
  113. case MML.NOTATION.ROUNDEDBOX:
  114. svg.Add(BBOX.FRAME(H,D,W,t,"solid",values.mathcolor,
  115. {rx:Math.floor(Math.min(H+D-t,W-t)/4)}));
  116. break;
  117. case MML.NOTATION.CIRCLE:
  118. svg.Add(BBOX.ELLIPSE(H,D,W,t,values.mathcolor));
  119. break;
  120. case MML.NOTATION.ACTUARIAL:
  121. borders[0] = true;
  122. case MML.NOTATION.RIGHT:
  123. borders[1] = true;
  124. break;
  125. case MML.NOTATION.LEFT:
  126. borders[3] = true;
  127. break;
  128. case MML.NOTATION.TOP:
  129. borders[0] = true;
  130. break;
  131. case MML.NOTATION.BOTTOM:
  132. borders[2] = true;
  133. break;
  134. case MML.NOTATION.VERTICALSTRIKE:
  135. svg.Add(BBOX.VLINE(H+D,t,"solid",values.mathcolor),(W-t)/2,-D);
  136. break;
  137. case MML.NOTATION.HORIZONTALSTRIKE:
  138. svg.Add(BBOX.HLINE(W,t,"solid",values.mathcolor),0,(H+D-t)/2-D);
  139. break;
  140. case MML.NOTATION.UPDIAGONALSTRIKE:
  141. if (this.arrow) {
  142. var l = Math.sqrt(W*W + (H+D)*(H+D)), f = 1/l * 10/SVG.em * t/.075;
  143. w = W * f; h = (H+D) * f; var x = .4*h;
  144. svg.Add(BBOX.DLINE(H-.5*h,D,W-.5*w,t,values.mathcolor,"up"));
  145. svg.Add(BBOX.FPOLY(
  146. [[x+w,h], [x-.4*h,.4*w], [x+.3*w,.3*h], [x+.4*h,-.4*w], [x+w,h]],
  147. values.mathcolor),W-w-x,H-h);
  148. } else {
  149. svg.Add(BBOX.DLINE(H,D,W,t,values.mathcolor,"up"));
  150. }
  151. break;
  152. case MML.NOTATION.DOWNDIAGONALSTRIKE:
  153. svg.Add(BBOX.DLINE(H,D,W,t,values.mathcolor,"down"));
  154. break;
  155. case MML.NOTATION.MADRUWB:
  156. borders[1] = borders[2] = true;
  157. break;
  158. case MML.NOTATION.RADICAL:
  159. svg.Add(BBOX.PPATH(H,D,W,
  160. "M "+this.SVGxy(t/2,.4*(H+D)) +
  161. " L "+this.SVGxy(p,t/2) +
  162. " L "+this.SVGxy(2*p,H+D-t/2) +
  163. " L "+this.SVGxy(W,H+D-t/2),
  164. t,values.mathcolor),0,t);
  165. dx = p;
  166. break;
  167. case MML.NOTATION.LONGDIV:
  168. svg.Add(BBOX.PPATH(H,D,W,
  169. "M "+this.SVGxy(t/2,t/2) +
  170. " a "+this.SVGxy(p,(H+D)/2-2*t) + " 0 0,1 " + this.SVGxy(t/2,H+D-t) +
  171. " L "+this.SVGxy(W,H+D-t/2),
  172. t,values.mathcolor),0,t/2);
  173. dx = p;
  174. break;
  175. }
  176. }
  177. var sides = [["H",W,0,H-t],["V",H+D,W-t,-D],["H",W,0,-D],["V",H+D,0,-D]];
  178. for (i = 0; i < 4; i++) {
  179. if (borders[i]) {
  180. var side = sides[i];
  181. svg.Add(BBOX[side[0]+"LINE"](side[1],t,"solid",values.mathcolor),side[2],side[3]);
  182. }
  183. }
  184. svg.Add(base,dx+p+t,0,false,true);
  185. svg.Clean();
  186. this.SVGhandleSpace(svg);
  187. this.SVGhandleColor(svg);
  188. this.SVGsaveData(svg);
  189. return svg;
  190. },
  191. SVGxy: function (x,y) {return Math.floor(x)+","+Math.floor(y)}
  192. });
  193. MathJax.Hub.Startup.signal.Post("SVG menclose Ready");
  194. MathJax.Ajax.loadComplete(SVG.autoloadDir+"/menclose.js");
  195. });