Scale:
PUBLIC
PROC[b:
BOX, v:
VEC]
RETURNS[
BOX] ~ {
effects: Returns the BOX which is b scaled by v.
BOX extents and offset are scaled.
RETURN[NEW[BoxRep ← [tag: b.tag, aliases: b.aliases, formatClass: b.formatClass, type: b.type, extents: [leftExtent: v.x * b.extents.leftExtent, rightExtent: v.x * b.extents.rightExtent, descent: v.y * b.extents.descent, ascent: v.y * b.extents.ascent], offset: [v.x * b.offset.x, v.y * b.offset.y]]]];
};
Inside:
PUBLIC
PROC[b:
BOX, x, y:
REAL]
RETURNS[
BOOL] ~ {
effects: Returns TRUE if the point [x, y] is enclosed by b.
Otherwise returns FALSE.
RETURN[(x >= b.offset.x - b.extents.leftExtent) AND (x <= b.offset.x + b.extents.rightExtent) AND (y >= b.offset.y - b.extents.descent) AND (y <= b.offset.y + b.extents.ascent)];
};
AlignHorizontal:
PUBLIC
PROC[box1: ImagerFont.Extents, offset1:
REAL, box2:
BOX, offset2:
REAL]
RETURNS[
REAL] ~ {
effects: Horizontally aligns box1 with box2 such that the
points (offset1 * WIDTH[box1]) and (offset2 * WIDTH[box2]) are aligned.
Offsets are measured from the left edge of a box.
Returns the x offset for box1.
drawing a vector diagram is the best way to understand this
RETURN[box2.offset.x + (offset2 * Width[box2]) - box2.extents.leftExtent + box1.leftExtent - (offset1 * (box1.leftExtent + box1.rightExtent))];
};
AlignVertical:
PUBLIC
PROC[box1: ImagerFont.Extents, offset1:
REAL, box2:
BOX, offset2:
REAL]
RETURNS[
REAL] ~ {
effects: Vertically aligns box1 with box2 s.t. the points
(offset1 * HEIGHT[box1]) and (offset2 * HEIGHT[box2]) are aligned.
Offsets are measured from the bottom edge of a box.
Returns the y offset for box1.
drawing a vector diagram is the best way to understand this
RETURN[box2.offset.y + (offset2 * Height[box2]) - box2.extents.descent + box1.descent - (offset1 * (box1.descent + box1.ascent))];
};
RelToAbsBox:
PUBLIC
PROC[relBox, parentBox:
BOX]
RETURNS[
BOX] ~ {
requires: relBox is a relative BOX, parentBox is an absolute BOX
effects: Converts relBox (relative units) into an absBox (absolute units)
by positioning it relative to parentBox
IF (relBox.type # relative) OR (parentBox.type # absolute) THEN ERROR wrongBoxType;
RETURN[MakeBox[tag: relBox.tag, aliases: relBox.aliases, formatClass: relBox.formatClass, type: absolute, extents: [leftExtent: Width[parentBox] * relBox.extents.leftExtent, rightExtent: Width[parentBox] * relBox.extents.rightExtent, ascent: Height[parentBox] * relBox.extents.ascent, descent: Height[parentBox] * relBox.extents.descent], offset: [parentBox.offset.x + (Width[parentBox] * relBox.offset.x), parentBox.offset.y + (Height[parentBox] * relBox.offset.y)]]];
};
Constructors
MakeBox:
PUBLIC
PROC[tag:
ATOM, aliases:
LIST
OF
ATOM, formatClass: FmtClass, type: BoxType, extents: ImagerFont.Extents ← [0.0, 0.0, 0.0, 0.0], offset:
VEC ← [0.0, 0.0]]
RETURNS[
BOX] ~ {
effects: Constructs and returns a new BOX with the specified parameters.
RETURN[NEW[BoxRep ← [tag: tag, aliases: aliases, formatClass: formatClass, type: type, extents: extents, offset: offset]]];
};
ChangeOffset:
PUBLIC
PROC[box:
BOX, newOffset:
VEC]
RETURNS[
BOX] ~ {
effects: Returns a new BOX which is box with offset newOffset.
RETURN[MakeBox[box.tag, box.aliases, box.formatClass, box.type, box.extents, newOffset]];
};
ChangeExtents:
PUBLIC
PROC[box:
BOX, newExtents: ImagerFont.Extents]
RETURNS[
BOX] ~ {
effects: Returns a new BOX which is box with Extents newExtents.
RETURN[MakeBox[box.tag, box.aliases, box.formatClass, box.type, newExtents, box.offset]];
};
ChangeType:
PUBLIC PROC[box:
BOX, newType: BoxType]
RETURNS[
BOX] ~ {
effects: Returns a new BOX which is box with type newType.
RETURN[MakeBox[box.tag, box.aliases, box.formatClass, newType, box.extents, box.offset]];
};
ChangeFormatClass:
PUBLIC PROC[box:
BOX, newFormatClass: FmtClass]
RETURNS[
BOX] ~ {
effects: Returns a new BOX which is box with format class newFormatClass.
RETURN[MakeBox[box.tag, box.aliases, newFormatClass, box.type, box.extents, box.offset]];
};
Width:
PUBLIC
PROC[b:
BOX]
RETURNS[
REAL] ~ {
effects: Returns the width of b.
RETURN[b.extents.leftExtent + b.extents.rightExtent];
};
Height:
PUBLIC
PROC[b:
BOX]
RETURNS[
REAL] ~ {
effects: Returns the height of b.
RETURN[b.extents.ascent + b.extents.descent];
};
Tag:
PUBLIC
PROC[b:
BOX]
RETURNS[
ATOM] ~ {
effects: Returns the tag associated with b.
RETURN[b.tag];
};
Aliases:
PUBLIC
PROC[b:
BOX]
RETURNS[
LIST
OF
ATOM] ~ {
effects: Returns the aliases assocaited with b
RETURN[b.aliases];
};
FormatClass:
PUBLIC
PROC[b:
BOX]
RETURNS[FmtClass] ~ {
effects: Returns the format class associated with b.
RETURN[b.formatClass];
};
Extents:
PUBLIC
PROC[b:
BOX]
RETURNS[ImagerFont.Extents] ~ {
effects: Returns the extents of b.
RETURN[b.extents];
};
Offset:
PUBLIC
PROC[b:
BOX]
RETURNS[
VEC] ~ {
effects: Returns the offset vector of b.
RETURN[b.offset];
};
Origin:
PUBLIC
PROC[b:
BOX]
RETURNS[
VEC] ~ {
effects: Returns the origin vector [b.Extents.leftExtent, b.Extents.descent]
RETURN[[b.extents.leftExtent, b.extents.descent]];
};
Type:
PUBLIC
PROC[b:
BOX]
RETURNS[BoxType] ~ {
effects: Returns relative if b is in relative units;
Else returns absolute.
RETURN[b.type];
};
Box List Operations
GetBox:
PUBLIC
PROC[tag:
ATOM, boxes:
LIST
OF
BOX, useAliases:
BOOL ←
TRUE]
RETURNS[
BOX] ~ {
effects: Returns the BOX in boxes associated with tag.
If useAliases = TRUE, then checks for BOX in boxes with alias tag.
SIGNALS boxNotFound if no association exists.
FOR l:
LIST
OF
BOX ← boxes, l.rest
UNTIL l =
NIL
DO
IF l.first.tag = tag THEN RETURN[l.first];
ENDLOOP;
not a normal tag, so check aliases
FOR l:
LIST
OF
BOX ← boxes, l.rest
UNTIL l =
NIL
DO
FOR aliases:
LIST
OF
ATOM ← l.first.aliases, aliases.rest
UNTIL aliases =
NIL
DO
IF aliases.first = tag THEN RETURN[l.first];
ENDLOOP;
ENDLOOP;
not found, so signal error
ERROR boxNotFound;
};
MapBoxList:
PUBLIC
PROC[boxes:
LIST
OF
BOX, proc:
PROC[b:
BOX]
RETURNS[
BOX]]
RETURNS[
LIST
OF
BOX] ~ {
effects: Constructs a new LIST OF BOX by applying proc to each
BOX in boxes. Element positions in list are not preserved.
newList: LIST OF BOX ← NIL;
FOR l:
LIST
OF
BOX ← boxes, l.rest
UNTIL l =
NIL
DO
newList ← CONS[proc[l.first], newList];
ENDLOOP;
RETURN[newList];
};