PDTextBitmapImpl.mesa
Copyright (C) 1984, Xerox Corporation. All rights reserved.
Michael Plass, September 26, 1984 5:33:47 pm PDT
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 POINTERNIL;
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: BOOLEANFALSE] = {
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 POINTERNIL;
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: NATNAT.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: NATNAT.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.