AM (21 march 2005) I realised the other day that the code in Drawing Diagrams (or at least the sofar unpublished version) is a suitable replacement - it will allow me to follow Kernighan's footsteps ... For now, I will have to sit down and implement these ideas!AM (10 january 2007) I finally started implementing these ideas ... The program I have now is not ready yet, but it is getting into shape nicely.
FF (25 february 2007) I suggest you looking at the W3C MathML Page [2] where you can find much useful resources. I seem cannot find a program that directly generates an image from a MathML expression; thus this may be a good start for doing a MathML widget. Is anyone seriously interested?AM (26 februari 2007) I am ;) even though I find MathML to be, well, rather verbose for the job.FF (27 february 2007) well, in fact I meant to point you to some of its implementations: it should give you nice ideas looking at the existing renderer's code (not properly at the Mozilla's one, which could be surprisingly huge ;)).FF (13 may 2007) I added a little proc in the example MimeTexPreview for interfacing mimetex with Tcl canvas. Give it a check!
# mathform.tcl --
# Simple script to render mathematical formulae
#
namespace eval ::MathFormula:: {
variable poshoriz 0
variable offhoriz 0
variable posvert 0
variable offvert 0
variable offset_add 0
variable symbol
array set symbol {
ALPHA \u391
BETA \u392
GAMMA \u393
DELTA \u394
EPSILON \u395
ZETA \u396
ETA \u397
THETA \u398
IOTA \u399
KAPPA \u39a
LAMBDA \u39b
MU \u39c
NU \u39d
XI \u39e
OMICRON \u39f
PI \u400
RHO \u401
SIGMA \u403
TAU \u404
UPSILON \u405
PHI \u406
CHI \u407
PSI \u408
OMEGA \u409
alpha \u3b1
beta \u3b2
gamma \u3b3
delta \u3b4
epsilon \u3b5
zeta \u3b6
eta \u3b7
theta \u3b8
iota \u3b9
kappa \u3ba
lambda \u3bb
mu \u3bc
nu \u3bd
xi \u3be
omicron \u3bf
pi \u3c0
rho \u3c1
sigma \u3c3
tau \u3c4
upsilon \u3c5
phi \u3c6
chi \u3c7
psi \u3c8
omega \u3c9
NABLA \u2207
DEL \u2207
SUM \u2211
PROD \u220f
INT \u222b
Inf \u221e
PARTIAL \u2202
ALL \u2200
EXIST \u2203
EMPTY \u2205
MEMBER \u2208
NOTMEMBER \u2209
APPROX \u224b
!= \u2260
<= \u2264
>= \u2265
<< \u226a
>> \u226b
SQRT \u221a
// \u221a
3// \u221b
4// \u221c
DOT \u2219
INTERSECT \u2229
UNION \u222a
ORDER \u223e
AND \u22c0
OR \u22c1
}
}
# drawFormula --
# Draw the formula at a given position (lower-left)
#
# Arguments:
# canvas The canvas to use
# xpos X-position to start
# ypos Y-position to start
# formula String holding the formula
#
# Result:
# None
#
# Side effect:
# The formula is rendered on the screen
#
#
proc ::MathFormula::drawFormula {canvas xpos ypos formula} {
variable poshoriz
variable offhoriz
variable posvert
variable offvert
variable offset_add
set poshoriz $xpos
set posvert $ypos
set offhoriz 0
set offvert 0
set offset_add 0
set tokens [analyseFormula $formula]
foreach {token xp yp advance} $tokens {
renderToken $canvas $token $xp $yp $advance
}
}
# renderToken --
# Render the given token
#
# Arguments:
# canvas Canvas in which to draw
# token Token to be drawn
# xp X-position relative to current drawing position
# yp Y-position relative to current drawing position
#
# Result:
# None
#
# Side effect:
# The token is drawn on the canvas
#
proc ::MathFormula::renderToken {canvas token xp yp advance} {
variable poshoriz
variable posvert
variable offhoriz
variable offvert
variable symbol
set xpos [expr {$poshoriz+$xp}]
set ypos [expr {$posvert+$yp}]
if { [info exists symbol($token)] } {
set unicode $symbol($token)
} else {
set unicode $token
}
switch -- $token {
"INT" { # Integral
set item [$canvas create text $xpos $ypos -font "Times 12" -text $unicode]
incr xpos 5
}
"SUM" { # Sum
set item [$canvas create text $xpos $ypos -font "Times 12" -text $unicode]
incr xpos 8
}
default { # Letters and other ordinary symbols
set item [$canvas create text $xpos $ypos -text $unicode -fill black -anchor w -font "Times 12"]
set bbox [$canvas bbox $item]
set width [expr {[lindex $bbox 2]-[lindex $bbox 0]}]
set xp $width
set xpos [expr {$xpos+$width}]
}
}
if { $advance } {
set poshoriz $xpos
} else {
set offhoriz [expr {$xp>$offhoriz? $xp : $offhoriz}]
}
}
# analyseFormula --
# Analyse the formula and determine the positions of the tokens
#
# Arguments:
# formula Formula to be drawn
#
# Result:
# List of tokens with relative positions and advancing information
#
proc ::MathFormula::analyseFormula {formula} {
set result [list]
set advance 1
set xp 0
set yp 0
foreach token $formula {
switch -- $token {
"_" { # Subscript
set yp 5
set advance 0
continue
}
"^" { # Superscript
set yp -3
set advance 0
continue
}
"~" { # Force space
set token " "
set advance 1
}
"`" { # Force extra space
incr xp 1
set advance 1
continue
}
"INT" { # Integral
set xp 0
set yp 0
set xtop -5
set ytop -12
set xbot -8
set ybot 14
set advance 1
}
"SUM" -
"PROD" { # Sum & Product
set xp 0
set yp 0
set xtop -20
set ytop -12
set xbot -12
set ybot 16
set advance 1
}
"from" { # Lower bound
set xp $xbot
set yp $ybot
set advance 0
continue
}
"to" { # Upper bound
set xp $xtop
set yp $ytop
set advance 0
continue
}
default { # Letters
set advance 1
}
}
lappend result $token $xp $yp $advance
if { $advance } {
set xp 0
set yp 0
}
}
return $result
}
# Main --
# Set up a canvas, analyse the formula and draw it
#
canvas .c -background white -height 400
pack .c -fill both
set string "SUM from i=0 to Inf ~ A _ i ~ = ~ INT from 0 to pi cos ^ 2 x dx"
::MathFormula::drawFormula .c 10 20 "Not ~ p ` erfect ~ yet, ~ but ..."
::MathFormula::drawFormula .c 10 60 $string
::MathFormula::drawFormula .c 10 100 "0.1 = e ^ -kT90"
::MathFormula::drawFormula .c 10 140 "f(x) = x ^ 3 - x ^ 2 + x - 1"
::MathFormula::drawFormula .c 10 180 "h(t) = cos( omega t - alpha )"
::MathFormula::drawFormula .c 10 220 \
"PARTIAL phi / PARTIAL t = D NABLA ^ 2 phi"
::MathFormula::drawFormula .c 10 260 "PROD (1-1/n) ^ n"
::MathFormula::drawFormula .c 10 300 "ALL x MEMBER Z ~ EXIST y MEMBER Z ~ x >= y"
