MathExprClassesDecoration.mesa
Carl Waldspurger, August 30, 1986 7:12:37 pm PDT
Bier, November 20, 1986 2:02:38 pm PST
Arnon, March 24, 1987 4:15:37 pm PST
DIRECTORY
MathExpr,
MathRules,
MathDB,
MathTypes,
MathBox,
Imager,
Rope,
Vector,
MathConstructors;
MathExprClassesDecoration: CEDAR PROGRAM
IMPORTS MathBox, MathRules, MathExpr,
MathDB, MathConstructors
~
BEGIN
Type Abbreviations from Imported Interfaces
EXPR: TYPE ~ MathExpr.EXPR;
BOX: TYPE ~ MathBox.BOX;
ROPE: TYPE ~ Rope.ROPE;
VEC: TYPE ~ Vector.VEC;
CompoundBoxProc: TYPE ~ MathRules.CompoundBoxProc;
CompositionProc: TYPE ~ MathRules.CompositionProc;
Alignment2D: TYPE ~ MathRules.Alignment2D;
Offset: TYPE ~ MathRules.Offset;
Size: TYPE ~ MathRules.Size;
Argument: TYPE ~ MathExpr.Argument;
Symbol: TYPE ~ MathExpr.Symbol;
CompoundClass: TYPE ~ MathExpr.CompoundClass;
FormatClass: TYPE ~ MathTypes.FormatClass;
Style: TYPE ~ MathTypes.Style;
Procedure Abbreviations from Imported Interfaces
MakeArgument: PROC[name: ATOM, aliases: LIST OF ATOM, size: Size] RETURNS[Argument] ~ MathExpr.MakeArgument;
MakeSymbol: PROC[name: ATOM, aliases: LIST OF ATOM, size: Size, value: EXPR] RETURNS[Symbol] ~ MathExpr.MakeSymbol;
MakeCompoundClass: PROC[name: ATOM, formatClass: FormatClass, description: ROPE, args: LIST OF Argument, syms: LIST OF Symbol, boxRule: CompoundBoxProc, compBox: CompositionProc, cvtAS: ROPENIL] RETURNS[CompoundClass] ~ MathExpr.MakeCompoundClass;
Constants
smallGap: REAL = 0.05;
medGap: REAL = 0.10;
bigGap: REAL = 0.25;
Box Procs for Compound Expr Classes
FixedSizeBoxRule: CompoundBoxProc ~ {
effects: Returns unaltered boxes (i.e. no resizing takes place)
RETURN[boxes];
};
BoxBoxRule: CompoundBoxProc ~ {
effects: Sizes boxes for expr of form ($box $arg)
should ENABLE noSuchBox
argBox: BOX ← MathBox.GetBox[$arg, boxes];
topBox: BOX ← MathBox.GetBox[$top, boxes];
bottomBox: BOX ← MathBox.GetBox[$bottom, boxes];
leftSideBox: BOX ← MathBox.GetBox[$leftSide, boxes];
rightSideBox: BOX ← MathBox.GetBox[$rightSide, boxes];
topSpaceBox: BOX ← MathBox.GetBox[$topSpace, boxes];
bottomSpaceBox: BOX ← MathBox.GetBox[$bottomSpace, boxes];
leftSpaceBox: BOX ← MathBox.GetBox[$leftSpace, boxes];
rightSpaceBox: BOX ← MathBox.GetBox[$rightSpace, boxes];
top and bottom bars and spaces must be as wide as arg
scale: REAL ← ( argBox.Width[] + leftSideBox.Width[] +rightSideBox.Width[] + leftSpaceBox.Width[] +rightSpaceBox.Width[] ) / topBox.Width[];
topBox ← MathBox.Scale[topBox, [scale, 1.0]];
bottomBox ← MathBox.Scale[bottomBox, [scale, 1.0]];
topSpaceBox ← MathBox.Scale[topSpaceBox, [scale, 1.0]];
bottomSpaceBox ← MathBox.Scale[bottomSpaceBox, [scale, 1.0]];
side bars and spaces must be as tall as arg
scale ← ( argBox.Height[] + topBox.Height[] + bottomBox.Height[] + topSpaceBox.Height[] + bottomSpaceBox.Height[] ) / leftSideBox.Height[];
leftSideBox ← MathBox.Scale[leftSideBox, [1.0, scale]];
rightSideBox ← MathBox.Scale[rightSideBox, [1.0, scale]];
leftSpaceBox ← MathBox.Scale[leftSpaceBox, [1.0, scale]];
rightSpaceBox ← MathBox.Scale[rightSpaceBox, [1.0, scale]];
RETURN[LIST[argBox, topBox, bottomBox, leftSideBox, rightSideBox, topSpaceBox, bottomSpaceBox, leftSpaceBox, rightSpaceBox]];
};
Composition Procs for Compound Expr Classes
PostfixUnaryOpCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($aliasUnaryOp $aliasA).
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$aliasSpace,
[$aliasUnaryOp, [right], [left]],
[$aliasUnaryOp, [origin], [origin]]],
[$aliasA,
[$aliasSpace, [right], [left]],
[$aliasSpace, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$aliasUnaryOp, [origin]],
[$aliasUnaryOp, [origin]]];
RETURN[tempBox, tempBoxes];
};
SubscriptCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($base $subscript)
tempBox: BOX;
tempBoxes: LIST OF BOX;
vertOffsetSubscript, vertOffsetBase: Offset;
alignments: LIST OF Alignment2D ← NIL;
IF MathBox.GetBox[$base, boxes].Height[] >
MathBox.GetBox[$subscript, boxes].Height[] THEN {
vertOffsetSubscript ← [top, -0.2];
vertOffsetBase ← [bottom];
}
ELSE {
vertOffsetSubscript ← [top];
vertOffsetBase ← [bottom, +0.2];
};
alignments ← LIST[
[$subscript,
[$base, [left], [right]],
[$base, vertOffsetSubscript, vertOffsetBase]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$base, [origin]], [$base, [origin]]];
make hint to place superscript over base instead of entire expression
tempBox ← tempBox.ChangeSuperHint[MathBox.GetBox[$base, tempBoxes]];
RETURN[tempBox, tempBoxes];
};
SuperscriptCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($base $superscript). Copy of exponentiation Comp Rule.
tempBox: BOX;
tempBoxes: LIST OF BOX;
vertOffsetExponent, vertOffsetBase, horizOffsetBase: Offset;
alignments: LIST OF Alignment2D ← NIL;
baseBox: BOX ← MathBox.GetBox[$base, boxes];
superscriptBox: BOX ← MathBox.GetBox[$superscript, boxes];
hintBox: BOX ← baseBox.SuperscriptHint[]; -- hint about where to place subscript w/i base
IF hintBox # NIL THEN {
hint, so align superscript with base via hintBox
horizOffsetBase ← [origin, hintBox.Offset[].x + hintBox.Extents[].rightExtent];
IF (hintBox.Height[] * baseBox.Height[]) > superscriptBox.Height[] THEN {
vertOffsetExponent ← [bottom, 0.2];
top of hint box inside base box
vertOffsetBase ← [origin, hintBox.Offset[].y + hintBox.Extents[].ascent];
}
ELSE {
vertOffsetExponent ← [bottom];
0.8 way up on hint box
vertOffsetBase ← [origin, 0.8 * (hintBox.Offset[].y + hintBox.Extents[].ascent)];
};
}
ELSE {
no hint, so align superscript directly with base
horizOffsetBase ← [right];
IF baseBox.Height[] > superscriptBox.Height[] THEN {
vertOffsetExponent ← [bottom, 0.2];
vertOffsetBase ← [top];
}
ELSE {
vertOffsetExponent ← [bottom];
vertOffsetBase ← [top, -0.2];
};
};
alignments ← LIST[
[$superscript,
[$base, [left], horizOffsetBase],
[$base, vertOffsetExponent, vertOffsetBase]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$base, [origin]], [$base, [origin]]];
RETURN[tempBox, tempBoxes];
};
AboveCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($above $topArg $bottomArg)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$bottomSpace,
[$bottomArg, [center], [center]],
[$bottomArg, [bottom], [top]]],
[$topSpace,
[$bottomArg, [center], [center]],
[$bottomSpace, [bottom], [top]]],
[$topArg,
[$bottomArg, [center], [center]],
[$topSpace, [bottom], [top]]]
];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$topArg, [origin]],
[$bottomSpace, [top]]];
RETURN[tempBox, tempBoxes];
};
HatCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($hat $base $hat)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$bottomSpace,
[$base, [center], [center]],
[$base, [bottom], [top]]],
[$hat,
[$base, [center], [center]],
[$bottomSpace, [bottom], [top]]]
];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$base, [origin]], [$base, [origin]]];
RETURN[tempBox, tempBoxes];
};
BoxCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($box $arg)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$topSpace,
[$arg, [center], [center]],
[$arg, [bottom], [top]]],
[$top,
[$topSpace, [center], [center]],
[$topSpace, [bottom], [top]]],
[$bottomSpace,
[$arg, [center], [center]],
[$arg, [top], [bottom]]],
[$bottom,
[$bottomSpace, [center], [center]],
[$bottomSpace, [top], [bottom]]],
[$leftSpace,
[$arg, [right], [left]],
[$arg, [center], [center]]],
[$leftSide,
[$leftSpace, [right], [left]],
[$leftSpace, [center], [center]]],
[$rightSpace,
[$arg, [left], [right]],
[$arg, [center], [center]]],
[$rightSide,
[$rightSpace, [left], [right]],
[$rightSpace, [center], [center]]]
];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$arg, [origin]],
[$arg, [origin]]];
RETURN[tempBox, tempBoxes];
};
Class Constructors
MakePostFixUnaryOpClass: PUBLIC PROC[class, op, arg: ATOM, operation: EXPR, description: ROPE, cvtAS: ROPE] RETURNS[CompoundClass] ~ {
effects: Creates and returns standard unary operation compound class named "class".
The alignment is "operation arg"; alignment is thru baselines.
Both op, arg are of fixed size "normal".
argArg: Argument ← MakeArgument[arg, LIST[$aliasA, $aliasHot], normal];
spaceSym: Symbol ← MakeSymbol[$Space, LIST[$aliasSpace], normal, MathConstructors.MakeSpace[$medium]];
unaryOpSym: Symbol ← MakeSymbol[op, LIST[$aliasUnaryOp], normal, operation];
RETURN[MakeCompoundClass[class, unaryOp, description, LIST[argArg], LIST[unaryOpSym, spaceSym], FixedSizeBoxRule, PostfixUnaryOpCompRule, cvtAS]];
};
Signals & Errors
wrongBoxType: PUBLIC ERROR = CODE;
Define & Install Expression Classes
InstallDecorationClassesAA: PROC [] ~ {
local declarations
subscriptClass, aboveClass, hatClass, superscriptClass, primeClass, boxClass: CompoundClass;
baseArg, subscriptArg, superscriptArg, hatArg, topArg, bottomArg, boxArg: Argument;
numerSpSym, denomSpSym: Symbol;
leftSideSym, rightSideSym, topSym, bottomSym: Symbol;
leftSpaceSym, rightSpaceSym, topSpaceSym, bottomSpaceSym: Symbol;
baseArg ← MakeArgument[$base, LIST[$aliasA, $aliasHot], normal];
subscriptArg ← MakeArgument[$subscript, LIST[$aliasB], script];
superscriptArg ← MakeArgument[$superscript, LIST[$aliasB], script];
hatArg ← MakeArgument[$hat, LIST[$aliasB], script];
define info for "box arg"
boxArg ← MakeArgument[$arg, LIST[$aliasA, $aliasHot], normal];
leftSideSym ← MakeSymbol[$leftSide, NIL, normal, MathConstructors.MakePlainSym['\174] ];
rightSideSym ← MakeSymbol[$rightSide, NIL, normal, MathConstructors.MakePlainSym['\174] ];
topSym ← MakeSymbol[$top, NIL, normal, MathConstructors.MakeLine[]];
bottomSym ← MakeSymbol[$bottom, NIL, normal, MathConstructors.MakeLine[]];
leftSpaceSym ← MakeSymbol[$leftSpace, NIL, normal, MathConstructors.MakeSpace[$medium]];
rightSpaceSym ← MakeSymbol[$rightSpace, NIL, normal, MathConstructors.MakeSpace[$medium]];
topSpaceSym ← MakeSymbol[$topSpace, NIL, normal, MathConstructors.MakeSpace[$medium]];
bottomSpaceSym ← MakeSymbol[$bottomSpace, NIL, normal, MathConstructors.MakeSpace[$medium]];
define info for "above top bottom"
topArg ← MakeArgument[$topArg, LIST[$aliasA, $aliasHot], normal];
bottomArg ← MakeArgument[$bottomArg, LIST[$aliasB], normal];
numerSpSym ← MakeSymbol[$topSpace, LIST[$aliasSpace], normal, MathConstructors.MakeSpace[$thin]];
denomSpSym ← MakeSymbol[$bottomSpace, LIST[$aliasSpace], normal, MathConstructors.MakeSpace[$thin]];
boxClass ← MakeCompoundClass[$box, other, "box a", LIST[boxArg], LIST[leftSideSym, rightSideSym, topSym, bottomSym, leftSpaceSym, rightSpaceSym, topSpaceSym, bottomSpaceSym], BoxBoxRule, BoxCompRule, "box $arg"];
subscriptClass ← MakeCompoundClass[$subscript, other, "a sub b", LIST[baseArg, subscriptArg], NIL, FixedSizeBoxRule, SubscriptCompRule, "$baseSub$subscript"];
superscriptClass ← MakeCompoundClass[$superscript, other, "a super b", LIST[baseArg, superscriptArg], NIL, FixedSizeBoxRule, SuperscriptCompRule, "$baseSuper$superscript"];
hatClass ← MakeCompoundClass[$hat, other, "a hat b", LIST[baseArg, hatArg], LIST[denomSpSym], FixedSizeBoxRule, HatCompRule, "$baseHat$hat"];
aboveClass ← MakeCompoundClass[$above, over, "a above b", LIST[topArg, bottomArg], LIST[numerSpSym, denomSpSym], FixedSizeBoxRule, AboveCompRule, "$topArg above $bottomArg"];
primeClass ← MakePostFixUnaryOpClass[$prime, $prime, $a, MathConstructors.MakePlainSym[''], "a prime", "$aPrime"];
MathDB.InstallCompoundClass[subscriptClass];
MathDB.AddOperator[subscriptClass, $Decoration];
MathDB.InstallCompoundClass[superscriptClass];
MathDB.AddOperator[superscriptClass, $Decoration];
MathDB.InstallCompoundClass[hatClass];
MathDB.AddOperator[hatClass, $Decoration];
MathDB.InstallCompoundClass[aboveClass];
MathDB.AddOperator[aboveClass, $Decoration];
MathDB.InstallCompoundClass[primeClass];
MathDB.AddOperator[primeClass, $Decoration];
MathDB.InstallCompoundClass[boxClass];
MathDB.AddOperator[boxClass, $Decoration];
};
Install Classes Defined in this Module
InstallDecorationClassesAA[];
END.