-- PDTextBitmapImpl.mesa -- Copyright (C) 1984, 1986 Xerox Corporation. All rights reserved. -- Michael Plass, September 26, 1984 5:33:47 pm PDT -- Tim Diebert, 5-Sep-86 14:09:16 -- DIRECTORY Environment, PDInterpBitmap, PDInterpSysCalls, PDTextBitmap, Stream, PDStrikeFormat, PDRemoteStream, Inline, String; PDTextBitmapImpl: PROGRAM IMPORTS PDInterpBitmap, PDInterpSysCalls, PDRemoteStream, Stream, Inline, String EXPORTS PDTextBitmap = BEGIN fontName: PUBLIC LONG STRING ← [120]; bc: CHAR = ' ; ec: CHAR = '~; charBitmap: ARRAY CHAR[bc..ec] OF PDInterpBitmap.BitmapDesc; charWidth: ARRAY CHAR[bc..ec] OF INTEGER; fontAscent: INTEGER ← 0; fontDescent: INTEGER ← 0; ksFontBuffer: LONG POINTER ← NIL; bytesPerWord: NAT = Environment.bytesPerWord; nilBitmap: PDInterpBitmap.BitmapDesc = [ sOrigin: 0, fOrigin: 0, sMin: 0, fMin: 0, sSize: 0, fSize: 0, pointer: NIL, rast: 0, lines: 0 ]; BadFont: ERROR = CODE; SetFont: PUBLIC PROC [fontFileName: LONG STRING, userName, password: LONG STRING] RETURNS [ok: BOOLEAN ← FALSE] = { cr: LONG STRING ← [40]; nameCopy: LONG STRING ← [120]; NameCopy: PROC RETURNS [LONG STRING] = { String.Copy[nameCopy, fontFileName]; RETURN [nameCopy] }; bytes: INT ← PDRemoteStream.Lookup[NameCopy[], cr, userName, password]; newBuffer: LONG POINTER ← NIL; bytesRead: INT ← 0; readFile: PROC[stream: Stream.Handle] = { bytesRead ← Stream.GetBlock[stream, [blockPointer: newBuffer, startIndex: 0, stopIndexPlusOne: bytes]].bytesTransferred; }; IF ksFontBuffer # NIL THEN { FOR c: CHAR IN [bc..ec] DO charBitmap[c] ← nilBitmap; charWidth[c] ← 0 ENDLOOP; PDInterpSysCalls.FreeSpace[ksFontBuffer]; fontAscent ← fontDescent ← 0; ksFontBuffer ← NIL }; fontName.length ← 0; newBuffer ← PDInterpSysCalls.AllocateSpace[(bytes+bytesPerWord-1)/bytesPerWord]; PDRemoteStream.Read[fontFileName, userName, password, readFile]; IF bytesRead # bytes THEN { PDInterpSysCalls.FreeSpace[newBuffer]; RETURN [FALSE] }; ok ← TRUE; ParseFont[fontFileName, newBuffer, bytes -- ! BadFont => {ok ← FALSE; CONTINUE}; ]; IF ok THEN { ksFontBuffer ← newBuffer; } ELSE { FOR c: CHAR IN [bc..ec] DO charBitmap[c] ← nilBitmap; charWidth[c] ← 0 ENDLOOP; PDInterpSysCalls.FreeSpace[newBuffer]; fontAscent ← fontDescent ← 0; String.Copy[to: fontName, from: fontFileName]; }; }; ParseFont: PUBLIC PROC [fontFileName: LONG STRING, buffer: LONG POINTER, bytes: INT] = { wordIndex: INT ← 0; ReadBlock: PROC [dest: LONG POINTER, words: CARDINAL, wordOffset: INT ← -1] = { IF wordOffset >= 0 THEN wordIndex ← wordOffset; Inline.LongCOPY[from: buffer+wordIndex, nwords: words, to: dest]; wordIndex ← wordIndex + words; }; strike: PDInterpBitmap.BitmapDesc ← nilBitmap; defaultCharBitmap: PDInterpBitmap.BitmapDesc ← nilBitmap; defaultCharWidth: INTEGER ← 0; header: PDStrikeFormat.Header; ReadBlock[@header, SIZE[PDStrikeFormat.Header], 0]; IF header.format.oneBit # T THEN ERROR BadFont; IF header.format.index # F THEN ERROR BadFont; IF header.format.unused # 0 THEN ERROR BadFont; IF header.format.kerned = T THEN { boundingBox: PDStrikeFormat.BoundingBox; body: PDStrikeFormat.Body; xInSegment, prevXInSegment: CARDINAL; xInSegmentOffset: INT; widthEntryOffset: INT; widthEntry: PDStrikeFormat.WidthEntry; bodyOffset: INT; ReadBlock[@boundingBox, SIZE[PDStrikeFormat.BoundingBox]]; bodyOffset ← wordIndex; ReadBlock[@body, SIZE[PDStrikeFormat.Body]]; fontAscent ← body.ascent; fontDescent ← body.descent; strike ← [ sOrigin: -body.ascent, fOrigin: 0, sMin: 0, fMin: 0, sSize: body.ascent+body.descent, fSize: body.raster*Environment.bitsPerWord, pointer: buffer+wordIndex, rast: body.raster, lines: body.ascent+body.descent ]; wordIndex ← wordIndex + strike.rast*strike.lines; widthEntryOffset ← wordIndex+(header.max-header.min+3)*SIZE[CARDINAL]; IF widthEntryOffset # bodyOffset + body.length THEN ERROR BadFont; ReadBlock[@prevXInSegment, SIZE[CARDINAL]]; xInSegmentOffset ← wordIndex; FOR char: CHAR IN [header.min..header.max] DO charPixels: PDInterpBitmap.BitmapDesc ← strike; ReadBlock[@xInSegment, SIZE[CARDINAL], xInSegmentOffset]; xInSegmentOffset ← xInSegmentOffset + SIZE[CARDINAL]; ReadBlock[@widthEntry, SIZE[PDStrikeFormat.WidthEntry], widthEntryOffset]; widthEntryOffset ← widthEntryOffset + SIZE[PDStrikeFormat.WidthEntry]; IF widthEntry # PDStrikeFormat.nullWidthEntry THEN { IF widthEntry.width > header.maxwidth THEN ERROR BadFont; charPixels.fOrigin ← widthEntry.offset+boundingBox.fbbox-prevXInSegment; charPixels.fMin ← prevXInSegment; charPixels.fSize ← xInSegment-prevXInSegment; IF char IN [bc..ec] THEN { charBitmap[char] ← charPixels; charWidth[char] ← widthEntry.width; }; }; prevXInSegment ← xInSegment; ENDLOOP; ReadBlock[@xInSegment, SIZE[CARDINAL], xInSegmentOffset]; xInSegmentOffset ← xInSegmentOffset + SIZE[CARDINAL]; ReadBlock[@widthEntry, SIZE[PDStrikeFormat.WidthEntry], widthEntryOffset]; widthEntryOffset ← widthEntryOffset + SIZE[PDStrikeFormat.WidthEntry]; IF widthEntry # PDStrikeFormat.nullWidthEntry THEN { strike.fOrigin ← widthEntry.offset+boundingBox.fbbox-prevXInSegment; strike.fMin ← prevXInSegment; strike.fSize ← xInSegment-prevXInSegment; defaultCharBitmap ← strike; defaultCharWidth ← widthEntry.width; } ELSE ERROR BadFont; } ELSE ERROR BadFont; FOR char: CHAR IN [bc..ec] DO IF charBitmap[char].pointer = NIL THEN { charBitmap[char] ← defaultCharBitmap; charWidth[char] ← defaultCharWidth; }; ENDLOOP; IF wordIndex*bytesPerWord # bytes THEN ERROR BadFont; }; FontAscent: PUBLIC PROC RETURNS [INTEGER] = {RETURN [fontAscent]}; FontDescent: PUBLIC PROC RETURNS [INTEGER] = {RETURN [fontDescent]}; TextWidth: PUBLIC PROC [string: LONG STRING, start: NAT ← 0, length: NAT ← NAT.LAST] RETURNS [textWidth: INTEGER] = { textWidth ← 0; FOR i: NAT IN [start..start+length) DO IF i >= string.length THEN EXIT ELSE { char: CHAR ← string[i]; IF char IN [bc..ec] THEN textWidth ← textWidth + charWidth[char]; }; ENDLOOP; }; TextToBitmap: PUBLIC PROC [dest: PDInterpBitmap.BitmapDesc, string: LONG STRING, start: NAT ← 0, length: NAT ← NAT.LAST, function: PDInterpBitmap.Function] = { w: INTEGER ← 0; FOR i: NAT IN [start..start+length) DO IF i >= string.length THEN EXIT ELSE { char: CHAR ← string[i]; IF char IN [bc..ec] THEN { bitmap: PDInterpBitmap.BitmapDesc ← charBitmap[char]; bitmap.fOrigin ← bitmap.fOrigin + w; PDInterpBitmap.Transfer[dest, bitmap, function]; w ← w + charWidth[char]; }; }; ENDLOOP; }; END.