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