(* FONTS.PAS -- handle GEOS fonts ** Copyright (c) 1995,1996 Jochen Metzinger ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2, or (at your option) ** any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *) UNIT fonts; INTERFACE USES global, errors, geos, cvt; FUNCTION is_font: BOOLEAN; (* is cvt file a GEOS font? *) PROCEDURE open_fonts; (* open font usage *) FUNCTION font_id: STRING; (* return a identifier string *) FUNCTION open_font(VAR height: BYTE): BOOLEAN; (* select font with size >= height *) FUNCTION get_underline: BYTE; (* returm underline value *) FUNCTION space_width: WORD; (* get width of space char *) FUNCTION select_char(ch: CHAR; VAR wd, underline: WORD): BOOLEAN; (* select character with code CH *) FUNCTION get_dot(x, y: INTEGER): BOOLEAN; (* is (X,Y) set? *) PROCEDURE close_font; (* unselect font *) PROCEDURE close_fonts; (* close font usage *) IMPLEMENTATION TYPE FontHeader = RECORD underline: BYTE; (* Pixels minus 1 above the underline. *) bit_size: WORD; (* Bytes in the bit stream *) point: BYTE; (* Point size, character height in pixels *) off_index: WORD; (* Index to table of bit stream indices *) off_bits: WORD; (* Index to first bit stream. *) END; FontIndices = ARRAY [32..127] OF WORD; (* Indices for char ' ' to '~' *) VAR id: STRING; size: INTEGER; header: FontHeader; index: FontIndices; buffer: BUFFER_PTR; code: INTEGER; bit_pos, width: WORD; FUNCTION is_font: BOOLEAN; VAR info: InfoRec; BEGIN cvt_info(info); is_font := (info.gtyp = 8); END; (* is_font *) PROCEDURE open_fonts; VAR info: InfoRec; BEGIN cvt_info(info); IF info.gtyp <> 8 THEN FATAL('not a font'); id := cvt_name + '['+long2str(info.w[128 DIV 2],0)+']'; size := -1; code := -1; END; (* open_fonts *) FUNCTION font_id: STRING; BEGIN font_id := id; END; (* font_id *) FUNCTION open_font(VAR height: BYTE): BOOLEAN; VAR result: WORD; c: BYTE; BEGIN open_font := FALSE; size := -1; code := -1; (* search font with size >= height *) WHILE cvt_size(height) < 0 DO BEGIN IF height > 125 THEN EXIT; INC(height); END; (* while *) (* load font *) cvt_chain(height); (* load header *) cvt_read(header, SizeOf(header), result); IF result < SizeOf(header) THEN BEGIN error('font '+long2str(height,0)+' too short'); EXIT; END; (* if *) WITH header DO BEGIN IF point <> height THEN error('font '+long2str(height,0)+' is in wrong chain') ELSE IF underline > point THEN error('font '+long2str(height,0)+' underline error') ELSE IF SizeOf(fontHeader) > off_index THEN error('font '+long2str(height,0)+' header & index crash') ELSE IF off_index+SizeOf(FontIndices) > off_bits THEN error('font '+long2str(height,0)+' index & stream crash') ELSE IF off_bits + point*bit_size > cvt_size(height) THEN error('font '+long2str(height,0)+' stream incomplete'); IF is_err THEN EXIT; END; (* with *) (* load index *) cvt_seek(header.off_index); cvt_read(index, SizeOf(index), result); IF result <> SizeOf(index) THEN BEGIN error('read error'); EXIT; END; (* if *) FOR c := 32 TO 126 DO BEGIN IF index[c] DIV 8 > header.bit_size THEN BEGIN error('font '+long2str(size,0)+' at "'+CHR(c)+'" index out of range'); EXIT; END; (* if *) IF index[c+1] - index[c] <= 0 THEN BEGIN error('font '+long2str(size,0)+' at "'+CHR(c)+'" negativ width'); EXIT; END; (* if *) END; (* for *) (* get buffer *) buffer := cvt_buffer; size := height; open_font := TRUE; END; (* open_font *) FUNCTION get_underline: BYTE; BEGIN get_underline := header.underline; END; (* get_underline *) FUNCTION space_width: WORD; BEGIN space_width := index[33] - index[32]; END; (* space_width *) FUNCTION select_char(ch: CHAR; VAR wd, underline: WORD): BOOLEAN; VAR cc: BYTE; BEGIN select_char := FALSE; code := -1; cc := ORD(ch); IF (cc < 32) OR (cc > 127) THEN EXIT; bit_pos := index[cc]; width := index[cc+1] - index[cc]; IF width = 0 THEN EXIT; wd := width; underline := header.underline; code := cc; select_char := TRUE; END; (* select_char *) FUNCTION get_dot(x, y: INTEGER): BOOLEAN; VAR data, mask: BYTE; BEGIN get_dot := FALSE; IF (x < 0) OR (width <= x) THEN EXIT; IF (y < 0) OR (size <= y) THEN EXIT; mask := $80 SHR ((bit_pos + x) AND $07); data := buffer^[header.off_bits+(bit_pos+x) SHR 3 + header.bit_size*y]; get_dot := ((data AND mask) <> 0); END; (* get_dot *) PROCEDURE close_font; BEGIN size := -1; code := -1; END; (* close_font *) PROCEDURE close_fonts; BEGIN id := ''; size := -1; code := -1; END; (* close_fonts *) BEGIN id := ''; size := -1; code := -1; END. (* fonts *)