TSOpsImpl.mesa
Michael Plass, November 2, 1982 10:30 am
Last Edited by: Beach, June 6, 1983 4:20 pm
DIRECTORY TSTypes, TSObject, TSFont, TSGlue, TSOps;
TSOpsImpl: CEDAR PROGRAM IMPORTS TSTypes, TSFont, TSObject, TSOps EXPORTS TSOps =
BEGIN OPEN TSTypes;
InsertLeading: PUBLIC PROCEDURE [self: TSObject.ItemList]
RETURNS [new: TSObject.ItemList] = {
new ← TSObject.CreateItemList[
ProduceLeading,
NEW[InterlineDataRec ← [reader: self.CreateReader[]]]
];
};
InterlineDataRec: TYPE = RECORD [
reader: TSObject.ListReader,
prevDepth: Dimn ← nilDimn
];
fillBottomSkip: LIST OF REF ANY = LIST[TSObject.filGlue];
pageBottomSkip: LIST OF REF ANY ← fillBottomSkip;
ProduceLeading: TSObject.ProducerProc = {
r: REF InterlineDataRec ← NARROW[listWriter.writerData];
joinList, leading: LIST OF REF ANY;
penalty: Penalty;
box: TSObject.Box;
item: REF ANY;
baselineDistance: Dimn;
kerf: TSObject.Kerf ← NEW[TSObject.KerfRec];
Finish: PROC = {
listWriter.ProduceEnd[];
r.reader.DestroyReader[]; r.reader ← NIL;
};
IF r.reader.End[] THEN {Finish[]; RETURN};
[joinList, penalty] ← AccumulateKerf[r.reader];
UNTIL r.reader.CurrentTag[] # exception OR NOT ISTYPE[r.reader.CurrentItem[], TSObject.MarkList] DO
afterJoinList: LIST OF REF ANY;
afterPenalty: Penalty;
item ← r.reader.CurrentItem[];
r.reader.Next[];
[afterJoinList, afterPenalty] ← AccumulateKerf[r.reader];
joinList ← CONS[joinList, afterJoinList];
penalty ← penalty + afterPenalty;
listWriter.ProduceItem[item];
ENDLOOP;
IF r.reader.CurrentTag[] = exception THEN {
item ← r.reader.CurrentItem[];
IF ISTYPE[item, TSObject.Box] THEN
box ← NARROW[item]
}
ELSE IF r.reader.CurrentTag[] = char THEN
item ← box ← NEW[TSObject.BoxRec ← [
r.reader.currentFont.CharDimensions[r.reader.CurrentChar[]],
char [r.reader.currentFont, r.reader.CurrentChar[]]
]];
baselineDistance ←
IF box = NIL OR r.prevDepth = nilDimn THEN zeroDimn
ELSE AddDimn[r.prevDepth, box.extent[up]];
IF baselineDistance.texPts >
r.reader.parameter[minbaseline].texPts + r.reader.parameter[mingaps].texPts THEN
leading ← r.reader.listParameter[lineskip]
ELSE leading ← LIST[NEW[Dimn ← SubDimn[r.reader.parameter[minbaseline], baselineDistance]
]];
kerf.join ← Concatenate[joinList, leading];
kerf.penalty ← penalty;
kerf.prebreak ← pageBottomSkip;
IF r.prevDepth # nilDimn THEN listWriter.ProduceItem[kerf];
IF item # NIL THEN listWriter.ProduceItem[item];
IF box # NIL THEN r.prevDepth ← box.extent[down]
ELSE r.prevDepth ← zeroDimn;
IF r.reader.End[] THEN Finish[] ELSE r.reader.Next[];
};
AccumulateKerf: PROCEDURE [self: TSObject.ListReader]
RETURNS [explicitList: LIST OF REF ANYNIL, penalty: Penalty ← 0] = {
SELECT self.CurrentTag[] FROM
exception => {
p: REF ANY ← self.CurrentItem[];
SELECT TRUE FROM
ISTYPE[p, TSObject.Glue] OR ISTYPE[p, TSObject.Kern] => {
self.Next[];
[explicitList, penalty] ← AccumulateKerf[self];
explicitList ← CONS[p, explicitList];
};
ISTYPE[p, TSObject.Penalty] => {
self.Next[];
[explicitList, penalty] ← AccumulateKerf[self];
penalty ← penalty + NARROW[p, TSObject.Penalty]^.penalty;
};
ISTYPE[p, TSObject.Parameter] OR ISTYPE[p, TSObject.ListParameter] => {
self.Next[];
[explicitList, penalty] ← AccumulateKerf[self];
};
ENDCASE;
};
ENDCASE;
}; 
Concatenate: PROC[a,b: LIST OF REF ANY] RETURNS [LIST OF REF ANY] = {
RETURN[IF a=NIL THEN b ELSE CONS[a.first, Concatenate[a.rest, b]]]
};
NumberOfBoxesIn: PUBLIC PROCEDURE [list: TSObject.ItemList] RETURNS [numberOfBoxes: INT ← 0] = {
listReader: TSObject.ListReader ← list.CreateReader[];
UNTIL listReader.End[] DO
IF listReader.CurrentTag[] = exception AND ISTYPE[listReader.CurrentItem[], TSObject.Box]
THEN numberOfBoxes ← numberOfBoxes + 1;
listReader.Next[];
ENDLOOP;
listReader.DestroyReader[];
};
FirstBoxOf: PUBLIC PROCEDURE [list: TSObject.ItemList] RETURNS [box: TSObject.Box ← NIL] = {
listReader: TSObject.ListReader ← list.CreateReader[];
UNTIL listReader.End[] OR box#NIL DO
IF listReader.CurrentTag[] = exception AND ISTYPE[listReader.CurrentItem[], TSObject.Box]
THEN box ← NARROW[listReader.CurrentItem[]];
listReader.Next[];
ENDLOOP;
listReader.DestroyReader[];
};
GetSlimBoxFrom: PUBLIC PROCEDURE [list: TSObject.ItemList] RETURNS [box: TSObject.Box] = {
IF NumberOfBoxesIn[list] = 1 THEN {
box ← FirstBoxOf[list];
TRUSTED {
WITH b: box SELECT FROM
list => box ← TSOps.Package[b.items.CreateReader[], right,
[zeroDimn, nilDimn, nilDimn, nilDimn]].box;
ENDCASE;
};
}
ELSE {
list ← TSOps.InsertLeading[list];
box ← TSOps.Package[list.CreateReader[], down,
[zeroDimn, nilDimn, zeroDimn, nilDimn]].box;
};
};
END.
Michael Plass, September 1, 1982 9:40 pm: Put in call to TSObject.DestroyReader.
Michael Plass, November 2, 1982 10:31 am. CEDARized.
Rick Beach, May 23, 1983 2:56 pm. Moved NumberOfBoxes and FirstBoxOf from TSArtworkImpl to TSOps., AccumulateKerf, Rick
Edited on May 23, 1983 2:55 pm, by Beach
changes to: ProduceLeading to properly accumulate kerfs around mark exceptions.
Edited on June 2, 1983 1:12 pm, by Beach
default action is to fill bottom of pages via pageBottomSkip.
changes to: pageBottomSkip default to fill bottom of pages, ProduceLeading add kerf.preBreak, fillBottomSkip, AnyFillGlue (local of ProduceLeading), AnyFillGlue (local of ProduceLeading)
Edited on June 6, 1983 4:20 pm, by Beach
changes to: ProduceLeading