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