TSBreakUpImpl.mesa
Breaking lists into lists of boxes
Michael Plass, November 2, 1982 10:34 am
Last Edited by: Beach, May 24, 1983 9:11 am
DIRECTORY TSTypes, TSObject, TSFont, TSGlue, TSOps;
TSBreakUpImpl: CEDAR PROGRAM
IMPORTS TSObject, TSTypes, TSFont, TSGlue, TSOps
EXPORTS TSOps =
BEGIN OPEN TSTypes;
BreakUp: PUBLIC PROCEDURE [
list: TSObject.ItemList,
direction: TSObject.Direction,
size: Dimn
] RETURNS [new: TSObject.ItemList] = {
brokenList: REF BrokenListRec ← NEW[BrokenListRec];
opposite: Direction ← SELECT direction FROM
right => left, down => up, left => right, up => down, ENDCASE => ERROR;
brokenList.source ← list.CreateReader[];
brokenList.direction ← direction;
brokenList.size ← [nilDimn, nilDimn, nilDimn, nilDimn];
brokenList.size[direction] ← size;
brokenList.size[opposite] ← zeroDimn;
new ← TSObject.CreateItemList[
producer: BrokenListProducer,
writerData: brokenList
];
};
BrokenListRec: TYPE = RECORD [
source: TSObject.ListReader,
direction: TSObject.Direction,
size: Dimensions,
front: LIST OF REF ANYNIL
];
BrokenListProducer: TSObject.ProducerProc = {
r: REF BrokenListRec ← NARROW[listWriter.writerData];
IF r.source.End[] THEN {
listWriter.ProduceEnd[];
r.source.DestroyReader[]; r.source ← NIL
}
ELSE {
box: TSObject.Box;
markList: TSObject.MarkList;
amount: INT;
rear: LIST OF REF ANY;
tempReader: TSObject.ListReader ← r.source.CopyReader[];
[amount, rear] ← MeasureOff[tempReader, r.direction, r.size[r.direction], r.front];
tempReader.DestroyReader[];
[box, markList] ← TSOps.Package[
source: r.source,
direction: r.direction,
desired: r.size,
itemCount: amount,
front: r.front,
rear: rear
];
listWriter.ProduceItem[markList];
listWriter.ProduceItem[box];
r.front ← Postbreak[r.source];
};
};
Postbreak: PROCEDURE [
source: TSObject.ListReader
] RETURNS [postbreak: LIST OF REF ANYNIL] = {
SELECT source.CurrentTag[] FROM
space => {
postbreak ← source.listParameter[leftfill];
source.Next[];
WHILE source.CurrentTag[] = space DO source.Next[] ENDLOOP;
};
hyphen => {
postbreak ← source.listParameter[leftfill];
source.Next[];
};
exception => {
SELECT TRUE FROM
ISTYPE[source.CurrentItem[], TSObject.Kerf] => {
postbreak ← NARROW[source.CurrentItem[], TSObject.Kerf]^.postbreak;
source.Next[]
};
ENDCASE => {};
};
ENDCASE;
};
MeasureOff: PROCEDURE [
list: TSObject.ListReader,
direction: TSObject.Direction,
size: Dimn,
front: LIST OF REF ANYNIL
] RETURNS [
bestNumberOfItems: INT ← 0,
rear: LIST OF REF ANY
] = {
totGlue: TSGlue.GlueSum ← TSGlue.zeroGlueSum;
AddGlue: PROC [glue: TSGlue.Glue] = INLINE {OPEN TSGlue;
totGlue.space.texPts ← totGlue.space.texPts + glue.space.texPts;
SELECT ABS[glue.stretch.texPts] FROM
< fil.texPts => totGlue.stretch[0].texPts ← totGlue.stretch[0].texPts + glue.stretch.texPts;
< fill.texPts => totGlue.stretch[1].texPts ← totGlue.stretch[1].texPts + glue.stretch.texPts;
< filll.texPts => totGlue.stretch[2].texPts ← totGlue.stretch[2].texPts + glue.stretch.texPts;
ENDCASE => totGlue.stretch[3].texPts ← totGlue.stretch[3].texPts + glue.stretch.texPts;
SELECT ABS[glue.shrink.texPts] FROM
< fil.texPts => totGlue.shrink[0].texPts ← totGlue.shrink[0].texPts + glue.shrink.texPts;
< fill.texPts => totGlue.shrink[1].texPts ← totGlue.shrink[1].texPts + glue.shrink.texPts;
< filll.texPts => totGlue.shrink[2].texPts ← totGlue.shrink[2].texPts + glue.shrink.texPts;
ENDCASE => totGlue.shrink[3].texPts ← totGlue.shrink[3].texPts + glue.shrink.texPts;
};
itemCount: INT ← 0;
prebreak: LIST OF REF ANY;
lowBad: Badness ← infBadness*2;
oldTot: TSGlue.GlueSum;
overfull: BOOLEANFALSE;
opposite: TSObject.Direction ← SELECT direction FROM
right => left, down => up, left => right, up => down, ENDCASE => ERROR;
CalculateBadness: PROC [hyphen: BOOLEANFALSE] = INLINE {
glueSet: TSGlue.GlueSet ← TSGlue.SetGlue[size, TSGlue.GlueFromSum[totGlue]];
curBad: Badness;
overfull ← (glueSet = TSGlue.overfullGlueSet);
curBad ← TSGlue.GlueBadness[glueSet];
IF curBad < lowBad THEN {
lowBad ← curBad; bestNumberOfItems ← itemCount; rear ← prebreak;
IF hyphen THEN rear ← CONS[NEW[TSObject.BoxRec ← [
list.currentFont.CharDimensions['-],
char [list.currentFont, '-]
]], rear]
};
totGlue ← oldTot;
};
MeasureException: PROC[x: REF ANY] = {
SELECT TRUE FROM
ISTYPE[x, TSObject.Glue] => {
g: TSObject.Glue ← NARROW[x];
AddGlue[g^];
};
ISTYPE[x, TSObject.Box] => {
b: TSObject.Box ← NARROW[x];
totGlue.space ← AddDimn[totGlue.space, AddDimn[b.extent[opposite], b.extent[direction]]];
};
ISTYPE[x, TSObject.Kerf] => {
p: LIST OF REF ANY;
oldTot ← totGlue;
prebreak ← p ← NARROW[x, TSObject.Kerf].prebreak;
WHILE p # NIL DO
MeasureException[p.first];
p ← p.rest;
ENDLOOP;
CalculateBadness[];
totGlue ← oldTot;
p ← NARROW[x, TSObject.Kerf].join;
WHILE p # NIL DO
MeasureException[p.first];
p ← p.rest;
ENDLOOP;
};
ISTYPE[x, TSObject.Kern] => {
totGlue.space ← AddDimn[totGlue.space, NARROW[x, TSObject.Kern]^];
};
ENDCASE => {};
};
WHILE front # NIL DO
MeasureException[front.first];
front ← front.rest;
ENDLOOP;
UNTIL list.End[] OR overfull DO
SELECT list.CurrentTag[] FROM
char => {
extent: Dimensions ← list.currentFont.CharDimensions[list.CurrentChar[]];
totGlue.space ← AddDimn[totGlue.space, AddDimn[extent[direction], extent[opposite]]];
list.Next[];
itemCount ← itemCount + 1;
};
space => {
oldTot ← totGlue;
prebreak ← list.listParameter[rightfill]; -- measure right glue
FOR p: LIST OF REF ANY ← prebreak, p.rest UNTIL p=NIL DO
MeasureException[p.first];
ENDLOOP;
CalculateBadness[];
totGlue ← oldTot;
WHILE list.CurrentTag[] = space DO
AddGlue[list.currentFont.SpaceGlue[]];
list.Next[];
itemCount ← itemCount + 1;
ENDLOOP;
};
hyphen => {
extent: Dimensions ← list.currentFont.CharDimensions['-];
oldTot ← totGlue;
totGlue.space ← AddDimn[totGlue.space, AddDimn[extent[direction], extent[opposite]]];
prebreak ← list.listParameter[rightfill]; -- measure right glue
FOR p: LIST OF REF ANY ← prebreak, p.rest UNTIL p=NIL DO
MeasureException[p.first];
ENDLOOP;
CalculateBadness[TRUE];
totGlue ← oldTot;
list.Next[];
itemCount ← itemCount + 1;
};
exception => {
MeasureException[list.CurrentItem[]];
list.Next[];
itemCount ← itemCount + 1;
};
ENDCASE => ERROR;
ENDLOOP;
IF list.End[] THEN {
prebreak ← NIL;
CalculateBadness[];
};
};
END.
Michael Plass, September 1, 1982 9:35 pm: Put in calls to TSObject.DestroyReader.
Michael Plass, November 2, 1982 10:34 am. CEDARized.
Rick Beach, May 13, 1983 1:54 pm. Package now returns marks to BrokenListProducer.