fontsupp.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,370 行 · 第 1/3 页

C
1,370
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Font file support (Windows .fon files, bitmap or vector).
*
****************************************************************************/


#include <string.h>
#include "gdefn.h"
#if !defined( _DEFAULT_WINDOWS )
#include "dotfunc.h"


typedef struct font_entry {
    short               type;       // 0 == bitmap, 1 == vector
    short               ascent;     // distance from top to baseline (in pixels)
    short               width;      // character width in pixels, 0 == proportional
    short               height;     // character height in pixels
    short               avgwidth;   // average character width
    short               firstchar;
    short               lastchar;
    char                filename[ 81 ];
    char                facename[ 32 ];
    char                filler;
    short               version;
    char _WCI86FAR      *glyph_table;
    char _WCI86FAR      *bitmap_table;
    long                start_offset;
    long                glyph_offset;
    long                bitmap_offset;
    unsigned short      bitmap_size;
    struct font_entry _WCI86FAR  *link;
} FONT_ENTRY;


typedef _Packed struct windows_font {
    short               dfVersion;
    long                dfSize;
    char                dfCopyright[ 60 ];
    short               dfType;     // 0 == bitmap, 1 == vector
    short               dfPoints;
    short               dfVertRes;
    short               dfHorizRes;
    short               dfAscent;
    short               dfInternalLeading;
    short               dfExternalLeading;
    char                dfItalic;
    char                dfUnderline;
    char                dfStrikeOut;
    short               dfWeight;
    char                dfCharSet;
    short               dfPixWidth;
    short               dfPixHeight;
    char                dfPitchAndFamily;
    short               dfAvgWidth;
    short               dfMaxWidth;
    char                dfFirstChar;
    char                dfLastChar;
    char                dfDefaultChar;
    char                dfBreakChar;
    short               dfWidthBytes;
    long                dfDevice;
    long                dfFace;
    long                dfBitsPointer;
    long                dfBitsOffset;
    // additional fields have been omitted
} WINDOWS_FONT;
#endif


#define _UNDEFINED      (-1)

#define _BITMAP         0
#define _STROKE         1

static short            _XVecDir = 1;      // text vector direction
static short            _YVecDir = 0;

#if defined( _DEFAULT_WINDOWS )
  #if defined( __WINDOWS__ )
    static short        StockFont = TRUE;
  #else
    // Font ID for OS2
    #include< limits.h >
    #define _STDFONTID  250
  #endif
    static int YVec2Degs( short YDir );
#else
    #define _PROPORTIONAL   0
    #define _FIXED          1

    extern FONT_ENTRY _WCI86FAR  _8x8Font;
    static FONT_ENTRY _WCI86FAR  *_CurFont = &_8x8Font;
    static FONT_ENTRY _WCI86FAR  *_FontList = NULL;
    static float            _XVecScale = 1;    // magnification factor for
    static float            _YVecScale = 1;    // stroke fonts
#endif

#if defined( __386__ )
    #define MemCpy( dst, src, len )     memcpy( dst, src, len )
    #define MemSet( s, c, len )         memset( s, c, len )
    #define StrNICmp( s1, s2, len )     strnicmp( s1, s2, len )
    #define StrCpy( dst, src )          strcpy( dst, src )
    #define StrCmp( dst, src )          strcmp( dst, src )
    #define StrLen( s )                 strlen( s )
#else
    #define MemCpy( dst, src, len )     _fmemcpy( dst, src, len )
    #define MemSet( s, c, len )         _fmemset( s, c, len )
    #define StrNICmp( s1, s2, len )     _fstrnicmp( s1, s2, len )
    #define StrCpy( dst, src )          _fstrcpy( dst, src )
    #define StrCmp( dst, src )          _fstrcmp( dst, src )
    #define StrLen( s )                 _fstrlen( s )
#endif

#if defined( __QNX__ )
  #include <dirent.h>
  #include <unistd.h>
  #include <fcntl.h>
  #include <malloc.h>
  #if !defined( __386__ )
    #include <sys/slib16.h>
  #endif
  #define tiny_ret_t                    int
  #define tiny_handle_t                 int
  #define TINY_ERROR( rc )              ( rc < 0 )
  #define TINY_OK( rc )                 ( rc >= 0 )
  #define TINY_INFO( rc )               ( rc )
  #define TinyOpen( f, m )              __open_slib( f, O_RDONLY, 0 )
  #define FontSeekSet( f, o )           ( ( lseek( f, o, SEEK_SET ) == -1 ) ? -1 : 0 )
  #define TinyRead( f, b, l )           read( f, b, l )
  #define MyTinyFarRead( f, b, l )      read( f, b, l )
  #define TinyClose( f )                close( f )
#else
  #include "tinyio.h"
  #if defined( __386__ )
    #define MyTinyFarRead( h, b, l )    TinyRead( h, b, l )
  #else
    #define MyTinyFarRead( h, b, l )    TinyFarRead( h, b, l )
  #endif
  #define FontSeekSet( f, o )           TinySeek( f, o, TIO_SEEK_START )
#endif


#if !defined( _DEFAULT_WINDOWS )

static void _WCI86FAR *Alloc( unsigned short size )
//=================================================

{
#if defined( __QNX__ )
  #if defined( __386__ )
    return( malloc( size ) );
  #else
    return( MK_FP( qnx_segment_alloc( size ), 0 ) );
  #endif
#else
  #if defined( __386__ )
    return( malloc( size ) );
  #else
    tiny_ret_t          rc;

    rc = TinyAllocBlock( ( size + 15 ) / 16 );
    if( TINY_ERROR( rc ) ) {
        return( NULL );
    } else {
        return( MK_FP( TINY_INFO( rc ), 0 ) );
    }
  #endif
#endif
}


static void Free( void _WCI86FAR *p )
//==============================

{
#if defined( __QNX__ )
  #if defined( __386__ )
    free( p );
  #else
    qnx_segment_free( FP_SEG( p ) );
  #endif
#else
  #if defined( __386__ )
    free( p );
  #else
    TinyFreeBlock( FP_SEG( p ) );
  #endif
#endif
}


static short seek_and_read( tiny_handle_t handle, long offset,
                     void _WCI86FAR *buf, unsigned short len )
/*===========================================================*/
{
    tiny_ret_t          rc;
    short               rlen;

    if( TINY_ERROR( FontSeekSet( handle, offset ) ) ) {
        _ErrorStatus = _GRINVALIDFONTFILE;
        TinyClose( handle );
        return( 0 );
    }
    rc = MyTinyFarRead( handle, buf, len );
    if( TINY_ERROR( rc ) ) {
        _ErrorStatus = _GRINVALIDFONTFILE;
        TinyClose( handle );
        return( 0 );
    }
    rlen = TINY_INFO( rc );
    if( rlen != len ) {
        _ErrorStatus = _GRINVALIDFONTFILE;
        TinyClose( handle );
        return( 0 );
    }
    return( 1 );
}


#define RS_HEADER   ( 4 * sizeof( short ) )
#define RS_DESC     ( 6 * sizeof( short ) )


static short addfont( long offset, tiny_handle_t handle, char *font_file )
//========================================================================

{
    tiny_ret_t          rc;
    WINDOWS_FONT        w_font;
    FONT_ENTRY _WCI86FAR     *curr;
    char                facename[ 32 ];

//  printf( "found font at %lx\n", offset );
    if( seek_and_read( handle, offset, &w_font, sizeof( WINDOWS_FONT ) ) == 0 ) {
        return( 0 );
    }
    // read facename, can't use seek_and_read, since it might be at end of file
    if( TINY_ERROR( FontSeekSet( handle, offset + w_font.dfFace ) ) ) {
        _ErrorStatus = _GRINVALIDFONTFILE;
        TinyClose( handle );
        return( 0 );
    }
    rc = TinyRead( handle, facename, 32 );
    if( TINY_ERROR( rc ) ) {        // only check for error, not length
        _ErrorStatus = _GRINVALIDFONTFILE;
        TinyClose( handle );
        return( 0 );
    }
    facename[ 31 ] = '\0';
    curr = Alloc( sizeof( FONT_ENTRY ) );
    if( curr == NULL ) {
        _ErrorStatus = _GRINSUFFICIENTMEMORY;
        TinyClose( handle );
        return( 0 );
    }
    MemSet( curr, 0, sizeof( FONT_ENTRY ) );
    curr->type      = w_font.dfType & 1;
    curr->ascent    = w_font.dfAscent;
    curr->width     = w_font.dfPixWidth;
    curr->height    = w_font.dfPixHeight;
    curr->avgwidth  = w_font.dfAvgWidth;
    curr->firstchar = w_font.dfFirstChar;
    curr->lastchar  = w_font.dfLastChar;
    curr->version   = w_font.dfVersion;
    StrCpy( curr->filename, font_file );
    StrCpy( curr->facename, facename );
    curr->start_offset = offset;
    offset += sizeof( WINDOWS_FONT );
    if( curr->type == _BITMAP && ( offset & 1 ) ) {
        ++offset;
    }
    if( w_font.dfVersion == 0x0300 ) {
        offset += 30;   // size of extra stuff in V3.0 files
    }
    curr->glyph_offset = offset;
    curr->bitmap_offset = w_font.dfBitsOffset;
    curr->bitmap_size = w_font.dfSize - w_font.dfBitsOffset;
    curr->link = _FontList;
    _FontList = curr;
    return( 1 );
}


static short readfontfile( char *font_file )
//==========================================

{
    char                sig;
    long                ne_offset;
    short               rs_offset;
    short               shift_count;
    unsigned short      type;
    short               count;
    short               i;
    tiny_ret_t          rc;
    tiny_handle_t       handle;
    short               table[ RS_DESC ];

//  printf( "Found file '%s'\n", font_file );
    rc = TinyOpen( font_file, TIO_READ );
    if( TINY_ERROR( rc ) ) {
        _ErrorStatus = _GRFONTFILENOTFOUND;
        return( 0 );
    }
    handle = TINY_INFO( rc );
    // check for signature of 0x40 at location 0x18
    if( seek_and_read( handle, 0x18, &sig, sizeof( char ) ) == 0 ) {
        return( 0 );
    }
    if( sig != 0x40 ) {
        _ErrorStatus = _GRINVALIDFONTFILE;
        TinyClose( handle );
        return( 0 );
    }
    // get offset of NE header
    if( seek_and_read( handle, 0x3c, &ne_offset, sizeof( long ) ) == 0 ) {
        return( 0 );
    }
    // find start of resource table
    if( seek_and_read( handle, ne_offset + 0x24, &rs_offset, sizeof( short ) ) == 0 ) {
        return( 0 );
    }
    // get shift_count at start of resource table
    ne_offset += rs_offset;
    if( seek_and_read( handle, ne_offset, &shift_count, sizeof( short ) ) == 0 ) {
        return( 0 );
    }
    // read entries in resource table, looking for font definitions
    ne_offset += sizeof( short );   // skip over shift_count
    for( ;; ) {
        if( seek_and_read( handle, ne_offset, &table, RS_HEADER ) == 0 ) {
            return( 0 );
        }
        type = table[ 0 ];
        count = table[ 1 ];
        if( type == 0 ) {
            break;
        } else if( type == 0x8008 ) {   // font
            for( i = 0; i < count; ++i ) {
                if( seek_and_read( handle, ne_offset + RS_HEADER + i * RS_DESC, &table, RS_DESC ) == 0 ) {
                    return( 0 );
                }
                if( addfont( (long) table[ 0 ] << shift_count, handle, font_file ) == 0 ) {
                    return( 0 );
                }
            }
        }
        ne_offset += RS_HEADER + count * RS_DESC;
    }
    TinyClose( handle );
    return( 1 );
}


static short GlyphWidth( FONT_ENTRY _WCI86FAR *curr )
//==============================================

// The format of the glyph table is as follows
//   For _BITMAP fonts, there are two words: width, offset
//   For _STROKE fonts, there are two words: offset, width
//   Note: V3.0 _BITMAP fonts have a long offset, and
//         fixed width _STROKE fonts do not include the width.

{
    short               width;

    if( curr->type == _BITMAP ) {
        if( curr->version == 0x200 ) {
            width = 2 * sizeof( short );
        } else {
            width = sizeof( short ) + sizeof( long );
        }
    } else {
        if( curr->width == 0 ) {    // proportional
            width = 2 * sizeof( short );
        } else {
            width = sizeof( short );
        }
    }
    return( width );
}


short _WCI86FAR _CGRAPH _registerfonts( char _WCI86FAR *font_path )
//=======================================================

{
#if defined( __QNX__ )
    DIR _WCI86FAR            *dirp;
    struct dirent _WCI86FAR  *direntp;
#else
    tiny_ret_t          rc;
    tiny_find_t         fileinfo;
    char _WCI86FAR           *p;
#endif
    short               count;
    FONT_ENTRY _WCI86FAR     *curr;
    short               len;
    char                curr_file[ _MAX_PATH ];

    _ErrorStatus = _GROK;
    _unregisterfonts();     // free previous fonts, if any
    StrCpy( curr_file, font_path );     // copy into near buffer
#if defined( __QNX__ )
    #if !defined( __386__ )     // shared library returns far pointers
      #define _dir _dir __far
    #endif
    dirp = opendir( curr_file );
    #if !defined( __386__ )
      #undef _dir
    #endif
    if( dirp == NULL ) {
        _ErrorStatus = _GRFONTFILENOTFOUND;
        return( -1 );   // No such file
    } else {
        for( ;; ) {
            #if !defined( __386__ )
              #define dirent dirent __far
            #endif
            direntp = readdir( dirp );
            #if !defined( __386__ )
              #undef dirent
            #endif
            if( direntp == NULL ) {
                break;
            }
            len = StrLen( direntp->d_name );
            if( len > 4 && StrCmp( direntp->d_name + len - 4, ".fon" ) == 0 ) {
                StrCpy( curr_file, font_path );
                len = strlen( curr_file );
                curr_file[ len ] = '/';
                StrCpy( curr_file + len + 1, direntp->d_name );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?