TSObject.mesa
Michael Plass, November 15, 1983 1:11 pm
Definitions for the object-oriented representation of boxes and glue.
Last Edited by: Beach, May 24, 1983 9:09 am
DIRECTORY
Rope,
TSTypes,
TSGlue,
TSFont,
TSGraphic;
TSObject: CEDAR DEFINITIONS IMPORTS Rope =
BEGIN
ROPE: TYPE = Rope.ROPE;
GlueRec: TYPE = TSGlue.Glue;
Dimn: TYPE = TSTypes.Dimn;
Direction: TYPE = TSTypes.Direction;
Dimensions: TYPE = TSTypes.Dimensions;
ParameterName: TYPE = {baselineskip, lineskip, lineskipstretch, lineskipshrink, lineskiplimit};
ItemList: TYPE = REF ItemListRec;
ListReader: TYPE = REF ListReaderRec;
ListWriter: TYPE = REF ListWriterRec;
Next: PROCEDURE [self: ListReader];
End: PROCEDURE [self: ListReader] RETURNS [BOOLEAN] = INLINE {
RETURN[self.itemList.tagList.first[self.tagOffset] = end]
};
CreateItemList: PROCEDURE [
producer: ProducerProc,
writerData: REF ANYNIL
] RETURNS [new: ItemList];
SingletonList: PROCEDURE [item: REF ANY] RETURNS [new: ItemList];
Copy: PROCEDURE [self: ItemList] RETURNS [new: ItemList];
Concat: PROCEDURE [a, b: TSObject.ItemList]; -- concatenates b onto the end of a.
CreateReader: PROCEDURE [list: ItemList] RETURNS [reader: ListReader];
CopyReader: PROCEDURE [reader: ListReader] RETURNS [copy: ListReader];
DestroyReader: PROCEDURE [reader: ListReader]; -- O.K. to never destroy a reader, but don't destroy one twice!
Expand: PROCEDURE [self: ListReader] RETURNS [explicitList: LIST OF REF ANYNIL];
ItemListFromExplicitList: PROCEDURE [explicitList: LIST OF REF ANYNIL]
RETURNS [new: ItemList]; -- the explicit list should be immutable.
CurrentTag: PROCEDURE [self: ListReader] RETURNS [Tag] = INLINE
{RETURN[self.itemList.tagList.first[self.tagOffset]]};
CurrentChar: PROCEDURE [self: ListReader] RETURNS [CHAR] = INLINE
{RETURN[self.baseRope.Fetch[self.ropeOffset]]};
CurrentItem: PROCEDURE [self: ListReader] RETURNS [REF ANY] = INLINE
{RETURN[self.itemList.exceptionList.first]};
ItemListRec: TYPE = RECORD [
listWriter: ListWriter,
tagList: LIST OF TagRec,
exceptionList: LIST OF REF ANY,
successor: ItemList ← NIL
];
ListReaderRec: TYPE = RECORD [
itemList: ItemListRec,
baseRope: ROPENIL,
ropeOffset: INT ← 0,
currentFont: TSFont.Ref ← NIL,
tagOffset: NAT ← 0,
parameter: ARRAY ParameterType OF Dimn,
listParameter: ARRAY ListParameterType OF LIST OF REF ANY
];
ListWriterRec: TYPE = RECORD [
producer: ProducerProc,
tagList: LIST OF TagRec ← NIL,
tagOffset: NAT ← 0,
exceptionList: LIST OF REF ANYNIL,
currentFont: TSFont.Ref ← NIL,
baseRope: ROPENIL,
ropeOffset: INT ← 0,
parameter: ARRAY ParameterType OF Dimn,
writerData: REF ANYNIL
];
tagRecSize: NAT = 100;
TagRec: TYPE = PACKED ARRAY [0..tagRecSize) OF Tag;
Tag: TYPE = {
char, -- get next character from the rope, using current font
space, -- normal space, in current font
hyphen, -- discretionary hyphen in current font
leading, -- calculated inter-line leading
exception, -- refer to the exception list for the next item
end, -- the end of the list
the following tags are never seen by readers
ignore, -- ignore the next character in the rope
produce -- call the producer proc to extend the list
};
These are the things that may appear in the exception list:
Box: TYPE = REF BoxRec;
Leader: TYPE = REF LeaderRec;
Glue: TYPE = REF TSGlue.Glue;
Kern: TYPE = REF Dimn;
Penalty: TYPE = REF PenaltyRec;
Kerf: TYPE = REF KerfRec;
Parameter: TYPE = REF ParameterRec;
ListParameter: TYPE = REF ListParameterRec;
MarkList: TYPE = REF MarkListItem;
The following things are never seen by readers.
Font: TYPE = TSFont.Ref;
ROPE;
RopeOffset: TYPE = REF RopeOffsetRec;
ProducerProc: TYPE = PROCEDURE [listWriter: ListWriter];
ProduceItem: PROCEDURE [self: ListWriter, item: REF ANY] = INLINE {
self.exceptionList.rest ← LIST[item];
self.exceptionList ← self.exceptionList.rest;
self.tagList.first[self.tagOffset] ← exception;
self.tagOffset ← self.tagOffset + 1;
IF self.tagOffset >= tagRecSize THEN Extend[self];
};
ProduceParameter: PROCEDURE [self: ListWriter, parameterType: ParameterType, parameterValue: Dimn];
ProduceFromRope: PROCEDURE [self: ListWriter, font: Font, rope: ROPE, offset: INT, tag: Tag] = INLINE {
IF font # self.currentFont THEN {
self.ProduceItem[font];
self.currentFont ← font;
};
IF rope # self.baseRope THEN {
self.ProduceItem[rope];
self.baseRope ← rope;
self.ropeOffset ← 0;
};
SELECT offset-self.ropeOffset FROM
0 => {};
1 => {self.ProduceTag[ignore]; self.ropeOffset ← self.ropeOffset + 1};
2 => {self.ProduceTag[ignore]; self.ProduceTag[ignore]; self.ropeOffset ← self.ropeOffset + 2};
ENDCASE => {
self.ProduceItem[NEW[RopeOffsetRec ← [offset]]];
self.ropeOffset ← offset;
};
self.ProduceTag[tag];
self.ropeOffset ← self.ropeOffset + 1;
};
ProduceHyphen: PROCEDURE [self: ListWriter, font: Font] = INLINE {
IF font # self.currentFont THEN {
self.ProduceItem[font];
self.currentFont ← font;
};
self.ProduceTag[hyphen];
};
ProduceLeading: PROCEDURE [self: ListWriter] = INLINE {
self.ProduceTag[leading];
};
ProduceEnd: PROCEDURE [self: ListWriter] = INLINE {
self.ProduceTag[end];
self.producer ← NIL;
self.tagList ← NIL;
self.exceptionList ← NIL;
self.currentFont ← NIL;
self.baseRope ← NIL;
self.writerData ← NIL;
};
BoxType: TYPE = {empty, char, list, rule, graphic};
BoxRec: TYPE = RECORD [
extent: Dimensions,
body: SELECT type: BoxType FROM
empty => [],
char => [font: TSFont.Ref, c: CHAR],
list => [direction: Direction, items: ItemList, glueset: TSGlue.GlueSet],
rule => [],
graphic => [graphicObject: TSGraphic.Object],
ENDCASE];
LeaderRec: TYPE = RECORD [
minExtent: Dimensions,
stretchDirection: Direction,
flexibility: Glue,
graphicObject: TSGraphic.Object
];
PenaltyRec: TYPE = RECORD [
penalty: TSTypes.Penalty
];
KerfRec: TYPE = RECORD [
penalty: TSTypes.Penalty,
prebreak, join, postbreak: LIST OF REF ANY
];
ParameterType: TYPE = {minbaseline, mingaps, shift, hue, saturation, brightness, strikeoutThickness, strikeoutBottom, underlineThickness, underlineBottom};
ParameterRec: TYPE = RECORD [
parameterType: ParameterType,
parameter: Dimn
];
ListParameterType: TYPE = {lineskip, columnskip, leftfill, rightfill};
ListParameterRec: TYPE = RECORD [
listParameterType: ListParameterType,
listParameter: LIST OF REF ANY
];
MarkListItem: TYPE = RECORD [
link: REF MarkListItem,
markKind: ATOM, -- Derived from the "mark" property on nodes; argument to .getmark and .getfirstmark in the page builder routine.
markValue: Box
];
RopeOffsetRec: TYPE = RECORD [
ropeOffset: INT
];
ProduceTag: PRIVATE PROCEDURE [self: ListWriter, tag: Tag] = INLINE {
self.tagList.first[self.tagOffset] ← tag;
self.tagOffset ← self.tagOffset + 1;
IF self.tagOffset >= tagRecSize THEN Extend[self];
};
MakeGlue: PROCEDURE [space, plus, minus: Dimn ← TSTypes.zeroDimn]
RETURNS [p: REF ANY]; -- makes glue or, if possible, a kern
MakeKerf: PUBLIC PROCEDURE [prebreak, join, postbreak: LIST OF REF ANYNIL, penalty: TSTypes.Penalty ← 0]
RETURNS [p: TSObject.Kerf];
fillGlue: READONLY REF ANY;
filGlue: READONLY REF ANY;
bigGlue: READONLY REF ANY;
Extend: PRIVATE PROCEDURE [self: ListWriter];
END.
Michael Plass, September 1, 1982 9:02 pm: changed tagRecSize from 12 to 100.
Michael Plass, November 2, 1982 10:19 am. CEDARized.
Michael Plass, November 12, 1982 9:21 am. Added pZone, undeline & strikeout parameters.
Michael Plass, May 12, 1983 4:22 pm. Added MarkList, MarkListItem.