Annotation of loncom/html/adm/jsMath/uncompressed/jsMath.js, revision 1.3
1.1 albertel 1: /*****************************************************************************
2: *
3: * jsMath: Mathematics on the Web
4: *
5: * This jsMath package makes it possible to display mathematics in HTML pages
6: * that are viewable by a wide range of browsers on both the Mac and the IBM PC,
7: * including browsers that don't process MathML. See
8: *
9: * http://www.math.union.edu/locate/jsMath
10: *
11: * for the latest version, and for documentation on how to use jsMath.
12: *
1.3 ! albertel 13: * Copyright 2004-2007 by Davide P. Cervone
1.1 albertel 14: *
15: * Licensed under the Apache License, Version 2.0 (the "License");
16: * you may not use this file except in compliance with the License.
17: * You may obtain a copy of the License at
18: *
19: * http://www.apache.org/licenses/LICENSE-2.0
20: *
21: * Unless required by applicable law or agreed to in writing, software
22: * distributed under the License is distributed on an "AS IS" BASIS,
23: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24: * See the License for the specific language governing permissions and
25: * limitations under the License.
26: *
27: *****************************************************************************/
28:
29: /*
30: * Prevent running everything again if this file is loaded twice
31: */
32: if (!window.jsMath || !window.jsMath.loaded) {
33:
34: var jsMath_old = window.jsMath; // save user customizations
35:
36: //
37: // debugging routine
38: //
39: /*
40: * function ShowObject (obj,spaces) {
41: * var s = ''; if (!spaces) {spaces = ""}
42: * for (var i in obj) {
43: * if (obj[i] != null) {
44: * if (typeof(obj[i]) == "object") {
45: * s += spaces + i + ": {\n"
46: * + ShowObject(obj[i],spaces + ' ')
47: * + spaces + "}\n";
48: * } else if (typeof(obj[i]) != "function") {
49: * s += spaces + i + ': ' + obj[i] + "\n";
50: * }
51: * }
52: * }
53: * return s;
54: * }
55: */
56:
57: /***************************************************************************/
58: //
59: // Check for DOM support
60: //
61: if (!document.getElementById || !document.childNodes || !document.createElement) {
62: alert('The mathematics on this page requires W3C DOM support in its JavaScript. '
63: + 'Unfortunately, your browser doesn\'t seem to have this.');
64: } else {
65:
66: /***************************************************************************/
67:
1.2 albertel 68: window.jsMath = {
1.1 albertel 69:
1.3 ! albertel 70: version: "3.4e", // change this if you edit the file, but don't edit this file
1.1 albertel 71:
72: document: document, // the document loading jsMath
73: window: window, // the window of the of loading document
74:
1.3 ! albertel 75: platform: (navigator.platform.match(/Mac/) ? "mac" :
! 76: navigator.platform.match(/Win/) ? "pc" : "unix"),
! 77:
1.1 albertel 78: // Font sizes for \tiny, \small, etc. (must match styles below)
79: sizes: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249],
80:
81: //
82: // The styles needed for the TeX fonts
83: //
84: styles: {
1.3 ! albertel 85: '.math': 'font-family:serif; font-style:normal; font-weight:normal',
1.1 albertel 86:
1.3 ! albertel 87: '.typeset': 'font-family:serif; font-style:normal; font-weight:normal; line-height:normal',
! 88: 'div.typeset': 'text-align:center; margin:1em 0px;',
! 89: 'span.typeset': 'text-align:left',
! 90: '.typeset span': 'text-align:left; border:0px; margin:0px; padding:0px',
! 91:
! 92: '.typeset .normal': 'font-family:serif; font-style:normal; font-weight:normal',
! 93:
! 94: '.typeset .size0': 'font-size:50%', // tiny (\scriptscriptsize)
! 95: '.typeset .size1': 'font-size:60%', // (50% of \large for consistency)
! 96: '.typeset .size2': 'font-size:70%', // scriptsize
! 97: '.typeset .size3': 'font-size:85%', // small (70% of \large for consistency)
! 98: '.typeset .size4': 'font-size:100%', // normalsize
! 99: '.typeset .size5': 'font-size:120%', // large
! 100: '.typeset .size6': 'font-size:144%', // Large
! 101: '.typeset .size7': 'font-size:173%', // LARGE
! 102: '.typeset .size8': 'font-size:207%', // huge
! 103: '.typeset .size9': 'font-size:249%', // Huge
! 104:
! 105: '.typeset .cmr10': 'font-family:jsMath-cmr10, serif',
! 106: '.typeset .cmbx10': 'font-family:jsMath-cmbx10, jsMath-cmr10',
! 107: '.typeset .cmti10': 'font-family:jsMath-cmti10, jsMath-cmr10',
! 108: '.typeset .cmmi10': 'font-family:jsMath-cmmi10',
! 109: '.typeset .cmsy10': 'font-family:jsMath-cmsy10',
! 110: '.typeset .cmex10': 'font-family:jsMath-cmex10',
! 111:
! 112: '.typeset .textit': 'font-family:serif; font-style:italic',
! 113: '.typeset .textbf': 'font-family:serif; font-weight:bold',
! 114:
! 115: '.typeset .link': 'text-decoration:none',
! 116: '.typeset .error': 'font-size:10pt; font-style:italic; '
! 117: + 'background-color:#FFFFCC; padding:1px; '
! 118: + 'border:1px solid #CC0000',
1.1 albertel 119:
120: '.typeset .blank': 'display:inline-block; overflow:hidden; border:0px none; width:0px; height:0px;',
121: '.typeset .spacer': 'display:inline-block',
1.3 ! albertel 122:
! 123: '#jsMath_hiddenSpan': 'visibility:hidden; position:absolute; top:0px;left:0px; '
! 124: + 'line-height:normal; text-indent:0px',
1.1 albertel 125:
1.2 albertel 126: '#jsMath_message': 'position:fixed; bottom:1px; left:2px; background-color:#E6E6E6; '
1.3 ! albertel 127: + 'border:solid 1px #959595; margin:0px; padding:1px 8px; '
1.2 albertel 128: + 'z-index:102; color: black; font-size:small; width:auto;',
1.3 ! albertel 129: '#jsMath_panel': 'position:fixed; bottom:1.5em; right:1.5em; padding:.8em 1.6em; '
! 130: + 'background-color:#DDDDDD; border:outset 2px; '
! 131: + 'z-index:103; width:auto; color:black; font-size:10pt; font-style:normal',
1.2 albertel 132: '#jsMath_panel .disabled': 'color:#888888',
133: '#jsMath_panel .infoLink': 'font-size:85%',
1.3 ! albertel 134: '#jsMath_panel *': 'font-size:inherit; font-style:inherit; font-family:inherit; line-height:normal',
! 135: '#jsMath_panel div': 'background-color:inherit; color:inherit;',
! 136: '#jsMath_panel span': 'background-color:inherit; color:inherit;',
! 137: '#jsMath_panel td': 'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;',
! 138: '#jsMath_panel tr': 'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;',
! 139: '#jsMath_panel table': 'border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;',
! 140:
1.2 albertel 141: '#jsMath_button': 'position:fixed; bottom:1px; right:2px; background-color:white; '
1.3 ! albertel 142: + 'border:solid 1px #959595; margin:0px; padding:0px 3px 1px 3px; '
1.2 albertel 143: + 'z-index:102; color:black; text-decoration:none; font-size:x-small; '
144: + 'width:auto; cursor:hand;',
1.3 ! albertel 145: '#jsMath_button *': 'padding:0px; border:0px; margin:0px; line-height:normal; '
! 146: + 'font-size:inherit; font-style:inherit; font-family:inherit',
! 147:
1.2 albertel 148: '#jsMath_global': 'font-style:italic;',
149: '#jsMath_float': 'position:absolute; top:0px; left:0px; max-width:80%; '
150: + 'z-index:101; width:auto; height:auto;',
1.3 ! albertel 151: '#jsMath_float .drag': 'background-color:#DDDDDD; border:outset 1px; height:12px; font-size:1px;',
! 152: '#jsMath_float .close': 'background-color:#E6E6E6; border:inset 1px; width:8px; height:8px; margin:1px 2px;',
! 153: '#jsMath_float .source': 'background-color:#E2E2E2; border:outset 1px; '
! 154: + 'width:auto; height:auto; padding:8px 15px; '
! 155: + 'font-family:courier, fixed; font-size:90%',
! 156:
! 157: '#jsMath_noFont .message': 'text-align: center; padding:.8em 1.6em; border:3px solid #DD0000; '
! 158: + 'background-color:#FFF8F8; color: #AA0000; font-size:small; width:auto;',
! 159: '#jsMath_noFont .link': 'padding:0px 5px 2px 5px; border:2px outset; background-color:#E8E8E8; '
1.2 albertel 160: + 'color:black; font-size:80%; width:auto; cursor:hand;',
161:
162: '#jsMath_PrintWarning .message':
1.3 ! albertel 163: 'text-align:center; padding:.8em 1.6em; border:3px solid #DD0000; '
1.2 albertel 164: + 'background-color: #FFF8F8; color: #AA0000; font-size:x-small; width:auto;',
165:
166: '@media print': '#jsMath_button {display:none}\n' +
167: '#jsMath_Warning {display:none}',
168:
169: '@media screen': '#jsMath_PrintWarning {display:none}'
1.1 albertel 170:
171: },
172:
173:
174: /***************************************************************************/
175:
176: /*
177: * Get a jsMath DOM element
178: */
179: Element: function (name) {return jsMath.document.getElementById('jsMath_'+name)},
180:
181: /*
182: * Get the width and height (in pixels) of an HTML string
183: */
184: BBoxFor: function (s) {
185: this.hidden.innerHTML =
186: '<nobr><span class="typeset"><span class="scale">'+s+'</span></span></nobr>';
187: var bbox = {w: this.hidden.offsetWidth, h: this.hidden.offsetHeight};
188: this.hidden.innerHTML = '';
189: return bbox;
190: },
191:
192: /*
1.2 albertel 193: * Get the width and height (in ems) of an HTML string.
194: * Check the cache first to see if we've already measured it.
1.1 albertel 195: */
196: EmBoxFor: function (s) {
1.2 albertel 197: var cache = jsMath.Global.cache.R;
198: if (!cache[this.em]) {cache[this.em] = {}}
199: if (!cache[this.em][s]) {
200: var bbox = this.BBoxFor(s);
201: cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em};
202: }
203: return cache[this.em][s];
1.1 albertel 204: },
205:
206: /*
1.2 albertel 207: * For browsers that don't handle sizes of italics properly (MSIE).
208: * Check the cache first to see if we've already measured it.
1.1 albertel 209: */
210: EmBoxForItalics: function (s) {
1.2 albertel 211: var cache = jsMath.Global.cache.R;
212: if (!cache[this.em]) {cache[this.em] = {}}
213: if (!cache[this.em][s]) {
214: var bbox = this.BBoxFor(s);
215: if (s.match(/<i>|class=\"(icm|italic|igreek|iaccent)/i)) {
1.3 ! albertel 216: bbox.w = bbox.Mw = this.BBoxFor(s+jsMath.Browser.italicString).w
! 217: - jsMath.Browser.italicCorrection;
1.2 albertel 218: }
219: cache[this.em][s] = {w: bbox.w/this.em, h: bbox.h/this.em};
1.1 albertel 220: }
1.2 albertel 221: return cache[this.em][s];
1.1 albertel 222: },
223:
224: /*
225: * Initialize jsMath. This determines the em size, and a variety
226: * of other parameters used throughout jsMath.
227: */
228: Init: function () {
229: if (jsMath.Setup.inited != 1) {
1.2 albertel 230: if (!jsMath.Setup.inited) {jsMath.Setup.Body()}
231: if (jsMath.Setup.inited != 1) {
1.3 ! albertel 232: if (jsMath.Setup.inited == -100) return;
1.1 albertel 233: alert("It looks like jsMath failed to set up properly (error code "
234: + jsMath.Setup.inited + "). "
1.2 albertel 235: + "I will try to keep going, but it could get ugly.");
1.1 albertel 236: jsMath.Setup.inited = 1;
237: }
238: }
1.2 albertel 239: this.em = this.BBoxFor('<span style="'+jsMath.Browser.block+';width:13em;height:1em"></span>').w/13;
1.1 albertel 240: if (this.em == 0) {
241: // handle older browsers
1.2 albertel 242: this.em = this.BBoxFor('<img src="'+jsMath.blank+'" style="width:13em;height:1em"/>').w/13;
1.1 albertel 243: }
1.2 albertel 244: var cache = jsMath.Global.cache.B;
245: if (!cache[this.em]) {
246: cache[this.em] = {};
247: cache[this.em].bb = this.BBoxFor('x'); var hh = cache[this.em].bb.h;
248: cache[this.em].d = this.BBoxFor('x'+jsMath.HTML.Rule(1,hh/jsMath.em)).h - hh;
249: if (jsMath.Browser.italicString)
250: {cache[this.em].ic = jsMath.BBoxFor(jsMath.Browser.italicString).w}
251: }
252: jsMath.Browser.italicCorrection = cache[this.em].ic;
253: var bb = cache[this.em].bb; var h = bb.h; var d = cache[this.em].d
1.1 albertel 254: this.h = (h-d)/this.em; this.d = d/this.em;
255: this.hd = this.h + this.d;
256: this.xWidth = bb.w; // used to tell if scale has changed
257:
258: this.Setup.TeXfonts();
259:
260: var x_height = this.EmBoxFor('<span class="cmr10">M</span>').w/2;
261: this.TeX.M_height = x_height*(26/14);
262: this.TeX.h = this.h; this.TeX.d = this.d; this.TeX.hd = this.hd;
263:
264: this.Img.Scale();
265: if (!this.initialized) {
266: this.Setup.Sizes();
267: this.Img.UpdateFonts();
268: }
269:
270: // factor for \big and its brethren
271: this.p_height = (this.TeX.cmex10[0].h + this.TeX.cmex10[0].d) / .85;
272:
273: this.initialized = 1;
274: },
275:
276: /*
277: * Get the xWidth size and if it has changed, reinitialize the sizes
278: */
279: ReInit: function () {
280: var w = this.BBoxFor('x').w;
281: if (w != this.xWidth) {this.Init()}
282: },
283:
284: /*
285: * Mark jsMath as loaded and copy any user-provided overrides
286: */
287: Loaded: function () {
288: if (jsMath_old) {
289: var override = ['Process', 'ProcessBeforeShowing',
290: 'ConvertTeX','ConvertTeX2','ConvertLaTeX','ConvertCustom',
291: 'CustomSearch', 'Synchronize', 'Macro', 'document'];
292: for (var i = 0; i < override.length; i++) {
1.2 albertel 293: if (jsMath_old[override[i]]) {delete jsMath_old[override[i]]}
1.1 albertel 294: }
295: }
296: if (jsMath_old) {this.Insert(jsMath,jsMath_old)}
297: jsMath_old = null;
298: jsMath.loaded = 1;
299: },
300:
301: /*
302: * Manage JavaScript objects:
303: *
304: * Add: add/replace items in an object
305: * Insert: add items to an object
306: * Package: add items to an object prototype
307: */
308: Add: function (dst,src) {for (var id in src) {dst[id] = src[id]}},
309: Insert: function (dst,src) {
310: for (var id in src) {
311: if (dst[id] && typeof(src[id]) == 'object'
312: && (typeof(dst[id]) == 'object'
313: || typeof(dst[id]) == 'function')) {
314: this.Insert(dst[id],src[id]);
315: } else {
316: dst[id] = src[id];
317: }
318: }
319: },
320: Package: function (obj,def) {this.Insert(obj.prototype,def)}
321:
1.2 albertel 322: };
323:
324:
325: /***************************************************************************/
326:
327: /*
328: * Implements items associated with the global cache.
329: *
330: * This object will be replaced by a global version when
331: * (and if) jsMath-global.html is loaded.
332: */
333: jsMath.Global = {
334: isLocal: 1, // a local copy if jsMath-global.html hasn't been loaded
335: cache: {T: {}, D: {}, R: {}, B: {}},
336:
337: /*
338: * Clear the global (or local) cache
339: */
340: ClearCache: function () {jsMath.Global.cache = {T: {}, D: {}, R: {}, B: {}}},
341:
342: /*
343: * Initiate global mode
344: */
345: GoGlobal: function (cookie) {
346: var url = String(jsMath.window.location);
1.3 ! albertel 347: var c = (jsMath.isCHMmode ? '#' : '?');
1.2 albertel 348: if (cookie) {url = url.replace(/\?.*/,'') + '?' + cookie}
349: jsMath.Controls.Reload(jsMath.root + "jsMath-global.html" + c +escape(url));
350: },
351:
352: /*
353: * Check if we need to go to global mode
354: */
355: Init: function () {
356: if (jsMath.Controls.cookie.global == "always" && !jsMath.noGoGlobal) {
1.3 ! albertel 357: if (navigator.accentColorName) return; // OmniWeb crashes on GoGlobal
1.2 albertel 358: if (!jsMath.window) {jsMath.window = window}
359: jsMath.Controls.loaded = 1;
360: jsMath.Controls.defaults.hiddenGlobal = null;
361: this.GoGlobal(jsMath.Controls.SetCookie(2));
362: }
363: },
364:
365: /*
366: * Try to register with a global.html window that contains us
367: */
368: Register: function () {
1.3 ! albertel 369: var parent = jsMath.window.parent;
! 370: if (!jsMath.isCHMode)
! 371: {jsMath.isCHMmode = (jsMath.window.location.protocol == 'mk:')}
1.2 albertel 372: try {
1.3 ! albertel 373: if (!jsMath.isCHMmode) this.Domain();
! 374: if (parent.jsMath && parent.jsMath.isGlobal)
1.2 albertel 375: {parent.jsMath.Register(jsMath.window)}
1.3 ! albertel 376: } catch (err) {jsMath.noGoGlobal = 1}
1.2 albertel 377: },
378:
379: /*
380: * If we're not the parent window, try to set the domain to
381: * match the parent's domain (so we can use the Global data
382: * if the surrounding frame is a Global frame.
383: */
384: Domain: function () {
385: // MSIE/Mac can't do domain changes, so don't bother trying
386: if (navigator.appName == 'Microsoft Internet Explorer' &&
1.3 ! albertel 387: jsMath.platform == 'mac' && navigator.userProfile != null) return;
1.2 albertel 388: if (window == parent) return;
389: var oldDomain = jsMath.document.domain;
390: try {
391: while (true) {
392: try {if (parent.document.title != null) return} catch (err) {}
1.3 ! albertel 393: if (!document.domain.match(/\..*\./)) break;
1.2 albertel 394: jsMath.document.domain = jsMath.document.domain.replace(/^[^.]*\./,'');
395: }
396: } catch (err) {}
397: jsMath.document.domain = oldDomain;
398: }
399:
400: };
401:
402:
1.1 albertel 403:
404: /***************************************************************************/
405:
406: /*
407: *
408: * Implement loading of remote scripts using XMLHttpRequest, if
409: * possible, otherwise use a hidden IFRAME and fake it. That
410: * method runs asynchronously, which causes lots of headaches.
411: * Solve these using Push command, which queues actions
412: * until files have loaded.
413: */
414:
415: jsMath.Script = {
416:
417: request: null, // the XMLHttpRequest object
418:
419: /*
420: * Create the XMLHttpRequest object, if we can.
421: * Otherwise, use the iframe-based fallback method.
422: */
423: Init: function () {
424: if (!(jsMath.Controls.cookie.asynch && jsMath.Controls.cookie.progress)) {
1.3 ! albertel 425: if (window.XMLHttpRequest &&
! 426: // MSIE can't use xmlRequest on local files, but we don't have
! 427: // jsMath.browser yet to tell, so use this check
! 428: !(jsMath.document.URL && jsMath.document.URL.match(/^file:\/\/.*\\/))) {
! 429: try {this.request = new XMLHttpRequest} catch (err) {}
! 430: }
! 431: if (!this.request && window.ActiveXObject) {
! 432: var xml = ["MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0",
! 433: "MSXML2.XMLHTTP","Microsoft.XMLHTTP"];
! 434: for (var i = 0; i < xml.length && !this.request; i++) {
! 435: try {this.request = new ActiveXObject(xml[i])} catch (err) {}
! 436: }
1.1 albertel 437: }
438: }
439: //
440: // Use the delayed-script fallback for MSIE/Mac and old versions
441: // of several browsers (Opera 7.5, OmniWeb 4.5).
442: //
443: if (!this.request || jsMath.Setup.domainChanged)
444: {this.Load = this.delayedLoad; this.needsBody = 1}
445: },
446:
447: /*
448: * Load a script and evaluate it in the window's context
449: */
450: Load: function (url,show) {
451: if (show) {
452: jsMath.Message.Set("Loading "+url);
453: jsMath.Script.Delay(1);
454: jsMath.Script.Push(this,'xmlRequest',url);
455: jsMath.Script.Push(jsMath.Message,'Clear');
456: } else {
457: jsMath.Script.Push(this,'xmlRequest',url);
458: }
459: },
460:
461: /*
462: * Load a URL and run the contents of the file
463: */
464: xmlRequest: function (url) {
1.2 albertel 465: this.blocking = 1;
466: // this.debug('xmlRequest: '+url);
1.1 albertel 467: try {
468: this.request.open("GET",url,false);
469: this.request.send(null);
470: } catch (err) {
1.3 ! albertel 471: this.blocking = 0;
! 472: if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""}
1.1 albertel 473: throw "jsMath can't load the file '"+url+"'\n"
474: + "Message: "+err.message;
475: }
476: if (this.request.status && this.request.status >= 400) {
477: // Do we need to deal with redirected links?
1.3 ! albertel 478: this.blocking = 0;
! 479: if (jsMath.Translate.restart && jsMath.Translate.asynchronous) {return ""}
1.1 albertel 480: throw "jsMath can't load the file '"+url+"'\n"
481: + "Error status: "+this.request.status;
482: }
1.3 ! albertel 483: if (!url.match(/\.js$/)) {return(this.request.responseText)}
1.2 albertel 484: var tmpQueue = this.queue; this.queue = [];
485: // this.debug('xml Eval ['+tmpQueue.length+']');
1.1 albertel 486: jsMath.window.eval(this.request.responseText);
1.2 albertel 487: // this.debug('xml Done ['+this.queue.length+' + '+tmpQueue.length+']');
488: this.blocking = 0; this.queue = this.queue.concat(tmpQueue);
1.1 albertel 489: this.Process();
1.3 ! albertel 490: return "";
1.1 albertel 491: },
492:
493: /********************************************************************
494: *
495: * Implement asynchronous loading and execution of scripts
496: * (via hidden IFRAME) interleved with other JavaScript commands
497: * that must be synchronized with the file loading. (Basically, this
498: * is for MSIE/Mac and Opera 7.5, which don't have XMLHttpRequest.)
499: */
500:
501: cancelTimeout: 30*1000, // delay for canceling load (30 sec)
502:
503: iframe: null, // the hidden iframe
504: blocking: 0, // true when an asynchronous action is being performed
505: cancelTimer: null, // timer to cancel load if it takes too long
506: needsBody: 0, // true if loading files requires BODY to be present
507:
508: queue: [], // the stack of pending actions
509:
510: /*
511: * Provide mechanism for synchronizing with the asynchronous jsMath
512: * file-loading mechanism. 'code' can be a string or a function.
513: */
514: Synchronize: function (code,data) {
515: if (typeof(code) != 'string') {jsMath.Script.Push(null,code,data)}
516: else {jsMath.Script.Push(jsMath.window,'eval',code)}
517: },
518:
519: /*
520: * Queue a function to be processed.
521: * If nothing is being loaded, do the pending commands.
522: */
523: Push: function (object,method,data) {
1.3 ! albertel 524: // this.debug('Pushing: '+method+' at '+this.queue.length); // debug
1.2 albertel 525: this.queue[this.queue.length] = [object,method,data];
1.1 albertel 526: if (!(this.blocking || (this.needsBody && !jsMath.document.body))) this.Process();
527: },
528:
529: /*
530: * Do any pending functions (stopping if a file load is started)
531: */
532: Process: function () {
533: while (this.queue.length && !this.blocking) {
1.3 ! albertel 534: var call = this.queue[0]; this.queue = this.queue.slice(1);
! 535: var savedQueue = this.SaveQueue();
1.1 albertel 536: var object = call[0]; var method = call[1]; var data = call[2];
1.3 ! albertel 537: // this.debug('Calling: '+method+' ['+savedQueue.length+']'); // debug
1.1 albertel 538: if (object) {object[method](data)} else if (method) {method(data)}
1.3 ! albertel 539: // this.debug('Done: '+method+' ['+this.queue.length+' + '+savedQueue.length+'] ('+this.blocking+')'); // debug
! 540: this.RestoreQueue(savedQueue);
1.1 albertel 541: }
542: },
543:
544: /*
1.3 ! albertel 545: * Allows pushes to occur at the FRONT of the queue
! 546: * (so a command acts as a single unit, including anything
! 547: * that it pushes on to the command stack)
! 548: */
! 549: SaveQueue: function () {
! 550: var queue = this.queue;
! 551: this.queue = [];
! 552: return queue;
! 553: },
! 554: RestoreQueue: function (queue) {
! 555: this.queue = this.queue.concat(queue);
! 556: },
! 557:
! 558: /*
1.1 albertel 559: * Handle loading of scripts that run asynchronously
560: */
561: delayedLoad: function (url) {
1.2 albertel 562: // this.debug('Loading: '+url);
1.1 albertel 563: this.Push(this,'startLoad',url);
564: },
565: startLoad: function (url) {
566: this.iframe = jsMath.document.createElement('iframe');
567: this.iframe.style.visibility = 'hidden';
568: this.iframe.style.position = 'absolute';
569: this.iframe.style.width = '0px';
570: this.iframe.style.height = '0px';
571: if (jsMath.document.body.firstChild) {
572: jsMath.document.body.insertBefore(this.iframe,jsMath.document.body.firstChild);
573: } else {
574: jsMath.document.body.appendChild(this.iframe);
575: }
576: this.blocking = 1; this.url = url;
577: if (!url.match(/\.js$/)) {this.iframe.src = url}
578: else {this.iframe.src = jsMath.root+"jsMath-loader.html"}
579: if (url.substr(0,jsMath.root.length) == jsMath.root)
580: {url = url.substr(jsMath.root.length)}
581: jsMath.Message.Set("Loading "+url);
582: this.cancelTimer = setTimeout('jsMath.Script.cancelLoad()',this.cancelTimeout);
583: },
584: endLoad: function (action) {
585: if (this.cancelTimer) {clearTimeout(this.cancelTimer); this.cancelTimer = null;}
586: jsMath.Message.Clear();
587: if (action != 'cancel') {this.blocking = 0; this.Process()}
588: },
1.2 albertel 589:
590: Start: function () {
591: // this.debug('Starting: ['+this.queue.length+'] '+this.url);
592: this.tmpQueue = this.queue; this.queue = [];
593: },
594: End: function () {
595: // this.debug('Ending: ['+this.queue.length+' + '+this.tmpQueue.length+'] '+this.url);
596: this.queue = this.queue.concat(this.tmpQueue); delete this.tmpQueue;
597: },
1.1 albertel 598:
599: /*
600: * If the loading takes too long, cancel it and end the load.
601: */
602: cancelLoad: function () {
603: this.cancelTimer = null;
604: jsMath.Message.Set("Can't load file");
605: this.endLoad("cancel");
606: },
607:
608: /*
609: * Perform a delay (to let the browser catch up)
610: */
611: Delay: function (time) {
612: this.blocking = 1;
613: setTimeout('jsMath.Script.endDelay()',time);
614: },
1.2 albertel 615: endDelay: function () {
616: // this.debug('endDelay');
617: this.blocking = 0;
618: this.Process();
619: },
1.1 albertel 620:
621: /*
622: * Load an image and wait for it
623: * (so MSIE won't load extra copies of it)
624: */
1.2 albertel 625: imageCount: 0,
1.1 albertel 626: WaitForImage: function (file) {
1.2 albertel 627: this.blocking = 1; this.imageCount++;
628: if (this.img == null) {this.img = []}
1.1 albertel 629: var img = new Image(); this.img[this.img.length] = img;
1.2 albertel 630: img.onload = function () {if (--jsMath.Script.imageCount == 0) jsMath.Script.endDelay()}
1.1 albertel 631: img.onerror = img.onload; img.onabort = img.onload;
632: img.src = file;
633: },
634:
635: /*
636: * The code uncompressor
637: */
638: Uncompress: function (data) {
639: for (var k = 0; k < data.length; k++) {
640: var d = data[k]; var n = d.length;
641: for (var i = 0; i < n; i++) {if (typeof(d[i]) == 'number') {d[i] = d[d[i]]}}
642: data[k] = d.join('');
643: }
644: window.eval(data.join(''));
1.3 ! albertel 645: }
1.1 albertel 646:
647: /*
648: * for debugging the event queue
649: */
1.3 ! albertel 650: /*
! 651: * ,debug: function (message) {
! 652: * if (jsMath.document.body && jsMath.window.debug) {jsMath.window.debug(message)}
! 653: * else {alert(message)}
! 654: * }
! 655: */
1.1 albertel 656:
657: };
658:
659: /***************************************************************************/
660:
661: /*
662: * Message and screen blanking facility
663: */
664:
665: jsMath.Message = {
666:
667: blank: null, // the div to blank out the screen
668: message: null, // the div for the messages
669: text: null, // the text node for messages
670: clear: null, // timer for clearing message
671:
672: /*
673: * Create the elements needed for the message box
674: */
675: Init: function () {
676: if (!jsMath.document.body || !jsMath.Controls.cookie.progress) return;
677: if (jsMath.Setup.stylesReady) {
678: this.message = jsMath.Setup.DIV('message',{visibility:'hidden'});
679: } else {
680: this.message = jsMath.Setup.DIV('message',{
681: visibility:'hidden', position:'absolute', bottom:'1px', left:'2px',
682: backgroundColor:'#E6E6E6', border:'solid 1px #959595',
683: margin:'0px', padding:'1px 8px', zIndex:102,
684: color:'black', fontSize:'small', width:'auto'
685: });
686: }
687: this.text = jsMath.document.createTextNode('');
688: this.message.appendChild(this.text);
689: this.message.onmousedown = jsMath.Translate.Cancel;
690: },
691:
692: /*
693: * Set the contents of the message box, or use the window status line
694: */
695: Set: function (text,canCancel) {
696: if (this.clear) {clearTimeout(this.clear); this.clear = null}
697: if (jsMath.Controls.cookie.progress) {
698: if (!this.text) {this.Init(); if (!this.text) return}
699: if (jsMath.Browser.textNodeBug) {this.message.innerHTML = text}
700: else {this.text.nodeValue = text}
701: this.message.style.visibility = 'visible';
702: if (canCancel) {
703: this.message.style.cursor = 'pointer';
704: if (!this.message.style.cursor) {this.message.style.cursor = 'hand'}
705: this.message.title = ' Cancel Processing of Math ';
706: } else {
1.2 albertel 707: this.message.style.cursor = '';
1.1 albertel 708: this.message.title = '';
709: }
710: } else {
711: if (text.substr(0,8) != "Loading ") {jsMath.window.status = text}
712: }
713: },
714:
715: /*
716: * Clear the message box or status line
717: */
718: Clear: function () {
719: if (this.clear) {clearTimeout(this.clear)}
720: this.clear = setTimeout("jsMath.Message.doClear()",1000);
721: },
722: doClear: function () {
723: if (this.clear) {
724: this.clear = null;
725: jsMath.window.status = '';
726: if (this.text) {this.text.nodeValue = ''}
727: if (this.message) {this.message.style.visibility = 'hidden'}
728: }
729: },
730:
731:
732: /*
733: * Put up a DIV that covers the window so that the
734: * "flicker" of processing the mathematics will not be visible
735: */
736: Blank: function () {
737: if (this.blank || !jsMath.document.body) return;
738: this.blank = jsMath.Setup.DIV("blank",{
739: position:(jsMath.Browser.msiePositionFixedBug? 'absolute': 'fixed'),
740: top:'0px', left:'0px', bottom:'0px', right:'0px',
741: zIndex:101, backgroundColor:'white'
742: });
743: if (jsMath.Browser.msieBlankBug) {
744: this.blank.innerHTML = ' ';
745: this.blank.style.width = "110%";
746: this.blank.style.height = "110%";
747: }
748: },
749:
750: UnBlank: function () {
751: if (this.blank) {jsMath.document.body.removeChild(this.blank)}
752: this.blank = null;
753: }
754: };
755:
756:
757: /***************************************************************************/
758:
759: /*
760: * Miscellaneous setup and initialization
761: */
762: jsMath.Setup = {
763:
764: loaded: [], // array of files already loaded
765:
766: /*
767: * Insert a DIV at the top of the page with given ID,
768: * attributes, and style settings
769: */
770: DIV: function (id,styles) {
771: var div = jsMath.document.createElement('div');
772: div.id = 'jsMath_'+id;
773: for (var i in styles) {div.style[i]= styles[i]}
774: if (!jsMath.document.body.hasChildNodes) {jsMath.document.body.appendChild(div)}
775: else {jsMath.document.body.insertBefore(div,jsMath.document.body.firstChild)}
776: return div;
777: },
778:
779: /*
780: * Source a jsMath JavaScript file (only load any given file once)
781: */
782: Script: function (file,show) {
783: if (this.loaded[file]) {return} else {this.loaded[file] = 1}
1.2 albertel 784: if (!file.match('^([a-zA-Z]+:/?)?/')) {file = jsMath.root + file}
1.1 albertel 785: jsMath.Script.Load(file,show);
786: },
787:
788: /*
789: * Use a hidden <DIV> for measuring the BBoxes of things
790: */
791: Hidden: function () {
792: jsMath.hidden = this.DIV("Hidden",{
793: visibility: 'hidden', position:"absolute",
794: top:0, left:0, border:0, padding:0, margin:0
795: });
796: jsMath.hiddenTop = jsMath.hidden;
797: return;
798: },
799:
800: /*
801: * Find the root URL for the jsMath files (so we can load
802: * the other .js and .gif files)
803: */
804: Source: function () {
805: if (jsMath.Autoload && jsMath.Autoload.root) {
806: jsMath.root = jsMath.Autoload.root;
807: } else {
808: jsMath.root = '';
809: var script = jsMath.document.getElementsByTagName('script');
810: if (script) {
811: for (var i = 0; i < script.length; i++) {
812: var src = script[i].src;
1.3 ! albertel 813: if (src && src.match('(^|/|\\\\)jsMath.js$')) {
1.1 albertel 814: jsMath.root = src.replace(/jsMath.js$/,'');
1.3 ! albertel 815: break;
1.1 albertel 816: }
817: }
818: }
819: }
1.3 ! albertel 820: if (jsMath.root.charAt(0) == '\\') {jsMath.root = jsMath.root.replace(/\\/g,'/')}
! 821: if (jsMath.root.charAt(0) == '/') {
! 822: if (jsMath.root.charAt(1) != '/') {
! 823: if (jsMath.document.location.port)
! 824: {jsMath.root = ':' + jsMath.document.location.port + jsMath.root}
! 825: jsMath.root = '//' + jsMath.document.location.host + jsMath.root;
! 826: }
! 827: jsMath.root = jsMath.document.location.protocol + jsMath.root;
! 828: } else if (!jsMath.root.match(/^[a-z]+:/i)) {
! 829: var src = new String(jsMath.document.location);
! 830: var pattern = new RegExp('/[^/]*/\\.\\./')
! 831: jsMath.root = src.replace(new RegExp('[^/]*$'),'') + jsMath.root;
! 832: while (jsMath.root.match(pattern))
! 833: {jsMath.root = jsMath.root.replace(pattern,'/')}
! 834: }
1.1 albertel 835: jsMath.Img.root = jsMath.root + "fonts/";
836: jsMath.blank = jsMath.root + "blank.gif";
837: this.Domain();
838: },
839:
840: /*
841: * Find the most restricted common domain for the main
842: * page and jsMath. Report an error if jsMath is outside
843: * the domain of the calling page.
844: */
845: Domain: function () {
1.2 albertel 846: try {jsMath.document.domain} catch (err) {return}
1.1 albertel 847: var jsDomain = ''; var pageDomain = jsMath.document.domain;
848: if (jsMath.root.match('://([^/]*)/')) {jsDomain = RegExp.$1}
849: jsDomain = jsDomain.replace(/:\d+$/,'');
850: if (jsDomain == "" || jsDomain == pageDomain) return;
851: //
852: // MSIE on the Mac can't change jsMath.document.domain and 'try' won't
853: // catch the error (Grrr!), so exit for them.
854: //
855: if (navigator.appName == 'Microsoft Internet Explorer' &&
1.3 ! albertel 856: jsMath.platform == 'mac' && navigator.onLine &&
1.1 albertel 857: navigator.userProfile && jsMath.document.all) return;
858: jsDomain = jsDomain.split(/\./); pageDomain = pageDomain.split(/\./);
859: if (jsDomain.length < 2 || pageDomain.length < 2 ||
860: jsDomain[jsDomain.length-1] != pageDomain[pageDomain.length-1] ||
861: jsDomain[jsDomain.length-2] != pageDomain[pageDomain.length-2]) {
862: this.DomainWarning();
863: return;
864: }
865: var domain = jsDomain[jsDomain.length-2] + '.' + jsDomain[jsDomain.length-1];
866: for (var i = 3; i <= jsDomain.length && i <= pageDomain.length; i++) {
867: if (jsDomain[jsDomain.length-i] != pageDomain[pageDomain.length-i]) break;
868: domain = jsDomain[jsDomain.length-i] + '.' + domain;
869: }
870: jsMath.document.domain = domain;
871: this.domainChanged = 1;
872: },
873:
874: DomainWarning: function () {
875: alert("In order for jsMath to be able to load the additional "
876: + "components that it may need, the jsMath.js file must be "
877: + "loaded from a server in the same domain as the page that "
878: + "contains it. Because that is not the case for this page, "
879: + "the mathematics displayed here may not appear correctly.");
880: },
881:
882: /*
883: * Initialize a font's encoding array
884: */
885: EncodeFont: function (name) {
886: var font = jsMath.TeX[name];
887: if (font[0].c != null) return;
888: for (var k = 0; k < 128; k++) {
889: var data = font[k]; font[k] = data[3];
890: if (font[k] == null) {font[k] = {}};
891: font[k].w = data[0]; font[k].h = data[1];
892: if (data[2] != null) {font[k].d = data[2]}
893: font[k].c = jsMath.TeX.encoding[k];
894: }
895: },
896:
897: /*
898: * Initialize the encodings for all fonts
899: */
900: Fonts: function () {
901: for (var i = 0; i < jsMath.TeX.fam.length; i++) {
902: var name = jsMath.TeX.fam[i];
903: if (name) {this.EncodeFont(name)}
904: }
905: },
906:
907: /*
908: * Look up the default height and depth for a TeX font
909: * and set the skewchar
910: */
911: TeXfont: function (name) {
912: var font = jsMath.TeX[name]; if (font == null) return;
913: var WH = jsMath.EmBoxFor('<span class="'+name+'">'+font[65].c+'</span>');
914: font.hd = WH.h; font.dh = .05;
915: font.d = jsMath.EmBoxFor('<span class="'+name+'">'+ font[65].c +
916: jsMath.HTML.Rule(1,font.hd) + '</span>').h - font.hd;
917: font.h = font.hd - font.d;
918: if (name == 'cmmi10') {font.skewchar = 0177}
919: else if (name == 'cmsy10') {font.skewchar = 060}
920: },
921:
922: /*
923: * Init all the TeX fonts
924: */
925: TeXfonts: function () {
926: for (var i = 0; i < jsMath.TeX.fam.length; i++)
927: {if (jsMath.TeX.fam[i]) {this.TeXfont(jsMath.TeX.fam[i])}}
928: },
929:
930: /*
931: * Compute font parameters for various sizes
932: */
933: Sizes: function () {
1.3 ! albertel 934: jsMath.TeXparams = []; var i; var j;
! 935: for (j=0; j < jsMath.sizes.length; j++) {jsMath.TeXparams[j] = {}}
! 936: for (i in jsMath.TeX) {
1.1 albertel 937: if (typeof(jsMath.TeX[i]) != 'object') {
1.3 ! albertel 938: for (j=0; j < jsMath.sizes.length; j++) {
1.1 albertel 939: jsMath.TeXparams[j][i] = jsMath.sizes[j]*jsMath.TeX[i]/100;
940: }
941: }
942: }
943: },
944:
945: /*
946: * Send the style definitions to the browser (these may be adjusted
947: * by the browser-specific code)
948: */
949: Styles: function (styles) {
950: if (!styles) {
951: styles = jsMath.styles;
952: styles['.typeset .scale'] = 'font-size:'+jsMath.Controls.cookie.scale+'%';
953: this.stylesReady = 1;
954: }
955: jsMath.Script.Push(this,'AddStyleSheet',styles);
956: if (jsMath.Browser.styleChangeDelay) {jsMath.Script.Push(jsMath.Script,'Delay',1)}
957: },
958:
959: AddStyleSheet: function (styles) {
960: var head = jsMath.document.getElementsByTagName('head')[0];
961: var string = ''; for (var id in styles) {string += id + ' {'+styles[id]+"}\n"}
962: if (jsMath.document.createStyleSheet) {// check for MSIE
963: head.insertAdjacentHTML('beforeEnd',
1.2 albertel 964: '<span style="display:none">x</span>' // MSIE needs this for some reason
965: + '<style type="text/css">'+string+'</style>');
1.1 albertel 966: } else {
967: var style = jsMath.document.createElement('style'); style.type = "text/css";
968: style.appendChild(jsMath.document.createTextNode(string));
969: head.appendChild(style);
970: }
971: },
972:
973: /*
974: * Do the initialization that requires the <body> to be in place.
975: */
976: Body: function () {
977: if (this.inited) return;
1.3 ! albertel 978:
1.1 albertel 979: this.inited = -1;
980:
981: jsMath.Setup.Hidden(); this.inited = -2;
982: jsMath.Browser.Init(); this.inited = -3;
983:
984: // blank screen if necessary
985: if (jsMath.Controls.cookie.blank) {jsMath.Message.Blank()}; this.inited = -4;
986:
987: jsMath.Setup.Styles(); this.inited = -5;
988: jsMath.Controls.Init(); this.inited = -6;
989:
990: // do user-specific initialization
991: jsMath.Script.Push(jsMath.Setup,'User','pre-font'); this.inited = -7;
992:
993: // make sure browser-specific loads are done before this
994: jsMath.Script.Push(jsMath.Font,'Check');
1.2 albertel 995: if (jsMath.Font.register.length)
996: {jsMath.Script.Push(jsMath.Font,'LoadRegistered')}
1.3 ! albertel 997:
1.1 albertel 998: this.inited = 1;
999: },
1000:
1001: /*
1.3 ! albertel 1002: * Web page author can override the entries to the UserEvent hash
! 1003: * functions that will be run at various times during jsMath's setup
! 1004: * process.
1.1 albertel 1005: */
1.3 ! albertel 1006: User: function (when) {
! 1007: if (jsMath.Setup.UserEvent[when]) {(jsMath.Setup.UserEvent[when])()}
! 1008: },
! 1009:
! 1010: UserEvent: {
! 1011: "pre-font": null, // after browser is set up but before fonts are tested
! 1012: "onload": null // after jsMath.js is loaded and finished running
! 1013: }
1.1 albertel 1014:
1015: };
1016:
1017: jsMath.Update = {
1018:
1019: /*
1020: * Update specific parameters for a limited number of font entries
1021: */
1022: TeXfonts: function (change) {
1023: for (var font in change) {
1024: for (var code in change[font]) {
1025: for (var id in change[font][code]) {
1026: jsMath.TeX[font][code][id] = change[font][code][id];
1027: }
1028: }
1029: }
1030: },
1031:
1032: /*
1033: * Update the character code for every character in a list
1034: * of fonts
1035: */
1036: TeXfontCodes: function (change) {
1037: for (var font in change) {
1038: for (var i = 0; i < change[font].length; i++) {
1039: jsMath.TeX[font][i].c = change[font][i];
1040: }
1041: }
1042: }
1043:
1044: };
1045:
1046: /***************************************************************************/
1047:
1048: /*
1049: * Implement browser-specific checks
1050: */
1051:
1052: jsMath.Browser = {
1053:
1054: allowAbsolute: 1, // tells if browser can nest absolutely positioned
1055: // SPANs inside relative SPANs
1056: allowAbsoluteDelim: 0, // OK to use absolute placement for building delims?
1057: separateSkips: 0, // MSIE doesn't do negative left margins, and
1058: // Netscape doesn't combine skips well
1059:
1060: valignBug: 0, // Konqueror doesn't nest vertical-align
1061: operaHiddenFix: '', // for Opera to fix bug with math in tables
1062: msieCenterBugFix: '', // for MSIE centering bug with image fonts
1063: msieInlineBlockFix: '', // for MSIE alignment bug in non-quirks mode
1.2 albertel 1064: msieSpaceFix: '', // for MSIE to avoid dropping empty spans
1.1 albertel 1065: imgScale: 1, // MSI scales images for 120dpi screens, so compensate
1066:
1067: renameOK: 1, // tells if brower will find a tag whose name
1068: // has been set via setAttributes
1069: styleChangeDelay: 0, // true if style changes need a delay in order
1070: // for them to be available
1071:
1072: delay: 1, // delay for asynchronous math processing
1073:
1074: version: 0, // browser version number (when needed)
1075:
1076: /*
1077: * Determine if the "top" of a <SPAN> is always at the same height
1078: * or varies with the height of the rest of the line (MSIE).
1079: */
1080: TestSpanHeight: function () {
1081: jsMath.hidden.innerHTML = '<span><span style="'+this.block+';height:2em;width:1px"></span></span>';
1082: var span = jsMath.hidden.firstChild;
1083: var img = span.firstChild;
1084: this.spanHeightVaries = (span.offsetHeight >= img.offsetHeight && span.offsetHeight > 0);
1085: this.spanHeightTooBig = (span.offsetHeight > img.offsetHeight);
1086: jsMath.hidden.innerHTML = '';
1087: },
1088:
1089: /*
1090: * Determine if an inline-block with 0 width is OK or not
1091: * and decide whether to use spans or images for spacing
1092: */
1093: TestInlineBlock: function () {
1.2 albertel 1094: this.block = "display:-moz-inline-box";
1.1 albertel 1095: this.hasInlineBlock = jsMath.BBoxFor('<span style="'+this.block+';width:10px;height:5px"></span>').w > 0;
1.2 albertel 1096: if (this.hasInlineBlock) {
1097: jsMath.styles['.typeset .blank'] = jsMath.styles['.typeset .blank'].replace(/display:inline-block/,this.block);
1098: jsMath.styles['.typeset .spacer'] = jsMath.styles['.typeset .spacer'].replace(/display:inline-block/,'');
1099: } else {
1100: this.block = "display:inline-block";
1.1 albertel 1101: this.hasInlineBlock = jsMath.BBoxFor('<span style="'+this.block+';width:10px;height:5px"></span>').w > 0;
1102: if (!this.hasInlineBlock) return;
1103: }
1104: this.block += ';overflow:hidden';
1105: var h = jsMath.BBoxFor('x').h;
1106: this.mozInlineBlockBug = jsMath.BBoxFor(
1107: '<span style="'+this.block+';height:'+h+'px;width:1px"></span>x'+
1108: '<span style="'+this.block+';height:'+h+'px;width:1px;vertical-align:-'+h+'px"></span>').h > 2*h;
1109: this.widthAddsBorder = jsMath.BBoxFor('<span style="'+this.block+
1110: ';overflow:hidden;height:1px;width:10px;border-left:10px solid"></span>').w > 10;
1111: this.msieBorderBug =
1112: jsMath.BBoxFor('<span style="'+this.block+';height:'+h+'px;width:1px"></span>x').h !=
1113: jsMath.BBoxFor('<span style="'+this.block+';height:'+h+'px;width:1px;border-left:1px solid"></span>x').h;
1114: this.blankWidthBug = this.msieBorderBug ||
1115: jsMath.BBoxFor('<span style="'+this.block+';height:2em;width:0px"></span>').h == 0;
1116: },
1117:
1118: /*
1119: * Determine if the NAME attribute of a tag can be changed
1120: * using the setAttribute function, and then be properly
1121: * returned by getElementByName.
1122: */
1123: TestRenameOK: function () {
1124: jsMath.hidden.innerHTML = '<span></span>';
1125: var test = jsMath.hidden.firstChild;
1126: test.setAttribute('name','jsMath_test');
1127: this.renameOK = (jsMath.document.getElementsByName('jsMath_test').length > 0);
1128: jsMath.hidden.innerHTML = '';
1129: },
1130:
1131: /*
1132: * See if style changes occur immediately, or if we need to delay
1133: * in order to let them take effect.
1134: */
1135: TestStyleChange: function () {
1136: jsMath.hidden.innerHTML = '<span ID="jsMath_test">x</span>';
1137: var span = jsMath.hidden.firstChild;
1138: var w = span.offsetWidth;
1139: jsMath.Setup.AddStyleSheet({'#jsMath_test': 'font-size:200%'});
1140: this.styleChangeDelay = (span.offsetWidth == w);
1141: jsMath.hidden.innerHTML = '';
1142: },
1143:
1144: /*
1145: * Perform a version check on a standard version string
1146: */
1147: VersionAtLeast: function (v) {
1148: var bv = new String(this.version).split('.');
1149: v = new String(v).split('.'); if (v[1] == null) {v[1] = '0'}
1150: return bv[0] > v[0] || (bv[0] == v[0] && bv[1] >= v[1]);
1151: },
1152:
1153: /*
1154: * Test for browser characteristics, and adjust things
1155: * to overcome specific browser bugs
1156: */
1157: Init: function () {
1158: jsMath.browser = 'unknown';
1159: this.TestInlineBlock();
1160: this.TestSpanHeight();
1161: this.TestRenameOK();
1162: this.TestStyleChange();
1163:
1164: this.MSIE();
1165: this.Mozilla();
1166: this.Opera();
1167: this.OmniWeb();
1168: this.Safari();
1169: this.Konqueror();
1170:
1171: //
1172: // Change some routines depending on the browser
1173: //
1174: if (this.allowAbsoluteDelim) {
1175: jsMath.Box.DelimExtend = jsMath.Box.DelimExtendAbsolute;
1176: jsMath.Box.Layout = jsMath.Box.LayoutAbsolute;
1177: } else {
1178: jsMath.Box.DelimExtend = jsMath.Box.DelimExtendRelative;
1179: jsMath.Box.Layout = jsMath.Box.LayoutRelative;
1180: }
1181:
1182: if (this.separateSkips) {
1183: jsMath.HTML.Place = jsMath.HTML.PlaceSeparateSkips;
1184: jsMath.Typeset.prototype.Place = jsMath.Typeset.prototype.PlaceSeparateSkips;
1185: }
1186: },
1187:
1188: //
1189: // Handle bug-filled Internet Explorer
1190: //
1191: MSIE: function () {
1192: if (this.spanHeightVaries && !this.spanHeightTooBig) {
1193: jsMath.browser = 'MSIE';
1.3 ! albertel 1194: if (jsMath.platform == 'pc') {
! 1195: this.IE7 = (window.XMLHttpRequest != null);
! 1196: this.quirks = (jsMath.document.compatMode == "BackCompat");
! 1197: this.msieStandard6 = !this.quirks && !this.IE7;
1.1 albertel 1198: this.allowAbsoluteDelim = 1; this.separateSkips = 1;
1199: this.buttonCheck = 1; this.msieBlankBug = 1;
1.3 ! albertel 1200: this.msieAccentBug = 1; this.msieRelativeClipBug = 1;
1.1 albertel 1201: this.msieDivWidthBug = 1; this.msiePositionFixedBug = 1;
1202: this.msieIntegralBug = 1; this.waitForImages = 1;
1.3 ! albertel 1203: this.msieAlphaBug = !this.IE7; this.alphaPrintBug = !this.IE7;
1.1 albertel 1204: this.msieCenterBugFix = 'position:relative; ';
1205: this.msieInlineBlockFix = ' display:inline-block;';
1.3 ! albertel 1206: this.msieTeXfontBaselineBug = !jsMath.Browser.quirks;
! 1207: if (!this.IE7) {this.msieSpaceFix = '<span style="display:inline-block"></span>'}
1.1 albertel 1208: jsMath.Macro('joinrel','\\mathrel{\\kern-5mu}'),
1.3 ! albertel 1209: jsMath.Parser.prototype.mathchardef.mapstocharOrig = jsMath.Parser.prototype.mathchardef.mapstochar;
! 1210: delete jsMath.Parser.prototype.mathchardef.mapstochar;
! 1211: jsMath.Macro('mapstochar','\\rlap{\\mapstocharOrig\\,}\\kern1mu'),
1.1 albertel 1212: jsMath.styles['.typeset .arial'] = "font-family: 'Arial unicode MS'";
1.3 ! albertel 1213: if (!this.IE7 || this.quirks) {
! 1214: // MSIE doesn't implement fixed positioning, so use absolute
! 1215: jsMath.styles['#jsMath_message'] =
1.1 albertel 1216: jsMath.styles['#jsMath_message'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
1.3 ! albertel 1217: jsMath.styles['#jsMath_panel'] =
1.1 albertel 1218: jsMath.styles['#jsMath_panel'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
1.3 ! albertel 1219: jsMath.styles['#jsMath_button'] = 'width:1px; '
1.1 albertel 1220: + jsMath.styles['#jsMath_button'].replace(/position:fixed/,"position:absolute").replace(/width:auto/,"");
1.3 ! albertel 1221: jsMath.window.attachEvent("onscroll",jsMath.Controls.MoveButton);
! 1222: if (this.IE7) jsMath.window.attachEvent("onresize",jsMath.Controls.MoveButton);
! 1223: this.msieMoveButtonHack = this.IE7;
! 1224: }
! 1225: // Make MSIE put borders around the whole button
! 1226: jsMath.styles['#jsMath_noFont .link'] += " display: inline-block;";
1.1 albertel 1227: // MSIE needs this NOT to be inline-block
1228: jsMath.styles['.typeset .spacer'] =
1229: jsMath.styles['.typeset .spacer'].replace(/display:inline-block/,'');
1.3 ! albertel 1230: // MSIE can't insert DIV's into text nodes, so tex2math must use SPAN's to fake DIV's
! 1231: jsMath.styles['.tex2math_div'] = jsMath.styles['div.typeset'] + '; width: 100%; display: inline-block';
1.1 albertel 1232: // MSIE will rescale images if the DPIs differ
1233: if (screen.deviceXDPI && screen.logicalXDPI
1234: && screen.deviceXDPI != screen.logicalXDPI) {
1235: this.imgScale *= screen.logicalXDPI/screen.deviceXDPI;
1236: jsMath.Controls.cookie.alpha = 0;
1237: }
1238: // Handle bug with getting width of italic text
1239: this.italicString = '<i>x</i>';
1240: jsMath.EmBoxFor = jsMath.EmBoxForItalics;
1.3 ! albertel 1241: } else if (jsMath.platform == 'mac') {
1.1 albertel 1242: this.msieAbsoluteBug = 1; this.msieButtonBug = 1;
1243: this.msieDivWidthBug = 1; this.msieBlankBug = 1;
1.3 ! albertel 1244: this.quirks = 1;
1.1 albertel 1245: jsMath.Setup.Script('jsMath-msie-mac.js');
1246: jsMath.Parser.prototype.macros.angle = ['Replace','ord','<font face="Symbol">‹</font>','normal'];
1.2 albertel 1247: jsMath.styles['#jsMath_panel'] = 'width:42em; ' + jsMath.styles['#jsMath_panel'].replace(/width:auto/,"");
1248: jsMath.Controls.cookie.printwarn = 0; // MSIE/Mac doesn't handle '@media screen'
1.1 albertel 1249: }
1250: jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
1251: }
1252: },
1253:
1254: //
1255: // Handle Netscape/Mozilla (any flavor)
1256: //
1257: Mozilla: function () {
1258: if (jsMath.hidden.ATTRIBUTE_NODE) {
1259: jsMath.browser = 'Mozilla';
1.3 ! albertel 1260: if (jsMath.platform == 'pc') {this.alphaPrintBug = 1}
1.2 albertel 1261: this.allowAbsoluteDelim = 1;
1262: jsMath.styles['#jsMath_button'] = jsMath.styles['#jsMath_button'].replace(/cursor:hand/,'cursor:pointer');
1263: jsMath.styles['#jsMath_noFont .link'] = jsMath.styles['#jsMath_noFont .link'].replace(/cursor:hand/,'cursor:pointer');
1.1 albertel 1264: jsMath.Macro('not','\\mathrel{\\rlap{\\kern3mu/}}');
1265: if (navigator.vendor == 'Firefox') {
1.2 albertel 1266: this.version = navigator.vendorSub;
1.1 albertel 1267: } else if (navigator.userAgent.match(' Firefox/([0-9.]+)( |$)')) {
1.2 albertel 1268: this.version = RegExp.$1;
1.1 albertel 1269: }
1270: }
1271: },
1272:
1273: //
1274: // Handle OmniWeb
1275: //
1276: OmniWeb: function () {
1277: if (navigator.accentColorName) {
1278: jsMath.browser = 'OmniWeb';
1279: this.allowAbsolute = this.hasInlineBlock;
1280: this.allowAbsoluteDelim = this.allowAbsolute;
1.2 albertel 1281: this.valignBug = !this.allowAbsolute;
1.1 albertel 1282: this.buttonCheck = 1; this.textNodeBug = 1;
1.2 albertel 1283: jsMath.noChangeGlobal = 1; // OmniWeb craches on GoGlobal
1.1 albertel 1284: if (!this.hasInlineBlock) {jsMath.Setup.Script('jsMath-old-browsers.js')}
1285: }
1286: },
1287:
1288: //
1289: // Handle Opera
1290: //
1291: Opera: function () {
1292: if (this.spanHeightTooBig) {
1293: jsMath.browser = 'Opera';
1294: var isOld = navigator.userAgent.match("Opera 7");
1295: this.allowAbsolute = 0;
1296: this.delay = 10;
1297: this.operaHiddenFix = '[Processing]';
1298: if (isOld) {jsMath.Setup.Script('jsMath-old-browsers.js')}
1299: }
1300: },
1301:
1302: //
1303: // Handle Safari
1304: //
1305: Safari: function () {
1306: if (navigator.appVersion.match(/Safari\//)) {
1307: jsMath.browser = 'Safari';
1308: var version = navigator.userAgent.match("Safari/([0-9]+)");
1309: version = (version)? version[1] : 400;
1.2 albertel 1310: for (var i = 0; i < jsMath.TeX.fam.length; i++) {
1311: if (jsMath.TeX.fam[i] && jsMath.TeX[jsMath.TeX.fam[i]])
1312: {jsMath.TeX[jsMath.TeX.fam[i]].dh = .1}
1313: }
1.1 albertel 1314: jsMath.TeX.axis_height += .05;
1.2 albertel 1315: jsMath.TeX.default_rule_thickness += .025;
1.1 albertel 1316: this.allowAbsoluteDelim = version >= 125;
1317: this.safariIFRAMEbug = version >= 312 && version < 412;
1.2 albertel 1318: this.safariButtonBug = version < 412;
1.1 albertel 1319: this.safariImgBug = 1; this.textNodeBug = 1;
1320: this.buttonCheck = 1;
1321: this.styleChangeDelay = 1;
1322: }
1323: },
1324:
1325: //
1326: // Handle Konqueror
1327: //
1328: Konqueror: function () {
1329: if (navigator.product && navigator.product.match("Konqueror")) {
1330: jsMath.browser = 'Konqueror';
1331: this.allowAbsolute = 0;
1332: this.allowAbsoluteDelim = 0;
1333: if (navigator.userAgent.match(/Konqueror\/(\d+)\.(\d+)/)) {
1334: if (RegExp.$1 < 3 || (RegExp.$1 == 3 && RegExp.$2 < 3)) {
1335: this.separateSkips = 1;
1336: this.valignBug = 1;
1337: jsMath.Setup.Script('jsMath-old-browsers.js');
1338: }
1339: }
1.3 ! albertel 1340: // Apparently, Konqueror wants the names without the hyphen
! 1341: jsMath.Add(jsMath.styles,{
! 1342: '.typeset .cmr10': 'font-family: jsMath-cmr10, jsMath cmr10, serif',
! 1343: '.typeset .cmbx10': 'font-family: jsMath-cmbx10, jsMath cmbx10, jsMath-cmr10, jsMath cmr10',
! 1344: '.typeset .cmti10': 'font-family: jsMath-cmti10, jsMath cmti10, jsMath-cmr10, jsMath cmr10',
! 1345: '.typeset .cmmi10': 'font-family: jsMath-cmmi10, jsMath cmmi10',
! 1346: '.typeset .cmsy10': 'font-family: jsMath-cmsy10, jsMath cmsy10',
! 1347: '.typeset .cmex10': 'font-family: jsMath-cmex10, jsMath cmex10'
! 1348: });
! 1349: jsMath.Font.testFont = "jsMath-cmex10, jsMath cmex10";
1.1 albertel 1350: }
1351: }
1352:
1353: };
1354:
1355: /***************************************************************************/
1356:
1357: /*
1358: * Implement font check and messages
1359: */
1360: jsMath.Font = {
1361:
1.3 ! albertel 1362: testFont: "jsMath-cmex10",
1.1 albertel 1363: fallback: "symbol", // the default fallback method
1.2 albertel 1364: register: [], // list of fonts registered before jsMath.Init()
1.1 albertel 1365:
1366: // the HTML for the missing font message
1367: message:
1368: '<b>No jsMath TeX fonts found</b> -- using image fonts instead.<br/>\n'
1369: + 'These may be slow and might not print well.<br/>\n'
1370: + 'Use the jsMath control panel to get additional information.',
1371:
1372: extra_message:
1373: 'Extra TeX fonts not found: <b><span id="jsMath_ExtraFonts"></span></b><br/>'
1374: + 'Using image fonts instead. This may be slow and might not print well.<br/>\n'
1375: + 'Use the jsMath control panel to get additional information.',
1.2 albertel 1376:
1377: print_message:
1378: 'To print higher-resolution math symbols, click the<br/>\n'
1.3 ! albertel 1379: + '<b>Hi-Res Fonts for Printing</b> button on the jsMath control panel.<br/>\n',
1.2 albertel 1380:
1381: alpha_message:
1382: 'If the math symbols print as black boxes, turn off <b>image alpha channels</b><br/>\n'
1383: + 'using the <B>Options</B> pane of the jsMath control panel.<br/>\n',
1.1 albertel 1384:
1385: /*
1386: * Look to see if a font is found.
1387: * Check the character in a given position, and see if it is
1388: * wider than the usual one in that position.
1389: */
1390: Test1: function (name,n,factor,prefix) {
1391: if (n == null) {n = 0x7C}; if (factor == null) {factor = 2}; if (prefix == null) {prefix = ''}
1392: var wh1 = jsMath.BBoxFor('<span style="font-family: '+prefix+name+', serif">'+jsMath.TeX[name][n].c+'</span>');
1393: var wh2 = jsMath.BBoxFor('<span style="font-family: serif">'+jsMath.TeX[name][n].c+'</span>');
1394: //alert([wh1.w,wh2.w,wh1.h,factor*wh2.w]);
1395: return (wh1.w > factor*wh2.w && wh1.h != 0);
1396: },
1397:
1398: Test2: function (name,n,factor,prefix) {
1399: if (n == null) {n = 0x7C}; if (factor == null) {factor = 2}; if (prefix == null) {prefix = ''}
1400: var wh1 = jsMath.BBoxFor('<span style="font-family: '+prefix+name+', serif">'+jsMath.TeX[name][n].c+'</span>');
1401: var wh2 = jsMath.BBoxFor('<span style="font-family: serif">'+jsMath.TeX[name][n].c+'</span>');
1402: //alert([wh2.w,wh1.w,wh1.h,factor*wh1.w]);
1403: return (wh2.w > factor*wh1.w && wh1.h != 0);
1404: },
1405:
1406: /*
1407: * Check for the new jsMath versions of the fonts (blacker with
1408: * different encoding) and if not found, look for old-style fonts.
1409: * If they are found, load the BaKoMa encoding information.
1410: */
1411: CheckTeX: function () {
1.3 ! albertel 1412: var wh = jsMath.BBoxFor('<span style="font-family: '+jsMath.Font.testFont+', serif">'+jsMath.TeX.cmex10[1].c+'</span>');
1.1 albertel 1413: jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10',null,null,'jsMath-'));
1.3 ! albertel 1414: if (jsMath.nofonts && (jsMath.platform != "mac" ||
1.1 albertel 1415: jsMath.browser != 'Mozilla' || !jsMath.Browser.VersionAtLeast(1.5))) {
1416: wh = jsMath.BBoxFor('<span style="font-family: cmex10, serif">'+jsMath.TeX.cmex10[1].c+'</span>');
1417: jsMath.nofonts = ((wh.w*3 > wh.h || wh.h == 0) && !this.Test1('cmr10'));
1418: if (!jsMath.nofonts) {jsMath.Setup.Script("jsMath-BaKoMa-fonts.js")}
1419: }
1420: },
1421:
1422: /*
1423: * Check for the availability of TeX fonts. We do this by looking at
1424: * the width and height of a character in the cmex10 font. The cmex10
1425: * font has depth considerably greater than most characters' widths (the
1426: * whole font has the depth of the character with greatest depth). This
1427: * is not the case for most fonts, so if we can access cmex10, the
1428: * height of a character should be much bigger than the width.
1429: * Otherwise, if we don't have cmex10, we'll get a character in another
1430: * font with normal height and width. In this case, we insert a message
1431: * pointing the user to the jsMath site, and load one of the fallback
1432: * definitions.
1433: *
1434: */
1435: Check: function () {
1436: var cookie = jsMath.Controls.cookie;
1437: this.CheckTeX();
1438: if (jsMath.nofonts) {
1439: if (cookie.autofont || cookie.font == 'tex') {
1440: cookie.font = this.fallback;
1441: if (cookie.warn) {
1442: jsMath.nofontMessage = 1;
1443: cookie.warn = 0; jsMath.Controls.SetCookie(0);
1444: if (jsMath.window.NoFontMessage) {jsMath.window.NoFontMessage()}
1445: else {this.Message(this.message)}
1446: }
1447: }
1448: } else {
1449: if (cookie.autofont) {cookie.font = 'tex'}
1450: if (cookie.font == 'tex') return;
1451: }
1452: if (jsMath.noImgFonts) {cookie.font = 'unicode'}
1453: if (cookie.font == 'unicode') {
1.3 ! albertel 1454: jsMath.Setup.Script('jsMath-fallback-'+jsMath.platform+'.js');
1.1 albertel 1455: jsMath.Box.TeXnonfallback = jsMath.Box.TeX;
1456: jsMath.Box.TeX = jsMath.Box.TeXfallback;
1457: return;
1458: }
1.2 albertel 1459: if (!cookie.print && cookie.printwarn) {
1460: this.PrintMessage(
1461: (jsMath.Browser.alphaPrintBug && jsMath.Controls.cookie.alpha) ?
1462: this.print_message + this.alpha_message : this.print_message);
1463: }
1.1 albertel 1464: if (jsMath.Browser.waitForImages) {
1465: jsMath.Script.Push(jsMath.Script,"WaitForImage",jsMath.blank);
1466: }
1467: if (cookie.font == 'symbol') {
1468: jsMath.Setup.Script('jsMath-fallback-symbols.js');
1469: jsMath.Box.TeXnonfallback = jsMath.Box.TeX;
1470: jsMath.Box.TeX = jsMath.Box.TeXfallback;
1471: return;
1472: }
1473: jsMath.Img.SetFont({
1474: cmr10: ['all'], cmmi10: ['all'], cmsy10: ['all'],
1475: cmex10: ['all'], cmbx10: ['all'], cmti10: ['all']
1476: });
1477: jsMath.Img.LoadFont('cm-fonts');
1478: },
1479:
1480: /*
1481: * The message for when no TeX fonts. You can eliminate this message
1482: * by including
1483: *
1484: * <script>jsMath = {Font: {Message: function () {}}}</script>
1485: *
1486: * in your HTML file, before loading jsMath.js, if you want. But this
1487: * means the user may not know that he or she can get a better version
1488: * of your page.
1489: */
1490: Message: function (message) {
1.2 albertel 1491: if (jsMath.Element("Warning")) return;
1.1 albertel 1492: var div = jsMath.Setup.DIV("Warning",{});
1493: div.innerHTML =
1494: '<center><table><tr><td>'
1.2 albertel 1495: + '<div id="jsMath_noFont"><div class="message">' + message
1.1 albertel 1496: + '<div style="text-align:left"><span style="float:left; margin: 8px 0px 0px 20px">'
1497: + '<span onclick="jsMath.Controls.Panel()" title=" Open the jsMath Control Panel " class="link">jsMath Control Panel</span>'
1498: + '</span><span style="margin: 8px 20px 0px 0px; float:right">'
1499: + '<span onclick="jsMath.Font.HideMessage()" title=" Remove this font warning message " class="link">Hide this Message</span>'
1.2 albertel 1500: + '</span></div><div style="height:6px"></div><br clear="all"/></div></div>'
1.1 albertel 1501: + '<div style="width:22em; height:1px"></div>'
1502: + '</td></tr></table></center><hr/>';
1503: },
1504:
1505: HideMessage: function () {
1506: var message = jsMath.Element("Warning");
1507: if (message) {message.style.display = "none"}
1508: },
1509:
1.2 albertel 1510: PrintMessage: function (message) {
1511: if (jsMath.Element("PrintWarning")) return;
1512: var div = jsMath.Setup.DIV("PrintWarning",{});
1513: div.innerHTML =
1514: '<center><table><tr><td>'
1515: + '<div class="message">' + message + '</div>'
1516: + '<div style="width:22em; height:1px"></div>'
1517: + '</td></tr></table></center><hr/>';
1518: },
1519:
1.1 albertel 1520: /*
1521: * Register an extra font so jsMath knows about it
1522: */
1.2 albertel 1523: Register: function (data,force) {
1.1 albertel 1524: if (typeof(data) == 'string') {data = {name: data}}
1.2 albertel 1525: if (!jsMath.Setup.inited && !force) {
1526: this.register[this.register.length] = data;
1527: return;
1528: }
1.1 albertel 1529: var fontname = data.name; var name = fontname.replace(/10$/,'');
1530: var fontfam = jsMath.TeX.fam.length;
1531: if (data.prefix == null) {data.prefix = ""}
1532: if (!data.style) {data.style = "font-family: "+data.prefix+fontname+", serif"}
1533: if (!data.styles) {data.styles = {}}
1534: if (!data.macros) {data.macros = {}}
1535: /*
1536: * Register font family
1537: */
1538: jsMath.TeX.fam[fontfam] = fontname;
1539: jsMath.TeX.famName[fontname] = fontfam;
1540: data.macros[name] = ['HandleFont',fontfam];
1541: jsMath.Add(jsMath.Parser.prototype.macros,data.macros);
1542: /*
1543: * Set up styles
1544: */
1545: data.styles['.typeset .'+fontname] = data.style;
1546: jsMath.Setup.Styles(data.styles);
1.2 albertel 1547: if (jsMath.initialized) {jsMath.Script.Push(jsMath.Setup,'TeXfont',fontname)}
1.1 albertel 1548: /*
1549: * Check for font and give message if missing
1550: */
1.3 ! albertel 1551: var cookie = jsMath.Controls.cookie;
1.1 albertel 1552: var hasTeXfont = !jsMath.nofonts &&
1553: data.test(fontname,data.testChar,data.testFactor,data.prefix);
1.3 ! albertel 1554: if (hasTeXfont && cookie.font == 'tex') {
1.1 albertel 1555: if (data.tex) {data.tex(fontname,fontfam,data)}
1556: return;
1557: }
1.3 ! albertel 1558: if (!hasTeXfont && cookie.warn && cookie.font == 'tex' && !jsMath.nofonts) {
! 1559: if (!cookie.fonts.match("/"+fontname+"/")) {
! 1560: cookie.fonts += fontname + "/"; jsMath.Controls.SetCookie(0);
! 1561: if (!jsMath.Element("Warning")) this.Message(this.extra_message);
! 1562: var extra = jsMath.Element("ExtraFonts");
! 1563: if (extra) {
! 1564: if (extra.innerHTML != "") {extra.innerHTML += ','}
! 1565: extra.innerHTML += " " + data.prefix+fontname;
! 1566: }
1.1 albertel 1567: }
1568: }
1.3 ! albertel 1569: if (cookie.font == 'unicode' || jsMath.noImgFonts) {
1.1 albertel 1570: if (data.fallback) {data.fallback(fontname,fontfam,data)}
1571: return;
1572: }
1573: // Image fonts
1574: var font = {}; font[fontname] = ['all'];
1575: jsMath.Img.SetFont(font);
1576: jsMath.Img.LoadFont(fontname);
1.2 albertel 1577: if (jsMath.initialized) {
1578: jsMath.Script.Push(jsMath.Img,'Scale');
1579: jsMath.Script.Push(jsMath.Img,'UpdateFonts');
1580: }
1581: },
1582: /*
1583: * If fonts are registered before jsMath.Init() is called, jsMath.em
1584: * will not be available, so they need to be delayed.
1585: */
1586: LoadRegistered: function () {
1587: var i = 0;
1588: while (i < this.register.length) {this.Register(this.register[i++],1)}
1589: this.register = [];
1.1 albertel 1590: },
1591:
1592: /*
1593: * Load a font
1594: */
1595: Load: function (name) {jsMath.Setup.Script(this.URL(name))},
1596: URL: function (name) {return jsMath.Img.root+name+'/def.js'}
1597:
1598: };
1599:
1600: /***************************************************************************/
1601:
1602: /*
1603: * Implements the jsMath control panel.
1604: * Much of the code is in jsMath-controls.html, which is
1605: * loaded into a hidden IFRAME on demand
1606: */
1607: jsMath.Controls = {
1608:
1609: // Data stored in the jsMath cookie
1610: cookie: {
1611: scale: 100,
1612: font: 'tex', autofont: 1, scaleImg: 0, alpha: 1,
1.3 ! albertel 1613: warn: 1, fonts: '/', printwarn: 1, stayhires: 0,
1.2 albertel 1614: button: 1, progress: 1, asynch: 0, blank: 0,
1615: print: 0, keep: '0D', global: 'auto', hiddenGlobal: 1
1.1 albertel 1616: },
1617:
1618: cookiePath: '/', // can also set cookieDomain
1.2 albertel 1619: noCookiePattern: /^(file|mk):$/, // pattern for handling cookies locally
1.1 albertel 1620:
1621:
1622: /*
1623: * Create the HTML needed for control panel
1624: */
1625: Init: function () {
1626: this.panel = jsMath.Setup.DIV("panel",{display:'none'});
1627: if (!jsMath.Browser.msieButtonBug) {this.Button()}
1628: else {setTimeout("jsMath.Controls.Button()",500)}
1629: },
1630:
1631: /*
1632: * Load the control panel
1633: */
1634: Panel: function () {
1635: jsMath.Translate.Cancel();
1636: if (this.loaded) {this.Main()}
1637: else {jsMath.Script.delayedLoad(jsMath.root+"jsMath-controls.html")}
1638: },
1639:
1640: /*
1641: * Create the control panel button
1642: */
1643: Button: function () {
1644: var button = jsMath.Setup.DIV("button",{});
1645: button.title = ' Open jsMath Control Panel ';
1.2 albertel 1646: button.innerHTML =
1647: '<span onclick="jsMath.Controls.Panel()">jsMath</span>';
1648: if (!jsMath.Global.isLocal && !jsMath.noShowGlobal) {
1649: button.innerHTML +=
1650: '<span id="jsMath_global" title=" Open jsMath Global Panel " '
1651: + 'onclick="jsMath.Global.Show(1)">Global </span>';
1652: }
1653: if (button.offsetWidth < 30) {button.style.width = "auto"}
1.1 albertel 1654: if (!this.cookie.button) {button.style.display = "none"}
1655: },
1656:
1.3 ! albertel 1657: /*
! 1658: * Since MSIE doesn't handle position:float, we need to have the
! 1659: * window repositioned every time the window scrolls. We do that
! 1660: * by hiding then showing the window, which apparently causes MSIE
! 1661: * to recompute its location. In MSIE7, that doesn't work anymore,
! 1662: * so we have to move the window by hand.
! 1663: */
1.1 albertel 1664: MoveButton: function () {
1.3 ! albertel 1665: var controls = jsMath.Controls;
! 1666: if (!controls.button) {controls.button = jsMath.Element("button")}
! 1667: if (controls.button) controls.MoveElement(controls.button,3,2);
! 1668: var dx = 20; var dy = 20;
! 1669: if (controls.button) {dy = controls.button.offsetHeight + 6; dx = dy + 5}
! 1670: if (controls.panel) controls.MoveElement(controls.panel,dx,dy);
! 1671: },
! 1672: MoveElement: function (obj,dx,dy) {
! 1673: if (jsMath.Browser.IE7) {
! 1674: var body = document.body;
! 1675: obj.style.right = "auto";
! 1676: obj.style.bottom = "auto";
! 1677: //
! 1678: // This position can't be overridden by CSS (grr)
! 1679: // (Perhaps we can look up the current position and which sides it's
! 1680: // attached to and use those. What a pain.)
! 1681: //
! 1682: obj.style.left = body.clientWidth + body.scrollLeft - obj.offsetWidth - dx + "px";
! 1683: obj.style.top = body.clientHeight + body.scrollTop - obj.offsetHeight - dy + "px";
! 1684: } else {
! 1685: obj.style.visibility = "hidden";
! 1686: obj.style.visibility = "visible";
! 1687: }
1.1 albertel 1688: },
1689:
1690: /*
1691: * Get the cookie data from the browser
1692: * (for file: references, use url '?' syntax)
1693: */
1694: GetCookie: function () {
1.2 albertel 1695: // save the current cookie settings as the defaults
1696: if (this.defaults == null) {this.defaults = {}}
1697: jsMath.Add(this.defaults,this.cookie); this.userSet = {};
1698: // get the browser's cookie data
1.1 albertel 1699: var cookies = jsMath.document.cookie;
1.2 albertel 1700: if (jsMath.window.location.protocol.match(this.noCookiePattern)) {
1701: cookies = this.localGetCookie();
1702: this.isLocalCookie = 1;
1703: }
1704: if (cookies.match(/jsMath=([^;]+)/)) {
1.3 ! albertel 1705: var data = unescape(RegExp.$1).split(/,/);
1.1 albertel 1706: for (var i = 0; i < data.length; i++) {
1707: var x = data[i].match(/(.*):(.*)/);
1708: if (x[2].match(/^\d+$/)) {x[2] = 1*x[2]} // convert from string
1709: this.cookie[x[1]] = x[2];
1.2 albertel 1710: this.userSet[x[1]] = 1;
1.1 albertel 1711: }
1712: }
1713: },
1.2 albertel 1714: localGetCookie: function () {
1.3 ! albertel 1715: return jsMath.window.location.search.substr(1);
1.2 albertel 1716: },
1.1 albertel 1717:
1718: /*
1719: * Save the cookie data in the browser
1720: * (for file: urls, append data like CGI reference)
1721: */
1722: SetCookie: function (warn) {
1723: var cookie = [];
1.2 albertel 1724: for (var id in this.cookie) {
1725: if (this.defaults[id] == null || this.cookie[id] != this.defaults[id])
1726: {cookie[cookie.length] = id + ':' + this.cookie[id]}
1727: }
1.1 albertel 1728: cookie = cookie.join(',');
1.2 albertel 1729: if (this.isLocalCookie) {
1730: if (warn == 2) {return 'jsMath='+escape(cookie)}
1731: this.localSetCookie(cookie,warn);
1.1 albertel 1732: } else {
1.3 ! albertel 1733: cookie = escape(cookie);
1.2 albertel 1734: if (cookie == '') {warn = 0}
1.1 albertel 1735: if (this.cookiePath) {cookie += '; path='+this.cookiePath}
1736: if (this.cookieDomain) {cookie += '; domain='+this.cookieDomain}
1737: if (this.cookie.keep != '0D') {
1738: var ms = {
1739: D: 1000*60*60*24,
1740: W: 1000*60*60*24*7,
1741: M: 1000*60*60*24*30,
1742: Y: 1000*60*60*24*365
1743: };
1744: var exp = new Date;
1745: exp.setTime(exp.getTime() +
1746: this.cookie.keep.substr(0,1) * ms[this.cookie.keep.substr(1,1)]);
1747: cookie += '; expires=' + exp.toGMTString();
1748: }
1.2 albertel 1749: if (cookie != '') {
1750: jsMath.document.cookie = 'jsMath='+cookie;
1751: var cookies = jsMath.document.cookie;
1752: if (warn && !cookies.match(/jsMath=/))
1753: {alert("Cookies must be enabled in order to save jsMath options")}
1754: }
1.1 albertel 1755: }
1.2 albertel 1756: return null;
1757: },
1758: localSetCookie: function (cookie,warn) {
1759: if (!warn) return;
1760: var href = String(jsMath.window.location).replace(/\?.*/,"");
1761: if (cookie != '') {href += '?jsMath=' + escape(cookie)}
1762: if (href != jsMath.window.location.href) {this.Reload(href)}
1763: },
1764:
1765: /*
1766: * Reload the page (with the given URL)
1767: */
1768: Reload: function (url) {
1769: if (!this.loaded) return;
1.3 ! albertel 1770: this.loaded = 0; jsMath.Setup.inited = -100;
1.2 albertel 1771: jsMath.Global.ClearCache();
1772: if (url) {jsMath.window.location.replace(url)}
1773: else {jsMath.window.location.reload()}
1.1 albertel 1774: }
1.2 albertel 1775:
1.1 albertel 1776: };
1777:
1778: /***************************************************************************/
1779:
1780: /*
1781: * Implements the actions for clicking and double-clicking
1782: * on math formulas
1783: */
1784: jsMath.Click = {
1785:
1786: /*
1787: * Handle clicking on math to get control panel
1788: */
1789: CheckClick: function (event) {
1790: if (!event) {event = jsMath.window.event}
1791: if (event.altKey) jsMath.Controls.Panel();
1792: },
1793:
1794: /*
1795: * Handle double-click for seeing TeX code
1796: */
1797:
1798: CheckDblClick: function (event) {
1799: if (!event) {event = jsMath.window.event}
1800: if (!jsMath.Click.DblClick) {
1801: jsMath.Extension.Require('double-click',1);
1802: // Firefox clears the event, so copy it
1803: var tmpEvent = event; event = {};
1804: for (var id in tmpEvent) {event[id] = tmpEvent[id]}
1805: }
1806: jsMath.Script.Push(jsMath.Click,'DblClick',[event,this.alt]);
1807: }
1808:
1809: };
1810:
1811: /***************************************************************************/
1812:
1813: /*
1814: * The TeX font information
1815: */
1816: jsMath.TeX = {
1817:
1818: //
1819: // The TeX font parameters
1820: //
1821: thinmuskip: 3/18,
1822: medmuskip: 4/18,
1823: thickmuskip: 5/18,
1824:
1825: x_height: .430554,
1826: quad: 1,
1827: num1: .676508,
1828: num2: .393732,
1829: num3: .44373,
1830: denom1: .685951,
1831: denom2: .344841,
1832: sup1: .412892,
1833: sup2: .362892,
1834: sup3: .288888,
1835: sub1: .15,
1836: sub2: .247217,
1837: sup_drop: .386108,
1838: sub_drop: .05,
1839: delim1: 2.39,
1840: delim2: 1.0,
1841: axis_height: .25,
1.2 albertel 1842: default_rule_thickness: .06,
1.1 albertel 1843: big_op_spacing1: .111111,
1844: big_op_spacing2: .166666,
1845: big_op_spacing3: .2,
1846: big_op_spacing4: .6,
1847: big_op_spacing5: .1,
1848:
1849: integer: 6553.6, // conversion of em's to TeX internal integer
1850: scriptspace: .05,
1851: nulldelimiterspace: .12,
1852: delimiterfactor: 901,
1853: delimitershortfall: .5,
1854: scale: 1, // scaling factor for font dimensions
1855:
1856: // The TeX math atom types (see Appendix G of the TeXbook)
1857: atom: ['ord', 'op', 'bin', 'rel', 'open', 'close', 'punct', 'ord'],
1858:
1859: // The TeX font families
1860: fam: ['cmr10','cmmi10','cmsy10','cmex10','cmti10','','cmbx10',''],
1861: famName: {cmr10:0, cmmi10:1, cmsy10:2, cmex10:3, cmti10:4, cmbx10:6},
1862:
1863: // Encoding used by jsMath fonts
1864: encoding: [
1865: 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç',
1866: 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï',
1867:
1868: '°', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '·',
1869: 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'µ', '¶', 'ß',
1870:
1871: 'ï', '!', '"', '#', '$', '%', '&', ''',
1872: '(', ')', '*', '+', ',', '-', '.', '/',
1873:
1874: '0', '1', '2', '3', '4', '5', '6', '7',
1875: '8', '9', ':', ';', '<', '=', '>', '?',
1876:
1877: '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1878: 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1879:
1880: 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1881: 'X', 'Y', 'Z', '[', '\', ']', '^', '_',
1882:
1883: '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1884: 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1885:
1886: 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1887: 'x', 'y', 'z', '{', '|', '}', '~', 'ÿ'
1888: ],
1889:
1890: /*
1891: * The following are the TeX font mappings and metrics. The metric
1892: * information comes directly from the TeX .tfm files. Browser-specific
1893: * adjustments are made to these tables in the Browser.Init() routine
1894: */
1895: cmr10: [
1896: [0.625,0.683], [0.833,0.683], [0.778,0.683], [0.694,0.683],
1897: [0.667,0.683], [0.75,0.683], [0.722,0.683], [0.778,0.683],
1898: [0.722,0.683], [0.778,0.683], [0.722,0.683],
1899: [0.583,0.694,0,{ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 14, '108': 15}}],
1900: [0.556,0.694], [0.556,0.694], [0.833,0.694], [0.833,0.694],
1901:
1902: [0.278,0.431], [0.306,0.431,0.194], [0.5,0.694], [0.5,0.694],
1903: [0.5,0.628], [0.5,0.694], [0.5,0.568], [0.75,0.694],
1904: [0.444,0,0.17], [0.5,0.694], [0.722,0.431], [0.778,0.431],
1905: [0.5,0.528,0.0972], [0.903,0.683], [1.01,0.683], [0.778,0.732,0.0486],
1906:
1907: [0.278,0.431,0,{krn: {'108': -0.278, '76': -0.319}}],
1908: [0.278,0.694,0,{lig: {'96': 60}}],
1909: [0.5,0.694], [0.833,0.694,0.194], [0.5,0.75,0.0556],
1910: [0.833,0.75,0.0556], [0.778,0.694],
1911: [0.278,0.694,0,{krn: {'63': 0.111, '33': 0.111}, lig: {'39': 34}}],
1912: [0.389,0.75,0.25], [0.389,0.75,0.25], [0.5,0.75],
1913: [0.778,0.583,0.0833], [0.278,0.106,0.194],
1914: [0.333,0.431,0,{lig: {'45': 123}}],
1915: [0.278,0.106], [0.5,0.75,0.25],
1916:
1917: [0.5,0.644], [0.5,0.644], [0.5,0.644], [0.5,0.644],
1918: [0.5,0.644], [0.5,0.644], [0.5,0.644], [0.5,0.644],
1919: [0.5,0.644], [0.5,0.644], [0.278,0.431], [0.278,0.431,0.194],
1920: [0.278,0.5,0.194], [0.778,0.367,-0.133], [0.472,0.5,0.194],
1921: [0.472,0.694,0,{lig: {'96': 62}}],
1922:
1923: [0.778,0.694],
1924: [0.75,0.683,0,{krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}],
1925: [0.708,0.683], [0.722,0.683],
1926: [0.764,0.683,0,{krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}],
1927: [0.681,0.683],
1928: [0.653,0.683,0,{krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}],
1929: [0.785,0.683], [0.75,0.683], [0.361,0.683,0,{krn: {'73': 0.0278}}],
1930: [0.514,0.683],
1931: [0.778,0.683,0,{krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}],
1932: [0.625,0.683,0,{krn: {'84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}],
1933: [0.917,0.683], [0.75,0.683],
1934: [0.778,0.683,0,{krn: {'88': -0.0278, '87': -0.0278, '65': -0.0278, '86': -0.0278, '89': -0.0278}}],
1935:
1936: [0.681,0.683,0,{krn: {'65': -0.0833, '111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}],
1937: [0.778,0.683,0.194],
1938: [0.736,0.683,0,{krn: {'116': -0.0278, '67': -0.0278, '79': -0.0278, '71': -0.0278, '85': -0.0278, '81': -0.0278, '84': -0.0833, '89': -0.0833, '86': -0.111, '87': -0.111}}],
1939: [0.556,0.683],
1940: [0.722,0.683,0,{krn: {'121': -0.0278, '101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}],
1941: [0.75,0.683],
1942: [0.75,0.683,0,{ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}],
1943: [1.03,0.683,0,{ic: 0.0139, krn: {'111': -0.0833, '101': -0.0833, '117': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.111, '79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}],
1944: [0.75,0.683,0,{krn: {'79': -0.0278, '67': -0.0278, '71': -0.0278, '81': -0.0278}}],
1945: [0.75,0.683,0,{ic: 0.025, krn: {'101': -0.0833, '111': -0.0833, '114': -0.0833, '97': -0.0833, '65': -0.0833, '117': -0.0833}}],
1946: [0.611,0.683], [0.278,0.75,0.25], [0.5,0.694],
1947: [0.278,0.75,0.25], [0.5,0.694], [0.278,0.668],
1948:
1949: [0.278,0.694,0,{lig: {'96': 92}}],
1950: [0.5,0.431,0,{krn: {'118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}],
1951: [0.556,0.694,0,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}],
1952: [0.444,0.431,0,{krn: {'104': -0.0278, '107': -0.0278}}],
1953: [0.556,0.694], [0.444,0.431],
1954: [0.306,0.694,0,{ic: 0.0778, krn: {'39': 0.0778, '63': 0.0778, '33': 0.0778, '41': 0.0778, '93': 0.0778}, lig: {'105': 12, '102': 11, '108': 13}}],
1955: [0.5,0.431,0.194,{ic: 0.0139, krn: {'106': 0.0278}}],
1956: [0.556,0.694,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}],
1957: [0.278,0.668], [0.306,0.668,0.194],
1958: [0.528,0.694,0,{krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}],
1959: [0.278,0.694],
1960: [0.833,0.431,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}],
1961: [0.556,0.431,0,{krn: {'116': -0.0278, '117': -0.0278, '98': -0.0278, '121': -0.0278, '118': -0.0278, '119': -0.0278}}],
1962: [0.5,0.431,0,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}],
1963:
1964: [0.556,0.431,0.194,{krn: {'101': 0.0278, '111': 0.0278, '120': -0.0278, '100': 0.0278, '99': 0.0278, '113': 0.0278, '118': -0.0278, '106': 0.0556, '121': -0.0278, '119': -0.0278}}],
1965: [0.528,0.431,0.194], [0.392,0.431], [0.394,0.431],
1966: [0.389,0.615,0,{krn: {'121': -0.0278, '119': -0.0278}}],
1967: [0.556,0.431,0,{krn: {'119': -0.0278}}],
1968: [0.528,0.431,0,{ic: 0.0139, krn: {'97': -0.0556, '101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}],
1969: [0.722,0.431,0,{ic: 0.0139, krn: {'101': -0.0278, '97': -0.0278, '111': -0.0278, '99': -0.0278}}],
1970: [0.528,0.431],
1971: [0.528,0.431,0.194,{ic: 0.0139, krn: {'111': -0.0278, '101': -0.0278, '97': -0.0278, '46': -0.0833, '44': -0.0833}}],
1972: [0.444,0.431], [0.5,0.431,0,{ic: 0.0278, lig: {'45': 124}}],
1973: [1,0.431,0,{ic: 0.0278}], [0.5,0.694], [0.5,0.668], [0.5,0.668]
1974: ],
1975:
1976: cmmi10: [
1977: [0.615,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}],
1978: [0.833,0.683,0,{krn: {'127': 0.167}}],
1979: [0.763,0.683,0,{ic: 0.0278, krn: {'127': 0.0833}}],
1980: [0.694,0.683,0,{krn: {'127': 0.167}}],
1981: [0.742,0.683,0,{ic: 0.0757, krn: {'127': 0.0833}}],
1982: [0.831,0.683,0,{ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}],
1983: [0.78,0.683,0,{ic: 0.0576, krn: {'127': 0.0833}}],
1984: [0.583,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0556}}],
1985: [0.667,0.683,0,{krn: {'127': 0.0833}}],
1986: [0.612,0.683,0,{ic: 0.11, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}],
1987: [0.772,0.683,0,{ic: 0.0502, krn: {'127': 0.0833}}],
1988: [0.64,0.431,0,{ic: 0.0037, krn: {'127': 0.0278}}],
1989: [0.566,0.694,0.194,{ic: 0.0528, krn: {'127': 0.0833}}],
1990: [0.518,0.431,0.194,{ic: 0.0556}],
1991: [0.444,0.694,0,{ic: 0.0378, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}}],
1992: [0.406,0.431,0,{krn: {'127': 0.0556}}],
1993:
1994: [0.438,0.694,0.194,{ic: 0.0738, krn: {'127': 0.0833}}],
1995: [0.497,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0556}}],
1996: [0.469,0.694,0,{ic: 0.0278, krn: {'127': 0.0833}}],
1997: [0.354,0.431,0,{krn: {'127': 0.0556}}],
1998: [0.576,0.431], [0.583,0.694],
1999: [0.603,0.431,0.194,{krn: {'127': 0.0278}}],
2000: [0.494,0.431,0,{ic: 0.0637, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}}],
2001: [0.438,0.694,0.194,{ic: 0.046, krn: {'127': 0.111}}],
2002: [0.57,0.431,0,{ic: 0.0359}],
2003: [0.517,0.431,0.194,{krn: {'127': 0.0833}}],
2004: [0.571,0.431,0,{ic: 0.0359, krn: {'59': -0.0556, '58': -0.0556}}],
2005: [0.437,0.431,0,{ic: 0.113, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0278}}],
2006: [0.54,0.431,0,{ic: 0.0359, krn: {'127': 0.0278}}],
2007: [0.596,0.694,0.194,{krn: {'127': 0.0833}}],
2008: [0.626,0.431,0.194,{krn: {'127': 0.0556}}],
2009:
2010: [0.651,0.694,0.194,{ic: 0.0359, krn: {'127': 0.111}}],
2011: [0.622,0.431,0,{ic: 0.0359}],
2012: [0.466,0.431,0,{krn: {'127': 0.0833}}],
2013: [0.591,0.694,0,{krn: {'127': 0.0833}}],
2014: [0.828,0.431,0,{ic: 0.0278}],
2015: [0.517,0.431,0.194,{krn: {'127': 0.0833}}],
2016: [0.363,0.431,0.0972,{ic: 0.0799, krn: {'127': 0.0833}}],
2017: [0.654,0.431,0.194,{krn: {'127': 0.0833}}],
2018: [1,0.367,-0.133], [1,0.367,-0.133], [1,0.367,-0.133], [1,0.367,-0.133],
2019: [0.278,0.464,-0.0363], [0.278,0.464,-0.0363], [0.5,0.465,-0.0347], [0.5,0.465,-0.0347],
2020:
2021: [0.5,0.431], [0.5,0.431], [0.5,0.431], [0.5,0.431,0.194],
2022: [0.5,0.431,0.194], [0.5,0.431,0.194], [0.5,0.644], [0.5,0.431,0.194],
2023: [0.5,0.644], [0.5,0.431,0.194], [0.278,0.106], [0.278,0.106,0.194],
2024: [0.778,0.539,0.0391],
2025: [0.5,0.75,0.25,{krn: {'1': -0.0556, '65': -0.0556, '77': -0.0556, '78': -0.0556, '89': 0.0556, '90': -0.0556}}],
2026: [0.778,0.539,0.0391], [0.5,0.465,-0.0347],
2027:
2028: [0.531,0.694,0,{ic: 0.0556, krn: {'127': 0.0833}}],
2029: [0.75,0.683,0,{krn: {'127': 0.139}}],
2030: [0.759,0.683,0,{ic: 0.0502, krn: {'127': 0.0833}}],
2031: [0.715,0.683,0,{ic: 0.0715, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}],
2032: [0.828,0.683,0,{ic: 0.0278, krn: {'127': 0.0556}}],
2033: [0.738,0.683,0,{ic: 0.0576, krn: {'127': 0.0833}}],
2034: [0.643,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}],
2035: [0.786,0.683,0,{krn: {'127': 0.0833}}],
2036: [0.831,0.683,0,{ic: 0.0812, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}],
2037: [0.44,0.683,0,{ic: 0.0785, krn: {'127': 0.111}}],
2038: [0.555,0.683,0,{ic: 0.0962, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.167}}],
2039: [0.849,0.683,0,{ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0556}}],
2040: [0.681,0.683,0,{krn: {'127': 0.0278}}],
2041: [0.97,0.683,0,{ic: 0.109, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}],
2042: [0.803,0.683,0,{ic: 0.109, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}],
2043: [0.763,0.683,0,{ic: 0.0278, krn: {'127': 0.0833}}],
2044:
2045: [0.642,0.683,0,{ic: 0.139, krn: {'61': -0.0556, '59': -0.111, '58': -0.111, '127': 0.0833}}],
2046: [0.791,0.683,0.194,{krn: {'127': 0.0833}}],
2047: [0.759,0.683,0,{ic: 0.00773, krn: {'127': 0.0833}}],
2048: [0.613,0.683,0,{ic: 0.0576, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}],
2049: [0.584,0.683,0,{ic: 0.139, krn: {'61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}],
2050: [0.683,0.683,0,{ic: 0.109, krn: {'59': -0.111, '58': -0.111, '61': -0.0556, '127': 0.0278}}],
2051: [0.583,0.683,0,{ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}],
2052: [0.944,0.683,0,{ic: 0.139, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}],
2053: [0.828,0.683,0,{ic: 0.0785, krn: {'61': -0.0833, '61': -0.0278, '59': -0.0556, '58': -0.0556, '127': 0.0833}}],
2054: [0.581,0.683,0,{ic: 0.222, krn: {'59': -0.167, '58': -0.167, '61': -0.111}}],
2055: [0.683,0.683,0,{ic: 0.0715, krn: {'61': -0.0556, '59': -0.0556, '58': -0.0556, '127': 0.0833}}],
2056: [0.389,0.75], [0.389,0.694,0.194], [0.389,0.694,0.194],
2057: [1,0.358,-0.142], [1,0.358,-0.142],
2058:
2059: [0.417,0.694,0,{krn: {'127': 0.111}}],
2060: [0.529,0.431], [0.429,0.694], [0.433,0.431,0,{krn: {'127': 0.0556}}],
2061: [0.52,0.694,0,{krn: {'89': 0.0556, '90': -0.0556, '106': -0.111, '102': -0.167, '127': 0.167}}],
2062: [0.466,0.431,0,{krn: {'127': 0.0556}}],
2063: [0.49,0.694,0.194,{ic: 0.108, krn: {'59': -0.0556, '58': -0.0556, '127': 0.167}}],
2064: [0.477,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0278}}],
2065: [0.576,0.694,0,{krn: {'127': -0.0278}}], [0.345,0.66],
2066: [0.412,0.66,0.194,{ic: 0.0572, krn: {'59': -0.0556, '58': -0.0556}}],
2067: [0.521,0.694,0,{ic: 0.0315}], [0.298,0.694,0,{ic: 0.0197, krn: {'127': 0.0833}}],
2068: [0.878,0.431], [0.6,0.431], [0.485,0.431,0,{krn: {'127': 0.0556}}],
2069:
2070: [0.503,0.431,0.194,{krn: {'127': 0.0833}}],
2071: [0.446,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0833}}],
2072: [0.451,0.431,0,{ic: 0.0278, krn: {'59': -0.0556, '58': -0.0556, '127': 0.0556}}],
2073: [0.469,0.431,0,{krn: {'127': 0.0556}}], [0.361,0.615,0,{krn: {'127': 0.0833}}],
2074: [0.572,0.431,0,{krn: {'127': 0.0278}}],
2075: [0.485,0.431,0,{ic: 0.0359, krn: {'127': 0.0278}}],
2076: [0.716,0.431,0,{ic: 0.0269, krn: {'127': 0.0833}}],
2077: [0.572,0.431,0,{krn: {'127': 0.0278}}],
2078: [0.49,0.431,0.194,{ic: 0.0359, krn: {'127': 0.0556}}],
2079: [0.465,0.431,0,{ic: 0.044, krn: {'127': 0.0556}}],
2080: [0.322,0.431,0,{krn: {'127': 0.0278}}],
2081: [0.384,0.431,0.194,{krn: {'127': 0.0833}}],
2082: [0.636,0.431,0.194,{krn: {'127': 0.111}}],
2083: [0.5,0.714,0,{ic: 0.154}], [0.278,0.694,0,{ic: 0.399}]
2084: ],
2085:
2086: cmsy10: [
2087: [0.778,0.583,0.0833], [0.278,0.444,-0.0556], [0.778,0.583,0.0833],
2088: [0.5,0.465,-0.0347], [0.778,0.583,0.0833], [0.5,0.444,-0.0556],
2089: [0.778,0.583,0.0833], [0.778,0.583,0.0833], [0.778,0.583,0.0833],
2090: [0.778,0.583,0.0833], [0.778,0.583,0.0833], [0.778,0.583,0.0833],
2091: [0.778,0.583,0.0833], [1,0.694,0.194], [0.5,0.444,-0.0556], [0.5,0.444,-0.0556],
2092:
2093: [0.778,0.464,-0.0363], [0.778,0.464,-0.0363], [0.778,0.636,0.136],
2094: [0.778,0.636,0.136], [0.778,0.636,0.136], [0.778,0.636,0.136],
2095: [0.778,0.636,0.136], [0.778,0.636,0.136], [0.778,0.367,-0.133],
2096: [0.778,0.483,-0.0169], [0.778,0.539,0.0391], [0.778,0.539,0.0391],
2097: [1,0.539,0.0391], [1,0.539,0.0391], [0.778,0.539,0.0391], [0.778,0.539,0.0391],
2098:
2099: [1,0.367,-0.133], [1,0.367,-0.133], [0.5,0.694,0.194], [0.5,0.694,0.194],
2100: [1,0.367,-0.133], [1,0.694,0.194], [1,0.694,0.194], [0.778,0.464,-0.0363],
2101: [1,0.367,-0.133], [1,0.367,-0.133], [0.611,0.694,0.194], [0.611,0.694,0.194],
2102: [1,0.367,-0.133], [1,0.694,0.194], [1,0.694,0.194], [0.778,0.431],
2103:
2104: [0.275,0.556], [1,0.431], [0.667,0.539,0.0391], [0.667,0.539,0.0391],
2105: [0.889,0.694,0.194], [0.889,0.694,0.194], [0,0.694,0.194], [0,0.367,-0.133],
2106: [0.556,0.694], [0.556,0.694], [0.667,0.431], [0.5,0.75,0.0556],
2107: [0.722,0.694], [0.722,0.694], [0.778,0.694], [0.778,0.694],
2108:
2109: [0.611,0.694], [0.798,0.683,0,{krn: {'48': 0.194}}],
2110: [0.657,0.683,0,{ic: 0.0304, krn: {'48': 0.139}}],
2111: [0.527,0.683,0,{ic: 0.0583, krn: {'48': 0.139}}],
2112: [0.771,0.683,0,{ic: 0.0278, krn: {'48': 0.0833}}],
2113: [0.528,0.683,0,{ic: 0.0894, krn: {'48': 0.111}}],
2114: [0.719,0.683,0,{ic: 0.0993, krn: {'48': 0.111}}],
2115: [0.595,0.683,0.0972,{ic: 0.0593, krn: {'48': 0.111}}],
2116: [0.845,0.683,0,{ic: 0.00965, krn: {'48': 0.111}}],
2117: [0.545,0.683,0,{ic: 0.0738, krn: {'48': 0.0278}}],
2118: [0.678,0.683,0.0972,{ic: 0.185, krn: {'48': 0.167}}],
2119: [0.762,0.683,0,{ic: 0.0144, krn: {'48': 0.0556}}],
2120: [0.69,0.683,0,{krn: {'48': 0.139}}], [1.2,0.683,0,{krn: {'48': 0.139}}],
2121: [0.82,0.683,0,{ic: 0.147, krn: {'48': 0.0833}}],
2122: [0.796,0.683,0,{ic: 0.0278, krn: {'48': 0.111}}],
2123:
2124: [0.696,0.683,0,{ic: 0.0822, krn: {'48': 0.0833}}],
2125: [0.817,0.683,0.0972,{krn: {'48': 0.111}}],
2126: [0.848,0.683,0,{krn: {'48': 0.0833}}],
2127: [0.606,0.683,0,{ic: 0.075, krn: {'48': 0.139}}],
2128: [0.545,0.683,0,{ic: 0.254, krn: {'48': 0.0278}}],
2129: [0.626,0.683,0,{ic: 0.0993, krn: {'48': 0.0833}}],
2130: [0.613,0.683,0,{ic: 0.0822, krn: {'48': 0.0278}}],
2131: [0.988,0.683,0,{ic: 0.0822, krn: {'48': 0.0833}}],
2132: [0.713,0.683,0,{ic: 0.146, krn: {'48': 0.139}}],
2133: [0.668,0.683,0.0972,{ic: 0.0822, krn: {'48': 0.0833}}],
2134: [0.725,0.683,0,{ic: 0.0794, krn: {'48': 0.139}}],
2135: [0.667,0.556], [0.667,0.556], [0.667,0.556], [0.667,0.556], [0.667,0.556],
2136:
2137: [0.611,0.694], [0.611,0.694], [0.444,0.75,0.25], [0.444,0.75,0.25],
2138: [0.444,0.75,0.25], [0.444,0.75,0.25], [0.5,0.75,0.25], [0.5,0.75,0.25],
2139: [0.389,0.75,0.25], [0.389,0.75,0.25], [0.278,0.75,0.25], [0.5,0.75,0.25],
2140: [0.5,0.75,0.25], [0.611,0.75,0.25], [0.5,0.75,0.25], [0.278,0.694,0.194],
2141:
2142: [0.833,0.04,0.96], [0.75,0.683], [0.833,0.683], [0.417,0.694,0.194,{ic: 0.111}],
2143: [0.667,0.556], [0.667,0.556], [0.778,0.636,0.136], [0.778,0.636,0.136],
2144: [0.444,0.694,0.194], [0.444,0.694,0.194], [0.444,0.694,0.194],
2145: [0.611,0.694,0.194], [0.778,0.694,0.13], [0.778,0.694,0.13],
2146: [0.778,0.694,0.13], [0.778,0.694,0.13]
2147: ],
2148:
2149: cmex10: [
2150: [0.458,0.04,1.16,{n: 16}], [0.458,0.04,1.16,{n: 17}],
2151: [0.417,0.04,1.16,{n: 104}], [0.417,0.04,1.16,{n: 105}],
2152: [0.472,0.04,1.16,{n: 106}], [0.472,0.04,1.16,{n: 107}],
2153: [0.472,0.04,1.16,{n: 108}], [0.472,0.04,1.16,{n: 109}],
2154: [0.583,0.04,1.16,{n: 110}], [0.583,0.04,1.16,{n: 111}],
2155: [0.472,0.04,1.16,{n: 68}], [0.472,0.04,1.16,{n: 69}],
2156: [0.333,0,0.6,{delim: {rep: 12}}], [0.556,0,0.6,{delim: {rep: 13}}],
2157: [0.578,0.04,1.16,{n: 46}], [0.578,0.04,1.16,{n: 47}],
2158:
2159: [0.597,0.04,1.76,{n: 18}], [0.597,0.04,1.76,{n: 19}],
2160: [0.736,0.04,2.36,{n: 32}], [0.736,0.04,2.36,{n: 33}],
2161: [0.528,0.04,2.36,{n: 34}], [0.528,0.04,2.36,{n: 35}],
2162: [0.583,0.04,2.36,{n: 36}], [0.583,0.04,2.36,{n: 37}],
2163: [0.583,0.04,2.36,{n: 38}], [0.583,0.04,2.36,{n: 39}],
2164: [0.75,0.04,2.36,{n: 40}], [0.75,0.04,2.36,{n: 41}],
2165: [0.75,0.04,2.36,{n: 42}], [0.75,0.04,2.36,{n: 43}],
2166: [1.04,0.04,2.36,{n: 44}], [1.04,0.04,2.36,{n: 45}],
2167:
2168: [0.792,0.04,2.96,{n: 48}], [0.792,0.04,2.96,{n: 49}],
2169: [0.583,0.04,2.96,{n: 50}], [0.583,0.04,2.96,{n: 51}],
2170: [0.639,0.04,2.96,{n: 52}], [0.639,0.04,2.96,{n: 53}],
2171: [0.639,0.04,2.96,{n: 54}], [0.639,0.04,2.96,{n: 55}],
2172: [0.806,0.04,2.96,{n: 56}], [0.806,0.04,2.96,{n: 57}],
2173: [0.806,0.04,2.96], [0.806,0.04,2.96],
2174: [1.28,0.04,2.96], [1.28,0.04,2.96],
2175: [0.811,0.04,1.76,{n: 30}], [0.811,0.04,1.76,{n: 31}],
2176:
2177: [0.875,0.04,1.76,{delim: {top: 48, bot: 64, rep: 66}}],
2178: [0.875,0.04,1.76,{delim: {top: 49, bot: 65, rep: 67}}],
2179: [0.667,0.04,1.76,{delim: {top: 50, bot: 52, rep: 54}}],
2180: [0.667,0.04,1.76,{delim: {top: 51, bot: 53, rep: 55}}],
2181: [0.667,0.04,1.76,{delim: {bot: 52, rep: 54}}],
2182: [0.667,0.04,1.76,{delim: {bot: 53, rep: 55}}],
2183: [0.667,0,0.6,{delim: {top: 50, rep: 54}}],
2184: [0.667,0,0.6,{delim: {top: 51, rep: 55}}],
2185: [0.889,0,0.9,{delim: {top: 56, mid: 60, bot: 58, rep: 62}}],
2186: [0.889,0,0.9,{delim: {top: 57, mid: 61, bot: 59, rep: 62}}],
2187: [0.889,0,0.9,{delim: {top: 56, bot: 58, rep: 62}}],
2188: [0.889,0,0.9,{delim: {top: 57, bot: 59, rep: 62}}],
2189: [0.889,0,1.8,{delim: {rep: 63}}],
2190: [0.889,0,1.8,{delim: {rep: 119}}],
2191: [0.889,0,0.3,{delim: {rep: 62}}],
2192: [0.667,0,0.6,{delim: {top: 120, bot: 121, rep: 63}}],
2193:
2194: [0.875,0.04,1.76,{delim: {top: 56, bot: 59, rep: 62}}],
2195: [0.875,0.04,1.76,{delim: {top: 57, bot: 58, rep: 62}}],
2196: [0.875,0,0.6,{delim: {rep: 66}}], [0.875,0,0.6,{delim: {rep: 67}}],
2197: [0.611,0.04,1.76,{n: 28}], [0.611,0.04,1.76,{n: 29}],
2198: [0.833,0,1,{n: 71}], [1.11,0.1,1.5], [0.472,0,1.11,{ic: 0.194, n: 73}],
2199: [0.556,0,2.22,{ic: 0.444}], [1.11,0,1,{n: 75}], [1.51,0.1,1.5],
2200: [1.11,0,1,{n: 77}], [1.51,0.1,1.5], [1.11,0,1,{n: 79}], [1.51,0.1,1.5],
2201:
2202: [1.06,0,1,{n: 88}], [0.944,0,1,{n: 89}], [0.472,0,1.11,{ic: 0.194, n: 90}],
2203: [0.833,0,1,{n: 91}], [0.833,0,1,{n: 92}], [0.833,0,1,{n: 93}],
2204: [0.833,0,1,{n: 94}], [0.833,0,1,{n: 95}], [1.44,0.1,1.5],
2205: [1.28,0.1,1.5], [0.556,0,2.22,{ic: 0.444}], [1.11,0.1,1.5],
2206: [1.11,0.1,1.5], [1.11,0.1,1.5], [1.11,0.1,1.5], [1.11,0.1,1.5],
2207:
2208: [0.944,0,1,{n: 97}], [1.28,0.1,1.5], [0.556,0.722,0,{n: 99}],
2209: [1,0.75,0,{n: 100}], [1.44,0.75], [0.556,0.722,0,{n: 102}],
2210: [1,0.75,0,{n: 103}], [1.44,0.75], [0.472,0.04,1.76,{n: 20}],
2211: [0.472,0.04,1.76,{n: 21}], [0.528,0.04,1.76,{n: 22}],
2212: [0.528,0.04,1.76,{n: 23}], [0.528,0.04,1.76,{n: 24}],
2213: [0.528,0.04,1.76,{n: 25}], [0.667,0.04,1.76,{n: 26}],
2214: [0.667,0.04,1.76,{n: 27}],
2215:
2216: [1,0.04,1.16,{n: 113}], [1,0.04,1.76,{n: 114}], [1,0.04,2.36,{n: 115}],
2217: [1,0.04,2.96,{n: 116}], [1.06,0,1.8,{delim: {top: 118, bot: 116, rep: 117}}],
2218: [1.06,0,0.6], [1.06,0.04,0.56],
2219: [0.778,0,0.6,{delim: {top: 126, bot: 127, rep: 119}}],
2220: [0.667,0,0.6,{delim: {top: 120, rep: 63}}],
2221: [0.667,0,0.6,{delim: {bot: 121, rep: 63}}],
2222: [0.45,0.12], [0.45,0.12], [0.45,0.12], [0.45,0.12],
2223: [0.778,0,0.6,{delim: {top: 126, rep: 119}}],
2224: [0.778,0,0.6,{delim: {bot: 127, rep: 119}}]
2225: ],
2226:
2227: cmti10: [
2228: [0.627,0.683,0,{ic: 0.133}], [0.818,0.683], [0.767,0.683,0,{ic: 0.094}],
2229: [0.692,0.683], [0.664,0.683,0,{ic: 0.153}], [0.743,0.683,0,{ic: 0.164}],
2230: [0.716,0.683,0,{ic: 0.12}], [0.767,0.683,0,{ic: 0.111}],
2231: [0.716,0.683,0,{ic: 0.0599}], [0.767,0.683,0,{ic: 0.111}],
2232: [0.716,0.683,0,{ic: 0.103}],
2233: [0.613,0.694,0.194,{ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 14, '108': 15}}],
2234: [0.562,0.694,0.194,{ic: 0.103}], [0.588,0.694,0.194,{ic: 0.103}],
2235: [0.882,0.694,0.194,{ic: 0.103}], [0.894,0.694,0.194,{ic: 0.103}],
2236:
2237: [0.307,0.431,0,{ic: 0.0767}], [0.332,0.431,0.194,{ic: 0.0374}],
2238: [0.511,0.694], [0.511,0.694,0,{ic: 0.0969}], [0.511,0.628,0,{ic: 0.083}],
2239: [0.511,0.694,0,{ic: 0.108}], [0.511,0.562,0,{ic: 0.103}], [0.831,0.694],
2240: [0.46,0,0.17], [0.537,0.694,0.194,{ic: 0.105}], [0.716,0.431,0,{ic: 0.0751}],
2241: [0.716,0.431,0,{ic: 0.0751}], [0.511,0.528,0.0972,{ic: 0.0919}],
2242: [0.883,0.683,0,{ic: 0.12}], [0.985,0.683,0,{ic: 0.12}],
2243: [0.767,0.732,0.0486,{ic: 0.094}],
2244:
2245: [0.256,0.431,0,{krn: {'108': -0.256, '76': -0.321}}],
2246: [0.307,0.694,0,{ic: 0.124, lig: {'96': 60}}],
2247: [0.514,0.694,0,{ic: 0.0696}], [0.818,0.694,0.194,{ic: 0.0662}],
2248: [0.769,0.694], [0.818,0.75,0.0556,{ic: 0.136}],
2249: [0.767,0.694,0,{ic: 0.0969}],
2250: [0.307,0.694,0,{ic: 0.124, krn: {'63': 0.102, '33': 0.102}, lig: {'39': 34}}],
2251: [0.409,0.75,0.25,{ic: 0.162}], [0.409,0.75,0.25,{ic: 0.0369}],
2252: [0.511,0.75,0,{ic: 0.149}], [0.767,0.562,0.0567,{ic: 0.0369}],
2253: [0.307,0.106,0.194], [0.358,0.431,0,{ic: 0.0283, lig: {'45': 123}}],
2254: [0.307,0.106], [0.511,0.75,0.25,{ic: 0.162}],
2255:
2256: [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}],
2257: [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}],
2258: [0.511,0.644,0.194,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}],
2259: [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0.194,{ic: 0.136}],
2260: [0.511,0.644,0,{ic: 0.136}], [0.511,0.644,0,{ic: 0.136}],
2261: [0.307,0.431,0,{ic: 0.0582}], [0.307,0.431,0.194,{ic: 0.0582}],
2262: [0.307,0.5,0.194,{ic: 0.0756}], [0.767,0.367,-0.133,{ic: 0.0662}],
2263: [0.511,0.5,0.194], [0.511,0.694,0,{ic: 0.122, lig: {'96': 62}}],
2264:
2265: [0.767,0.694,0,{ic: 0.096}],
2266: [0.743,0.683,0,{krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2267: [0.704,0.683,0,{ic: 0.103}], [0.716,0.683,0,{ic: 0.145}],
2268: [0.755,0.683,0,{ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}],
2269: [0.678,0.683,0,{ic: 0.12}],
2270: [0.653,0.683,0,{ic: 0.133, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}],
2271: [0.774,0.683,0,{ic: 0.0872}], [0.743,0.683,0,{ic: 0.164}],
2272: [0.386,0.683,0,{ic: 0.158}], [0.525,0.683,0,{ic: 0.14}],
2273: [0.769,0.683,0,{ic: 0.145, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}],
2274: [0.627,0.683,0,{krn: {'84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2275: [0.897,0.683,0,{ic: 0.164}], [0.743,0.683,0,{ic: 0.164}],
2276: [0.767,0.683,0,{ic: 0.094, krn: {'88': -0.0256, '87': -0.0256, '65': -0.0256, '86': -0.0256, '89': -0.0256}}],
2277:
2278: [0.678,0.683,0,{ic: 0.103, krn: {'65': -0.0767}}],
2279: [0.767,0.683,0.194,{ic: 0.094}],
2280: [0.729,0.683,0,{ic: 0.0387, krn: {'110': -0.0256, '108': -0.0256, '114': -0.0256, '117': -0.0256, '109': -0.0256, '116': -0.0256, '105': -0.0256, '67': -0.0256, '79': -0.0256, '71': -0.0256, '104': -0.0256, '98': -0.0256, '85': -0.0256, '107': -0.0256, '118': -0.0256, '119': -0.0256, '81': -0.0256, '84': -0.0767, '89': -0.0767, '86': -0.102, '87': -0.102, '101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2281: [0.562,0.683,0,{ic: 0.12}],
2282: [0.716,0.683,0,{ic: 0.133, krn: {'121': -0.0767, '101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}],
2283: [0.743,0.683,0,{ic: 0.164}],
2284: [0.743,0.683,0,{ic: 0.184, krn: {'111': -0.0767, '101': -0.0767, '117': -0.0767, '114': -0.0767, '97': -0.0767, '65': -0.102, '79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}],
2285: [0.999,0.683,0,{ic: 0.184, krn: {'65': -0.0767}}],
2286: [0.743,0.683,0,{ic: 0.158, krn: {'79': -0.0256, '67': -0.0256, '71': -0.0256, '81': -0.0256}}],
2287: [0.743,0.683,0,{ic: 0.194, krn: {'101': -0.0767, '111': -0.0767, '114': -0.0767, '97': -0.0767, '117': -0.0767, '65': -0.0767}}],
2288: [0.613,0.683,0,{ic: 0.145}], [0.307,0.75,0.25,{ic: 0.188}],
2289: [0.514,0.694,0,{ic: 0.169}], [0.307,0.75,0.25,{ic: 0.105}],
2290: [0.511,0.694,0,{ic: 0.0665}], [0.307,0.668,0,{ic: 0.118}],
2291:
2292: [0.307,0.694,0,{ic: 0.124, lig: {'96': 92}}], [0.511,0.431,0,{ic: 0.0767}],
2293: [0.46,0.694,0,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2294: [0.46,0.431,0,{ic: 0.0565, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2295: [0.511,0.694,0,{ic: 0.103, krn: {'108': 0.0511}}],
2296: [0.46,0.431,0,{ic: 0.0751, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2297: [0.307,0.694,0.194,{ic: 0.212, krn: {'39': 0.104, '63': 0.104, '33': 0.104, '41': 0.104, '93': 0.104}, lig: {'105': 12, '102': 11, '108': 13}}],
2298: [0.46,0.431,0.194,{ic: 0.0885}], [0.511,0.694,0,{ic: 0.0767}],
2299: [0.307,0.655,0,{ic: 0.102}], [0.307,0.655,0.194,{ic: 0.145}],
2300: [0.46,0.694,0,{ic: 0.108}], [0.256,0.694,0,{ic: 0.103, krn: {'108': 0.0511}}],
2301: [0.818,0.431,0,{ic: 0.0767}], [0.562,0.431,0,{ic: 0.0767, krn: {'39': -0.102}}],
2302: [0.511,0.431,0,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2303:
2304: [0.511,0.431,0.194,{ic: 0.0631, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2305: [0.46,0.431,0.194,{ic: 0.0885}],
2306: [0.422,0.431,0,{ic: 0.108, krn: {'101': -0.0511, '97': -0.0511, '111': -0.0511, '100': -0.0511, '99': -0.0511, '103': -0.0511, '113': -0.0511}}],
2307: [0.409,0.431,0,{ic: 0.0821}], [0.332,0.615,0,{ic: 0.0949}],
2308: [0.537,0.431,0,{ic: 0.0767}], [0.46,0.431,0,{ic: 0.108}],
2309: [0.664,0.431,0,{ic: 0.108, krn: {'108': 0.0511}}],
2310: [0.464,0.431,0,{ic: 0.12}], [0.486,0.431,0.194,{ic: 0.0885}],
2311: [0.409,0.431,0,{ic: 0.123}], [0.511,0.431,0,{ic: 0.0921, lig: {'45': 124}}],
2312: [1.02,0.431,0,{ic: 0.0921}], [0.511,0.694,0,{ic: 0.122}],
2313: [0.511,0.668,0,{ic: 0.116}], [0.511,0.668,0,{ic: 0.105}]
2314: ],
2315:
2316: cmbx10: [
2317: [0.692,0.686], [0.958,0.686], [0.894,0.686], [0.806,0.686],
2318: [0.767,0.686], [0.9,0.686], [0.831,0.686], [0.894,0.686],
2319: [0.831,0.686], [0.894,0.686], [0.831,0.686],
2320: [0.671,0.694,0,{ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 14, '108': 15}}],
2321: [0.639,0.694], [0.639,0.694], [0.958,0.694], [0.958,0.694],
2322:
2323: [0.319,0.444], [0.351,0.444,0.194], [0.575,0.694], [0.575,0.694],
2324: [0.575,0.632], [0.575,0.694], [0.575,0.596], [0.869,0.694],
2325: [0.511,0,0.17], [0.597,0.694], [0.831,0.444], [0.894,0.444],
2326: [0.575,0.542,0.0972], [1.04,0.686], [1.17,0.686], [0.894,0.735,0.0486],
2327:
2328: [0.319,0.444,0,{krn: {'108': -0.319, '76': -0.378}}],
2329: [0.35,0.694,0,{lig: {'96': 60}}], [0.603,0.694], [0.958,0.694,0.194],
2330: [0.575,0.75,0.0556], [0.958,0.75,0.0556], [0.894,0.694],
2331: [0.319,0.694,0,{krn: {'63': 0.128, '33': 0.128}, lig: {'39': 34}}],
2332: [0.447,0.75,0.25], [0.447,0.75,0.25], [0.575,0.75], [0.894,0.633,0.133],
2333: [0.319,0.156,0.194], [0.383,0.444,0,{lig: {'45': 123}}],
2334: [0.319,0.156], [0.575,0.75,0.25],
2335:
2336: [0.575,0.644], [0.575,0.644], [0.575,0.644], [0.575,0.644],
2337: [0.575,0.644], [0.575,0.644], [0.575,0.644], [0.575,0.644],
2338: [0.575,0.644], [0.575,0.644], [0.319,0.444], [0.319,0.444,0.194],
2339: [0.35,0.5,0.194], [0.894,0.391,-0.109], [0.543,0.5,0.194],
2340: [0.543,0.694,0,{lig: {'96': 62}}],
2341:
2342: [0.894,0.694],
2343: [0.869,0.686,0,{krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}],
2344: [0.818,0.686], [0.831,0.686],
2345: [0.882,0.686,0,{krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}}],
2346: [0.756,0.686],
2347: [0.724,0.686,0,{krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}],
2348: [0.904,0.686], [0.9,0.686], [0.436,0.686,0,{krn: {'73': 0.0319}}],
2349: [0.594,0.686],
2350: [0.901,0.686,0,{krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}],
2351: [0.692,0.686,0,{krn: {'84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}],
2352: [1.09,0.686], [0.9,0.686],
2353: [0.864,0.686,0,{krn: {'88': -0.0319, '87': -0.0319, '65': -0.0319, '86': -0.0319, '89': -0.0319}}],
2354:
2355: [0.786,0.686,0,{krn: {'65': -0.0958, '111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}}],
2356: [0.864,0.686,0.194],
2357: [0.862,0.686,0,{krn: {'116': -0.0319, '67': -0.0319, '79': -0.0319, '71': -0.0319, '85': -0.0319, '81': -0.0319, '84': -0.0958, '89': -0.0958, '86': -0.128, '87': -0.128}}],
2358: [0.639,0.686],
2359: [0.8,0.686,0,{krn: {'121': -0.0319, '101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}}],
2360: [0.885,0.686],
2361: [0.869,0.686,0,{ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}],
2362: [1.19,0.686,0,{ic: 0.016, krn: {'111': -0.0958, '101': -0.0958, '117': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.128, '79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}],
2363: [0.869,0.686,0,{krn: {'79': -0.0319, '67': -0.0319, '71': -0.0319, '81': -0.0319}}],
2364: [0.869,0.686,0,{ic: 0.0287, krn: {'101': -0.0958, '111': -0.0958, '114': -0.0958, '97': -0.0958, '65': -0.0958, '117': -0.0958}}],
2365: [0.703,0.686], [0.319,0.75,0.25], [0.603,0.694], [0.319,0.75,0.25],
2366: [0.575,0.694], [0.319,0.694],
2367:
2368: [0.319,0.694,0,{lig: {'96': 92}}],
2369: [0.559,0.444,0,{krn: {'118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}],
2370: [0.639,0.694,0,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}],
2371: [0.511,0.444,0,{krn: {'104': -0.0319, '107': -0.0319}}],
2372: [0.639,0.694], [0.527,0.444],
2373: [0.351,0.694,0,{ic: 0.109, krn: {'39': 0.109, '63': 0.109, '33': 0.109, '41': 0.109, '93': 0.109}, lig: {'105': 12, '102': 11, '108': 13}}],
2374: [0.575,0.444,0.194,{ic: 0.016, krn: {'106': 0.0319}}],
2375: [0.639,0.694,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}],
2376: [0.319,0.694], [0.351,0.694,0.194],
2377: [0.607,0.694,0,{krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}],
2378: [0.319,0.694],
2379: [0.958,0.444,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}],
2380: [0.639,0.444,0,{krn: {'116': -0.0319, '117': -0.0319, '98': -0.0319, '121': -0.0319, '118': -0.0319, '119': -0.0319}}],
2381: [0.575,0.444,0,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}],
2382:
2383: [0.639,0.444,0.194,{krn: {'101': 0.0319, '111': 0.0319, '120': -0.0319, '100': 0.0319, '99': 0.0319, '113': 0.0319, '118': -0.0319, '106': 0.0639, '121': -0.0319, '119': -0.0319}}],
2384: [0.607,0.444,0.194], [0.474,0.444], [0.454,0.444],
2385: [0.447,0.635,0,{krn: {'121': -0.0319, '119': -0.0319}}],
2386: [0.639,0.444,0,{krn: {'119': -0.0319}}],
2387: [0.607,0.444,0,{ic: 0.016, krn: {'97': -0.0639, '101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}],
2388: [0.831,0.444,0,{ic: 0.016, krn: {'101': -0.0319, '97': -0.0319, '111': -0.0319, '99': -0.0319}}],
2389: [0.607,0.444],
2390: [0.607,0.444,0.194,{ic: 0.016, krn: {'111': -0.0319, '101': -0.0319, '97': -0.0319, '46': -0.0958, '44': -0.0958}}],
2391: [0.511,0.444], [0.575,0.444,0,{ic: 0.0319, lig: {'45': 124}}],
2392: [1.15,0.444,0,{ic: 0.0319}], [0.575,0.694], [0.575,0.694], [0.575,0.694]
2393: ]
2394: };
2395:
2396: /***************************************************************************/
2397:
2398: /*
2399: * Implement image-based fonts for fallback method
2400: */
2401: jsMath.Img = {
2402:
2403: // font sizes available
2404: fonts: [50, 60, 70, 85, 100, 120, 144, 173, 207, 249, 298, 358, 430],
2405:
2406: // em widths for the various font size directories
2407: w: {'50': 6.9, '60': 8.3, '70': 9.7, '85': 11.8, '100': 13.9,
2408: '120': 16.7, '144': 20.0, '173': 24.0, '207': 28.8, '249': 34.6,
2409: '298': 41.4, '358': 49.8, '430': 59.8},
2410:
2411: best: 4, // index of best font size in the fonts list
2412: update: {}, // fonts to update (see UpdateFonts below)
2413: factor: 1, // factor by which to shrink images (for better printing)
2414: loaded: 0, // image fonts are loaded
2415:
2416: // add characters to be drawn using images
2417: SetFont: function (change) {
2418: for (var font in change) {
2419: if (!this.update[font]) {this.update[font] = []}
2420: this.update[font] = this.update[font].concat(change[font]);
2421: }
2422: },
2423:
2424: /*
2425: * Called by the exta-font definition files to add an image font
2426: * into the mix
2427: */
2428: AddFont: function (size,def) {
2429: if (!jsMath.Img[size]) {jsMath.Img[size] = {}};
2430: jsMath.Add(jsMath.Img[size],def);
2431: },
2432:
2433: /*
2434: * Update font(s) to use image data rather than native fonts
2435: * It looks in the jsMath.Img.update array to find the names
2436: * of the fonts to udpate, and the arrays of character codes
2437: * to set (or 'all' to change every character);
2438: */
2439: UpdateFonts: function () {
2440: var change = this.update; if (!this.loaded) return;
2441: for (var font in change) {
2442: for (var i = 0; i < change[font].length; i++) {
2443: var c = change[font][i];
2444: if (c == 'all') {for (c in jsMath.TeX[font]) {jsMath.TeX[font][c].img = {}}}
2445: else {jsMath.TeX[font][c].img = {}}
2446: }
2447: }
2448: this.update = {};
2449: },
2450:
2451: /*
2452: * Find the font size that best fits our current font
2453: * (this is the directory name for the img files used
2454: * in some fallback modes).
2455: */
2456: BestSize: function () {
2457: var w = jsMath.em * this.factor;
2458: var m = this.w[this.fonts[0]];
2459: for (var i = 1; i < this.fonts.length; i++) {
2460: if (w < (this.w[this.fonts[i]] + 2*m) / 3) {return i-1}
2461: m = this.w[this.fonts[i]];
2462: }
2463: return i-1;
2464: },
2465:
2466: /*
2467: * Get the scaling factor for the image fonts
2468: */
2469: Scale: function () {
2470: if (!this.loaded) return;
2471: this.best = this.BestSize();
2472: this.em = jsMath.Img.w[this.fonts[this.best]];
2473: this.scale = (jsMath.em/this.em);
2474: if (Math.abs(this.scale - 1) < .12) {this.scale = 1}
2475: },
2476:
2477: /*
2478: * Get URL to directory for given font and size, based on the
2479: * user's alpha/plain setting
2480: */
2481: URL: function (name,size,C) {
2482: var type = (jsMath.Controls.cookie.alpha) ? '/alpha/': '/plain/';
2483: if (C == null) {C = "def.js"} else {C = 'char'+C+'.png'}
2484: if (size != "") {size += '/'}
2485: return this.root+name+type+size+C;
2486: },
2487:
2488: /*
2489: * Laod the data for an image font
2490: */
2491: LoadFont: function (name) {
2492: if (!this.loaded) this.Init();
2493: jsMath.Setup.Script(this.URL(name,""));
2494: },
2495:
2496: /*
2497: * Setup for print mode, and create the hex code table
2498: */
2499: Init: function () {
1.2 albertel 2500: if (jsMath.Controls.cookie.print || jsMath.Controls.cookie.stayhires) {
2501: jsMath.Controls.cookie.print = jsMath.Controls.cookie.stayhires;
1.1 albertel 2502: this.factor *= 3;
1.2 albertel 2503: if (!jsMath.Controls.isLocalCookie || !jsMath.Global.isLocal) {jsMath.Controls.SetCookie(0)}
1.1 albertel 2504: if (jsMath.Browser.alphaPrintBug) {jsMath.Controls.cookie.alpha = 0}
2505: }
2506: var codes = '0123456789ABCDEF';
2507: this.HexCode = [];
2508: for (var i = 0; i < 128; i++) {
2509: var h = Math.floor(i/16); var l = i - 16*h;
2510: this.HexCode[i] = codes.charAt(h)+codes.charAt(l);
2511: }
2512: this.loaded = 1;
2513: }
2514:
2515: };
2516:
2517: /***************************************************************************/
2518:
2519: /*
2520: * jsMath.HTML handles creation of most of the HTML needed for
2521: * presenting mathematics in HTML pages.
2522: */
2523:
2524: jsMath.HTML = {
2525:
2526: /*
2527: * Produce a string version of a measurement in ems,
2528: * showing only a limited number of digits, and
2529: * using 0 when the value is near zero.
2530: */
2531: Em: function (m) {
2532: var n = 5; if (m < 0) {n++}
2533: if (Math.abs(m) < .000001) {m = 0}
2534: var s = String(m); s = s.replace(/(\.\d\d\d).+/,'$1');
2535: return s+'em'
2536: },
2537:
2538: /*
2539: * Create a horizontal space of width w
2540: */
2541: Spacer: function (w) {
2542: if (w == 0) {return ''};
1.2 albertel 2543: return jsMath.Browser.msieSpaceFix+'<span class="spacer" style="margin-left:'+this.Em(w)+'"></span>';
1.1 albertel 2544: },
2545:
2546: /*
2547: * Create a blank rectangle of the given size
2548: * If the height is small, it is converted to pixels so that it
2549: * will not disappear at small font sizes.
2550: */
2551:
2552: Blank: function (w,h,d,isRule) {
2553: var backspace = ''; var style = ''
2554: if (isRule) {
2555: style += 'border-left:'+this.Em(w)+' solid;';
2556: if (jsMath.Browser.widthAddsBorder) {w = 0};
2557: }
2558: if (w == 0) {
2559: if (jsMath.Browser.blankWidthBug) {
2560: style += 'width:1px;';
2561: backspace = '<span class="spacer" style="margin-right:-1px"></span>'
2562: }
2563: } else {style += 'width:'+this.Em(w)+';'}
2564: if (d == null) {d = 0}
2565: if (h) {
2566: var H = this.Em(h+d);
1.2 albertel 2567: if (isRule && h*jsMath.em < 1.5) {H = "1px"; h = 1/jsMath.em}
1.1 albertel 2568: style += 'height:'+H+';';
2569: }
2570: if (jsMath.Browser.mozInlineBlockBug) {d = -h}
2571: if (jsMath.Browser.msieBorderBug && !isRule) {d -= jsMath.d}
2572: if (d) {style += 'vertical-align:'+this.Em(-d)}
2573: return backspace+'<span class="blank" style="'+style+'"></span>';
2574: },
2575:
2576: /*
2577: * Create a rule line for fractions, etc.
2578: */
2579: Rule: function (w,h) {
2580: if (h == null) {h = jsMath.TeX.default_rule_thickness}
2581: return this.Blank(w,h,0,1);
2582: },
2583:
2584: /*
2585: * Add a <SPAN> tag to activate a specific CSS class
2586: */
2587: Class: function (tclass,html) {
2588: return '<span class="'+tclass+'">'+html+'</span>';
2589: },
2590:
2591: /*
2592: * Use a <SPAN> to place some HTML at a specific position.
2593: * (This can be replaced by the ones below to overcome
2594: * some browser-specific bugs.)
2595: */
2596: Place: function (html,x,y) {
2597: if (Math.abs(x) < .0001) {x = 0}
2598: if (Math.abs(y) < .0001) {y = 0}
2599: if (x || y) {
2600: var span = '<span style="position: relative;';
2601: if (x) {span += ' margin-left:'+this.Em(x)+';'}
2602: if (y) {span += ' top:'+this.Em(-y)+';'}
2603: html = span + '">' + html + '</span>';
2604: }
2605: return html;
2606: },
2607:
2608: /*
2609: * For MSIE on Windows, backspacing must be done in a separate
2610: * <SPAN>, otherwise the contents will be clipped. Netscape
2611: * also doesn't combine vertical and horizontal spacing well.
2612: * Here the x and y positioning are done in separate <SPAN> tags
2613: */
1.3 ! albertel 2614: PlaceSeparateSkips: function (html,x,y,mw,Mw,w) {
1.1 albertel 2615: if (Math.abs(x) < .0001) {x = 0}
2616: if (Math.abs(y) < .0001) {y = 0}
1.3 ! albertel 2617: if (y) {
! 2618: var lw = 0; var rw = 0; var width = "";
! 2619: if (mw != null) {
! 2620: rw = Mw - w; lw = mw;
! 2621: width = ' width:'+this.Em(Mw-mw)+';';
! 2622: }
! 2623: html =
! 2624: this.Spacer(lw-rw) +
! 2625: '<span style="position: relative; '
! 2626: + 'top:'+this.Em(-y)+';'
! 2627: + 'left:'+this.Em(rw)+';'
! 2628: + width + '">' +
! 2629: this.Spacer(-lw) +
! 2630: html +
! 2631: this.Spacer(rw) +
! 2632: '</span>'
! 2633: }
1.1 albertel 2634: if (x) {html = this.Spacer(x) + html}
2635: return html;
2636: },
2637:
2638: /*
2639: * Place a SPAN with absolute coordinates
2640: */
1.3 ! albertel 2641: PlaceAbsolute: function (html,x,y,mw,Mw,w) {
1.1 albertel 2642: if (Math.abs(x) < .0001) {x = 0}
2643: if (Math.abs(y) < .0001) {y = 0}
1.3 ! albertel 2644: var leftSpace = ""; var rightSpace = "";
! 2645: if (jsMath.Browser.msieRelativeClipBug && mw != null) {
! 2646: leftSpace = this.Spacer(-mw); x += mw;
! 2647: rightSpace = this.Spacer(Mw-w);
! 2648: }
! 2649: html =
! 2650: '<span style="position:absolute; left:'+this.Em(x)+'; '
! 2651: + 'top:'+this.Em(y)+';">' +
! 2652: leftSpace + html + rightSpace +
! 2653: ' ' + // space normalizes line height in script styles
! 2654: '</span>';
1.1 albertel 2655: return html;
2656: },
2657:
2658: Absolute: function(html,w,h,d,y,H) {
2659: if (y != "none") {
2660: if (Math.abs(y) < .0001) {y = 0}
2661: html = '<span style="position:absolute; '
2662: + 'top:'+jsMath.HTML.Em(y)+'; left:0em;">'
2663: + html + ' ' // space normalizes line height in script styles
2664: + '</span>';
2665: }
2666: if (d == "none") {d = 0}
2667: html += this.Blank(w,h-d,d);
2668: if (jsMath.Browser.msieAbsoluteBug) { // for MSIE (Mac)
2669: html = '<span style="position:relative;">' + html + '</span>';
2670: }
1.3 ! albertel 2671: if (jsMath.Browser.spanHeightVaries) {
! 2672: html = '<span style="position:relative;'
! 2673: + ' width:'+jsMath.HTML.Em(w)+';'
! 2674: + ' height:'+jsMath.HTML.Em(H)+';'
! 2675: + jsMath.Browser.msieInlineBlockFix
! 2676: + '">'
1.1 albertel 2677: + html
2678: + '</span>';
1.3 ! albertel 2679: } else {
! 2680: html = '<span style="position:relative">' + html + '</span>';
! 2681: }
1.1 albertel 2682: return html;
2683: }
2684:
2685: };
2686:
2687:
2688: /***************************************************************************/
2689:
2690: /*
2691: * jsMath.Box handles TeX's math boxes and jsMath's equivalent of hboxes.
2692: */
2693:
2694: jsMath.Box = function (format,text,w,h,d) {
2695: if (d == null) {d = jsMath.d}
2696: this.type = 'typeset';
2697: this.w = w; this.h = h; this.d = d; this.bh = h; this.bd = d;
1.3 ! albertel 2698: this.x = 0; this.y = 0; this.mw = 0; this.Mw = w;
1.1 albertel 2699: this.html = text; this.format = format;
2700: };
2701:
2702:
2703: jsMath.Add(jsMath.Box,{
2704:
2705: defaultH: 0, // default height for characters with none specified
2706:
2707: /*
2708: * An empty box
2709: */
1.3 ! albertel 2710: Null: function () {return new jsMath.Box('null','',0,0,0)},
1.1 albertel 2711:
2712: /*
2713: * A box containing only text whose class and style haven't been added
2714: * yet (so that we can combine ones with the same styles). It gets
2715: * the text dimensions, if needed. (In general, this has been
2716: * replaced by TeX() below, but is still used in fallback mode.)
2717: */
2718: Text: function (text,tclass,style,size,a,d) {
2719: var html = jsMath.Typeset.AddClass(tclass,text);
2720: html = jsMath.Typeset.AddStyle(style,size,html);
2721: var BB = jsMath.EmBoxFor(html); var TeX = jsMath.Typeset.TeX(style,size);
2722: var bd = ((tclass == 'cmsy10' || tclass == 'cmex10')? BB.h-TeX.h: TeX.d*BB.h/TeX.hd);
2723: var box = new jsMath.Box('text',text,BB.w,BB.h-bd,bd);
2724: box.style = style; box.size = size; box.tclass = tclass;
2725: if (d != null) {box.d = d*TeX.scale} else {box.d = 0}
2726: if (a == null || a == 1) {box.h = .9*TeX.M_height}
2727: else {box.h = 1.1*TeX.x_height + TeX.scale*a}
2728: return box;
2729: },
2730:
2731: /*
2732: * Produce a box containing a given TeX character from a given font.
2733: * The box is a text box (like the ones above), so that characters from
2734: * the same font can be combined.
2735: */
2736: TeX: function (C,font,style,size) {
2737: var c = jsMath.TeX[font][C];
2738: if (c.d == null) {c.d = 0}; if (c.h == null) {c.h = 0}
2739: if (c.img != null && c.c != '') this.TeXIMG(font,C,jsMath.Typeset.StyleSize(style,size));
2740: var scale = jsMath.Typeset.TeX(style,size).scale;
2741: var h = c.h + jsMath.TeX[font].dh
2742: var box = new jsMath.Box('text',c.c,c.w*scale,h*scale,c.d*scale);
2743: box.style = style; box.size = size;
2744: if (c.tclass) {
2745: box.tclass = c.tclass;
2746: if (c.img) {box.bh = c.img.bh; box.bd = c.img.bd}
2747: else {box.bh = scale*jsMath.h; box.bd = scale*jsMath.d}
2748: } else {
2749: box.tclass = font;
2750: box.bh = scale*jsMath.TeX[font].h;
2751: box.bd = scale*jsMath.TeX[font].d;
2752: if (jsMath.Browser.msieFontBug && box.html.match(/&#/)) {
2753: // hack to avoid font changing back to the default
2754: // font when a unicode reference is not followed
2755: // by a letter or number
1.2 albertel 2756: box.html += '<span style="display:none">x</span>';
1.1 albertel 2757: }
2758: }
2759: return box;
2760: },
2761:
2762: /*
2763: * In fallback modes, handle the fact that we don't have the
2764: * sizes of the characters precomputed
2765: */
2766: TeXfallback: function (C,font,style,size) {
1.2 albertel 2767: var c = jsMath.TeX[font][C]; if (!c.tclass) {c.tclass = font}
1.1 albertel 2768: if (c.img != null) {return this.TeXnonfallback(C,font,style,size)}
2769: if (c.h != null && c.a == null) {c.a = c.h-1.1*jsMath.TeX.x_height}
1.3 ! albertel 2770: var a = c.a; var d = c.d; // avoid Firefox warnings
! 2771: var box = this.Text(c.c,c.tclass,style,size,a,d);
1.1 albertel 2772: var scale = jsMath.Typeset.TeX(style,size).scale;
2773: if (c.bh != null) {
2774: box.bh = c.bh*scale;
2775: box.bd = c.bd*scale;
2776: } else {
2777: var h = box.bd+box.bh;
2778: var html = jsMath.Typeset.AddClass(box.tclass,box.html);
2779: html = jsMath.Typeset.AddStyle(style,size,html);
2780: box.bd = jsMath.EmBoxFor(html+jsMath.HTML.Blank(1,h)).h - h;
2781: box.bh = h - box.bd;
2782: if (scale == 1) {c.bh = box.bh; c.bd = box.bd}
2783: }
2784: if (jsMath.msieFontBug && box.html.match(/&#/))
2785: {box.html += '<span style="display:none">x</span>'}
2786: return box;
2787: },
2788:
2789: /*
2790: * Set the character's string to the appropriate image file
2791: */
2792: TeXIMG: function (font,C,size) {
2793: var c = jsMath.TeX[font][C];
2794: if (c.img.size != null && c.img.size == size &&
2795: c.img.best != null && c.img.best == jsMath.Img.best) return;
2796: var mustScale = (jsMath.Img.scale != 1);
2797: var id = jsMath.Img.best + size - 4;
2798: if (id < 0) {id = 0; mustScale = 1} else
2799: if (id >= jsMath.Img.fonts.length) {id = jsMath.Img.fonts.length-1; mustScale = 1}
2800: var imgFont = jsMath.Img[jsMath.Img.fonts[id]];
2801: var img = imgFont[font][C];
2802: var scale = 1/jsMath.Img.w[jsMath.Img.fonts[id]];
2803: if (id != jsMath.Img.best + size - 4) {
2804: if (c.w != null) {scale = c.w/img[0]} else {
2805: scale *= jsMath.Img.fonts[size]/jsMath.Img.fonts[4]
2806: * jsMath.Img.fonts[jsMath.Img.best]/jsMath.Img.fonts[id];
2807: }
2808: }
2809: var w = img[0]*scale; var h = img[1]*scale; var d = -img[2]*scale; var v;
2810: var wadjust = (c.w == null || Math.abs(c.w-w) < .01)? "" : " margin-right:"+jsMath.HTML.Em(c.w-w)+';';
2811: var resize = ""; C = jsMath.Img.HexCode[C];
2812: if (!mustScale && !jsMath.Controls.cookie.scaleImg) {
2813: if (2*w < h || (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha))
2814: {resize = "height:"+(img[1]*jsMath.Browser.imgScale)+'px;'}
2815: resize += " width:"+(img[0]*jsMath.Browser.imgScale)+'px;'
2816: v = -img[2]+'px';
2817: } else {
2818: if (2*w < h || (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha))
2819: {resize = "height:"+jsMath.HTML.Em(h*jsMath.Browser.imgScale)+';'}
2820: resize += " width:"+jsMath.HTML.Em(w*jsMath.Browser.imgScale)+';'
2821: v = jsMath.HTML.Em(d);
2822: }
2823: var vadjust = (Math.abs(d) < .01 && !jsMath.Browser.valignBug)?
2824: "": " vertical-align:"+v+';';
2825: var URL = jsMath.Img.URL(font,jsMath.Img.fonts[id],C);
2826: if (jsMath.Browser.msieAlphaBug && jsMath.Controls.cookie.alpha) {
2827: c.c = '<img src="'+jsMath.blank+'" '
2828: + 'style="'+jsMath.Browser.msieCenterBugFix
2829: + resize + vadjust + wadjust
2830: + ' filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' + "'"
2831: + URL + "', sizingMethod='scale'" + ');" />';
2832: } else {
2833: c.c = '<img src="'+URL+'" style="'+jsMath.Browser.msieCenterBugFix
2834: + resize + vadjust + wadjust + '" />';
2835: }
2836: c.tclass = "normal";
2837: c.img.bh = h+d; c.img.bd = -d;
2838: c.img.size = size; c.img.best = jsMath.Img.best;
2839: },
2840:
2841: /*
2842: * A box containing a spacer of a specific width
2843: */
2844: Space: function (w) {
2845: return new jsMath.Box('html',jsMath.HTML.Spacer(w),w,0,0);
2846: },
2847:
2848: /*
2849: * A box containing a horizontal rule
2850: */
2851: Rule: function (w,h) {
2852: if (h == null) {h = jsMath.TeX.default_rule_thickness}
2853: var html = jsMath.HTML.Rule(w,h);
2854: return new jsMath.Box('html',html,w,h,0);
2855: },
2856:
2857: /*
2858: * Get a character from a TeX font, and make sure that it has
2859: * its metrics specified.
2860: */
2861: GetChar: function (code,font) {
2862: var c = jsMath.TeX[font][code];
2863: if (c.img != null) {this.TeXIMG(font,code,4)}
2864: if (c.tclass == null) {c.tclass = font}
2865: if (!c.computedW) {
2866: c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w;
2867: if (c.h == null) {c.h = jsMath.Box.defaultH}; if (c.d == null) {c.d = 0}
2868: c.computedW = 1;
2869: }
2870: return c;
2871: },
2872:
2873: /*
2874: * Locate the TeX delimiter character that matches a given height.
2875: * Return the character, font, style and actual height used.
2876: */
2877: DelimBestFit: function (H,c,font,style) {
2878: if (c == 0 && font == 0) return null;
2879: var C; var h; font = jsMath.TeX.fam[font];
2880: var isSS = (style.charAt(1) == 'S');
2881: var isS = (style.charAt(0) == 'S');
2882: while (c != null) {
2883: C = jsMath.TeX[font][c];
2884: if (C.h == null) {C.h = jsMath.Box.defaultH}; if (C.d == null) {C.d = 0}
2885: h = C.h+C.d;
2886: if (C.delim) {return [c,font,'',H]}
2887: if (isSS && .5*h >= H) {return [c,font,'SS',.5*h]}
2888: if (isS && .7*h >= H) {return [c,font,'S',.7*h]}
2889: if (h >= H || C.n == null) {return [c,font,'T',h]}
2890: c = C.n;
2891: }
2892: return null;
2893: },
2894:
2895: /*
2896: * Create the HTML needed for a stretchable delimiter of a given height,
2897: * either centered or not. This version uses relative placement (i.e.,
2898: * backspaces, not line-breaks). This works with more browsers, but
2899: * if the font size changes, the backspacing may not be right, so the
2900: * delimiters may become jagged.
2901: */
2902: DelimExtendRelative: function (H,c,font,a,nocenter) {
2903: var C = jsMath.TeX[font][c];
2904: var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font);
2905: var rep = this.GetChar(C.delim.rep,font);
2906: var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);
2907: var ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);
2908: var w = rep.w; var h = rep.h+rep.d
1.3 ! albertel 2909: var y; var Y; var html; var dx; var i; var n;
1.1 albertel 2910: if (C.delim.mid) {// braces
2911: var mid = this.GetChar(C.delim.mid,font);
1.3 ! albertel 2912: n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d)-(bot.h+bot.d))/(2*(rep.h+rep.d)));
1.1 albertel 2913: H = 2*n*(rep.h+rep.d) + (top.h+top.d) + (mid.h+mid.d) + (bot.h+bot.d);
1.3 ! albertel 2914: if (nocenter) {y = 0} else {y = H/2+a}; Y = y;
! 2915: html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)
! 2916: + jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(top.w+bot.w)/2,y-(H-bot.d))
! 2917: + jsMath.HTML.Place(jsMath.Typeset.AddClass(mid.tclass,mid.c),-(bot.w+mid.w)/2,y-(H+mid.h-mid.d)/2);
1.1 albertel 2918: dx = (w-mid.w)/2; if (Math.abs(dx) < .0001) {dx = 0}
2919: if (dx) {html += jsMath.HTML.Spacer(dx)}
2920: y -= top.h+top.d + rep.h;
1.3 ! albertel 2921: for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
1.1 albertel 2922: y -= H/2 - rep.h/2;
1.3 ! albertel 2923: for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
1.1 albertel 2924: } else {// everything else
1.3 ! albertel 2925: n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d))/(rep.h+rep.d));
1.1 albertel 2926: // make sure two-headed arrows have an extender
2927: if (top.h+top.d < .9*(rep.h+rep.d)) {n = Math.max(1,n)}
2928: H = n*(rep.h+rep.d) + (top.h+top.d) + (bot.h+bot.d);
1.3 ! albertel 2929: if (nocenter) {y = 0} else {y = H/2+a}; Y = y;
! 2930: html = jsMath.HTML.Place(jsMath.Typeset.AddClass(top.tclass,top.c),0,y-top.h)
1.1 albertel 2931: dx = (w-top.w)/2; if (Math.abs(dx) < .0001) {dx = 0}
2932: if (dx) {html += jsMath.HTML.Spacer(dx)}
2933: y -= top.h+top.d + rep.h;
1.3 ! albertel 2934: for (i = 0; i < n; i++) {html += jsMath.HTML.Place(ext,-w,y-i*h)}
1.1 albertel 2935: html += jsMath.HTML.Place(jsMath.Typeset.AddClass(bot.tclass,bot.c),-(w+bot.w)/2,Y-(H-bot.d));
2936: }
2937: if (nocenter) {h = top.h} else {h = H/2+a}
2938: var box = new jsMath.Box('html',html,rep.w,h,H-h);
2939: box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;
2940: return box;
2941: },
2942:
2943: /*
2944: * Create the HTML needed for a stretchable delimiter of a given height,
2945: * either centered or not. This version uses absolute placement (i.e.,
2946: * line-breaks, not backspacing). This gives more reliable results,
2947: * but doesn't work with all browsers.
2948: */
2949: DelimExtendAbsolute: function (H,c,font,a,nocenter) {
2950: var Font = jsMath.TeX[font];
1.2 albertel 2951: var C = Font[c]; var html;
1.1 albertel 2952: var top = this.GetChar(C.delim.top? C.delim.top: C.delim.rep,font);
2953: var rep = this.GetChar(C.delim.rep,font);
2954: var bot = this.GetChar(C.delim.bot? C.delim.bot: C.delim.rep,font);
1.3 ! albertel 2955: var n; var h; var y; var ext; var i;
1.1 albertel 2956:
2957: if (C.delim.mid) {// braces
2958: var mid = this.GetChar(C.delim.mid,font);
1.3 ! albertel 2959: n = Math.ceil((H-(top.h+top.d)-(mid.h+mid.d-.05)-(bot.h+bot.d-.05))/(2*(rep.h+rep.d-.05)));
1.1 albertel 2960: H = 2*n*(rep.h+rep.d-.05) + (top.h+top.d) + (mid.h+mid.d-.05) + (bot.h+bot.d-.05);
2961:
2962: html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);
1.3 ! albertel 2963: h = rep.h+rep.d - .05; y = top.d-.05 + rep.h;
! 2964: ext = jsMath.Typeset.AddClass(font,rep.c)
! 2965: for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
1.1 albertel 2966: html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(mid.tclass,mid.c),0,y+n*h-rep.h+mid.h);
2967: y += n*h + mid.h+mid.d - .05;
1.3 ! albertel 2968: for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
1.1 albertel 2969: html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);
2970: } else {// all others
1.3 ! albertel 2971: n = Math.ceil((H - (top.h+top.d) - (bot.h+bot.d-.05))/(rep.h+rep.d-.05));
1.1 albertel 2972: H = n*(rep.h+rep.d-.05) + (top.h+top.d) + (bot.h+bot.d-.05);
2973:
2974: html = jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(top.tclass,top.c),0,0);
1.3 ! albertel 2975: h = rep.h+rep.d-.05; y = top.d-.05 + rep.h;
! 2976: ext = jsMath.Typeset.AddClass(rep.tclass,rep.c);
! 2977: for (i = 0; i < n; i++) {html += jsMath.HTML.PlaceAbsolute(ext,0,y+i*h)}
1.1 albertel 2978: html += jsMath.HTML.PlaceAbsolute(jsMath.Typeset.AddClass(bot.tclass,bot.c),0,y+n*h-rep.h+bot.h);
2979: }
2980:
2981: var w = top.w;
2982: if (nocenter) {h = top.h; y = 0} else {h = H/2 + a; y = h - top.h}
1.3 ! albertel 2983: // html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,top.h);
! 2984: html = jsMath.HTML.Absolute(html,w,Font.h,"none",-y,jsMath.h);
1.1 albertel 2985: var box = new jsMath.Box('html',html,rep.w,h,H-h);
2986: box.bh = jsMath.TeX[font].h; box.bd = jsMath.TeX[font].d;
2987: return box;
2988: },
2989:
2990: /*
2991: * Get the HTML for a given delimiter of a given height.
2992: * It will return either a single character, if one exists, or the
2993: * more complex HTML needed for a stretchable delimiter.
2994: */
2995: Delimiter: function (H,delim,style,nocenter) {
2996: var size = 4; //### pass this?
2997: var TeX = jsMath.Typeset.TeX(style,size);
2998: if (!delim) {return this.Space(TeX.nulldelimiterspace)}
2999: var CFSH = this.DelimBestFit(H,delim[2],delim[1],style);
3000: if (CFSH == null || CFSH[3] < H)
3001: {CFSH = this.DelimBestFit(H,delim[4],delim[3],style)}
3002: if (CFSH == null) {return this.Space(TeX.nulldelimiterspace)}
3003: if (CFSH[2] == '')
3004: {return this.DelimExtend(H,CFSH[0],CFSH[1],TeX.axis_height,nocenter)}
1.2 albertel 3005: var box = jsMath.Box.TeX(CFSH[0],CFSH[1],CFSH[2],size).Styled();
1.1 albertel 3006: if (nocenter) {box.y = -jsMath.TeX[CFSH[1]].dh*TeX.scale}
3007: else {box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height)}
3008: if (Math.abs(box.y) < .0001) {box.y = 0}
3009: if (box.y) {box = jsMath.Box.SetList([box],CFSH[2],size)}
3010: return box;
3011: },
3012:
3013: /*
3014: * Get a character by its TeX charcode, and make sure its width
3015: * is specified.
3016: */
3017: GetCharCode: function (code) {
3018: var font = jsMath.TeX.fam[code[0]];
3019: var Font = jsMath.TeX[font];
3020: var c = Font[code[1]];
3021: if (c.img != null) {this.TeXIMG(font,code[1],4)}
3022: if (c.w == null) {c.w = jsMath.EmBoxFor(jsMath.Typeset.AddClass(c.tclass,c.c)).w}
3023: if (c.font == null) {c.font = font}
3024: return c;
3025: },
3026:
3027: /*
3028: * Add the class to the html, and use the font if there isn't one
3029: * specified already
3030: */
3031:
3032: AddClass: function (tclass,html,font) {
3033: if (tclass == null) {tclass = font}
3034: return jsMath.Typeset.AddClass(tclass,html);
3035: },
3036:
3037: /*
3038: * Create the HTML for an alignment (e.g., array or matrix)
3039: * Since the widths are not really accurate (they are based on pixel
3040: * widths not the sub-pixel widths of the actual characters), there
3041: * is some drift involved. We lay out the table column by column
3042: * to help reduce the problem.
3043: *
3044: * ### still need to allow users to specify row and column attributes,
3045: * and do things like \span and \multispan ###
3046: */
1.3 ! albertel 3047: LayoutRelative: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) {
1.1 albertel 3048: if (align == null) {align = []}
3049: if (cspacing == null) {cspacing = []}
1.2 albertel 3050: if (rspacing == null) {rspacing = []}
1.3 ! albertel 3051: if (useStrut == null) {useStrut = 1}
! 3052: if (addWidth == null) {addWidth = 1}
1.1 albertel 3053:
3054: // get row and column maximum dimensions
3055: var scale = jsMath.sizes[size]/100;
3056: var W = []; var H = []; var D = [];
3057: var unset = -1000; var bh = unset; var bd = unset;
3058: var i; var j; var row;
3059: for (i = 0; i < table.length; i++) {
1.2 albertel 3060: if (rspacing[i] == null) {rspacing[i] = 0}
1.3 ! albertel 3061: row = table[i];
! 3062: H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale;
1.1 albertel 3063: for (j = 0; j < row.length; j++) {
3064: row[j] = row[j].Remeasured();
3065: if (row[j].h > H[i]) {H[i] = row[j].h}
3066: if (row[j].d > D[i]) {D[i] = row[j].d}
3067: if (j >= W.length) {W[j] = row[j].w}
3068: else if (row[j].w > W[j]) {W[j] = row[j].w}
3069: if (row[j].bh > bh) {bh = row[j].bh}
3070: if (row[j].bd > bd) {bd = row[j].bd}
3071: }
3072: }
1.2 albertel 3073: if (rspacing[table.length] == null) {rspacing[table.length] = 0}
1.1 albertel 3074: if (bh == unset) {bh = 0}; if (bd == unset) {bd = 0}
3075:
3076: // lay out the columns
1.3 ! albertel 3077: var HD = useStrut*(jsMath.hd-.01)*scale;
1.2 albertel 3078: var dy = (vspace || 1) * scale/6;
1.1 albertel 3079: var html = ''; var pW = 0; var cW = 0;
3080: var w; var h; var y;
3081: var box; var mlist; var entry;
3082: for (j = 0; j < W.length; j++) {
1.2 albertel 3083: mlist = []; y = -H[0]-rspacing[0]; pW = 0;
1.1 albertel 3084: for (i = 0; i < table.length; i++) {
3085: entry = table[i][j];
3086: if (entry && entry.format != 'null') {
3087: if (align[j] == 'l') {w = 0} else
3088: if (align[j] == 'r') {w = W[j] - entry.w} else
3089: {w = (W[j] - entry.w)/2}
3090: entry.x = w - pW; pW = entry.w + w; entry.y = y;
3091: mlist[mlist.length] = entry;
3092: }
1.2 albertel 3093: if (i+1 < table.length) {y -= Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]}
1.1 albertel 3094: }
3095: if (cspacing[j] == null) cspacing[j] = scale;
3096: if (mlist.length > 0) {
3097: box = jsMath.Box.SetList(mlist,'T',size);
3098: html += jsMath.HTML.Place(box.html,cW,0);
3099: cW = W[j] - box.w + cspacing[j];
3100: } else {cW += cspacing[j]}
3101: }
3102:
3103: // get the full width and height
1.2 albertel 3104: w = -cspacing[W.length-1]; y = (H.length-1)*dy + rspacing[0];
1.1 albertel 3105: for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}
1.2 albertel 3106: for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]}
1.1 albertel 3107: h = y/2 + jsMath.TeX.axis_height; var d = y-h;
3108:
3109: // adjust the final row width, and vcenter the table
3110: // (add 1/6em at each side for the \,)
1.3 ! albertel 3111: html += jsMath.HTML.Spacer(cW-cspacing[W.length-1] + addWidth*scale/6);
! 3112: html = jsMath.HTML.Place(html,addWidth*scale/6,h);
! 3113: box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d);
1.1 albertel 3114: box.bh = bh; box.bd = bd;
3115: return box;
3116: },
3117:
3118: /*
3119: * Create the HTML for an alignment (e.g., array or matrix)
3120: * Use absolute position for elements in the array.
3121: *
3122: * ### still need to allow users to specify row and column attributes,
3123: * and do things like \span and \multispan ###
3124: */
1.3 ! albertel 3125: LayoutAbsolute: function (size,table,align,cspacing,rspacing,vspace,useStrut,addWidth) {
1.1 albertel 3126: if (align == null) {align = []}
3127: if (cspacing == null) {cspacing = []}
1.2 albertel 3128: if (rspacing == null) {rspacing = []}
1.3 ! albertel 3129: if (useStrut == null) {useStrut = 1}
! 3130: if (addWidth == null) {addWidth = 1}
1.1 albertel 3131:
3132: // get row and column maximum dimensions
3133: var scale = jsMath.sizes[size]/100;
1.3 ! albertel 3134: var HD = useStrut*(jsMath.hd-.01)*scale;
1.2 albertel 3135: var dy = (vspace || 1) * scale/6;
1.1 albertel 3136: var W = []; var H = []; var D = [];
3137: var w = 0; var h; var x; var y;
3138: var i; var j; var row;
3139: for (i = 0; i < table.length; i++) {
1.2 albertel 3140: if (rspacing[i] == null) {rspacing[i] = 0}
1.1 albertel 3141: row = table[i];
1.3 ! albertel 3142: H[i] = useStrut*jsMath.h*scale; D[i] = useStrut*jsMath.d*scale;
1.1 albertel 3143: for (j = 0; j < row.length; j++) {
3144: row[j] = row[j].Remeasured();
3145: if (row[j].h > H[i]) {H[i] = row[j].h}
3146: if (row[j].d > D[i]) {D[i] = row[j].d}
3147: if (j >= W.length) {W[j] = row[j].w}
3148: else if (row[j].w > W[j]) {W[j] = row[j].w}
3149: }
3150: }
1.2 albertel 3151: if (rspacing[table.length] == null) {rspacing[table.length] = 0}
1.1 albertel 3152:
3153: // get the height and depth of the centered table
1.2 albertel 3154: y = (H.length-1)*dy + rspacing[0];
3155: for (i = 0; i < H.length; i++) {y += Math.max(HD,H[i]+D[i]) + rspacing[i+1]}
1.1 albertel 3156: h = y/2 + jsMath.TeX.axis_height; var d = y - h;
3157:
3158: // lay out the columns
1.3 ! albertel 3159: var html = ''; var entry; w = addWidth*scale/6;
1.1 albertel 3160: for (j = 0; j < W.length; j++) {
1.2 albertel 3161: y = H[0]-h + rspacing[0];
1.1 albertel 3162: for (i = 0; i < table.length; i++) {
3163: entry = table[i][j];
3164: if (entry && entry.format != 'null') {
1.2 albertel 3165: if (align[j] && align[j] == 'l') {x = 0} else
3166: if (align[j] && align[j] == 'r') {x = W[j] - entry.w} else
1.1 albertel 3167: {x = (W[j] - entry.w)/2}
3168: html += jsMath.HTML.PlaceAbsolute(entry.html,w+x,
1.3 ! albertel 3169: y-Math.max(0,entry.bh-jsMath.h*scale),
! 3170: entry.mw,entry.Mw,entry.w);
1.1 albertel 3171: }
1.2 albertel 3172: if (i+1 < table.length) {y += Math.max(HD,D[i]+H[i+1]) + dy + rspacing[i+1]}
1.1 albertel 3173: }
3174: if (cspacing[j] == null) cspacing[j] = scale;
3175: w += W[j] + cspacing[j];
3176: }
3177:
3178: // get the full width
1.3 ! albertel 3179: w = -cspacing[W.length-1]+addWidth*scale/3;
1.1 albertel 3180: for (i = 0; i < W.length; i++) {w += W[i] + cspacing[i]}
3181:
1.3 ! albertel 3182: html = jsMath.HTML.Spacer(addWidth*scale/6)+html+jsMath.HTML.Spacer(addWidth*scale/6);
1.1 albertel 3183: if (jsMath.Browser.spanHeightVaries) {y = h-jsMath.h} else {y = 0}
1.3 ! albertel 3184: // html = jsMath.HTML.Absolute(html,w,h+d,d,y,H[0]);
! 3185: html = jsMath.HTML.Absolute(html,w,h+d,d,y,h);
! 3186: var box = new jsMath.Box('html',html,w+addWidth*scale/3,h,d);
1.1 albertel 3187: return box;
3188: },
3189:
3190: /*
3191: * Look for math within \hbox and other non-math text
3192: */
3193: InternalMath: function (text,size) {
1.3 ! albertel 3194: text = text.replace(/@\(([^)]*)\)/g,'<$1>');
1.1 albertel 3195: if (!text.match(/\$|\\\(/)) {return this.Text(text,'normal','T',size).Styled()}
3196:
3197: var i = 0; var k = 0; var c; var match = '';
1.3 ! albertel 3198: var mlist = []; var parse;
1.1 albertel 3199: while (i < text.length) {
3200: c = text.charAt(i++);
3201: if (c == '$') {
3202: if (match == '$') {
3203: parse = jsMath.Parse(text.slice(k,i-1),null,size);
3204: if (parse.error) {
3205: mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,.2);
3206: } else {
3207: parse.Atomize();
3208: mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled();
3209: }
3210: match = ''; k = i;
3211: } else {
3212: mlist[mlist.length] = this.Text(text.slice(k,i-1),'normal','T',size,1,.2);
3213: match = '$'; k = i;
3214: }
3215: } else if (c == '\\') {
3216: c = text.charAt(i++);
3217: if (c == '(' && match == '') {
3218: mlist[mlist.length] = this.Text(text.slice(k,i-2),'normal','T',size,1,.2);
3219: match = ')'; k = i;
3220: } else if (c == ')' && match == ')') {
3221: parse = jsMath.Parse(text.slice(k,i-2),null,size);
3222: if (parse.error) {
3223: mlist[mlist.length] = this.Text(parse.error,'error','T',size,1,.2);
3224: } else {
3225: parse.Atomize();
3226: mlist[mlist.length] = parse.mlist.Typeset('T',size).Styled();
3227: }
3228: match = ''; k = i;
3229: }
3230: }
3231: }
3232: mlist[mlist.length] = this.Text(text.slice(k),'normal','T',size,1,.2);
3233: return this.SetList(mlist,'T',size);
3234: },
3235:
3236: /*
3237: * Convert an abitrary box to a typeset box. I.e., make an
3238: * HTML version of the contents of the box, at its desired (x,y)
3239: * position.
3240: */
3241: Set: function (box,style,size,addstyle) {
3242: if (box && box.type) {
3243: if (box.type == 'typeset') {return box}
3244: if (box.type == 'mlist') {
3245: box.mlist.Atomize(style,size);
3246: return box.mlist.Typeset(style,size);
3247: }
3248: if (box.type == 'text') {
1.2 albertel 3249: box = this.Text(box.text,box.tclass,style,size,box.ascend||null,box.descend||null);
1.1 albertel 3250: if (addstyle != 0) {box.Styled()}
3251: return box;
3252: }
3253: box = this.TeX(box.c,box.font,style,size);
3254: if (addstyle != 0) {box.Styled()}
3255: return box;
3256: }
1.3 ! albertel 3257: return jsMath.Box.Null();
1.1 albertel 3258: },
3259:
3260: /*
3261: * Convert a list of boxes to a single typeset box. I.e., finalize
3262: * the HTML for the list of boxes, properly spaced and positioned.
3263: */
3264: SetList: function (boxes,style,size) {
3265: var mlist = []; var box;
3266: for (var i = 0; i < boxes.length; i++) {
3267: box = boxes[i];
3268: if (box.type == 'typeset') {box = jsMath.mItem.Typeset(box)}
3269: mlist[mlist.length] = box;
3270: }
3271: var typeset = new jsMath.Typeset(mlist);
3272: return typeset.Typeset(style,size);
3273: }
3274:
3275: });
3276:
3277:
3278: jsMath.Package(jsMath.Box,{
3279:
3280: /*
3281: * Add the class and style to a text box (i.e., finalize the
3282: * unpositioned HTML for the box).
3283: */
3284: Styled: function () {
3285: if (this.format == 'text') {
3286: this.html = jsMath.Typeset.AddClass(this.tclass,this.html);
3287: this.html = jsMath.Typeset.AddStyle(this.style,this.size,this.html);
3288: delete this.tclass; delete this.style;
3289: this.format = 'html';
3290: }
3291: return this;
3292: },
3293:
3294: /*
3295: * Recompute the box width to make it more accurate.
3296: */
3297: Remeasured: function () {
1.2 albertel 3298: if (this.w > 0) {this.w = jsMath.EmBoxFor(this.html).w}
1.1 albertel 3299: return this;
3300: }
3301:
3302: });
3303:
3304:
3305: /***************************************************************************/
3306:
3307: /*
3308: * mItems are the building blocks of mLists (math lists) used to
3309: * store the information about a mathematical expression. These are
3310: * basically the items listed in the TeXbook in Appendix G (plus some
3311: * minor extensions).
3312: */
3313: jsMath.mItem = function (type,def) {
3314: this.type = type;
3315: jsMath.Add(this,def);
3316: }
3317:
3318: jsMath.Add(jsMath.mItem,{
3319:
3320: /*
3321: * A general atom (given a nucleus for the atom)
3322: */
3323: Atom: function (type,nucleus) {
3324: return new jsMath.mItem(type,{atom: 1, nuc: nucleus});
3325: },
3326:
3327: /*
3328: * An atom whose nucleus is a piece of text, in a given
3329: * class, with a given additional height and depth
3330: */
3331: TextAtom: function (type,text,tclass,a,d) {
3332: var atom = new jsMath.mItem(type,{
3333: atom: 1,
3334: nuc: {
3335: type: 'text',
3336: text: text,
3337: tclass: tclass
3338: }
3339: });
3340: if (a != null) {atom.nuc.ascend = a}
3341: if (d != null) {atom.nuc.descend = d}
3342: return atom;
3343: },
3344:
3345: /*
3346: * An atom whose nucleus is a TeX character in a specific font
3347: */
3348: TeXAtom: function (type,c,font) {
3349: return new jsMath.mItem(type,{
3350: atom: 1,
3351: nuc: {
3352: type: 'TeX',
3353: c: c,
3354: font: font
3355: }
3356: });
3357: },
3358:
3359: /*
3360: * A generalized fraction atom, with given delimiters, rule
3361: * thickness, and a numerator and denominator.
3362: */
3363: Fraction: function (name,num,den,thickness,left,right) {
3364: return new jsMath.mItem('fraction',{
3365: from: name, num: num, den: den,
3366: thickness: thickness, left: left, right: right
3367: });
3368: },
3369:
3370: /*
3371: * An atom that inserts some glue
3372: */
3373: Space: function (w) {return new jsMath.mItem('space',{w: w})},
3374:
3375: /*
3376: * An atom that contains a typeset box (like an hbox or vbox)
3377: */
3378: Typeset: function (box) {return new jsMath.mItem('ord',{atom:1, nuc: box})},
3379:
3380: /*
3381: * An atom that contains some finished HTML (acts like a typeset box)
3382: */
3383: HTML: function (html) {return new jsMath.mItem('html',{html: html})}
3384:
3385: });
3386:
3387: /***************************************************************************/
3388:
3389: /*
3390: * mLists are lists of mItems, and encode the contents of
3391: * mathematical expressions and sub-expressions. They act as
3392: * the expression "stack" as the mathematics is parsed, and
3393: * contain some state information, like the position of the
3394: * most recent open paren and \over command, and the current font.
3395: */
3396: jsMath.mList = function (list,font,size,style) {
3397: if (list) {this.mlist = list} else {this.mlist = []}
3398: if (style == null) {style = 'T'}; if (size == null) {size = 4}
3399: this.data = {openI: null, overI: null, overF: null,
3400: font: font, size: size, style: style};
3401: this.init = {size: size, style: style};
3402: }
3403:
3404: jsMath.Package(jsMath.mList,{
3405:
3406: /*
3407: * Add an mItem to the list
3408: */
3409: Add: function (box) {return (this.mlist[this.mlist.length] = box)},
3410:
3411: /*
3412: * Get the i-th mItem from the list
3413: */
3414: Get: function (i) {return this.mlist[i]},
3415:
3416: /*
3417: * Get the length of the list
3418: */
3419: Length: function() {return this.mlist.length},
3420:
3421: /*
3422: * Get the tail mItem of the list
3423: */
3424: Last: function () {
3425: if (this.mlist.length == 0) {return null}
3426: return this.mlist[this.mlist.length-1]
3427: },
3428:
3429: /*
3430: * Get a sublist of an mList
3431: */
3432: Range: function (i,j) {
3433: if (j == null) {j = this.mlist.length}
3434: return new jsMath.mList(this.mlist.slice(i,j+1));
3435: },
3436:
3437: /*
3438: * Remove a range of mItems from the list.
3439: */
3440: Delete: function (i,j) {
3441: if (j == null) {j = i}
3442: if (this.mlist.splice) {this.mlist.splice(i,j-i+1)} else {
3443: var mlist = [];
3444: for (var k = 0; k < this.mlist.length; k++)
3445: {if (k < i || k > j) {mlist[mlist.length] = this.mlist[k]}}
3446: this.mlist = mlist;
3447: }
3448: },
3449:
3450: /*
3451: * Add an open brace and maintain the stack information
3452: * about the previous open brace so we can recover it
3453: * when this one os closed.
3454: */
3455: Open: function (left) {
3456: var box = this.Add(new jsMath.mItem('boundary',{data: this.data}));
3457: var olddata = this.data;
3458: this.data = {}; for (var i in olddata) {this.data[i] = olddata[i]}
3459: delete this.data.overI; delete this.data.overF;
3460: this.data.openI = this.mlist.length-1;
3461: if (left != null) {box.left = left}
3462: return box;
3463: },
3464:
3465: /*
3466: * Attempt to close a brace. Recover the stack information
3467: * about previous open braces and \over commands. If there was an
3468: * \over (or \above, etc) in this set of braces, create a fraction
3469: * atom from the two halves, otherwise create an inner or ord
3470: * from the contents of the braces.
3471: * Remove the braced material from the list and add the newly
3472: * created atom (the fraction, inner or ord).
3473: */
3474: Close: function (right) {
3475: if (right != null) {right = new jsMath.mItem('boundary',{right: right})}
3476: var atom; var open = this.data.openI;
3477: var over = this.data.overI; var from = this.data.overF;
3478: this.data = this.mlist[open].data;
3479: if (over) {
3480: atom = jsMath.mItem.Fraction(from.name,
3481: {type: 'mlist', mlist: this.Range(open+1,over-1)},
3482: {type: 'mlist', mlist: this.Range(over)},
3483: from.thickness,from.left,from.right);
3484: if (right) {
3485: var mlist = new jsMath.mList([this.mlist[open],atom,right]);
3486: atom = jsMath.mItem.Atom('inner',{type: 'mlist', mlist: mlist});
3487: }
3488: } else {
3489: var openI = open+1; if (right) {this.Add(right); openI--}
3490: atom = jsMath.mItem.Atom((right)?'inner':'ord',
3491: {type: 'mlist', mlist: this.Range(openI)});
3492: }
3493: this.Delete(open,this.Length());
3494: return this.Add(atom);
3495: },
3496:
3497: /*
3498: * Create a generalized fraction from an mlist that
3499: * contains an \over (or \above, etc).
3500: */
3501: Over: function () {
3502: var over = this.data.overI; var from = this.data.overF;
3503: var atom = jsMath.mItem.Fraction(from.name,
3504: {type: 'mlist', mlist: this.Range(open+1,over-1)},
3505: {type: 'mlist', mlist: this.Range(over)},
3506: from.thickness,from.left,from.right);
3507: this.mlist = [atom];
3508: },
3509:
3510: /*
3511: * Take a raw mList (that has been produced by parsing some TeX
3512: * expression), and perform the modifications outlined in
3513: * Appendix G of the TeXbook.
3514: */
3515: Atomize: function (style,size) {
3516: var mitem; var prev = '';
3517: this.style = style; this.size = size;
3518: for (var i = 0; i < this.mlist.length; i++) {
3519: mitem = this.mlist[i]; mitem.delta = 0;
3520: if (mitem.type == 'choice')
3521: {this.mlist = this.Atomize.choice(this.style,mitem,i,this.mlist); i--}
3522: else if (this.Atomize[mitem.type]) {
3523: var f = this.Atomize[mitem.type]; // Opera needs separate name
3524: f(this.style,this.size,mitem,prev,this,i);
3525: }
3526: prev = mitem;
3527: }
3528: if (mitem && mitem.type == 'bin') {mitem.type = 'ord'}
3529: if (this.mlist.length >= 2 && mitem.type == 'boundary' &&
3530: this.mlist[0].type == 'boundary') {this.AddDelimiters(style,size)}
3531: },
3532:
3533: /*
3534: * For a list that has boundary delimiters as its first and last
3535: * entries, we replace the boundary atoms by open and close
3536: * atoms whose nuclii are the specified delimiters properly sized
3537: * for the contents of the list. (Rule 19)
3538: */
3539: AddDelimiters: function(style,size) {
3540: var unset = -10000; var h = unset; var d = unset;
3541: for (var i = 0; i < this.mlist.length; i++) {
1.2 albertel 3542: var mitem = this.mlist[i];
1.1 albertel 3543: if (mitem.atom || mitem.type == 'box') {
3544: h = Math.max(h,mitem.nuc.h+mitem.nuc.y);
3545: d = Math.max(d,mitem.nuc.d-mitem.nuc.y);
3546: }
3547: }
3548: var TeX = jsMath.TeX; var a = jsMath.Typeset.TeX(style,size).axis_height;
3549: var delta = Math.max(h-a,d+a);
3550: var H = Math.max(Math.floor(TeX.integer*delta/500)*TeX.delimiterfactor,
3551: TeX.integer*(2*delta-TeX.delimitershortfall))/TeX.integer;
3552: var left = this.mlist[0]; var right = this.mlist[this.mlist.length-1];
3553: left.nuc = jsMath.Box.Delimiter(H,left.left,style);
3554: right.nuc = jsMath.Box.Delimiter(H,right.right,style);
3555: left.type = 'open'; left.atom = 1; delete left.left;
3556: right.type = 'close'; right.atom = 1; delete right.right;
3557: },
3558:
3559: /*
3560: * Typeset a math list to produce final HTML for the list.
3561: */
3562: Typeset: function (style,size) {
3563: var typeset = new jsMath.Typeset(this.mlist);
3564: return typeset.Typeset(style,size);
3565: }
3566:
3567: });
3568:
3569:
3570: /*
3571: * These routines implement the main rules given in Appendix G of the
3572: * TeXbook
3573: */
3574:
3575: jsMath.Add(jsMath.mList.prototype.Atomize,{
3576:
3577: /*
3578: * Handle \displaystyle, \textstyle, etc.
3579: */
3580: style: function (style,size,mitem,prev,mlist) {
3581: mlist.style = mitem.style;
3582: },
3583:
3584: /*
3585: * Handle \tiny, \small, etc.
3586: */
3587: size: function (style,size,mitem,prev,mlist) {
3588: mlist.size = mitem.size;
3589: },
3590:
3591: /*
3592: * Create empty boxes of the proper sizes for the various
3593: * phantom-type commands
3594: */
3595: phantom: function (style,size,mitem) {
3596: var box = mitem.nuc = jsMath.Box.Set(mitem.phantom,style,size);
3597: if (mitem.h) {box.Remeasured(); box.html = jsMath.HTML.Spacer(box.w)}
1.3 ! albertel 3598: else {box.html = '', box.w = box.Mw = box.mw = 0;}
1.1 albertel 3599: if (!mitem.v) {box.h = box.d = 0}
3600: box.bd = box.bh = 0;
3601: delete mitem.phantom;
3602: mitem.type = 'box';
3603: },
3604:
3605: /*
3606: * Create a box of zero height and depth containing the
3607: * contents of the atom
3608: */
3609: smash: function (style,size,mitem) {
3610: var box = mitem.nuc = jsMath.Box.Set(mitem.smash,style,size).Remeasured();
1.3 ! albertel 3611: box.h = box.d = 0;
1.1 albertel 3612: delete mitem.smash;
3613: mitem.type = 'box';
3614: },
3615:
3616: /*
3617: * Move a box up or down vertically
3618: */
3619: raise: function (style,size,mitem) {
3620: mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size);
3621: var y = mitem.raise;
1.3 ! albertel 3622: mitem.nuc.html =
! 3623: jsMath.HTML.Place(mitem.nuc.html,0,y,mitem.nuc.mw,mitem.nuc.Mw,mitem.nuc.w);
1.1 albertel 3624: mitem.nuc.h += y; mitem.nuc.d -= y;
3625: mitem.type = 'ord'; mitem.atom = 1;
3626: },
3627:
3628: /*
3629: * Hide the size of a box so that it laps to the left or right, or
3630: * up or down.
3631: */
3632: lap: function (style,size,mitem) {
3633: var box = jsMath.Box.Set(mitem.nuc,style,size).Remeasured();
3634: var mlist = [box];
3635: if (mitem.lap == 'llap') {box.x = -box.w} else
3636: if (mitem.lap == 'rlap') {mlist[1] = jsMath.mItem.Space(-box.w)} else
3637: if (mitem.lap == 'ulap') {box.y = box.d; box.h = box.d = 0} else
3638: if (mitem.lap == 'dlap') {box.y = -box.h; box.h = box.d = 0}
3639: mitem.nuc = jsMath.Box.SetList(mlist,style,size);
3640: if (mitem.lap == 'ulap' || mitem.lap == 'dlap') {mitem.nuc.h = mitem.nuc.d = 0}
3641: mitem.type = 'box'; delete mitem.atom;
3642: },
3643:
3644: /*
3645: * Handle a Bin atom. (Rule 5)
3646: */
3647: bin: function (style,size,mitem,prev) {
1.2 albertel 3648: if (prev && prev.type) {
1.1 albertel 3649: var type = prev.type;
3650: if (type == 'bin' || type == 'op' || type == 'rel' ||
3651: type == 'open' || type == 'punct' || type == '' ||
3652: (type == 'boundary' && prev.left != '')) {mitem.type = 'ord'}
3653: } else {mitem.type = 'ord'}
3654: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3655: },
3656:
3657: /*
3658: * Handle a Rel atom. (Rule 6)
3659: */
3660: rel: function (style,size,mitem,prev) {
1.2 albertel 3661: if (prev.type && prev.type == 'bin') {prev.type = 'ord'}
1.1 albertel 3662: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3663: },
3664:
3665: /*
3666: * Handle a Close atom. (Rule 6)
3667: */
3668: close: function (style,size,mitem,prev) {
1.2 albertel 3669: if (prev.type && prev.type == 'bin') {prev.type = 'ord'}
1.1 albertel 3670: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3671: },
3672:
3673: /*
3674: * Handle a Punct atom. (Rule 6)
3675: */
3676: punct: function (style,size,mitem,prev) {
1.2 albertel 3677: if (prev.type && prev.type == 'bin') {prev.type = 'ord'}
1.1 albertel 3678: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3679: },
3680:
3681: /*
3682: * Handle an Open atom. (Rule 7)
3683: */
3684: open: function (style,size,mitem) {
3685: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3686: },
3687:
3688: /*
3689: * Handle an Inner atom. (Rule 7)
3690: */
3691: inner: function (style,size,mitem) {
3692: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3693: },
3694:
3695: /*
3696: * Handle a Vcent atom. (Rule 8)
3697: */
3698: vcenter: function (style,size,mitem) {
3699: var box = jsMath.Box.Set(mitem.nuc,style,size);
3700: var TeX = jsMath.Typeset.TeX(style,size);
3701: box.y = TeX.axis_height - (box.h-box.d)/2;
3702: mitem.nuc = box; mitem.type = 'ord';
3703: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3704: },
3705:
3706: /*
3707: * Handle an Over atom. (Rule 9)
3708: */
3709: overline: function (style,size,mitem) {
3710: var TeX = jsMath.Typeset.TeX(style,size);
3711: var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured();
3712: var t = TeX.default_rule_thickness;
3713: var rule = jsMath.Box.Rule(box.w,t);
3714: rule.x = -rule.w; rule.y = box.h + 3*t;
3715: mitem.nuc = jsMath.Box.SetList([box,rule],style,size);
3716: mitem.nuc.h += t;
3717: mitem.type = 'ord';
3718: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3719: },
3720:
3721: /*
3722: * Handle an Under atom. (Rule 10)
3723: */
3724: underline: function (style,size,mitem) {
3725: var TeX = jsMath.Typeset.TeX(style,size);
3726: var box = jsMath.Box.Set(mitem.nuc,jsMath.Typeset.PrimeStyle(style),size).Remeasured();
3727: var t = TeX.default_rule_thickness;
3728: var rule = jsMath.Box.Rule(box.w,t);
3729: rule.x = -rule.w; rule.y = -box.d - 3*t - t;
3730: mitem.nuc = jsMath.Box.SetList([box,rule],style,size);
3731: mitem.nuc.d += t;
3732: mitem.type = 'ord';
3733: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3734: },
3735:
3736: /*
3737: * Handle a Rad atom. (Rule 11 plus stuff for \root..\of)
3738: */
3739: radical: function (style,size,mitem) {
3740: var TeX = jsMath.Typeset.TeX(style,size);
3741: var Cp = jsMath.Typeset.PrimeStyle(style);
3742: var box = jsMath.Box.Set(mitem.nuc,Cp,size).Remeasured();
3743: var t = TeX.default_rule_thickness;
3744: var p = t; if (style == 'D' || style == "D'") {p = TeX.x_height}
3745: var r = t + p/4;
3746: var surd = jsMath.Box.Delimiter(box.h+box.d+r+t,[0,2,0x70,3,0x70],style,1);
1.2 albertel 3747: // if (surd.h > 0) {t = surd.h} // thickness of rule is height of surd character
1.1 albertel 3748: if (surd.d > box.h+box.d+r) {r = (r+surd.d-box.h-box.d)/2}
3749: surd.y = box.h+r;
3750: var rule = jsMath.Box.Rule(box.w,t);
3751: rule.y = surd.y-t/2; rule.h += 3*t/2; box.x = -box.w;
3752: var Cr = jsMath.Typeset.UpStyle(jsMath.Typeset.UpStyle(style));
1.2 albertel 3753: var root = jsMath.Box.Set(mitem.root || null,Cr,size).Remeasured();
1.1 albertel 3754: if (mitem.root) {
3755: root.y = .55*(box.h+box.d+3*t+r)-box.d;
3756: surd.x = Math.max(root.w-(11/18)*surd.w,0);
3757: rule.x = (7/18)*surd.w;
3758: root.x = -(root.w+rule.x);
3759: }
3760: mitem.nuc = jsMath.Box.SetList([surd,root,rule,box],style,size);
3761: mitem.type = 'ord';
3762: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3763: },
3764:
3765: /*
3766: * Handle an Acc atom. (Rule 12)
3767: */
3768: accent: function (style,size,mitem) {
3769: var TeX = jsMath.Typeset.TeX(style,size);
3770: var Cp = jsMath.Typeset.PrimeStyle(style);
3771: var box = jsMath.Box.Set(mitem.nuc,Cp,size);
1.3 ! albertel 3772: var u = box.w; var s; var Font; var ic = 0;
1.1 albertel 3773: if (mitem.nuc.type == 'TeX') {
3774: Font = jsMath.TeX[mitem.nuc.font];
3775: if (Font[mitem.nuc.c].krn && Font.skewchar)
3776: {s = Font[mitem.nuc.c].krn[Font.skewchar]}
1.3 ! albertel 3777: ic = Font[mitem.nuc.c].ic; if (ic == null) {ic = 0}
1.1 albertel 3778: }
3779: if (s == null) {s = 0}
3780:
3781: var c = mitem.accent[2];
3782: var font = jsMath.TeX.fam[mitem.accent[1]]; Font = jsMath.TeX[font];
3783: while (Font[c].n && Font[Font[c].n].w <= u) {c = Font[c].n}
3784:
3785: var delta = Math.min(box.h,TeX.x_height);
3786: if (mitem.nuc.type == 'TeX') {
3787: var nitem = jsMath.mItem.Atom('ord',mitem.nuc);
3788: nitem.sup = mitem.sup; nitem.sub = mitem.sub; nitem.delta = 0;
3789: jsMath.mList.prototype.Atomize.SupSub(style,size,nitem);
3790: delta += (nitem.nuc.h - box.h);
3791: box = mitem.nuc = nitem.nuc;
3792: delete mitem.sup; delete mitem.sub;
3793: }
3794: var acc = jsMath.Box.TeX(c,font,style,size);
3795: acc.y = box.h - delta; acc.x = -box.w + s + (u-acc.w)/2;
1.3 ! albertel 3796: if (jsMath.Browser.msieAccentBug)
! 3797: {acc.html += jsMath.HTML.Spacer(.1); acc.w += .1; acc.Mw += .1}
! 3798: if (Font[c].ic || ic) {acc.x += (ic - (Font[c].ic||0)) * TeX.scale}
1.1 albertel 3799:
3800: mitem.nuc = jsMath.Box.SetList([box,acc],style,size);
3801: if (mitem.nuc.w != box.w) {
3802: var space = jsMath.mItem.Space(box.w-mitem.nuc.w);
3803: mitem.nuc = jsMath.Box.SetList([mitem.nuc,space],style,size);
3804: }
3805: mitem.type = 'ord';
3806: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3807: },
3808:
3809: /*
3810: * Handle an Op atom. (Rules 13 and 13a)
3811: */
3812: op: function (style,size,mitem) {
3813: var TeX = jsMath.Typeset.TeX(style,size); var box;
3814: mitem.delta = 0; var isD = (style.charAt(0) == 'D');
3815: if (mitem.limits == null && isD) {mitem.limits = 1}
3816:
3817: if (mitem.nuc.type == 'TeX') {
3818: var C = jsMath.TeX[mitem.nuc.font][mitem.nuc.c];
3819: if (isD && C.n) {mitem.nuc.c = C.n; C = jsMath.TeX[mitem.nuc.font][C.n]}
1.3 ! albertel 3820: box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size);
1.1 albertel 3821: if (C.ic) {
3822: mitem.delta = C.ic * TeX.scale;
1.3 ! albertel 3823: if (mitem.limits || !mitem.sub || jsMath.Browser.msieIntegralBug) {
! 3824: box = mitem.nuc = jsMath.Box.SetList([box,jsMath.mItem.Space(mitem.delta)],style,size);
! 3825: }
1.1 albertel 3826: }
3827: box.y = -((box.h+box.d)/2 - box.d - TeX.axis_height);
3828: if (Math.abs(box.y) < .0001) {box.y = 0}
3829: }
1.3 ! albertel 3830:
! 3831: if (!box) {box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size).Remeasured()}
1.1 albertel 3832: if (mitem.limits) {
3833: var W = box.w; var x = box.w;
3834: var mlist = [box]; var dh = 0; var dd = 0;
3835: if (mitem.sup) {
3836: var sup = jsMath.Box.Set(mitem.sup,jsMath.Typeset.UpStyle(style),size).Remeasured();
3837: sup.x = ((box.w-sup.w)/2 + mitem.delta/2) - x; dh = TeX.big_op_spacing5;
3838: W = Math.max(W,sup.w); x += sup.x + sup.w;
3839: sup.y = box.h+sup.d + box.y +
3840: Math.max(TeX.big_op_spacing1,TeX.big_op_spacing3-sup.d);
3841: mlist[mlist.length] = sup; delete mitem.sup;
3842: }
3843: if (mitem.sub) {
3844: var sub = jsMath.Box.Set(mitem.sub,jsMath.Typeset.DownStyle(style),size).Remeasured();
3845: sub.x = ((box.w-sub.w)/2 - mitem.delta/2) - x; dd = TeX.big_op_spacing5;
3846: W = Math.max(W,sub.w); x += sub.x + sub.w;
3847: sub.y = -box.d-sub.h + box.y -
3848: Math.max(TeX.big_op_spacing2,TeX.big_op_spacing4-sub.h);
3849: mlist[mlist.length] = sub; delete mitem.sub;
3850: }
3851: if (W > box.w) {box.x = (W-box.w)/2; x += box.x}
3852: if (x < W) {mlist[mlist.length] = jsMath.mItem.Space(W-x)}
3853: mitem.nuc = jsMath.Box.SetList(mlist,style,size);
3854: mitem.nuc.h += dh; mitem.nuc.d += dd;
3855: } else {
3856: if (jsMath.Browser.msieIntegralBug && mitem.sub && C && C.ic)
3857: {mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(-C.ic*TeX.scale)],style,size)}
3858: else if (box.y) {mitem.nuc = jsMath.Box.SetList([box],style,size)}
3859: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3860: }
3861: },
3862:
3863: /*
3864: * Handle an Ord atom. (Rule 14)
3865: */
3866: ord: function (style,size,mitem,prev,mList,i) {
3867: if (mitem.nuc.type == 'TeX' && !mitem.sup && !mitem.sub) {
3868: var nitem = mList.mlist[i+1];
3869: if (nitem && nitem.atom && nitem.type &&
3870: (nitem.type == 'ord' || nitem.type == 'op' || nitem.type == 'bin' ||
3871: nitem.type == 'rel' || nitem.type == 'open' ||
3872: nitem.type == 'close' || nitem.type == 'punct')) {
3873: if (nitem.nuc.type == 'TeX' && nitem.nuc.font == mitem.nuc.font) {
3874: mitem.textsymbol = 1;
3875: var krn = jsMath.TeX[mitem.nuc.font][mitem.nuc.c].krn;
3876: krn *= jsMath.Typeset.TeX(style,size).scale;
3877: if (krn && krn[nitem.nuc.c]) {
3878: for (var k = mList.mlist.length-1; k > i; k--)
3879: {mList.mlist[k+1] = mList.mlist[k]}
3880: mList.mlist[i+1] = jsMath.mItem.Space(krn[nitem.nuc.c]);
3881: }
3882: }
3883: }
3884: }
3885: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3886: },
3887:
3888: /*
3889: * Handle a generalized fraction. (Rules 15 to 15e)
3890: */
3891: fraction: function (style,size,mitem) {
3892: var TeX = jsMath.Typeset.TeX(style,size); var t = 0;
3893: if (mitem.thickness != null) {t = mitem.thickness}
3894: else if (mitem.from.match(/over/)) {t = TeX.default_rule_thickness}
3895: var isD = (style.charAt(0) == 'D');
3896: var Cn = (style == 'D')? 'T': (style == "D'")? "T'": jsMath.Typeset.UpStyle(style);
3897: var Cd = (isD)? "T'": jsMath.Typeset.DownStyle(style);
3898: var num = jsMath.Box.Set(mitem.num,Cn,size).Remeasured();
3899: var den = jsMath.Box.Set(mitem.den,Cd,size).Remeasured();
3900:
1.3 ! albertel 3901: var u; var v; var w; var p; var r;
1.1 albertel 3902: var H = (isD)? TeX.delim1 : TeX.delim2;
3903: var mlist = [jsMath.Box.Delimiter(H,mitem.left,style)]
3904: var right = jsMath.Box.Delimiter(H,mitem.right,style);
3905:
3906: if (num.w < den.w) {
3907: num.x = (den.w-num.w)/2;
3908: den.x = -(num.w + num.x);
3909: w = den.w; mlist[1] = num; mlist[2] = den;
3910: } else {
3911: den.x = (num.w-den.w)/2;
3912: num.x = -(den.w + den.x);
3913: w = num.w; mlist[1] = den; mlist[2] = num;
3914: }
3915: if (isD) {u = TeX.num1; v = TeX.denom1} else {
3916: u = (t != 0)? TeX.num2: TeX.num3;
3917: v = TeX.denom2;
3918: }
3919: if (t == 0) {// atop
1.3 ! albertel 3920: p = (isD)? 7*TeX.default_rule_thickness: 3*TeX.default_rule_thickness;
! 3921: r = (u - num.d) - (den.h - v);
1.1 albertel 3922: if (r < p) {u += (p-r)/2; v += (p-r)/2}
3923: } else {// over
1.3 ! albertel 3924: p = (isD)? 3*t: t; var a = TeX.axis_height;
! 3925: r = (u-num.d)-(a+t/2); if (r < p) {u += p-r}
! 3926: r = (a-t/2)-(den.h-v); if (r < p) {v += p-r}
1.1 albertel 3927: var rule = jsMath.Box.Rule(w,t); rule.x = -w; rule.y = a - t/2;
3928: mlist[mlist.length] = rule;
3929: }
3930: num.y = u; den.y = -v;
3931:
3932: mlist[mlist.length] = right;
3933: mitem.nuc = jsMath.Box.SetList(mlist,style,size);
3934: mitem.type = 'ord'; mitem.atom = 1;
3935: delete mitem.num; delete mitem.den;
3936: jsMath.mList.prototype.Atomize.SupSub(style,size,mitem);
3937: },
3938:
3939: /*
3940: * Add subscripts and superscripts. (Rules 17-18f)
3941: */
3942: SupSub: function (style,size,mitem) {
3943: var TeX = jsMath.Typeset.TeX(style,size);
3944: var nuc = mitem.nuc;
3945: var box = mitem.nuc = jsMath.Box.Set(mitem.nuc,style,size,0);
3946: if (box.format == 'null')
3947: {box = mitem.nuc = jsMath.Box.Text('','normal',style,size)}
3948:
3949: if (nuc.type == 'TeX') {
3950: if (!mitem.textsymbol) {
3951: var C = jsMath.TeX[nuc.font][nuc.c];
3952: if (C.ic) {
3953: mitem.delta = C.ic * TeX.scale;
3954: if (!mitem.sub) {
3955: box = mitem.nuc = jsMath.Box.SetList([box,jsMath.Box.Space(mitem.delta)],style,size);
3956: mitem.delta = 0;
3957: }
3958: }
3959: } else {mitem.delta = 0}
3960: }
3961:
3962: if (!mitem.sup && !mitem.sub) return;
3963: mitem.nuc.Styled();
3964:
3965: var Cd = jsMath.Typeset.DownStyle(style);
3966: var Cu = jsMath.Typeset.UpStyle(style);
3967: var q = jsMath.Typeset.TeX(Cu,size).sup_drop;
3968: var r = jsMath.Typeset.TeX(Cd,size).sub_drop;
3969: var u = 0; var v = 0; var p;
3970: if (nuc.type && nuc.type != 'text' && nuc.type != 'TeX' && nuc.type != 'null')
3971: {u = box.h - q; v = box.d + r}
3972:
3973: if (mitem.sub) {
3974: var sub = jsMath.Box.Set(mitem.sub,Cd,size);
3975: sub = jsMath.Box.SetList([sub,jsMath.mItem.Space(TeX.scriptspace)],style,size);
3976: }
3977:
3978: if (!mitem.sup) {
3979: sub.y = -Math.max(v,TeX.sub1,sub.h-(4/5)*jsMath.Typeset.TeX(Cd,size).x_height);
3980: mitem.nuc = jsMath.Box.SetList([box,sub],style,size).Styled(); delete mitem.sub;
3981: return;
3982: }
3983:
3984: var sup = jsMath.Box.Set(mitem.sup,Cu,size);
3985: sup = jsMath.Box.SetList([sup,jsMath.mItem.Space(TeX.scriptspace)],style,size);
3986: if (style == 'D') {p = TeX.sup1}
3987: else if (style.charAt(style.length-1) == "'") {p = TeX.sup3}
3988: else {p = TeX.sup2}
3989: u = Math.max(u,p,sup.d+jsMath.Typeset.TeX(Cu,size).x_height/4);
3990:
3991: if (!mitem.sub) {
3992: sup.y = u;
3993: mitem.nuc = jsMath.Box.SetList([box,sup],style,size); delete mitem.sup;
3994: return;
3995: }
3996:
3997: v = Math.max(v,jsMath.Typeset.TeX(Cd,size).sub2);
3998: var t = TeX.default_rule_thickness;
3999: if ((u-sup.d) - (sub.h -v) < 4*t) {
4000: v = 4*t + sub.h - (u-sup.d);
4001: p = (4/5)*TeX.x_height - (u-sup.d);
4002: if (p > 0) {u += p; v -= p}
4003: }
4004: sup.Remeasured(); sub.Remeasured();
4005: sup.y = u; sub.y = -v; sup.x = mitem.delta;
4006: if (sup.w+sup.x > sub.w)
4007: {sup.x -= sub.w; mitem.nuc = jsMath.Box.SetList([box,sub,sup],style,size)} else
4008: {sub.x -= (sup.w+sup.x); mitem.nuc = jsMath.Box.SetList([box,sup,sub],style,size)}
4009:
4010: delete mitem.sup; delete mitem.sub;
4011: }
4012:
4013: });
4014:
4015:
4016: /***************************************************************************/
4017:
4018: /*
4019: * The Typeset object handles most of the TeX-specific processing
4020: */
4021:
4022: jsMath.Typeset = function (mlist) {
4023: this.type = 'typeset';
4024: this.mlist = mlist;
4025: }
4026:
4027: jsMath.Add(jsMath.Typeset,{
4028:
4029: /*
4030: * The "C-uparrow" style table (TeXbook, p. 441)
4031: */
4032: upStyle: {
4033: D: "S", T: "S", "D'": "S'", "T'": "S'",
4034: S: "SS", SS: "SS", "S'": "SS'", "SS'": "SS'"
4035: },
4036:
4037: /*
4038: * The "C-downarrow" style table (TeXbook, p. 441)
4039: */
4040: downStyle: {
4041: D: "S'", T: "S'", "D'": "S'", "T'": "S'",
4042: S: "SS'", SS: "SS'", "S'": "SS'", "SS'": "SS'"
4043: },
4044:
4045: /*
4046: * Get the various styles given the current style
4047: * (see TeXbook, p. 441)
4048: */
4049: UpStyle: function (style) {return this.upStyle[style]},
4050: DownStyle: function (style) {return this.downStyle[style]},
4051: PrimeStyle: function (style) {
4052: if (style.charAt(style.length-1) == "'") {return style}
4053: return style + "'"
4054: },
4055:
4056: /*
4057: * A value scaled to the appropriate size for scripts
4058: */
4059: StyleValue: function (style,v) {
4060: if (style == "S" || style == "S'") {return .7*v}
4061: if (style == "SS" || style == "SS'") {return .5*v}
4062: return v;
4063: },
4064:
4065: /*
4066: * Return the size associated with a given style and size
4067: */
4068: StyleSize: function (style,size) {
4069: if (style == "S" || style == "S'") {size = Math.max(0,size-2)}
4070: else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)}
4071: return size;
4072: },
4073:
4074: /*
4075: * Return the font parameter table for the given style
4076: */
4077: TeX: function (style,size) {
4078: if (style == "S" || style == "S'") {size = Math.max(0,size-2)}
4079: else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)}
4080: return jsMath.TeXparams[size];
4081: },
4082:
4083:
4084: /*
4085: * Add the CSS class for the given TeX style
4086: */
4087: AddStyle: function (style,size,html) {
4088: if (style == "S" || style == "S'") {size = Math.max(0,size-2)}
4089: else if (style == "SS" || style == "SS'") {size = Math.max(0,size-4)}
4090: if (size != 4) {html = '<span class="size'+size+'">' + html + '</span>'}
4091: return html;
4092: },
4093:
4094: /*
4095: * Add the font class, if needed
4096: */
4097: AddClass: function (tclass,html) {
4098: if (tclass != '' && tclass != 'normal') {html = jsMath.HTML.Class(tclass,html)}
4099: return html;
4100: }
4101:
4102: });
4103:
4104:
4105: jsMath.Package(jsMath.Typeset,{
4106:
4107: /*
4108: * The spacing tables for inter-atom spacing
4109: * (See rule 20, and Chapter 18, p 170)
4110: */
4111: DTsep: {
4112: ord: {op: 1, bin: 2, rel: 3, inner: 1},
4113: op: {ord: 1, op: 1, rel: 3, inner: 1},
4114: bin: {ord: 2, op: 2, open: 2, inner: 2},
4115: rel: {ord: 3, op: 3, open: 3, inner: 3},
4116: open: {},
4117: close: {op: 1, bin:2, rel: 3, inner: 1},
4118: punct: {ord: 1, op: 1, rel: 1, open: 1, close: 1, punct: 1, inner: 1},
4119: inner: {ord: 1, op: 1, bin: 2, rel: 3, open: 1, punct: 1, inner: 1}
4120: },
4121:
4122: SSsep: {
4123: ord: {op: 1},
4124: op: {ord: 1, op: 1},
4125: bin: {},
4126: rel: {},
4127: open: {},
4128: close: {op: 1},
4129: punct: {},
4130: inner: {op: 1}
4131: },
4132:
4133: /*
4134: * The sizes used in the tables above
4135: */
4136: sepW: ['','thinmuskip','medmuskip','thickmuskip'],
4137:
4138:
4139: /*
4140: * Find the amount of separation to use between two adjacent
4141: * atoms in the given style
4142: */
4143: GetSeparation: function (l,r,style) {
4144: if (l && l.atom && r.atom) {
4145: var table = this.DTsep; if (style.charAt(0) == "S") {table = this.SSsep}
4146: var row = table[l.type];
4147: if (row && row[r.type] != null) {return jsMath.TeX[this.sepW[row[r.type]]]}
4148: }
4149: return 0;
4150: },
4151:
4152: /*
4153: * Typeset an mlist (i.e., turn it into HTML).
4154: * Here, text items of the same class and style are combined
4155: * to reduce the number of <SPAN> tags used (though it is still
4156: * huge). Spaces are combined, when possible.
4157: * ### More needs to be done with that. ###
4158: * The width of the final box is recomputed at the end, since
4159: * the final width is not necessarily the sum of the widths of
4160: * the individual parts (widths are in pixels, but the browsers
4161: * puts pieces together using sub-pixel accuracy).
4162: */
4163: Typeset: function (style,size) {
4164: this.style = style; this.size = size; var unset = -10000
1.3 ! albertel 4165: this.w = 0; this.mw = 0; this.Mw = 0;
! 4166: this.h = unset; this.d = unset;
1.1 albertel 4167: this.bh = this.h; this.bd = this.d;
4168: this.tbuf = ''; this.tx = 0; this.tclass = '';
4169: this.cbuf = ''; this.hbuf = ''; this.hx = 0;
4170: var mitem = null; var prev; this.x = 0; this.dx = 0;
4171:
4172: for (var i = 0; i < this.mlist.length; i++) {
4173: prev = mitem; mitem = this.mlist[i];
4174: switch (mitem.type) {
4175:
4176: case 'size':
4177: this.FlushClassed();
4178: this.size = mitem.size;
4179: mitem = prev; // hide this from TeX
4180: break;
4181:
4182: case 'style':
4183: this.FlushClassed();
4184: if (this.style.charAt(this.style.length-1) == "'")
4185: {this.style = mitem.style + "'"} else {this.style = mitem.style}
4186: mitem = prev; // hide this from TeX
4187: break;
4188:
4189: case 'space':
4190: if (typeof(mitem.w) == 'object') {
4191: if (this.style.charAt(1) == 'S') {mitem.w = .5*mitem.w[0]/18}
4192: else if (this.style.charAt(0) == 'S') {mitem.w = .7*mitem.w[0]/18}
4193: else {mitem.w = mitem.w[0]/18}
4194: }
4195: this.dx += mitem.w-0; // mitem.w is sometimes a string?
4196: mitem = prev; // hide this from TeX
4197: break;
4198:
4199: case 'html':
4200: this.FlushClassed();
4201: if (this.hbuf == '') {this.hx = this.x}
4202: this.hbuf += mitem.html;
4203: mitem = prev; // hide this from TeX
4204: break;
4205:
4206: default: // atom
4207: if (!mitem.atom && mitem.type != 'box') break;
4208: mitem.nuc.x += this.dx + this.GetSeparation(prev,mitem,this.style);
1.3 ! albertel 4209: if (mitem.nuc.x || mitem.nuc.y) mitem.nuc.Styled();
1.1 albertel 4210: this.dx = 0; this.x = this.x + this.w;
1.3 ! albertel 4211: if (this.x + mitem.nuc.x + mitem.nuc.mw < this.mw)
! 4212: {this.mw = this.x + mitem.nuc.x + mitem.nuc.mw}
! 4213: if (this.w + mitem.nuc.x + mitem.nuc.Mw > this.Mw)
! 4214: {this.Mw = this.w + mitem.nuc.x + mitem.nuc.Mw}
1.1 albertel 4215: this.w += mitem.nuc.w + mitem.nuc.x;
4216: if (mitem.nuc.format == 'text') {
4217: if (this.tclass != mitem.nuc.tclass && this.tclass != '') this.FlushText();
4218: if (this.tbuf == '' && this.cbuf == '') {this.tx = this.x}
4219: this.tbuf += mitem.nuc.html; this.tclass = mitem.nuc.tclass;
4220: } else {
4221: this.FlushClassed();
4222: if (mitem.nuc.x || mitem.nuc.y) this.Place(mitem.nuc);
4223: if (this.hbuf == '') {this.hx = this.x}
4224: this.hbuf += mitem.nuc.html;
4225: }
4226: this.h = Math.max(this.h,mitem.nuc.h+mitem.nuc.y); this.bh = Math.max(this.bh,mitem.nuc.bh);
4227: this.d = Math.max(this.d,mitem.nuc.d-mitem.nuc.y); this.bd = Math.max(this.bd,mitem.nuc.bd);
4228: break;
4229: }
4230: }
1.3 ! albertel 4231:
1.1 albertel 4232: this.FlushClassed(); // make sure scaling is included
1.3 ! albertel 4233: if (this.dx) {
! 4234: this.hbuf += jsMath.HTML.Spacer(this.dx); this.w += this.dx;
! 4235: if (this.w > this.Mw) {this.Mw = this.w}
! 4236: if (this.w < this.mw) {this.mw = this.w}
! 4237: }
! 4238: if (this.hbuf == '') {return jsMath.Box.Null()}
1.1 albertel 4239: if (this.h == unset) {this.h = 0}
4240: if (this.d == unset) {this.d = 0}
4241: var box = new jsMath.Box('html',this.hbuf,this.w,this.h,this.d);
4242: box.bh = this.bh; box.bd = this.bd;
1.3 ! albertel 4243: box.mw = this.mw; box.Mw = this.Mw;
1.1 albertel 4244: return box;
4245: },
4246:
4247: /*
4248: * Add the font to the buffered text and move it to the
4249: * classed-text buffer.
4250: */
4251: FlushText: function () {
4252: if (this.tbuf == '') return;
4253: this.cbuf += jsMath.Typeset.AddClass(this.tclass,this.tbuf);
4254: this.tbuf = ''; this.tclass = '';
4255: },
4256:
4257: /*
4258: * Add the script or scriptscript style to the text and
4259: * move it to the HTML buffer
4260: */
4261: FlushClassed: function () {
4262: this.FlushText();
4263: if (this.cbuf == '') return;
4264: if (this.hbuf == '') {this.hx = this.tx}
4265: this.hbuf += jsMath.Typeset.AddStyle(this.style,this.size,this.cbuf);
4266: this.cbuf = '';
4267: },
4268:
4269: /*
4270: * Add a <SPAN> to position an item's HTML, and
4271: * adjust the item's height and depth.
4272: * (This may be replaced buy one of the following browser-specific
4273: * versions by Browser.Init().)
4274: */
4275: Place: function (item) {
4276: var html = '<span style="position: relative;';
4277: if (item.x) {html += ' margin-left:'+jsMath.HTML.Em(item.x)+';'}
4278: if (item.y) {html += ' top:'+jsMath.HTML.Em(-item.y)+';'}
4279: item.html = html + '">' + item.html + '</span>';
4280: item.h += item.y; item.d -= item.y;
4281: item.x = 0; item.y = 0;
4282: },
4283:
4284: /*
4285: * For MSIE on Windows, backspacing must be done in a separate
4286: * <SPAN>, otherwise the contents will be clipped. Netscape
4287: * also doesn't combine vertical and horizontal spacing well.
4288: * Here, the horizontal and vertical spacing are done separately.
4289: */
1.3 ! albertel 4290:
1.1 albertel 4291: PlaceSeparateSkips: function (item) {
4292: if (item.y) {
1.3 ! albertel 4293: var rw = item.Mw - item.w; var lw = item.mw;
! 4294: var W = item.Mw - item.mw;
! 4295: item.html =
! 4296: jsMath.HTML.Spacer(lw-rw) +
! 4297: '<span style="position: relative; '
! 4298: + 'top:'+jsMath.HTML.Em(-item.y)+';'
! 4299: + 'left:'+jsMath.HTML.Em(rw)+'; width:'+jsMath.HTML.Em(W)+';">' +
! 4300: jsMath.HTML.Spacer(-lw) +
! 4301: item.html +
! 4302: jsMath.HTML.Spacer(rw) +
! 4303: '</span>'
1.1 albertel 4304: }
4305: if (item.x) {item.html = jsMath.HTML.Spacer(item.x) + item.html}
4306: item.h += item.y; item.d -= item.y;
4307: item.x = 0; item.y = 0;
4308: }
1.3 ! albertel 4309:
1.1 albertel 4310: });
4311:
4312:
4313:
4314: /***************************************************************************/
4315:
4316: /*
4317: * The Parse object handles the parsing of the TeX input string, and creates
4318: * the mList to be typeset by the Typeset object above.
4319: */
4320:
4321: jsMath.Parse = function (s,font,size,style) {
4322: var parse = new jsMath.Parser(s,font,size,style);
4323: parse.Parse();
4324: return parse;
4325: }
4326:
4327: jsMath.Parser = function (s,font,size,style) {
4328: this.string = s; this.i = 0;
4329: this.mlist = new jsMath.mList(null,font,size,style);
4330: }
4331:
4332: jsMath.Package(jsMath.Parser,{
4333:
4334: // special characters
4335: cmd: '\\',
4336: open: '{',
4337: close: '}',
4338:
4339: // patterns for letters and numbers
4340: letter: /[a-z]/i,
4341: number: /[0-9]/,
4342: // pattern for macros to ^ and _ that should be read with arguments
1.2 albertel 4343: scriptargs: /^((math|text)..|mathcal|[hm]box)$/,
1.1 albertel 4344:
4345: // the \mathchar definitions (see Appendix B of the TeXbook).
4346: mathchar: {
4347: '!': [5,0,0x21],
4348: '(': [4,0,0x28],
4349: ')': [5,0,0x29],
4350: '*': [2,2,0x03], // \ast
4351: '+': [2,0,0x2B],
4352: ',': [6,1,0x3B],
4353: '-': [2,2,0x00],
4354: '.': [0,1,0x3A],
4355: '/': [0,1,0x3D],
4356: ':': [3,0,0x3A],
4357: ';': [6,0,0x3B],
4358: '<': [3,1,0x3C],
4359: '=': [3,0,0x3D],
4360: '>': [3,1,0x3E],
4361: '?': [5,0,0x3F],
4362: '[': [4,0,0x5B],
4363: ']': [5,0,0x5D],
4364: // '{': [4,2,0x66],
4365: // '}': [5,2,0x67],
4366: '|': [0,2,0x6A]
4367: },
4368:
4369: // handle special \catcode characters
4370: special: {
4371: '~': 'Tilde',
4372: '^': 'HandleSuperscript',
4373: '_': 'HandleSubscript',
4374: ' ': 'Space',
4375: '\01': 'Space',
4376: "\t": 'Space',
4377: "\r": 'Space',
4378: "\n": 'Space',
4379: "'": 'Prime',
4380: '%': 'HandleComment',
1.3 ! albertel 4381: '&': 'HandleEntry',
! 4382: '#': 'Hash'
1.1 albertel 4383: },
4384:
4385: // the \mathchardef table (see Appendix B of the TeXbook).
4386: mathchardef: {
4387: // brace parts
4388: braceld: [0,3,0x7A],
4389: bracerd: [0,3,0x7B],
4390: bracelu: [0,3,0x7C],
4391: braceru: [0,3,0x7D],
4392:
4393: // Greek letters
4394: alpha: [0,1,0x0B],
4395: beta: [0,1,0x0C],
4396: gamma: [0,1,0x0D],
4397: delta: [0,1,0x0E],
4398: epsilon: [0,1,0x0F],
4399: zeta: [0,1,0x10],
4400: eta: [0,1,0x11],
4401: theta: [0,1,0x12],
4402: iota: [0,1,0x13],
4403: kappa: [0,1,0x14],
4404: lambda: [0,1,0x15],
4405: mu: [0,1,0x16],
4406: nu: [0,1,0x17],
4407: xi: [0,1,0x18],
4408: pi: [0,1,0x19],
4409: rho: [0,1,0x1A],
4410: sigma: [0,1,0x1B],
4411: tau: [0,1,0x1C],
4412: upsilon: [0,1,0x1D],
4413: phi: [0,1,0x1E],
4414: chi: [0,1,0x1F],
4415: psi: [0,1,0x20],
4416: omega: [0,1,0x21],
4417: varepsilon: [0,1,0x22],
4418: vartheta: [0,1,0x23],
4419: varpi: [0,1,0x24],
4420: varrho: [0,1,0x25],
4421: varsigma: [0,1,0x26],
4422: varphi: [0,1,0x27],
4423:
4424: Gamma: [7,0,0x00],
4425: Delta: [7,0,0x01],
4426: Theta: [7,0,0x02],
4427: Lambda: [7,0,0x03],
4428: Xi: [7,0,0x04],
4429: Pi: [7,0,0x05],
4430: Sigma: [7,0,0x06],
4431: Upsilon: [7,0,0x07],
4432: Phi: [7,0,0x08],
4433: Psi: [7,0,0x09],
4434: Omega: [7,0,0x0A],
4435:
4436: // Ord symbols
4437: aleph: [0,2,0x40],
4438: imath: [0,1,0x7B],
4439: jmath: [0,1,0x7C],
4440: ell: [0,1,0x60],
4441: wp: [0,1,0x7D],
4442: Re: [0,2,0x3C],
4443: Im: [0,2,0x3D],
4444: partial: [0,1,0x40],
4445: infty: [0,2,0x31],
4446: prime: [0,2,0x30],
4447: emptyset: [0,2,0x3B],
4448: nabla: [0,2,0x72],
4449: surd: [1,2,0x70],
4450: top: [0,2,0x3E],
4451: bot: [0,2,0x3F],
4452: triangle: [0,2,0x34],
4453: forall: [0,2,0x38],
4454: exists: [0,2,0x39],
4455: neg: [0,2,0x3A],
4456: lnot: [0,2,0x3A],
4457: flat: [0,1,0x5B],
4458: natural: [0,1,0x5C],
4459: sharp: [0,1,0x5D],
4460: clubsuit: [0,2,0x7C],
4461: diamondsuit: [0,2,0x7D],
4462: heartsuit: [0,2,0x7E],
4463: spadesuit: [0,2,0x7F],
4464:
4465: // big ops
4466: coprod: [1,3,0x60],
4467: bigvee: [1,3,0x57],
4468: bigwedge: [1,3,0x56],
4469: biguplus: [1,3,0x55],
4470: bigcap: [1,3,0x54],
4471: bigcup: [1,3,0x53],
4472: intop: [1,3,0x52],
4473: prod: [1,3,0x51],
4474: sum: [1,3,0x50],
4475: bigotimes: [1,3,0x4E],
4476: bigoplus: [1,3,0x4C],
4477: bigodot: [1,3,0x4A],
4478: ointop: [1,3,0x48],
4479: bigsqcup: [1,3,0x46],
4480: smallint: [1,2,0x73],
4481:
4482: // binary operations
4483: triangleleft: [2,1,0x2F],
4484: triangleright: [2,1,0x2E],
4485: bigtriangleup: [2,2,0x34],
4486: bigtriangledown: [2,2,0x35],
4487: wedge: [2,2,0x5E],
4488: land: [2,2,0x5E],
4489: vee: [2,2,0x5F],
4490: lor: [2,2,0x5F],
4491: cap: [2,2,0x5C],
4492: cup: [2,2,0x5B],
4493: ddagger: [2,2,0x7A],
4494: dagger: [2,2,0x79],
4495: sqcap: [2,2,0x75],
4496: sqcup: [2,2,0x74],
4497: uplus: [2,2,0x5D],
4498: amalg: [2,2,0x71],
4499: diamond: [2,2,0x05],
4500: bullet: [2,2,0x0F],
4501: wr: [2,2,0x6F],
4502: div: [2,2,0x04],
4503: odot: [2,2,0x0C],
4504: oslash: [2,2,0x0B],
4505: otimes: [2,2,0x0A],
4506: ominus: [2,2,0x09],
4507: oplus: [2,2,0x08],
4508: mp: [2,2,0x07],
4509: pm: [2,2,0x06],
4510: circ: [2,2,0x0E],
4511: bigcirc: [2,2,0x0D],
4512: setminus: [2,2,0x6E], // for set difference A\setminus B
4513: cdot: [2,2,0x01],
4514: ast: [2,2,0x03],
4515: times: [2,2,0x02],
4516: star: [2,1,0x3F],
4517:
4518: // Relations
4519: propto: [3,2,0x2F],
4520: sqsubseteq: [3,2,0x76],
4521: sqsupseteq: [3,2,0x77],
4522: parallel: [3,2,0x6B],
4523: mid: [3,2,0x6A],
4524: dashv: [3,2,0x61],
4525: vdash: [3,2,0x60],
4526: leq: [3,2,0x14],
4527: le: [3,2,0x14],
4528: geq: [3,2,0x15],
4529: ge: [3,2,0x15],
1.3 ! albertel 4530: lt: [3,1,0x3C], // extra since < and > are hard
! 4531: gt: [3,1,0x3E], // to get in HTML
1.1 albertel 4532: succ: [3,2,0x1F],
4533: prec: [3,2,0x1E],
4534: approx: [3,2,0x19],
4535: succeq: [3,2,0x17],
4536: preceq: [3,2,0x16],
4537: supset: [3,2,0x1B],
4538: subset: [3,2,0x1A],
4539: supseteq: [3,2,0x13],
4540: subseteq: [3,2,0x12],
4541: 'in': [3,2,0x32],
4542: ni: [3,2,0x33],
4543: owns: [3,2,0x33],
4544: gg: [3,2,0x1D],
4545: ll: [3,2,0x1C],
4546: not: [3,2,0x36],
4547: sim: [3,2,0x18],
4548: simeq: [3,2,0x27],
4549: perp: [3,2,0x3F],
4550: equiv: [3,2,0x11],
4551: asymp: [3,2,0x10],
4552: smile: [3,1,0x5E],
4553: frown: [3,1,0x5F],
4554:
4555: // Arrows
4556: Leftrightarrow: [3,2,0x2C],
4557: Leftarrow: [3,2,0x28],
4558: Rightarrow: [3,2,0x29],
4559: leftrightarrow: [3,2,0x24],
4560: leftarrow: [3,2,0x20],
4561: gets: [3,2,0x20],
4562: rightarrow: [3,2,0x21],
4563: to: [3,2,0x21],
4564: mapstochar: [3,2,0x37],
4565: leftharpoonup: [3,1,0x28],
4566: leftharpoondown: [3,1,0x29],
4567: rightharpoonup: [3,1,0x2A],
4568: rightharpoondown: [3,1,0x2B],
4569: nearrow: [3,2,0x25],
4570: searrow: [3,2,0x26],
4571: nwarrow: [3,2,0x2D],
4572: swarrow: [3,2,0x2E],
4573:
1.3 ! albertel 4574: minuschar: [3,2,0x00], // for longmapsto
1.1 albertel 4575: hbarchar: [0,0,0x16], // for \hbar
4576: lhook: [3,1,0x2C],
4577: rhook: [3,1,0x2D],
4578:
4579: ldotp: [6,1,0x3A], // ldot as a punctuation mark
4580: cdotp: [6,2,0x01], // cdot as a punctuation mark
4581: colon: [6,0,0x3A], // colon as a punctuation mark
4582:
4583: '#': [7,0,0x23],
4584: '$': [7,0,0x24],
4585: '%': [7,0,0x25],
4586: '&': [7,0,0x26]
4587: },
4588:
4589: // The delimiter table (see Appendix B of the TeXbook)
4590: delimiter: {
4591: '(': [0,0,0x28,3,0x00],
4592: ')': [0,0,0x29,3,0x01],
4593: '[': [0,0,0x5B,3,0x02],
4594: ']': [0,0,0x5D,3,0x03],
4595: '<': [0,2,0x68,3,0x0A],
4596: '>': [0,2,0x69,3,0x0B],
1.3 ! albertel 4597: '\\lt': [0,2,0x68,3,0x0A], // extra since < and > are
! 4598: '\\gt': [0,2,0x69,3,0x0B], // hard to get in HTML
1.1 albertel 4599: '/': [0,0,0x2F,3,0x0E],
4600: '|': [0,2,0x6A,3,0x0C],
4601: '.': [0,0,0x00,0,0x00],
4602: '\\': [0,2,0x6E,3,0x0F],
4603: '\\lmoustache': [4,3,0x7A,3,0x40], // top from (, bottom from )
4604: '\\rmoustache': [5,3,0x7B,3,0x41], // top from ), bottom from (
4605: '\\lgroup': [4,6,0x28,3,0x3A], // extensible ( with sharper tips
4606: '\\rgroup': [5,6,0x29,3,0x3B], // extensible ) with sharper tips
4607: '\\arrowvert': [0,2,0x6A,3,0x3C], // arrow without arrowheads
4608: '\\Arrowvert': [0,2,0x6B,3,0x3D], // double arrow without arrowheads
4609: // '\\bracevert': [0,7,0x7C,3,0x3E], // the vertical bar that extends braces
4610: '\\bracevert': [0,2,0x6A,3,0x3E], // we don't load tt, so use | instead
4611: '\\Vert': [0,2,0x6B,3,0x0D],
4612: '\\|': [0,2,0x6B,3,0x0D],
4613: '\\vert': [0,2,0x6A,3,0x0C],
4614: '\\uparrow': [3,2,0x22,3,0x78],
4615: '\\downarrow': [3,2,0x23,3,0x79],
4616: '\\updownarrow': [3,2,0x6C,3,0x3F],
4617: '\\Uparrow': [3,2,0x2A,3,0x7E],
4618: '\\Downarrow': [3,2,0x2B,3,0x7F],
4619: '\\Updownarrow': [3,2,0x6D,3,0x77],
4620: '\\backslash': [0,2,0x6E,3,0x0F], // for double coset G\backslash H
4621: '\\rangle': [5,2,0x69,3,0x0B],
4622: '\\langle': [4,2,0x68,3,0x0A],
4623: '\\rbrace': [5,2,0x67,3,0x09],
4624: '\\lbrace': [4,2,0x66,3,0x08],
4625: '\\}': [5,2,0x67,3,0x09],
4626: '\\{': [4,2,0x66,3,0x08],
4627: '\\rceil': [5,2,0x65,3,0x07],
4628: '\\lceil': [4,2,0x64,3,0x06],
4629: '\\rfloor': [5,2,0x63,3,0x05],
4630: '\\lfloor': [4,2,0x62,3,0x04],
4631: '\\lbrack': [0,0,0x5B,3,0x02],
4632: '\\rbrack': [0,0,0x5D,3,0x03]
4633: },
4634:
4635: /*
4636: * The basic macros for plain TeX.
4637: *
4638: * When the control sequence on the left is called, the JavaScript
4639: * funtion on the right is called, with the name of the control sequence
4640: * as its first parameter (this way, the same function can be called by
4641: * several different control sequences to do similar actions, and the
4642: * function can still tell which TeX command was issued). If the right
4643: * is an array, the first entry is the routine to call, and the
4644: * remaining entries in the array are parameters to pass to the function
4645: * as the second parameter (they are in an array reference).
4646: *
4647: * Note: TeX macros as defined by the user are discussed below.
4648: */
4649: macros: {
4650: displaystyle: ['HandleStyle','D'],
4651: textstyle: ['HandleStyle','T'],
4652: scriptstyle: ['HandleStyle','S'],
4653: scriptscriptstyle: ['HandleStyle','SS'],
4654:
4655: rm: ['HandleFont',0],
4656: mit: ['HandleFont',1],
4657: oldstyle: ['HandleFont',1],
4658: cal: ['HandleFont',2],
4659: it: ['HandleFont',4],
4660: bf: ['HandleFont',6],
4661:
1.2 albertel 4662: font: ['Extension','font'],
4663:
1.1 albertel 4664: left: 'HandleLeft',
4665: right: 'HandleRight',
4666:
4667: arcsin: ['NamedOp',0],
4668: arccos: ['NamedOp',0],
4669: arctan: ['NamedOp',0],
4670: arg: ['NamedOp',0],
4671: cos: ['NamedOp',0],
4672: cosh: ['NamedOp',0],
4673: cot: ['NamedOp',0],
4674: coth: ['NamedOp',0],
4675: csc: ['NamedOp',0],
4676: deg: ['NamedOp',0],
4677: det: 'NamedOp',
4678: dim: ['NamedOp',0],
4679: exp: ['NamedOp',0],
4680: gcd: 'NamedOp',
4681: hom: ['NamedOp',0],
4682: inf: 'NamedOp',
4683: ker: ['NamedOp',0],
4684: lg: ['NamedOp',0],
4685: lim: 'NamedOp',
4686: liminf: ['NamedOp',null,'lim<span style="margin-left: '+1/6+'em"></span>inf'],
4687: limsup: ['NamedOp',null,'lim<span style="margin-left: '+1/6+'em"></span>sup'],
4688: ln: ['NamedOp',0],
4689: log: ['NamedOp',0],
4690: max: 'NamedOp',
4691: min: 'NamedOp',
4692: Pr: 'NamedOp',
4693: sec: ['NamedOp',0],
4694: sin: ['NamedOp',0],
4695: sinh: ['NamedOp',0],
4696: sup: 'NamedOp',
4697: tan: ['NamedOp',0],
4698: tanh: ['NamedOp',0],
4699:
4700: vcenter: ['HandleAtom','vcenter'],
4701: overline: ['HandleAtom','overline'],
4702: underline: ['HandleAtom','underline'],
4703: over: 'HandleOver',
4704: overwithdelims: 'HandleOver',
4705: atop: 'HandleOver',
4706: atopwithdelims: 'HandleOver',
4707: above: 'HandleOver',
4708: abovewithdelims: 'HandleOver',
4709: brace: ['HandleOver','\\{','\\}'],
4710: brack: ['HandleOver','[',']'],
4711: choose: ['HandleOver','(',')'],
4712:
4713: overbrace: ['Extension','leaders'],
4714: underbrace: ['Extension','leaders'],
4715: overrightarrow: ['Extension','leaders'],
1.3 ! albertel 4716: underrightarrow: ['Extension','leaders'],
1.1 albertel 4717: overleftarrow: ['Extension','leaders'],
1.3 ! albertel 4718: underleftarrow: ['Extension','leaders'],
! 4719: overleftrightarrow: ['Extension','leaders'],
! 4720: underleftrightarrow: ['Extension','leaders'],
1.1 albertel 4721: overset: ['Extension','underset-overset'],
4722: underset: ['Extension','underset-overset'],
4723:
4724: llap: 'HandleLap',
4725: rlap: 'HandleLap',
4726: ulap: 'HandleLap',
4727: dlap: 'HandleLap',
4728: raise: 'RaiseLower',
4729: lower: 'RaiseLower',
4730: moveleft: 'MoveLeftRight',
4731: moveright: 'MoveLeftRight',
4732:
4733: frac: 'Frac',
4734: root: 'Root',
4735: sqrt: 'Sqrt',
4736:
4737: // TeX substitution macros
4738: hbar: ['Macro','\\hbarchar\\kern-.5em h'],
4739: ne: ['Macro','\\not='],
4740: neq: ['Macro','\\not='],
4741: notin: ['Macro','\\mathrel{\\rlap{\\kern2mu/}}\\in'],
4742: cong: ['Macro','\\mathrel{\\lower2mu{\\mathrel{{\\rlap{=}\\raise6mu\\sim}}}}'],
4743: bmod: ['Macro','\\mathbin{\\rm mod}'],
4744: pmod: ['Macro','\\kern 18mu ({\\rm mod}\\,\\,#1)',1],
4745: 'int': ['Macro','\\intop\\nolimits'],
4746: oint: ['Macro','\\ointop\\nolimits'],
4747: doteq: ['Macro','\\buildrel\\textstyle.\\over='],
4748: ldots: ['Macro','\\mathinner{\\ldotp\\ldotp\\ldotp}'],
4749: cdots: ['Macro','\\mathinner{\\cdotp\\cdotp\\cdotp}'],
4750: vdots: ['Macro','\\mathinner{\\rlap{\\raise8pt{.\\rule 0pt 6pt 0pt}}\\rlap{\\raise4pt{.}}.}'],
4751: ddots: ['Macro','\\mathinner{\\kern1mu\\raise7pt{\\rule 0pt 7pt 0pt .}\\kern2mu\\raise4pt{.}\\kern2mu\\raise1pt{.}\\kern1mu}'],
4752: joinrel: ['Macro','\\mathrel{\\kern-4mu}'],
4753: relbar: ['Macro','\\mathrel{\\smash-}'], // \smash, because - has the same height as +
4754: Relbar: ['Macro','\\mathrel='],
4755: bowtie: ['Macro','\\mathrel\\triangleright\\joinrel\\mathrel\\triangleleft'],
4756: models: ['Macro','\\mathrel|\\joinrel='],
1.3 ! albertel 4757: mapsto: ['Macro','\\mathrel{\\mapstochar\\rightarrow}'],
1.1 albertel 4758: rightleftharpoons: ['Macro','\\vcenter{\\mathrel{\\rlap{\\raise3mu{\\rightharpoonup}}}\\leftharpoondown}'],
4759: hookrightarrow: ['Macro','\\lhook\\joinrel\\rightarrow'],
4760: hookleftarrow: ['Macro','\\leftarrow\\joinrel\\rhook'],
4761: Longrightarrow: ['Macro','\\Relbar\\joinrel\\Rightarrow'],
4762: longrightarrow: ['Macro','\\relbar\\joinrel\\rightarrow'],
4763: longleftarrow: ['Macro','\\leftarrow\\joinrel\\relbar'],
4764: Longleftarrow: ['Macro','\\Leftarrow\\joinrel\\Relbar'],
1.3 ! albertel 4765: longmapsto: ['Macro','\\mathrel{\\mapstochar\\minuschar\\joinrel\\rightarrow}'],
1.1 albertel 4766: longleftrightarrow: ['Macro','\\leftarrow\\joinrel\\rightarrow'],
4767: Longleftrightarrow: ['Macro','\\Leftarrow\\joinrel\\Rightarrow'],
4768: iff: ['Macro','\\;\\Longleftrightarrow\\;'],
4769: mathcal: ['Macro','{\\cal #1}',1],
4770: mathrm: ['Macro','{\\rm #1}',1],
4771: mathbf: ['Macro','{\\bf #1}',1],
4772: mathbb: ['Macro','{\\bf #1}',1],
4773: mathit: ['Macro','{\\it #1}',1],
4774: textrm: ['Macro','\\mathord{\\hbox{#1}}',1],
4775: textit: ['Macro','\\mathord{\\class{textit}{\\hbox{#1}}}',1],
4776: textbf: ['Macro','\\mathord{\\class{textbf}{\\hbox{#1}}}',1],
1.3 ! albertel 4777: pmb: ['Macro','\\rlap{#1}\\kern1px{#1}',1],
1.1 albertel 4778:
4779: TeX: ['Macro','T\\kern-.1667em\\lower.5ex{E}\\kern-.125em X'],
4780:
4781: limits: ['Limits',1],
4782: nolimits: ['Limits',0],
4783:
4784: ',': ['Spacer',1/6],
4785: ':': ['Spacer',1/6], // for LaTeX
4786: '>': ['Spacer',2/9],
4787: ';': ['Spacer',5/18],
4788: '!': ['Spacer',-1/6],
4789: enspace: ['Spacer',1/2],
4790: quad: ['Spacer',1],
4791: qquad: ['Spacer',2],
4792: thinspace: ['Spacer',1/6],
4793: negthinspace: ['Spacer',-1/6],
4794:
4795: hskip: 'Hskip',
4796: kern: 'Hskip',
4797: rule: ['Rule','colored'],
4798: space: ['Rule','blank'],
4799:
4800: big: ['MakeBig','ord',0.85],
4801: Big: ['MakeBig','ord',1.15],
4802: bigg: ['MakeBig','ord',1.45],
4803: Bigg: ['MakeBig','ord',1.75],
4804: bigl: ['MakeBig','open',0.85],
4805: Bigl: ['MakeBig','open',1.15],
4806: biggl: ['MakeBig','open',1.45],
4807: Biggl: ['MakeBig','open',1.75],
4808: bigr: ['MakeBig','close',0.85],
4809: Bigr: ['MakeBig','close',1.15],
4810: biggr: ['MakeBig','close',1.45],
4811: Biggr: ['MakeBig','close',1.75],
4812: bigm: ['MakeBig','rel',0.85],
4813: Bigm: ['MakeBig','rel',1.15],
4814: biggm: ['MakeBig','rel',1.45],
4815: Biggm: ['MakeBig','rel',1.75],
4816:
4817: mathord: ['HandleAtom','ord'],
4818: mathop: ['HandleAtom','op'],
4819: mathopen: ['HandleAtom','open'],
4820: mathclose: ['HandleAtom','close'],
4821: mathbin: ['HandleAtom','bin'],
4822: mathrel: ['HandleAtom','rel'],
4823: mathpunct: ['HandleAtom','punct'],
4824: mathinner: ['HandleAtom','inner'],
4825:
4826: mathchoice: ['Extension','mathchoice'],
4827: buildrel: 'BuildRel',
4828:
4829: hbox: 'HBox',
4830: text: 'HBox',
4831: mbox: 'HBox',
4832: fbox: ['Extension','fbox'],
4833:
4834: strut: 'Strut',
4835: mathstrut: ['Macro','\\vphantom{(}'],
4836: phantom: ['Phantom',1,1],
4837: vphantom: ['Phantom',1,0],
4838: hphantom: ['Phantom',0,1],
4839: smash: 'Smash',
4840:
4841: acute: ['MathAccent', [7,0,0x13]],
4842: grave: ['MathAccent', [7,0,0x12]],
4843: ddot: ['MathAccent', [7,0,0x7F]],
4844: tilde: ['MathAccent', [7,0,0x7E]],
4845: bar: ['MathAccent', [7,0,0x16]],
4846: breve: ['MathAccent', [7,0,0x15]],
4847: check: ['MathAccent', [7,0,0x14]],
4848: hat: ['MathAccent', [7,0,0x5E]],
4849: vec: ['MathAccent', [0,1,0x7E]],
4850: dot: ['MathAccent', [7,0,0x5F]],
4851: widetilde: ['MathAccent', [0,3,0x65]],
4852: widehat: ['MathAccent', [0,3,0x62]],
4853:
4854: '_': ['Replace','ord','_','normal',-.4,.1],
4855: ' ': ['Replace','ord',' ','normal'],
4856: angle: ['Replace','ord','∠','normal'],
4857:
4858: matrix: 'Matrix',
4859: array: 'Matrix', // ### still need to do alignment options ###
4860: pmatrix: ['Matrix','(',')','c'],
1.2 albertel 4861: cases: ['Matrix','\\{','.',['l','l'],null,2],
4862: eqalign: ['Matrix',null,null,['r','l'],[5/18],3,'D'],
4863: displaylines: ['Matrix',null,null,['c'],null,3,'D'],
1.1 albertel 4864: cr: 'HandleRow',
4865: '\\': 'HandleRow',
1.3 ! albertel 4866: newline: 'HandleRow',
1.2 albertel 4867: noalign: 'HandleNoAlign',
4868: eqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'],
4869: leqalignno: ['Matrix',null,null,['r','l','r'],[5/8,3],3,'D'],
1.1 albertel 4870:
4871: // LaTeX
4872: begin: 'Begin',
4873: end: 'End',
4874: tiny: ['HandleSize',0],
4875: Tiny: ['HandleSize',1], // non-standard
4876: scriptsize: ['HandleSize',2],
4877: small: ['HandleSize',3],
4878: normalsize: ['HandleSize',4],
4879: large: ['HandleSize',5],
4880: Large: ['HandleSize',6],
4881: LARGE: ['HandleSize',7],
4882: huge: ['HandleSize',8],
4883: Huge: ['HandleSize',9],
4884: dots: ['Macro','\\ldots'],
4885:
1.3 ! albertel 4886: newcommand: ['Extension','newcommand'],
! 4887: newenvironment: ['Extension','newcommand'],
! 4888: def: ['Extension','newcommand'],
1.1 albertel 4889:
4890: // Extensions to TeX
4891: color: ['Extension','HTML'],
4892: href: ['Extension','HTML'],
4893: 'class': ['Extension','HTML'],
4894: style: ['Extension','HTML'],
4895: cssId: ['Extension','HTML'],
4896: unicode: ['Extension','HTML'],
1.2 albertel 4897: bbox: ['Extension','bbox'],
1.1 albertel 4898:
4899: require: 'Require',
4900:
4901: // debugging and test routines
4902: 'char': 'Char'
4903: },
4904:
4905: /*
4906: * LaTeX environments
4907: */
4908: environments: {
1.3 ! albertel 4909: array: 'Array',
! 4910: matrix: ['Array',null,null,'c'],
! 4911: pmatrix: ['Array','(',')','c'],
! 4912: bmatrix: ['Array','[',']','c'],
! 4913: Bmatrix: ['Array','\\{','\\}','c'],
! 4914: vmatrix: ['Array','\\vert','\\vert','c'],
! 4915: Vmatrix: ['Array','\\Vert','\\Vert','c'],
! 4916: cases: ['Array','\\{','.','ll',null,2],
! 4917: eqnarray: ['Array',null,null,'rcl',[5/18,5/18],3,'D'],
! 4918:
! 4919: align: ['Extension','AMSmath'],
! 4920: 'align*': ['Extension','AMSmath'],
! 4921: multline: ['Extension','AMSmath'],
! 4922: 'multline*': ['Extension','AMSmath'],
! 4923: split: ['Extension','AMSmath'],
! 4924: gather: ['Extension','AMSmath'],
! 4925: 'gather*': ['Extension','AMSmath']
1.1 albertel 4926: },
4927:
4928:
4929: /***************************************************************************/
4930:
4931: /*
4932: * Add special characters to list above. (This makes it possible
4933: * to define them in a variable that the user can change.)
4934: */
4935: AddSpecial: function (obj) {
4936: for (var id in obj) {
4937: jsMath.Parser.prototype.special[jsMath.Parser.prototype[id]] = obj[id];
4938: }
4939: },
4940:
4941: /*
4942: * Throw an error
4943: */
4944: Error: function (s) {
4945: this.i = this.string.length;
4946: if (s.error) {this.error = s.error} else {
4947: if (!this.error) {this.error = s}
4948: }
4949: },
4950:
4951: /***************************************************************************/
4952:
4953: /*
4954: * Check if the next character is a space
4955: */
4956: nextIsSpace: function () {
4957: return this.string.charAt(this.i) == ' ';
4958: },
4959:
4960: /*
4961: * Trim spaces from a string
4962: */
4963: trimSpaces: function (text) {
4964: if (typeof(text) != 'string') {return text}
4965: return text.replace(/^\s+|\s+/g,'');
4966: },
4967:
4968: /*
4969: * Parse a substring to get its mList, and return it.
4970: * Check that no errors occured
4971: */
4972: Process: function (arg) {
4973: var data = this.mlist.data;
4974: arg = jsMath.Parse(arg,data.font,data.size,data.style);
4975: if (arg.error) {this.Error(arg); return null}
4976: if (arg.mlist.Length() == 0) {return null}
4977: if (arg.mlist.Length() == 1) {
4978: var atom = arg.mlist.Last();
4979: if (atom.atom && atom.type == 'ord' && atom.nuc &&
4980: !atom.sub && !atom.sup && (atom.nuc.type == 'text' || atom.nuc.type == 'TeX'))
4981: {return atom.nuc}
4982: }
4983: return {type: 'mlist', mlist: arg.mlist};
4984: },
4985:
4986: /*
4987: * Get and return a control-sequence name from the TeX string
4988: */
4989: GetCommand: function () {
4990: var letter = /^([a-z]+|.) ?/i;
4991: var cmd = letter.exec(this.string.slice(this.i));
4992: if (cmd) {this.i += cmd[1].length; return cmd[1]}
1.2 albertel 4993: this.i++; return " ";
1.1 albertel 4994: },
4995:
4996: /*
4997: * Get and return a TeX argument (either a single character or control sequence,
4998: * or the contents of the next set of braces).
4999: */
5000: GetArgument: function (name,noneOK) {
5001: while (this.nextIsSpace()) {this.i++}
5002: if (this.i >= this.string.length) {if (!noneOK) this.Error("Missing argument for "+name); return null}
5003: if (this.string.charAt(this.i) == this.close) {if (!noneOK) this.Error("Extra close brace"); return null}
5004: if (this.string.charAt(this.i) == this.cmd) {this.i++; return this.cmd+this.GetCommand()}
5005: if (this.string.charAt(this.i) != this.open) {return this.string.charAt(this.i++)}
5006: var j = ++this.i; var pcount = 1; var c = '';
5007: while (this.i < this.string.length) {
5008: c = this.string.charAt(this.i++);
5009: if (c == this.cmd) {this.i++}
5010: else if (c == this.open) {pcount++}
5011: else if (c == this.close) {
5012: if (pcount == 0) {this.Error("Extra close brace"); return null}
5013: if (--pcount == 0) {return this.string.slice(j,this.i-1)}
5014: }
5015: }
5016: this.Error("Missing close brace");
5017: return null;
5018: },
5019:
5020: /*
5021: * Get an argument and process it into an mList
5022: */
5023: ProcessArg: function (name) {
5024: var arg = this.GetArgument(name); if (this.error) {return null}
5025: return this.Process(arg);
5026: },
5027:
5028: /*
5029: * Get and process an argument for a super- or subscript.
5030: * (read extra args for \frac, \sqrt, \mathrm, etc.)
5031: * This handles these macros as special cases, so is really
5032: * rather a hack. A more general method for indicating
5033: * how to handle macros in scripts needs to be developed.
5034: */
5035: ProcessScriptArg: function (name) {
5036: var arg = this.GetArgument(name); if (this.error) {return null}
5037: if (arg.charAt(0) == this.cmd) {
1.2 albertel 5038: var csname = arg.substr(1);
1.1 albertel 5039: if (csname == "frac") {
5040: arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}
5041: arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}
5042: } else if (csname == "sqrt") {
5043: arg += '['+this.GetBrackets(csname)+']'; if (this.error) {return null}
5044: arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}
5045: } else if (csname.match(this.scriptargs)) {
5046: arg += '{'+this.GetArgument(csname)+'}'; if (this.error) {return null}
5047: }
5048: }
5049: return this.Process(arg);
5050: },
5051:
5052: /*
5053: * Get the name of a delimiter (check it in the delimiter list).
5054: */
5055: GetDelimiter: function (name) {
5056: while (this.nextIsSpace()) {this.i++}
5057: var c = this.string.charAt(this.i);
5058: if (this.i < this.string.length) {
5059: this.i++;
5060: if (c == this.cmd) {c = '\\'+this.GetCommand(name); if (this.error) return null}
5061: if (this.delimiter[c] != null) {return this.delimiter[c]}
5062: }
5063: this.Error("Missing or unrecognized delimiter for "+name);
5064: return null;
5065: },
5066:
5067: /*
5068: * Get a dimension (including its units).
5069: * Convert the dimen to em's, except for mu's, which must be
5070: * converted when typeset.
5071: */
5072: GetDimen: function (name,nomu) {
5073: var rest; var advance = 0;
5074: if (this.nextIsSpace()) {this.i++}
5075: if (this.string.charAt(this.i) == '{') {
5076: rest = this.GetArgument(name);
5077: } else {
5078: rest = this.string.slice(this.i);
5079: advance = 1;
5080: }
1.2 albertel 5081: return this.ParseDimen(rest,name,advance,nomu);
5082: },
5083:
5084: ParseDimen: function (dimen,name,advance,nomu) {
5085: var match = dimen.match(/^\s*([-+]?(\.\d+|\d+(\.\d*)?))(pt|em|ex|mu|px)/);
1.1 albertel 5086: if (!match) {this.Error("Missing dimension or its units for "+name); return null}
5087: if (advance) {
5088: this.i += match[0].length;
5089: if (this.nextIsSpace()) {this.i++}
5090: }
5091: var d = match[1]-0;
5092: if (match[4] == 'px') {d /= jsMath.em}
5093: else if (match[4] == 'pt') {d /= 10}
5094: else if (match[4] == 'ex') {d *= jsMath.TeX.x_height}
5095: else if (match[4] == 'mu') {if (nomu) {d = d/18} else {d = [d,'mu']}}
5096: return d;
5097: },
5098:
5099: /*
5100: * Get the next non-space character
5101: */
5102: GetNext: function () {
5103: while (this.nextIsSpace()) {this.i++}
5104: return this.string.charAt(this.i);
5105: },
5106:
5107: /*
5108: * Get an optional LaTeX argument in brackets
5109: */
5110: GetBrackets: function (name) {
5111: var c = this.GetNext(); if (c != '[') return '';
5112: var start = ++this.i; var pcount = 0;
5113: while (this.i < this.string.length) {
1.3 ! albertel 5114: c = this.string.charAt(this.i++);
1.1 albertel 5115: if (c == '{') {pcount++}
5116: else if (c == '}') {
5117: if (pcount == 0)
5118: {this.Error("Extra close brace while looking for ']'"); return null}
5119: pcount --;
5120: } else if (c == this.cmd) {
5121: this.i++;
5122: } else if (c == ']') {
5123: if (pcount == 0) {return this.string.slice(start,this.i-1)}
5124: }
5125: }
5126: this.Error("Couldn't find closing ']' for argument to "+this.cmd+name);
5127: return null;
5128: },
5129:
5130: /*
5131: * Get everything up to the given control sequence name (token)
5132: */
5133: GetUpto: function (name,token) {
5134: while (this.nextIsSpace()) {this.i++}
5135: var start = this.i; var pcount = 0;
5136: while (this.i < this.string.length) {
5137: var c = this.string.charAt(this.i++);
5138: if (c == '{') {pcount++}
5139: else if (c == '}') {
5140: if (pcount == 0)
5141: {this.Error("Extra close brace while looking for "+this.cmd+token); return null}
5142: pcount --;
5143: } else if (c == this.cmd) {
5144: // really need separate counter for begin/end
5145: // and it should really be a stack (new pcount for each begin)
5146: if (this.string.slice(this.i,this.i+5) == "begin") {pcount++; this.i+=4}
5147: else if (this.string.slice(this.i,this.i+3) == "end") {
5148: if (pcount > 0) {pcount--; this.i += 2}
5149: }
5150: if (pcount == 0) {
5151: if (this.string.slice(this.i,this.i+token.length) == token) {
5152: c = this.string.charAt(this.i+token.length);
5153: if (c.match(/[^a-z]/i) || !token.match(/[a-z]/i)) {
5154: var arg = this.string.slice(start,this.i-1);
5155: this.i += token.length;
5156: return arg;
5157: }
5158: }
5159: }
5160: this.i++;
5161: }
5162: }
5163: this.Error("Couldn't find "+this.cmd+token+" for "+name);
5164: return null;
5165: },
5166:
5167: /*
5168: * Get a parameter delimited by a control sequence, and
5169: * process it to get its mlist
5170: */
5171: ProcessUpto: function (name,token) {
5172: var arg = this.GetUpto(name,token); if (this.error) return null;
5173: return this.Process(arg);
5174: },
5175:
5176: /*
5177: * Get everything up to \end{env}
5178: */
5179: GetEnd: function (env) {
5180: var body = ''; var name = '';
5181: while (name != env) {
5182: body += this.GetUpto('begin{'+env+'}','end'); if (this.error) return null;
5183: name = this.GetArgument(this.cmd+'end'); if (this.error) return null;
5184: }
5185: return body;
5186: },
5187:
5188:
5189: /***************************************************************************/
5190:
5191:
5192: /*
5193: * Ignore spaces
5194: */
5195: Space: function () {},
5196:
5197: /*
5198: * Collect together any primes and convert them to a superscript
5199: */
5200: Prime: function (c) {
5201: var base = this.mlist.Last();
5202: if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
5203: {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}
5204: if (base.sup) {this.Error("Prime causes double exponent: use braces to clarify"); return}
5205: var sup = '';
5206: while (c == "'") {sup += this.cmd+'prime'; c = this.GetNext(); if (c == "'") {this.i++}}
5207: base.sup = this.Process(sup);
5208: base.sup.isPrime = 1;
5209: },
5210:
5211: /*
5212: * Raise or lower its parameter by a given amount
5213: * @@@ Note that this is different from TeX, which requires an \hbox @@@
5214: * ### make this work with mu's ###
5215: */
5216: RaiseLower: function (name) {
5217: var h = this.GetDimen(this.cmd+name,1); if (this.error) return;
1.2 albertel 5218: var box = this.ProcessScriptArg(this.cmd+name); if (this.error) return;
1.1 albertel 5219: if (name == 'lower') {h = -h}
5220: this.mlist.Add(new jsMath.mItem('raise',{nuc: box, raise: h}));
5221: },
5222:
5223: /*
5224: * Shift an expression to the right or left
5225: * @@@ Note that this is different from TeX, which requires a \vbox @@@
5226: * ### make this work with mu's ###
5227: */
5228: MoveLeftRight: function (name) {
5229: var x = this.GetDimen(this.cmd+name,1); if (this.error) return;
5230: var box = this.ProcessArg(this.cmd+name); if (this.error) return;
5231: if (name == 'moveleft') {x = -x}
5232: this.mlist.Add(jsMath.mItem.Space(x));
5233: this.mlist.Add(jsMath.mItem.Atom('ord',box));
5234: this.mlist.Add(jsMath.mItem.Space(-x));
5235: },
5236:
5237: /*
5238: * Load an extension if it has not already been loaded
5239: */
5240: Require: function (name) {
5241: var file = this.GetArgument(this.cmd+name); if (this.error) return;
5242: file = jsMath.Extension.URL(file);
5243: if (jsMath.Setup.loaded[file]) return;
5244: this.Extension(null,[file]);
5245: },
5246:
5247: /*
5248: * Load an extension file and restart processing the math
5249: */
5250: Extension: function (name,data) {
5251: jsMath.Translate.restart = 1;
5252: if (name != null) {delete jsMath.Parser.prototype[data[1]||'macros'][name]}
5253: jsMath.Extension.Require(data[0],jsMath.Translate.asynchronous);
5254: throw "restart";
5255: },
5256:
5257: /*
5258: * Implements \frac{num}{den}
5259: */
5260: Frac: function (name) {
5261: var num = this.ProcessArg(this.cmd+name); if (this.error) return;
5262: var den = this.ProcessArg(this.cmd+name); if (this.error) return;
5263: this.mlist.Add(jsMath.mItem.Fraction('over',num,den));
5264: },
5265:
5266: /*
5267: * Implements \sqrt[n]{...}
5268: */
5269: Sqrt: function (name) {
5270: var n = this.GetBrackets(this.cmd+name); if (this.error) return;
5271: var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
1.2 albertel 5272: var box = jsMath.mItem.Atom('radical',arg);
5273: if (n != '') {box.root = this.Process(n); if (this.error) return}
1.1 albertel 5274: this.mlist.Add(box);
5275: },
5276:
5277: /*
5278: * Implements \root...\of{...}
5279: */
5280: Root: function (name) {
5281: var n = this.ProcessUpto(this.cmd+name,'of'); if (this.error) return;
5282: var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
1.2 albertel 5283: var box = jsMath.mItem.Atom('radical',arg);
1.1 albertel 5284: box.root = n; this.mlist.Add(box);
5285: },
5286:
5287:
5288: /*
5289: * Implements \buildrel...\over{...}
5290: */
5291: BuildRel: function (name) {
5292: var top = this.ProcessUpto(this.cmd+name,'over'); if (this.error) return;
5293: var bot = this.ProcessArg(this.cmd+name); if (this.error) return;
5294: var op = jsMath.mItem.Atom('op',bot);
5295: op.limits = 1; op.sup = top;
5296: this.mlist.Add(op);
5297: },
5298:
5299: /*
5300: * Create a delimiter of the type and size specified in the parameters
5301: */
5302: MakeBig: function (name,data) {
5303: var type = data[0]; var h = data[1] * jsMath.p_height;
5304: var delim = this.GetDelimiter(this.cmd+name); if (this.error) return;
5305: this.mlist.Add(jsMath.mItem.Atom(type,jsMath.Box.Delimiter(h,delim,'T')));
5306: },
5307:
5308: /*
5309: * Insert the specified character in the given font.
5310: * (Try to load the font if it is not already available.)
5311: */
5312: Char: function (name) {
5313: var font = this.GetArgument(this.cmd+name); if (this.error) return;
5314: var n = this.GetArgument(this.cmd+name); if (this.error) return;
5315: if (!jsMath.TeX[font]) {
5316: jsMath.TeX[font] = [];
5317: this.Extension(null,[jsMath.Font.URL(font)]);
5318: } else {
5319: this.mlist.Add(jsMath.mItem.Typeset(jsMath.Box.TeX(n-0,font,'T',this.mlist.data.size)));
5320: }
5321: },
5322:
5323: /*
5324: * Create an array or matrix.
5325: */
5326: Matrix: function (name,delim) {
5327: var data = this.mlist.data;
5328: var arg = this.GetArgument(this.cmd+name); if (this.error) return;
1.2 albertel 5329: var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,delim[5] || 'T');
5330: parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = [];
1.1 albertel 5331: parse.Parse(); if (parse.error) {this.Error(parse); return}
5332: parse.HandleRow(name,1); // be sure the last row is recorded
1.2 albertel 5333: var box = jsMath.Box.Layout(data.size,parse.table,delim[2]||null,delim[3]||null,parse.rspacing,delim[4]||null);
1.1 albertel 5334: // Add parentheses, if needed
5335: if (delim[0] && delim[1]) {
1.2 albertel 5336: var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T');
5337: var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T');
1.1 albertel 5338: box = jsMath.Box.SetList([left,box,right],data.style,data.size);
5339: }
5340: this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
5341: },
5342:
5343: /*
5344: * When we see an '&', try to add a matrix entry to the row data.
5345: * (Use all the data in the current mList, and then clear it)
5346: */
5347: HandleEntry: function (name) {
5348: if (!this.matrix)
5349: {this.Error(name+" can only appear in a matrix or array"); return}
5350: if (this.mlist.data.openI != null) {
5351: var open = this.mlist.Get(this.mlist.data.openI);
5352: if (open.left) {this.Error("Missing "+this.cmd+"right")}
5353: else {this.Error("Missing close brace")}
5354: }
5355: if (this.mlist.data.overI != null) {this.mlist.Over()}
5356: var data = this.mlist.data;
5357: this.mlist.Atomize(data.style,data.size);
5358: var box = this.mlist.Typeset(data.style,data.size);
1.3 ! albertel 5359: box.entry = data.entry; delete data.entry; if (!box.entry) {box.entry = {}};
1.1 albertel 5360: this.row[this.row.length] = box;
5361: this.mlist = new jsMath.mList(null,null,data.size,data.style);
5362: },
5363:
5364: /*
5365: * When we see a \cr or \\, try to add a row to the table
5366: */
5367: HandleRow: function (name,last) {
1.2 albertel 5368: var dimen;
5369: if (!this.matrix) {this.Error(this.cmd+name+" can only appear in a matrix or array"); return}
5370: if (name == "\\") {
5371: dimen = this.GetBrackets(this.cmd+name); if (this.error) return;
5372: if (dimen) {dimen = this.ParseDimen(dimen,this.cmd+name,0,1)}
5373: }
1.1 albertel 5374: this.HandleEntry(name);
5375: if (!last || this.row.length > 1 || this.row[0].format != 'null')
5376: {this.table[this.table.length] = this.row}
1.2 albertel 5377: if (dimen) {this.rspacing[this.table.length] = dimen}
1.1 albertel 5378: this.row = [];
5379: },
5380:
5381: /*
1.2 albertel 5382: * Look for \vskip or \vspace in \noalign parameters
5383: */
5384: HandleNoAlign: function (name) {
5385: var arg = this.GetArgument(this.cmd+name); if (this.error) return;
5386: var skip = arg.replace(/^.*(vskip|vspace)([^a-z])/i,'$2');
5387: if (skip.length == arg.length) return;
5388: var d = this.ParseDimen(skip,this.cmd+RegExp.$1,0,1); if (this.error) return;
5389: this.rspacing[this.table.length] = (this.rspacing[this.table.length] || 0) + d;
5390: },
5391:
5392: /*
1.1 albertel 5393: * LaTeX array environment
5394: */
5395: Array: function (name,delim) {
5396: var columns = delim[2]; var cspacing = delim[3];
5397: if (!columns) {
5398: columns = this.GetArgument(this.cmd+'begin{'+name+'}');
5399: if (this.error) return;
5400: }
5401: columns = columns.replace(/[^clr]/g,'');
5402: columns = columns.split('');
1.2 albertel 5403: var data = this.mlist.data; var style = delim[5] || 'T';
1.1 albertel 5404: var arg = this.GetEnd(name); if (this.error) return;
5405: var parse = new jsMath.Parser(arg+this.cmd+'\\',null,data.size,style);
1.2 albertel 5406: parse.matrix = name; parse.row = []; parse.table = []; parse.rspacing = [];
1.1 albertel 5407: parse.Parse(); if (parse.error) {this.Error(parse); return}
5408: parse.HandleRow(name,1); // be sure the last row is recorded
1.3 ! albertel 5409: var box = jsMath.Box.Layout(data.size,parse.table,columns,cspacing,parse.rspacing,delim[4],delim[6],delim[7]);
1.1 albertel 5410: // Add parentheses, if needed
5411: if (delim[0] && delim[1]) {
1.2 albertel 5412: var left = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[0]],'T');
5413: var right = jsMath.Box.Delimiter(box.h+box.d-jsMath.hd/4,this.delimiter[delim[1]],'T');
1.1 albertel 5414: box = jsMath.Box.SetList([left,box,right],data.style,data.size);
5415: }
5416: this.mlist.Add(jsMath.mItem.Atom((delim[0]? 'inner': 'ord'),box));
5417: },
5418:
5419: /*
5420: * LaTeX \begin{env}
5421: */
5422: Begin: function (name) {
5423: var env = this.GetArgument(this.cmd+name); if (this.error) return;
5424: if (env.match(/[^a-z*]/i)) {this.Error('Invalid environment name "'+env+'"'); return}
5425: if (!this.environments[env]) {this.Error('Unknown environment "'+env+'"'); return}
5426: var cmd = this.environments[env];
5427: if (typeof(cmd) == "string") {cmd = [cmd]}
5428: this[cmd[0]](env,cmd.slice(1));
5429: },
5430:
5431: /*
5432: * LaTeX \end{env}
5433: */
5434: End: function (name) {
5435: var env = this.GetArgument(this.cmd+name); if (this.error) return;
5436: this.Error(this.cmd+name+'{'+env+'} without matching '+this.cmd+'begin');
5437: },
5438:
5439: /*
5440: * Add a fixed amount of horizontal space
5441: */
5442: Spacer: function (name,w) {
5443: this.mlist.Add(jsMath.mItem.Space(w-0));
5444: },
5445:
5446: /*
5447: * Add horizontal space given by the argument
5448: */
5449: Hskip: function (name) {
5450: var w = this.GetDimen(this.cmd+name); if (this.error) return;
5451: this.mlist.Add(jsMath.mItem.Space(w));
5452: },
5453:
5454: /*
5455: * Typeset the argument as plain text rather than math.
5456: */
5457: HBox: function (name) {
5458: var text = this.GetArgument(this.cmd+name); if (this.error) return;
5459: var box = jsMath.Box.InternalMath(text,this.mlist.data.size);
5460: this.mlist.Add(jsMath.mItem.Typeset(box));
5461: },
5462:
5463: /*
5464: * Insert a rule of a particular width, height and depth
5465: * This replaces \hrule and \vrule
5466: * @@@ not a standard TeX command, and all three parameters must be given @@@
5467: */
5468: Rule: function (name,style) {
5469: var w = this.GetDimen(this.cmd+name,1); if (this.error) return;
5470: var h = this.GetDimen(this.cmd+name,1); if (this.error) return;
5471: var d = this.GetDimen(this.cmd+name,1); if (this.error) return;
5472: h += d; var html;
5473: if (h != 0) {h = Math.max(1.05/jsMath.em,h)}
5474: if (h == 0 || w == 0 || style == "blank")
5475: {html = jsMath.HTML.Blank(w,h)} else {html = jsMath.HTML.Rule(w,h)}
5476: if (d) {
5477: html = '<span style="vertical-align:'+jsMath.HTML.Em(-d)+'">'
5478: + html + '</span>';
5479: }
5480: this.mlist.Add(jsMath.mItem.Typeset(new jsMath.Box('html',html,w,h-d,d)));
5481: },
5482:
5483: /*
5484: * Inserts an empty box of a specific height and depth
5485: */
5486: Strut: function () {
5487: var size = this.mlist.data.size;
5488: var box = jsMath.Box.Text('','normal','T',size).Styled();
1.3 ! albertel 5489: box.bh = box.bd = 0; box.h = .8; box.d = .3; box.w = box.Mw = 0;
1.1 albertel 5490: this.mlist.Add(jsMath.mItem.Typeset(box));
5491: },
5492:
5493: /*
5494: * Handles \phantom, \vphantom and \hphantom
5495: */
5496: Phantom: function (name,data) {
5497: var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
5498: this.mlist.Add(new jsMath.mItem('phantom',{phantom: arg, v: data[0], h: data[1]}));
5499: },
5500:
5501: /*
5502: * Implements \smash
5503: */
5504: Smash: function (name,data) {
5505: var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
5506: this.mlist.Add(new jsMath.mItem('smash',{smash: arg}));
5507: },
5508:
5509: /*
5510: * Puts an accent on the following argument
5511: */
5512: MathAccent: function (name,accent) {
5513: var c = this.ProcessArg(this.cmd+name); if (this.error) return;
5514: var atom = jsMath.mItem.Atom('accent',c); atom.accent = accent[0];
5515: this.mlist.Add(atom);
5516: },
5517:
5518: /*
5519: * Handles functions and operators like sin, cos, sum, etc.
5520: */
5521: NamedOp: function (name,data) {
5522: var a = (name.match(/[^acegm-su-z]/)) ? 1: 0;
5523: var d = (name.match(/[gjpqy]/)) ? .2: 0;
5524: if (data[1]) {name = data[1]}
5525: var box = jsMath.mItem.TextAtom('op',name,'cmr10',a,d);
5526: if (data[0] != null) {box.limits = data[0]}
5527: this.mlist.Add(box);
5528: },
5529:
5530: /*
5531: * Implements \limits
5532: */
5533: Limits: function (name,data) {
5534: var atom = this.mlist.Last();
5535: if (!atom || atom.type != 'op')
5536: {this.Error(this.cmd+name+" is allowed only on operators"); return}
5537: atom.limits = data[0];
5538: },
5539:
5540: /*
5541: * Implements macros like those created by \def. The named control
5542: * sequence is replaced by the string given as the first data value.
5543: * If there is a second data value, this specifies how many arguments
5544: * the macro uses, and in this case, those arguments are substituted
5545: * for #1, #2, etc. within the replacement string.
5546: *
5547: * See the jsMath.Macro() command below for more details.
5548: * The "newcommand" extension implements \newcommand and \def
5549: * and are loaded automatically if needed.
5550: */
5551: Macro: function (name,data) {
5552: var text = data[0];
5553: if (data[1]) {
5554: var args = [];
5555: for (var i = 0; i < data[1]; i++)
5556: {args[args.length] = this.GetArgument(this.cmd+name); if (this.error) return}
5557: text = this.SubstituteArgs(args,text);
5558: }
5559: this.string = this.AddArgs(text,this.string.slice(this.i));
5560: this.i = 0;
5561: },
5562:
5563: /*
5564: * Replace macro paramters with their values
5565: */
5566: SubstituteArgs: function (args,string) {
5567: var text = ''; var newstring = ''; var c; var i = 0;
5568: while (i < string.length) {
5569: c = string.charAt(i++);
5570: if (c == this.cmd) {text += c + string.charAt(i++)}
5571: else if (c == '#') {
5572: c = string.charAt(i++);
5573: if (c == "#") {text += c} else {
5574: if (!c.match(/[1-9]/) || c > args.length)
1.2 albertel 5575: {this.Error("Illegal macro parameter reference"); return null}
1.1 albertel 5576: newstring = this.AddArgs(this.AddArgs(newstring,text),args[c-1]);
5577: text = '';
5578: }
5579: } else {text += c}
5580: }
5581: return this.AddArgs(newstring,text);
5582: },
5583:
5584: /*
5585: * Make sure that macros are followed by a space if their names
5586: * could accidentally be continued into the following text.
5587: */
5588: AddArgs: function (s1,s2) {
5589: if (s2.match(/^[a-z]/i) && s1.match(/(^|[^\\])(\\\\)*\\[a-z]+$/i)) {s1 += ' '}
5590: return s1+s2;
5591: },
5592:
5593: /*
5594: * Replace the control sequence with the given text
5595: */
5596: Replace: function (name,data) {
5597: this.mlist.Add(jsMath.mItem.TextAtom(data[0],data[1],data[2],data[3]));
5598: },
5599:
5600: /*
1.3 ! albertel 5601: * Error for # (must use \#)
! 5602: */
! 5603: Hash: function (name) {
! 5604: this.Error("You can't use 'macro parameter character #' in math mode");
! 5605: },
! 5606:
! 5607: /*
1.1 albertel 5608: * Insert space for ~
5609: */
5610: Tilde: function (name) {
5611: this.mlist.Add(jsMath.mItem.TextAtom('ord',' ','normal'));
5612: },
5613:
5614: /*
5615: * Implements \llap, \rlap, etc.
5616: */
5617: HandleLap: function (name) {
5618: var box = this.ProcessArg(); if (this.error) return;
5619: box = this.mlist.Add(new jsMath.mItem('lap',{nuc: box, lap: name}));
5620: },
5621:
5622: /*
5623: * Adds the argument as a specific type of atom (for commands like
5624: * \overline, etc.)
5625: */
5626: HandleAtom: function (name,data) {
5627: var arg = this.ProcessArg(this.cmd+name); if (this.error) return;
1.3 ! albertel 5628: this.mlist.Add(jsMath.mItem.Atom(data[0],arg));
1.1 albertel 5629: },
5630:
5631:
5632: /*
5633: * Process the character associated with a specific \mathcharcode
5634: */
5635: HandleMathCode: function (name,code) {
5636: this.HandleTeXchar(code[0],code[1],code[2]);
5637: },
5638:
5639: /*
5640: * Add a specific character from a TeX font (use the current
5641: * font if the type is 7 (variable) or the font is not specified)
5642: * Load the font if it is not already loaded.
5643: */
5644: HandleTeXchar: function (type,font,code) {
5645: if (type == 7 && this.mlist.data.font != null) {font = this.mlist.data.font}
5646: font = jsMath.TeX.fam[font];
5647: if (!jsMath.TeX[font]) {
5648: jsMath.TeX[font] = [];
5649: this.Extension(null,[jsMath.Font.URL(font)]);
5650: } else {
5651: this.mlist.Add(jsMath.mItem.TeXAtom(jsMath.TeX.atom[type],code,font));
5652: }
5653: },
5654:
5655: /*
5656: * Add a TeX variable character or number
5657: */
5658: HandleVariable: function (c) {this.HandleTeXchar(7,1,c.charCodeAt(0))},
5659: HandleNumber: function (c) {this.HandleTeXchar(7,0,c.charCodeAt(0))},
5660:
5661: /*
5662: * For unmapped characters, just add them in as normal
5663: * (non-TeX) characters
5664: */
5665: HandleOther: function (c) {
5666: this.mlist.Add(jsMath.mItem.TextAtom('ord',c,'normal'));
5667: },
5668:
5669: /*
5670: * Ignore comments in TeX data
5671: * ### Some browsers remove the newlines, so this might cause
5672: * extra stuff to be ignored; look into this ###
5673: */
5674: HandleComment: function () {
5675: var c;
5676: while (this.i < this.string.length) {
5677: c = this.string.charAt(this.i++);
5678: if (c == "\r" || c == "\n") return;
5679: }
5680: },
5681:
5682: /*
5683: * Add a style change (e.g., \displaystyle, etc)
5684: */
5685: HandleStyle: function (name,style) {
5686: this.mlist.data.style = style[0];
5687: this.mlist.Add(new jsMath.mItem('style',{style: style[0]}));
5688: },
5689:
5690: /*
5691: * Implements \small, \large, etc.
5692: */
5693: HandleSize: function (name,size) {
5694: this.mlist.data.size = size[0];
5695: this.mlist.Add(new jsMath.mItem('size',{size: size[0]}));
5696: },
5697:
5698: /*
5699: * Set the current font (e.g., \rm, etc)
5700: */
5701: HandleFont: function (name,font) {
5702: this.mlist.data.font = font[0];
5703: },
5704:
5705: /*
5706: * Look for and process a control sequence
5707: */
5708: HandleCS: function () {
5709: var cmd = this.GetCommand(); if (this.error) return;
5710: if (this.macros[cmd]) {
5711: var macro = this.macros[cmd];
5712: if (typeof(macro) == "string") {macro = [macro]}
5713: this[macro[0]](cmd,macro.slice(1)); return;
5714: }
5715: if (this.mathchardef[cmd]) {
5716: this.HandleMathCode(cmd,this.mathchardef[cmd]);
5717: return;
5718: }
5719: if (this.delimiter[this.cmd+cmd]) {
5720: this.HandleMathCode(cmd,this.delimiter[this.cmd+cmd].slice(0,3))
5721: return;
5722: }
5723: this.Error("Unknown control sequence '"+this.cmd+cmd+"'");
5724: },
5725:
5726: /*
5727: * Process open and close braces
5728: */
5729: HandleOpen: function () {this.mlist.Open()},
5730: HandleClose: function () {
5731: if (this.mlist.data.openI == null) {this.Error("Extra close brace"); return}
5732: var open = this.mlist.Get(this.mlist.data.openI);
5733: if (!open || open.left == null) {this.mlist.Close()}
5734: else {this.Error("Extra close brace or missing "+this.cmd+"right"); return}
5735: },
5736:
5737: /*
5738: * Implements \left
5739: */
5740: HandleLeft: function (name) {
5741: var left = this.GetDelimiter(this.cmd+name); if (this.error) return;
5742: this.mlist.Open(left);
5743: },
5744:
5745: /*
5746: * Implements \right
5747: */
5748: HandleRight: function (name) {
5749: var right = this.GetDelimiter(this.cmd+name); if (this.error) return;
5750: var open = this.mlist.Get(this.mlist.data.openI);
5751: if (open && open.left != null) {this.mlist.Close(right)}
5752: else {this.Error("Extra open brace or missing "+this.cmd+"left");}
5753: },
5754:
5755: /*
5756: * Implements generalized fractions (\over, \above, etc.)
5757: */
5758: HandleOver: function (name,data) {
5759: if (this.mlist.data.overI != null)
5760: {this.Error('Ambiguous use of '+this.cmd+name); return}
5761: this.mlist.data.overI = this.mlist.Length();
5762: this.mlist.data.overF = {name: name};
5763: if (data.length > 0) {
5764: this.mlist.data.overF.left = this.delimiter[data[0]];
5765: this.mlist.data.overF.right = this.delimiter[data[1]];
5766: } else if (name.match(/withdelims$/)) {
5767: this.mlist.data.overF.left = this.GetDelimiter(this.cmd+name); if (this.error) return;
5768: this.mlist.data.overF.right = this.GetDelimiter(this.cmd+name); if (this.error) return;
5769: } else {
5770: this.mlist.data.overF.left = null;
5771: this.mlist.data.overF.right = null;
5772: }
5773: if (name.match(/^above/)) {
1.2 albertel 5774: this.mlist.data.overF.thickness = this.GetDimen(this.cmd+name,1);
1.1 albertel 5775: if (this.error) return;
5776: } else {
5777: this.mlist.data.overF.thickness = null;
5778: }
5779: },
5780:
5781: /*
5782: * Add a superscript to the preceeding atom
5783: */
5784: HandleSuperscript: function () {
5785: var base = this.mlist.Last();
1.3 ! albertel 5786: if (this.mlist.data.overI == this.mlist.Length()) {base = null}
1.1 albertel 5787: if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
5788: {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}
5789: if (base.sup) {
5790: if (base.sup.isPrime) {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}
5791: else {this.Error("Double exponent: use braces to clarify"); return}
5792: }
5793: base.sup = this.ProcessScriptArg('superscript'); if (this.error) return;
5794: },
5795:
5796: /*
5797: * Add a subscript to the preceeding atom
5798: */
5799: HandleSubscript: function () {
5800: var base = this.mlist.Last();
1.3 ! albertel 5801: if (this.mlist.data.overI == this.mlist.Length()) {base = null}
1.1 albertel 5802: if (base == null || (!base.atom && base.type != 'box' && base.type != 'frac'))
5803: {base = this.mlist.Add(jsMath.mItem.Atom('ord',{type:null}))}
5804: if (base.sub) {this.Error("Double subscripts: use braces to clarify"); return}
5805: base.sub = this.ProcessScriptArg('subscript'); if (this.error) return;
5806: },
5807:
5808: /*
5809: * Parse a TeX math string, handling macros, etc.
5810: */
5811: Parse: function () {
5812: var c;
5813: while (this.i < this.string.length) {
5814: c = this.string.charAt(this.i++);
5815: if (this.mathchar[c]) {this.HandleMathCode(c,this.mathchar[c])}
5816: else if (this.special[c]) {this[this.special[c]](c)}
5817: else if (this.letter.test(c)) {this.HandleVariable(c)}
5818: else if (this.number.test(c)) {this.HandleNumber(c)}
5819: else {this.HandleOther(c)}
5820: }
5821: if (this.mlist.data.openI != null) {
5822: var open = this.mlist.Get(this.mlist.data.openI);
5823: if (open.left) {this.Error("Missing "+this.cmd+"right")}
5824: else {this.Error("Missing close brace")}
5825: }
5826: if (this.mlist.data.overI != null) {this.mlist.Over()}
5827: },
5828:
5829: /*
5830: * Perform the processing of Appendix G
5831: */
5832: Atomize: function () {
5833: var data = this.mlist.init;
5834: if (!this.error) this.mlist.Atomize(data.style,data.size)
5835: },
5836:
5837: /*
5838: * Produce the final HTML.
5839: *
5840: * We have to wrap the HTML it appropriate <SPAN> tags to hide its
5841: * actual dimensions when these don't match the TeX dimensions of the
5842: * results. We also include an image to force the results to take up
5843: * the right amount of space. The results may need to be vertically
5844: * adjusted to make the baseline appear in the correct place.
5845: */
5846: Typeset: function () {
5847: var data = this.mlist.init;
5848: var box = this.typeset = this.mlist.Typeset(data.style,data.size);
5849: if (this.error) {return '<span class="error">'+this.error+'</span>'}
5850: if (box.format == 'null') {return ''};
5851:
5852: box.Styled().Remeasured(); var isSmall = 0; var isBig = 0;
5853: if (box.bh > box.h && box.bh > jsMath.h+.001) {isSmall = 1}
5854: if (box.bd > box.d && box.bd > jsMath.d+.001) {isSmall = 1}
5855: if (box.h > jsMath.h || box.d > jsMath.d) {isBig = 1}
5856:
5857: var html = box.html;
5858: if (isSmall) {// hide the extra size
5859: if (jsMath.Browser.allowAbsolute) {
5860: var y = 0;
5861: if (box.bh > jsMath.h+.001) {y = jsMath.h - box.bh}
1.3 ! albertel 5862: if (jsMath.Browser.msieTeXfontBaselineBug &&
! 5863: jsMath.Controls.cookie.font == 'tex') {y -= jsMath.d}
1.1 albertel 5864: html = jsMath.HTML.Absolute(html,box.w,jsMath.h,0,y,jsMath.h);
1.2 albertel 5865: } else if (jsMath.Browser.valignBug) {
5866: // remove line height
5867: html = '<span style="line-height:'+jsMath.HTML.Em(jsMath.d)+';">'
5868: + html + '</span>';
5869: } else {
1.1 albertel 5870: // remove line height and try to hide the depth
5871: var dy = jsMath.HTML.Em(Math.max(0,box.bd-jsMath.hd)/3);
1.2 albertel 5872: html = '<span style="line-height:'+jsMath.HTML.Em(jsMath.d)+';'
1.1 albertel 5873: + ' position:relative; top:'+dy+'; vertical-align:'+dy
5874: + '">' + html + '</span>';
5875: }
5876: isBig = 1;
5877: }
5878: if (isBig) {
5879: // add height and depth to the line
5880: // (force a little extra to separate lines if needed)
5881: html += jsMath.HTML.Blank(0,box.h+.05,box.d+.05);
5882: }
5883: return '<nobr><span class="scale">'+html+'</span></nobr>';
5884: }
5885:
5886: });
5887:
5888: /*
5889: * Make these characters special (and call the given routines)
5890: */
5891: jsMath.Parser.prototype.AddSpecial({
5892: cmd: 'HandleCS',
5893: open: 'HandleOpen',
5894: close: 'HandleClose'
5895: });
5896:
5897:
5898: /*
5899: * The web-page author can call jsMath.Macro to create additional
5900: * TeX macros for use within his or her mathematics. See the
5901: * author's documentation for more details.
5902: */
5903:
5904: jsMath.Add(jsMath,{
5905: Macro: function (name) {
5906: var macro = jsMath.Parser.prototype.macros;
5907: macro[name] = ['Macro'];
5908: for (var i = 1; i < arguments.length; i++)
5909: {macro[name][macro[name].length] = arguments[i]}
5910: }
5911: });
5912:
5913: /*
5914: * Use these commands to create macros that load
5915: * JavaScript files and reprocess the mathematics when
5916: * the file is loaded. This lets you to have macros or
5917: * LaTeX environments that autoload their own definitions
5918: * only when they are needed, saving initial download time
5919: * on pages where they are not used. See the author's
5920: * documentation for more details.
5921: *
5922: */
5923:
5924: jsMath.Extension = {
5925:
5926: safeRequire: 1, // disables access to files outside of jsMath/extensions
5927:
5928: Macro: function (name,file) {
5929: var macro = jsMath.Parser.prototype.macros;
5930: if (file == null) {file = name}
5931: macro[name] = ['Extension',file];
5932: },
5933:
5934: LaTeX: function (env,file) {
5935: var latex = jsMath.Parser.prototype.environments;
5936: latex[env] = ['Extension',file,'environments'];
5937: },
5938:
5939: Font: function (name,font) {
5940: if (font == null) {font = name + "10"}
5941: var macro = jsMath.Parser.prototype.macros;
5942: macro[name] = ['Extension',jsMath.Font.URL(font)];
5943: },
5944:
5945: MathChar: function (font,defs) {
5946: var fam = jsMath.TeX.famName[font];
5947: if (fam == null) {
5948: fam = jsMath.TeX.fam.length;
5949: jsMath.TeX.fam[fam] = font;
5950: jsMath.TeX.famName[font] = fam;
5951: }
5952: var mathchardef = jsMath.Parser.prototype.mathchardef;
5953: for (var c in defs) {mathchardef[c] = [defs[c][0],fam,defs[c][1]]}
5954: },
5955:
5956: Require: function (file,show) {
5957: if (this.safeRequire && (file.match(/\.\.\/|[^-a-z0-9.\/:_+=%~]/i) ||
5958: (file.match(/:/) && file.substr(0,jsMath.root.length) != jsMath.root))) {
5959: jsMath.Setup.loaded[file] = 1;
5960: return;
5961: }
5962: jsMath.Setup.Script(this.URL(file),show);
5963: },
5964:
5965: URL: function (file) {
5966: file = file.replace(/^\s+|\s+$/g,'');
5967: if (!file.match(/^([a-z]+:|\/|fonts|extensions\/)/i)) {file = 'extensions/'+file}
5968: if (!file.match(/\.js$/)) {file += '.js'}
5969: return file;
5970: }
5971: }
5972:
5973:
5974: /***************************************************************************/
5975:
5976: /*
5977: * These routines look through the web page for math elements to process.
5978: * There are two main entry points you can call:
5979: *
5980: * <script> jsMath.Process() </script>
5981: * or
5982: * <script> jsMath.ProcessBeforeShowing() </script>
5983: *
5984: * The first will process the page asynchronously (so the user can start
5985: * reading the top of the file while jsMath is still processing the bottom)
5986: * while the second does not update until all the mathematics is typeset.
5987: */
5988:
5989: jsMath.Add(jsMath,{
5990: /*
5991: * Call this at the bottom of your HTML page to have the
5992: * mathematics typeset asynchronously. This lets the user
5993: * start reading the mathematics while the rest of the page
5994: * is being processed.
5995: */
5996: Process: function (obj) {
5997: jsMath.Setup.Body();
5998: jsMath.Script.Push(jsMath.Translate,'Asynchronous',obj);
5999: },
6000:
6001: /*
6002: * Call this at the bottom of your HTML page to have the
6003: * mathematics typeset before the page is displayed.
6004: * This can take a long time, so the user could cancel the
6005: * page before it is complete; use it with caution, and only
6006: * when there is a relatively small amount of math on the page.
6007: */
6008: ProcessBeforeShowing: function (obj) {
6009: jsMath.Setup.Body();
6010: var method = (jsMath.Controls.cookie.asynch ? "Asynchronous": "Synchronous");
6011: jsMath.Script.Push(jsMath.Translate,method,obj);
6012: }
6013:
6014: });
6015:
6016: jsMath.Translate = {
6017:
6018: element: [], // the list of math elements on the page
6019: cancel: 0, // set to 1 to cancel asynchronous processing
1.2 albertel 6020:
1.1 albertel 6021: /*
1.2 albertel 6022: * Parse a TeX string in Text or Display mode and return
6023: * the HTML for it (taking it from the cache, if available)
1.1 albertel 6024: */
1.2 albertel 6025: Parse: function (style,s,noCache) {
6026: var cache = jsMath.Global.cache[style];
6027: if (!cache[jsMath.em]) {cache[jsMath.em] = {}}
6028: var HTML = cache[jsMath.em][s];
6029: if (!HTML || noCache) {
6030: var parse = jsMath.Parse(s,null,null,style);
6031: parse.Atomize(); HTML = parse.Typeset();
6032: if (!noCache) {cache[jsMath.em][s] = HTML}
6033: }
6034: return HTML;
1.1 albertel 6035: },
6036:
1.2 albertel 6037: TextMode: function (s,noCache) {this.Parse('T',s,noCache)},
6038: DisplayMode: function (s,noCache) {this.Parse('D',s,noCache)},
1.1 albertel 6039:
6040: /*
6041: * Return the text of a given DOM element
6042: */
6043: GetElementText: function (element) {
6044: var text = this.recursiveElementText(element);
6045: element.alt = text;
6046: if (text.search('&') >= 0) {
6047: text = text.replace(/</g,'<');
6048: text = text.replace(/>/g,'>');
6049: text = text.replace(/"/g,'"');
6050: text = text.replace(/&/g,'&');
6051: }
6052: return text;
6053: },
6054: recursiveElementText: function (element) {
6055: if (element.nodeValue != null) {return element.nodeValue}
6056: if (element.childNodes.length == 0) {return " "}
6057: var text = '';
6058: for (var i = 0; i < element.childNodes.length; i++)
6059: {text += this.recursiveElementText(element.childNodes[i])}
6060: return text;
6061: },
6062:
6063: /*
6064: * Move hidden to the location of the math element to be
6065: * processed and reinitialize sizes for that location.
6066: */
6067: ResetHidden: function (element) {
6068: element.innerHTML =
1.3 ! albertel 6069: '<span class="jsMath_hiddenSpan" style="position:absolute"></span>'
1.1 albertel 6070: + jsMath.Browser.operaHiddenFix; // needed by Opera in tables
1.2 albertel 6071: element.className = '';
1.1 albertel 6072: jsMath.hidden = element.firstChild;
6073: if (!jsMath.BBoxFor("x").w) {jsMath.hidden = jsMath.hiddenTop}
6074: jsMath.ReInit();
6075: },
6076:
6077:
6078: /*
6079: * Typeset the contents of an element in \textstyle
6080: */
1.2 albertel 6081: ConvertText: function (element,noCache) {
1.1 albertel 6082: var text = this.GetElementText(element);
6083: this.ResetHidden(element);
1.2 albertel 6084: if (text.match(/^\s*\\nocache([^a-zA-Z])/))
6085: {noCache = true; text = text.replace(/\s*\\nocache/,'')}
6086: text = this.Parse('T',text,noCache);
1.1 albertel 6087: element.className = 'typeset';
6088: element.innerHTML = text;
6089: },
6090:
6091: /*
6092: * Typeset the contents of an element in \displaystyle
6093: */
1.2 albertel 6094: ConvertDisplay: function (element,noCache) {
1.1 albertel 6095: var text = this.GetElementText(element);
6096: this.ResetHidden(element);
1.2 albertel 6097: if (text.match(/^\s*\\nocache([^a-zA-Z])/))
6098: {noCache = true; text = text.replace(/\s*\\nocache/,'')}
6099: text = this.Parse('D',text,noCache);
1.1 albertel 6100: element.className = 'typeset';
6101: element.innerHTML = text;
6102: },
6103:
6104: /*
6105: * Process a math element
6106: */
6107: ProcessElement: function (element) {
6108: this.restart = 0;
1.3 ! albertel 6109: if (!element.className.match(/(^| )math( |$)/)) return; // don't reprocess elements
1.2 albertel 6110: var noCache = (element.className.toLowerCase().match(/(^| )nocache( |$)/) != null);
1.1 albertel 6111: try {
6112: if (element.tagName.toLowerCase() == 'div') {
1.2 albertel 6113: this.ConvertDisplay(element,noCache);
1.1 albertel 6114: element.onclick = jsMath.Click.CheckClick;
6115: element.ondblclick = jsMath.Click.CheckDblClick;
6116: } else if (element.tagName.toLowerCase() == 'span') {
1.2 albertel 6117: this.ConvertText(element,noCache);
1.1 albertel 6118: element.onclick = jsMath.Click.CheckClick;
6119: element.ondblclick = jsMath.Click.CheckDblClick;
6120: }
6121: } catch (err) {
6122: if (element.alt) {
6123: var tex = element.alt;
6124: tex = tex.replace(/&/g,'&');
6125: tex = tex.replace(/</g,'<');
6126: tex = tex.replace(/>/g,'>');
6127: element.innerHTML = tex;
1.2 albertel 6128: element.className = 'math';
6129: if (noCache) {element.className += ' nocache'}
1.1 albertel 6130: }
6131: jsMath.hidden = jsMath.hiddenTop;
6132: }
6133: },
6134:
6135: /*
6136: * Asynchronously process all the math elements starting with
6137: * the k-th one
6138: */
6139: ProcessElements: function (k) {
6140: jsMath.Script.blocking = 1;
6141: if (k >= this.element.length || this.cancel) {
6142: this.ProcessComplete();
6143: if (this.cancel) {
6144: jsMath.Message.Set("Process Math: Canceled");
6145: jsMath.Message.Clear()
6146: }
6147: jsMath.Script.blocking = 0;
6148: jsMath.Script.Process();
6149: } else {
1.3 ! albertel 6150: var savedQueue = jsMath.Script.SaveQueue();
1.1 albertel 6151: this.ProcessElement(this.element[k]);
1.3 ! albertel 6152: jsMath.Script.RestoreQueue(savedQueue);
1.1 albertel 6153: if (this.restart) {
6154: jsMath.Script.Push(this,'ProcessElements',k);
6155: jsMath.Script.blocking = 0;
6156: setTimeout('jsMath.Script.Process()',jsMath.Browser.delay);
6157: } else {
6158: k++; var p = Math.floor(100 * k / this.element.length);
6159: jsMath.Message.Set('Processing Math: '+p+'%');
6160: setTimeout('jsMath.Translate.ProcessElements('+k+')',jsMath.Browser.delay);
6161: }
6162: }
6163: },
6164:
6165: /*
6166: * Start the asynchronous processing of mathematics
6167: */
6168: Asynchronous: function (obj) {
6169: if (!jsMath.initialized) {jsMath.Init()}
6170: this.element = this.GetMathElements(obj);
1.3 ! albertel 6171: jsMath.Script.blocking = 1;
1.1 albertel 6172: this.cancel = 0; this.asynchronous = 1;
6173: jsMath.Message.Set('Processing Math: 0%',1);
6174: setTimeout('jsMath.Translate.ProcessElements(0)',jsMath.Browser.delay);
6175: },
6176:
6177: /*
6178: * Do synchronous processing of mathematics
6179: */
6180: Synchronous: function (obj,i) {
6181: if (i == null) {
6182: if (!jsMath.initialized) {jsMath.Init()}
6183: this.element = this.GetMathElements(obj);
6184: i = 0;
6185: }
6186: this.asynchronous = 0;
6187: while (i < this.element.length) {
6188: this.ProcessElement(this.element[i]);
6189: if (this.restart) {
6190: jsMath.Synchronize('jsMath.Translate.Synchronous(null,'+i+')');
6191: jsMath.Script.Process();
6192: return;
6193: }
6194: i++;
6195: }
6196: this.ProcessComplete(1);
6197: },
6198:
6199: /*
6200: * Look up all the math elements on the page and
6201: * put them in a list sorted from top to bottom of the page
6202: */
6203: GetMathElements: function (obj) {
1.3 ! albertel 6204: var element = []; var k;
1.1 albertel 6205: if (!obj) {obj = jsMath.document}
6206: if (typeof(obj) == 'string') {obj = jsMath.document.getElementById(obj)}
6207: if (!obj.getElementsByTagName) return null;
6208: var math = obj.getElementsByTagName('div');
1.3 ! albertel 6209: for (k = 0; k < math.length; k++) {
! 6210: if (math[k].className && math[k].className.match(/(^| )math( |$)/)) {
1.1 albertel 6211: if (jsMath.Browser.renameOK && obj.getElementsByName)
6212: {math[k].setAttribute('name','_jsMath_')}
6213: else {element[element.length] = math[k]}
6214: }
6215: }
6216: math = obj.getElementsByTagName('span');
1.3 ! albertel 6217: for (k = 0; k < math.length; k++) {
! 6218: if (math[k].className && math[k].className.match(/(^| )math( |$)/)) {
1.1 albertel 6219: if (jsMath.Browser.renameOK && obj.getElementsByName)
6220: {math[k].setAttribute('name','_jsMath_')}
6221: else {element[element.length] = math[k]}
6222: }
6223: }
6224: // this gets the SPAN and DIV elements interleaved in order
6225: if (jsMath.Browser.renameOK && obj.getElementsByName) {
6226: element = obj.getElementsByName('_jsMath_');
6227: } else if (jsMath.hidden.sourceIndex) {
6228: element.sort(function (a,b) {return a.sourceIndex - b.sourceIndex});
6229: }
6230: return element;
6231: },
6232:
6233: /*
6234: * Remove the window message about processing math
6235: * and clean up any marked <SPAN> or <DIV> tags
6236: */
6237: ProcessComplete: function (noMessage) {
6238: if (jsMath.Browser.renameOK) {
6239: var element = jsMath.document.getElementsByName('_jsMath_');
6240: for (var i = element.length-1; i >= 0; i--) {
6241: element[i].removeAttribute('name');
6242: }
6243: }
6244: jsMath.hidden = jsMath.hiddenTop;
1.3 ! albertel 6245: this.element = []; this.restart = null;
1.1 albertel 6246: if (!noMessage) {
6247: jsMath.Message.Set('Processing Math: Done');
6248: jsMath.Message.Clear();
6249: }
6250: jsMath.Message.UnBlank();
6251: if (jsMath.Browser.safariImgBug &&
6252: (jsMath.Controls.cookie.font == 'symbol' ||
6253: jsMath.Controls.cookie.font == 'image')) {
6254: //
6255: // For Safari, the images don't always finish
6256: // updating, so nudge the window to cause a
6257: // redraw. (Hack!)
6258: //
6259: if (this.timeout) {clearTimeout(this.timeout)}
6260: this.timeout = setTimeout("jsMath.window.resizeBy(-1,0); "
6261: + "jsMath.window.resizeBy(1,0); "
6262: + "jsMath.Translate.timeout = null",2000);
6263: }
6264: },
6265:
6266: /*
6267: * Cancel procesing elements
6268: */
6269: Cancel: function () {
6270: jsMath.Translate.cancel = 1;
6271: if (jsMath.Script.cancelTimer) {jsMath.Script.cancelLoad()}
6272: }
6273:
6274: };
6275:
6276: jsMath.Add(jsMath,{
6277: //
6278: // Synchronize these with the loading of the tex2math plugin.
6279: //
6280: ConvertTeX: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertTeX',element)},
6281: ConvertTeX2: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertTeX2',element)},
6282: ConvertLaTeX: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertLaTeX',element)},
6283: ConvertCustom: function (element) {jsMath.Script.Push(jsMath.tex2math,'ConvertCustom',element)},
6284: CustomSearch: function (om,cm,od,cd) {jsMath.Script.Push(null,function () {jsMath.tex2math.CustomSearch(om,cm,od,cd)})},
6285: tex2math: {
6286: ConvertTeX: function () {},
6287: ConvertTeX2: function () {},
6288: ConvertLaTeX: function () {},
6289: ConvertCustom: function () {},
6290: CustomSearch: function () {}
6291: }
6292: });
6293: jsMath.Synchronize = jsMath.Script.Synchronize;
6294:
6295: /***************************************************************************/
6296:
1.2 albertel 6297:
1.1 albertel 6298: /*
6299: * Initialize things
6300: */
1.2 albertel 6301: try {
6302: if (window.parent != window && window.jsMathAutoload) {
6303: window.parent.jsMath = jsMath;
6304: jsMath.document = window.parent.document;
6305: jsMath.window = window.parent;
6306: }
6307: } catch (err) {}
6308:
6309: jsMath.Global.Register();
1.1 albertel 6310: jsMath.Loaded();
6311: jsMath.Controls.GetCookie();
6312: jsMath.Setup.Source();
1.2 albertel 6313: jsMath.Global.Init();
1.1 albertel 6314: jsMath.Script.Init();
6315: jsMath.Setup.Fonts();
6316: if (jsMath.document.body) {jsMath.Setup.Body()}
1.3 ! albertel 6317: jsMath.Setup.User("onload");
1.1 albertel 6318:
6319: }}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>