wpi_ffnt.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 387 行

C
387
字号
/****************************************************************************
*
*                            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:  Alternate WPI font routines.
*
****************************************************************************/


#define INCL_PM
#define INCL_DOSNLS
#include <os2.h>
#include "wpi.h"

/***** _WPI_F_* Font Functions *****/
/* These functions are a set of replacement WPI font functions
   which should work. All the other functions are crap; this
   is an attempt to do it right. DJP */

#define FONT_SET_ID     1       // font index in the PRES which we use

void _wpi_f_setfontfacename( WPI_F_FONT *font, PSZ name )
/*******************************************************/

{
    font->attr.szFacename[0] = '\0';
    if( name != NULL ) {
        if( strcmp( name, "MS Sans Serif" ) == 0 ) {
            strcpy( font->attr.szFacename, "Helvetica" );
        } else if( strcmp( name, "MS Serif" ) == 0 ) {
            strcpy( font->attr.szFacename, "Times New Roman" );
        } else if( strcmp( name, "Arial" ) == 0 ) {
            strcpy( font->attr.szFacename, "Helvetica" );
        } else if( strcmp( name, "Times" ) == 0 ) {
            strcpy( font->attr.szFacename, "Times New Roman" );
        } else {
            strcpy( font->attr.szFacename, name );
        }
    }
}

HFONT _wpi_f_createfont( WPI_F_FONT *font )
/*****************************************/

{
    /* In Windows, the CreateFont function takes a LOGFONT and builds
       a HFONT. With our WPI_F_FONT structure in WPI OS/2, we don't
       really need this. But, somebody may build a WPI_F_FONT,
       call this function, then return the result. Hence,
       we do have to allocates and copy it */

    WPI_F_FONT                  *copy_font;

    _wpi_malloc2( copy_font, 1 );

    memcpy( copy_font, font, sizeof( *font ) );

    return( (LONG)copy_font );
}

void _wpi_f_getoldfont( WPI_PRES pres, HFONT ofont )
/**************************************************/

{
    WPI_F_FONT                  *font;

    font = (void *) ofont;
    GpiSetCharSet( pres, LCID_DEFAULT );
    GpiDeleteSetId( pres, FONT_SET_ID );        // delete any leftover first
    GpiCreateLogFont( pres, NULL, FONT_SET_ID, &font->attr );
    GpiSetCharSet( pres, FONT_SET_ID );
    if( font->attr.fsFontUse & FATTR_FONTUSE_OUTLINE ) {
        /* set character attrs too */
        GpiSetAttrs( pres, PRIM_CHAR, CBB_BOX | CBB_ANGLE | CBB_SHEAR,
                                                        0, &font->bundle );
    }

    _wpi_free( font );
}

static WPI_F_FONT *get_f_attrs( WPI_PRES pres, WPI_F_FONT *font )
/***************************************************************/
/* get the current font information in the pres into the font structure */

{
    FONTMETRICS                 fm;
    HDC                         dc;
    LONG                        vert_res;

    GpiQueryFontMetrics( pres, sizeof(FONTMETRICS), &fm );

    font->attr.usRecordLength = sizeof( FATTRS );

    font->attr.fsSelection = fm.fsSelection;
    font->attr.lMatch = fm.lMatch;
    strcpy( font->attr.szFacename, fm.szFacename );
    font->attr.idRegistry = fm.idRegistry;
    font->attr.lMaxBaselineExt = fm.lMaxBaselineExt;
    font->attr.lAveCharWidth = fm.lAveCharWidth;
    if( fm.fsDefn & FM_DEFN_OUTLINE ) {
        font->attr.fsFontUse = FATTR_FONTUSE_OUTLINE;
        GpiQueryCharShear( pres, &font->bundle.ptlShear );
        GpiQueryCharAngle( pres, &font->bundle.ptlAngle );
        GpiQueryCharBox( pres, &font->bundle.sizfxCell );

        /* compute point size */
        dc = GpiQueryDevice( pres );
        DevQueryCaps( dc, CAPS_VERTICAL_FONT_RES, 1L, &vert_res );

        font->pt_size = font->bundle.sizfxCell.cy * 72 / vert_res;
    } else {
        font->pt_size = fm.sNominalPointSize / 10;
    }

    font->retrieved = TRUE;

    return( font );
}

static BOOL find_font( WPI_PRES pres, FATTRS *attr, WPI_F_FONT *font )
/********************************************************************/

{
    HDC                         dc;
    LONG                        horz_res;
    LONG                        vert_res;
    LONG                        num_fonts;
    FONTMETRICS                 *fonts;
    int                         i;
    int                         best_outline;
    int                         best_outline_diff;
    SHORT                       size;
    int                         size_diff;
    SIZEF                       sizef;
    BOOL                        found_match;

    dc = GpiQueryDevice( pres );

    DevQueryCaps( dc, CAPS_HORIZONTAL_FONT_RES, 1L, &horz_res );
    DevQueryCaps( dc, CAPS_VERTICAL_FONT_RES,   1L, &vert_res );

    memset( attr, 0, sizeof( *attr ) );
    attr->usRecordLength = sizeof( FATTRS );
    if( font->attr.szFacename[0] == '\0' ) {
        /* default font requested. The books claim that we can just
           set the facename to the null string, and it will select
           the default font for the DC */

        return( TRUE );
    }

    /* First, see if we can match the font with an image
       font based on the definition resolution and the size */

    num_fonts = 0;
    num_fonts = GpiQueryFonts( pres, QF_PUBLIC, font->attr.szFacename,
                                   &num_fonts, 0L, NULL);
    if( num_fonts == 0 ) {
        return( FALSE );
    }

    fonts = _wpi_malloc( num_fonts * sizeof( FONTMETRICS ) );
    GpiQueryFonts( pres, QF_PUBLIC, font->attr.szFacename,
                    &num_fonts, (LONG) sizeof( FONTMETRICS ), fonts );

    found_match = FALSE;
    best_outline = -1;
    size = font->pt_size * 10;
    for( i = 0; i < num_fonts; i++ ) {
        size_diff = abs( size - fonts[i].sNominalPointSize );
        if( fonts[i].fsDefn & FM_DEFN_OUTLINE ) {
            /* outline font. Record it if it is a good fit */
            if( best_outline == -1 ||
                ( best_outline_diff < size_diff &&
                ( font->attr.usCodePage == 0 ||
                fonts[i].usCodePage == 0 ||
                ( font->attr.usCodePage == fonts[i].usCodePage ) ) ) ) {
                best_outline = i;
                best_outline_diff = size_diff;
            }
        } else {
            if( fonts[i].sXDeviceRes == (SHORT) horz_res &&
                fonts[i].sYDeviceRes == (SHORT) vert_res &&
                fonts[i].sNominalPointSize == (SHORT) size &&
                ( font->attr.usCodePage == 0 ||
                fonts[i].usCodePage == 0 ||
                ( font->attr.usCodePage == fonts[i].usCodePage ) ) ) {
                /* this is a good image font match. Select it */
                break;
            }
        }
    }

    size = font->pt_size;
    if( i == num_fonts ) {
        if( best_outline != -1 ) {
            /* use an outline font */
            found_match = TRUE;
            i = best_outline;
            attr->fsFontUse |= FATTR_FONTUSE_OUTLINE;
            attr->lMatch = 0;

            /* the size is unusual for OS/2. The conversion to
               logical units has to be by you, not the OS.
               So this is what that does */
            sizef.cx = MAKEFIXED( size * horz_res / 72, 0 );
            sizef.cy = MAKEFIXED( size * vert_res / 72, 0 );
            font->bundle.sizfxCell = sizef;
            attr->lMaxBaselineExt = 0;
            attr->lAveCharWidth = 0;
        }
    } else {
        found_match = TRUE;
        attr->fsFontUse &= ~FATTR_FONTUSE_OUTLINE;
        attr->lMatch = fonts[i].lMatch;
        attr->lMaxBaselineExt = fonts[i].lMaxBaselineExt;
        attr->lAveCharWidth = fonts[i].lAveCharWidth;
    }

    if( found_match ) {
        strcpy( attr->szFacename, fonts[i].szFacename );
        attr->fsSelection = font->attr.fsSelection;
        attr->idRegistry = fonts[i].idRegistry;
        attr->usCodePage = fonts[i].usCodePage;
        //attr->fsType ... // doesn't need to be set
    }

    _wpi_free( fonts );

    return( found_match );
}


HFONT _wpi_f_selectfont( WPI_PRES pres, HFONT f )
/***********************************************/
/* this code mimics the behaviour of the OS/2 font palette program.
   Hence, corresponding fonts in the palette program and
   from this code will appear the same. */

{
    WPI_F_FONT                  *font;
    FATTRS                      attr;
    ULONG                       mask;
    char                        old_face[FACESIZE];
    char                        tmp_face[500];
    WPI_F_FONT                  *old_font;
    BOOL                        find_normal;
    CHARBUNDLE                  bundle;

    font = (void *)f;

    _wpi_malloc2( old_font, 1 );
    get_f_attrs( pres, old_font );

    /* The OS/2 font palette will choose a non-synthesized bold/italic
       font by title, if you ask for a 'bold' one */
    find_normal = TRUE;
    if( font->attr.fsSelection & FATTR_SEL_ITALIC ||
                                font->attr.fsSelection & FATTR_SEL_BOLD ) {
        strcpy( old_face, font->attr.szFacename );
        strcpy( tmp_face, font->attr.szFacename );
        if( font->attr.fsSelection & FATTR_SEL_BOLD ) {
            strcat( tmp_face, " Bold" );
        }
        if( font->attr.fsSelection & FATTR_SEL_ITALIC ) {
            strcat( tmp_face, " Italic" );
        }
        if( strlen( tmp_face ) < FACESIZE ) {
            strcpy( font->attr.szFacename, tmp_face );
            if( find_font( pres, &attr, font ) ) {
                find_normal = FALSE;
                attr.fsSelection &= ~FATTR_SEL_BOLD;
                attr.fsSelection &= ~FATTR_SEL_ITALIC;
            }
            strcpy( font->attr.szFacename, old_face );
        }
    }
    if( find_normal ) {
        find_font( pres, &attr, font );
    }

    /* select the font in the PS */
    GpiSetCharSet( pres, LCID_DEFAULT );
    GpiDeleteSetId( pres, FONT_SET_ID );        // delete any leftover first
    GpiCreateLogFont( pres, (PSTR8) NULL, FONT_SET_ID, &attr );
    GpiSetCharSet( pres, FONT_SET_ID );

    /* set the charbundle features */
    if( attr.fsFontUse & FATTR_FONTUSE_OUTLINE ) {
        mask = CBB_BOX;
        if( font->bundle.ptlAngle.x != 0 || font->bundle.ptlAngle.y != 0 ) {
            mask |= CBB_ANGLE;
        }
        if( font->bundle.ptlShear.x != 0 || font->bundle.ptlShear.y != 0 ) {
            mask |= CBB_SHEAR;
        }
        GpiSetAttrs( pres, PRIM_CHAR, mask, 0, &font->bundle );
    } else {
        /* we stil must set the attrs for image fonts. AND, DON'T TRY
           and set these to 'defaults'; the defaults are different for
           different devices! */
        bundle.ptlAngle.x = 1;
        bundle.ptlAngle.y = 0;
        bundle.ptlShear.x = 0;
        bundle.ptlShear.y = 1;
        GpiSetAttrs( pres, PRIM_CHAR,
                        CBB_ANGLE | CBB_SHEAR | CBB_BOX, CBB_BOX, &bundle );
    }

    return( (HFONT) old_font );
}

void _wpi_f_getsystemfont( WPI_PRES in_pres, WPI_F_FONT *font )
/*************************************************************/

{
    FATTRS                      attr;
    WPI_F_FONT                  old_font;
    WPI_PRES                    pres;

    if( in_pres == NULL ) {
        /* assume screen */
        pres = _wpi_getpres( HWND_DESKTOP );
    } else {
        pres = in_pres;
    }
    /* select a default font into the presentation space */
    memset( &attr, 0, sizeof( attr ) );
    attr.usRecordLength = sizeof( FATTRS );

    get_f_attrs( pres, &old_font );

    GpiSetCharSet( pres, LCID_DEFAULT );
    GpiDeleteSetId( pres, FONT_SET_ID );        // delete any leftover first
    GpiCreateLogFont( pres, (PSTR8) NULL, FONT_SET_ID, &attr );
    GpiSetCharSet( pres, FONT_SET_ID );

    get_f_attrs( pres, font );

    _wpi_f_deletefont( (WPI_F_FONT *)_wpi_f_selectfont( pres,
                                                (HFONT)&old_font ) );

    if( in_pres == NULL ) {
        _wpi_releasepres( HWND_DESKTOP, pres );
    }
}

void _wpi_f_default( WPI_F_FONT *font )
/*************************************/
/* this is here, rather than wpi_os2.h, so that people don't have
   to recompile the world when we change WPI_F_FONT */

{
    memset( font, 0, sizeof( *font ) );
}

LONG _wpi_f_getfontsize( WPI_F_FONT *font )
/*****************************************/

{
    return( font->pt_size );
}

/***** end of _WPI_F_* Font Functions *****/

⌨️ 快捷键说明

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