-- TSBcplFontFileImpl.mesa -- Modified by Geschke on November 6, 1979 10:31 AM -- Changed by Maureen Stone, 30-Dec-81 17:14:57 -- Changed by Michael Plass, June 24, 1982 3:25 pm DIRECTORY TSBcplFontFile, RealConvert USING [BcplToIeee], Mopcodes, IO, Rope, Heap; TSBcplFontFileImpl: PROGRAM IMPORTS TSBcplFontFile, RealConvert, Heap, IO EXPORTS TSBcplFontFile = BEGIN OPEN TSBcplFontFile, IO; ROPE: TYPE = Rope.ROPE; BcplToMesaReal: PROCEDURE[b: BcplREAL] RETURNS[REAL] = INLINE BEGIN RETURN[RealConvert.BcplToIeee[LOOPHOLE[b]]] END; Allocate: PROC[nwords: INTEGER] RETURNS[LONG POINTER] = {RETURN[Heap.MakeNode[Heap.systemZone,nwords]]}; Free: PROC[p: LONG POINTER] = {Heap.FreeNode[Heap.systemZone,p]}; Stream: TYPE = IO.STREAM; StreamIndex: TYPE = INT; inStream: Stream ← NIL; inSDname: LONG POINTER TO name RawIndex; inSDsplines: LONG POINTER TO splines RawIndex; inSDfontname: LONG STRING; inBaseIndex: StreamIndex; mesaSplineData: mesaSplineDataDesc; mesaSplineDir: mesaSplineDirDesc; OpenSDFontFile: PUBLIC PROCEDURE [file: ROPE] = BEGIN c: CHARACTER; inSDend: LONG POINTER TO end RawIndex; inSplineData: SplineDataDesc; inSplineDir: SplineDirDesc; nChars: CARDINAL; IF inStream # NIL THEN ERROR; inStream ← IO.CreateFileStream[file, read]; inSDname ← GetRawIndex[]; IF inSDname.hdr.type # name THEN ERROR; inSDfontname ← BcplToMesaString[inSDname.fontname]; inSDsplines ← GetRawIndex[]; IF inSDsplines.hdr.type # splines OR inSDsplines.rotation # 0 THEN ERROR; inSDend ← GetRawIndex[]; IF inSDend.hdr.type # end THEN ERROR; Free[inSDend]; nChars ← inSDsplines.ec-inSDsplines.bc+1; --number of characters in this font --read in the character information (bounding boxes, etc.) inSplineData ← DESCRIPTOR[Allocate[nChars*SIZE[BcplSplineData]],nChars]; IO.SetIndex[ inStream, LongPointerToStreamIndex[BcplToMesaLongPointer[inSDsplines.startaddress]]]; ReadBlock[inStream,BASE[inSplineData],nChars*SIZE[BcplSplineData]]; mesaSplineData ← LOOPHOLE[inSplineData]; inBaseIndex←IO.GetIndex[inStream]; --the directory addresses are relative to this point --read in the directory information (pointers to actual spline information) inSplineDir ← DESCRIPTOR[Allocate[nChars*SIZE[bcplLONGPOINTER]],nChars]; ReadBlock[inStream,BASE[inSplineDir],nChars*SIZE[bcplLONGPOINTER]]; mesaSplineDir ← LOOPHOLE[inSplineDir]; -- convert BCPL dir and spline data to Mesa FOR c IN [inSDsplines.bc..inSDsplines.ec] DO IF inSplineDir[c-inSDsplines.bc] = --set the unused entries to NIL and LOOP LOOPHOLE[LOOPHOLE[LONG[-1], LONG INTEGER], bcplLONGPOINTER] THEN BEGIN mesaSplineDir[c-inSDsplines.bc] ← NIL; LOOP END; mesaSplineDir[c-inSDsplines.bc] ← BcplToMesaLongPointer[inSplineDir[c-inSDsplines.bc]]; BEGIN bcplData: LONG POINTER TO BcplSplineData ← @inSplineData[c-inSDsplines.bc]; mesaData: LONG POINTER TO SplineData ← @mesaSplineData[c-inSDsplines.bc]; mesaData.xwidth ← BcplToMesaReal[bcplData.xwidth]; mesaData.ywidth ← BcplToMesaReal[bcplData.ywidth]; mesaData.bbox ← BcplToMesaReal[bcplData.bbox]; mesaData.bboy ← BcplToMesaReal[bcplData.bboy]; mesaData.rightx ← BcplToMesaReal[bcplData.rightx]; mesaData.topy ← BcplToMesaReal[bcplData.topy]; END; ENDLOOP; -- at this point we are prepared to read splines from the SD file RETURN END; CloseSDFontFile: PUBLIC PROCEDURE = BEGIN IO.Close[inStream]; inStream ← NIL; Free[inSDname]; Free[inSDsplines]; Free[BASE[mesaSplineData]]; Free[BASE[mesaSplineDir]]; END; GetRawIndex: PROCEDURE RETURNS [LONG POINTER] = BEGIN p: LONG POINTER TO RawIndex; p← Allocate[SIZE[RawIndex]]; ReadBlock[inStream,p,SIZE[IndexHeader]]; ReadBlock[inStream,p+SIZE[IndexHeader],p.hdr.length-1]; RETURN[p]; END; GetSplineCommands: PUBLIC PROCEDURE[char: CHARACTER, userAlloc: AllocProc] RETURNS [sd: SplineDataPtr, scp: SplineCommandPtr] = BEGIN index: StreamIndex; last: SplineCommandPtr; IF char-inSDsplines.bc NOT IN[0..LENGTH[mesaSplineDir]) OR mesaSplineDir[char-inSDsplines.bc] = NIL THEN RETURN[NIL, NIL]; sd ← @mesaSplineData[char-inSDsplines.bc]; index ← LongPointerToStreamIndex[StreamIndexToLongCardinal[inBaseIndex]+mesaSplineDir[char-inSDsplines.bc]]; IO.SetIndex[inStream, index]; [scp,index] ← GetNextCommand[index, userAlloc]; last ← scp; DO [last.next,index] ← GetNextCommand[index, userAlloc]; IF last.next.type = EndDefinition THEN EXIT; last ← last.next; ENDLOOP; RETURN END; GetNextCommand: PROCEDURE[index: StreamIndex, userAlloc: AllocProc] RETURNS [SplineCommandPtr, StreamIndex] = BEGIN bsc: BcplSplineCommand; --machine dependent record scc: SplineCommandCode; scp: SplineCommandPtr; IO.SetIndex[inStream, index]; scc ← BcplToMesaCommandCode[bsc.type ← GetWord[inStream]]; ReadBlock[ inStream, @bsc+1, --it's really ok (SELECT scc FROM MoveTo, DrawTo => SIZE[MoveTo BcplSplineCommand], DrawCurve => SIZE[DrawCurve BcplSplineCommand], ENDCASE => SIZE[EndDefinition BcplSplineCommand])-1]; scp ← userAlloc[SELECT scc FROM MoveTo, DrawTo => SIZE[MoveTo SplineCommand], DrawCurve => SIZE[DrawCurve SplineCommand], ENDCASE => SIZE[EndDefinition SplineCommand]]; SELECT scc FROM MoveTo => scp↑ ← [, MoveTo[,]]; DrawTo => scp↑ ← [, DrawTo[,]]; DrawCurve => scp↑ ← [, DrawCurve[,,,,,]]; NewObject => scp↑ ← [, NewObject[]]; EndDefinition => scp↑ ← [, EndDefinition[]]; ENDCASE; scp.next ← NIL; WITH scp SELECT FROM MoveTo, DrawTo => BEGIN x ← BcplToMesaReal[bsc.x]; y ← BcplToMesaReal[bsc.y]; END; DrawCurve => BEGIN x0 ← BcplToMesaReal[bsc.x0]; y0 ← BcplToMesaReal[bsc.y0]; x1 ← BcplToMesaReal[bsc.x1]; y1 ← BcplToMesaReal[bsc.y1]; x2 ← BcplToMesaReal[bsc.x2]; y2 ← BcplToMesaReal[bsc.y2]; END; ENDCASE; RETURN[scp, IO.GetIndex[inStream]] END; BcplToMesaCommandCode: PROCEDURE[bcc: BcplCommandCode] RETURNS [SplineCommandCode] = BEGIN SELECT bcc FROM 1 => RETURN[MoveTo]; 2 => RETURN[DrawTo]; 3 => RETURN[DrawCurve]; -1 => RETURN[NewObject]; -2 => RETURN[EndDefinition]; ENDCASE => ERROR END; LongPointerToStreamIndex: PROCEDURE [l: LONG POINTER] RETURNS [StreamIndex]= BEGIN RETURN[2*LOOPHOLE[l,INT]]; END; StreamIndexToLongCardinal: PROCEDURE [s:StreamIndex] RETURNS [LONG CARDINAL]= BEGIN RETURN[s/2]; END; BcplToMesaString: PROCEDURE [t: BcplSTRING] RETURNS[s: LONG STRING] = { len: INTEGER ← LOOPHOLE[t[0]]; --one byte of length IF len NOT IN[0..255] THEN ERROR; s ← Heap.MakeString[Heap.systemZone,len]; FOR i: INTEGER IN [0..len) DO s[i] ← t.body[i+1]; ENDLOOP; }; ReadBlock: PROC[stream: Stream, p: LONG POINTER, nwords: INT] = { block: IO.UnsafeBlock ← [base: p, startIndex: 0, stopIndexPlusOne: 2*nwords]; [] ← IO.UnsafeGetBlock[stream,block]; }; GetWord: PROC[stream: Stream] RETURNS [INTEGER] = { word: INTEGER; foo: LONG POINTER TO INTEGER ← @word; block: IO.UnsafeBlock ← [base: foo, startIndex: 0, stopIndexPlusOne: 2]; [] ← IO.UnsafeGetBlock[stream,block]; RETURN[word]; }; END. -- Changed by Maureen Stone, 30-Dec-81 17:14:57 to convert to Cedar 2.2 -- Changed by Michael Plass, May 27, 1982 8:35 am. IOStream => IO, file name LONG STRING => ROPE. -- Changed by Michael Plass, June 24, 1982 3:25 pm. Cedar 3.2 conversion.