⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 varbitmap.c

📁 在ADS环境下MiniGUI的源码
💻 C
字号:
/*
** $Id: varbitmap.c,v 1.33 2004/04/01 08:57:13 weiym Exp $
** 
** varbitmap.c: The Var Bitmap Font operation set.
**
** Copyright (C) 2000, 2001, 2002 Wei Yongming
** Copyright (C) 2003 Feynman Software
**
** Create date: 2000/06/13
*/

/*
** 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/*
** TODO:
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "common.h"

#ifdef _VBF_SUPPORT

#include "minigui.h"
#include "gdi.h"
#include "endianrw.h"
#include "misc.h"

#ifdef HAVE_MMAP
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
#endif

#include "devfont.h"
#include "varbitmap.h"
#include "charset.h"
#include "fontname.h"

/*************** Variable bitmap font operations *********************************/
static int get_char_width (LOGFONT* logfont, DEVFONT* devfont, 
                const unsigned char* mchar, int len)
{
    VBFINFO* vbf_info = VARFONT_INFO_P (devfont);

    if (vbf_info->width == NULL)
        return vbf_info->max_width;

    assert (len == 1);

    if (*mchar < vbf_info->first_char || *mchar > vbf_info->last_char)
        return vbf_info->width [vbf_info->def_char - vbf_info->first_char];

    return vbf_info->width [*mchar - vbf_info->first_char];   
}

static int get_max_width (LOGFONT* logfont, DEVFONT* devfont)
{
   return VARFONT_INFO_P (devfont)->max_width; 
}

static int get_str_width (LOGFONT* logfont, DEVFONT* devfont, 
                const unsigned char* mstr, int n, int cExtra)
{
    int i;
    int str_width;
    VBFINFO* vbf_info = VARFONT_INFO_P (devfont);
    
    if (vbf_info->width == NULL)
        return n * (vbf_info->max_width + cExtra);

    str_width = 0;
    for (i = 0; i < n; i++) {
        if (mstr [i] < vbf_info->first_char || mstr [i] > vbf_info->last_char)
            str_width += vbf_info->width [vbf_info->def_char - vbf_info->first_char];
        else
            str_width += vbf_info->width [mstr[i] - vbf_info->first_char];
        str_width += cExtra;
    }

    return str_width;
}

static int get_ave_width (LOGFONT* logfont, DEVFONT* devfont)
{
    return VARFONT_INFO_P(devfont)->ave_width;
}

static int get_font_height (LOGFONT* logfont, DEVFONT* devfont)
{
    return VARFONT_INFO_P (devfont)->height;
}

static int get_font_size (LOGFONT* logfont, DEVFONT* devfont, int expect)
{
    return VARFONT_INFO_P (devfont)->height;
}

static int get_font_ascent (LOGFONT* logfont, DEVFONT* devfont)
{
    return VARFONT_INFO_P (devfont)->height - VARFONT_INFO_P (devfont)->descent;
}

static int get_font_descent (LOGFONT* logfont, DEVFONT* devfont)
{
    return VARFONT_INFO_P (devfont)->descent;
}

static size_t char_bitmap_size (LOGFONT* logfont, DEVFONT* devfont, 
                const unsigned char* mchar, int len)
{
    int width;
    VBFINFO* vbf_info = VARFONT_INFO_P (devfont);

    if (vbf_info->width == NULL)
        width = vbf_info->max_width;
    else if (*mchar < vbf_info->first_char || *mchar > vbf_info->last_char)
        width = vbf_info->width [vbf_info->def_char - vbf_info->first_char];
    else
        width = vbf_info->width [*mchar - vbf_info->first_char];   

    return ((width + 7) >> 3) * vbf_info->height;
}

static size_t max_bitmap_size (LOGFONT* logfont, DEVFONT* devfont)
{
    return (((size_t)VARFONT_INFO_P (devfont)->max_width + 7) >> 3) 
                * VARFONT_INFO_P (devfont)->height;
}

static const void* get_char_bitmap (LOGFONT* logfont, DEVFONT* devfont,
            const unsigned char* mchar, int len)
{
    int offset;
    unsigned char eff_char = *mchar;
    VBFINFO* vbf_info = VARFONT_INFO_P (devfont);

    if (*mchar < vbf_info->first_char || *mchar > vbf_info->last_char)
        eff_char = vbf_info->def_char;

    if (vbf_info->offset == NULL)
        offset = (((size_t)vbf_info->max_width + 7) >> 3) * vbf_info->height 
                    * (eff_char - vbf_info->first_char);
    else {
        offset = vbf_info->offset [eff_char - vbf_info->first_char];
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
        if (vbf_info->font_size)
            offset = ArchSwap16 (offset);
#endif
    }

    return vbf_info->bits + offset;
}

/**************************** Global data ************************************/
static FONTOPS var_bitmap_font_ops = {
    get_char_width,
    get_str_width,
    get_ave_width,
    get_max_width,  
    get_font_height,
    get_font_size,
    get_font_ascent,
    get_font_descent,
    char_bitmap_size,
    max_bitmap_size,
    get_char_bitmap,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL
};

/******************* In-core var bitmap fonts ********************************/
static VBFINFO* incore_vbfonts [] = {
#ifdef _INCOREFONT_SANSSERIF
    &vbf_SansSerif11x13,
#endif
#ifdef _INCOREFONT_COURIER
    &vbf_Courier8x13,
#endif
#ifdef _INCOREFONT_SYMBOL
    &vbf_symb12,
#endif
#ifdef _INCOREFONT_VGAS
    &vbf_VGAOEM8x8,
    &vbf_Terminal8x12,
    &vbf_System14x16,
    &vbf_Fixedsys8x15,
#endif
#ifdef _INCOREFONT_HELV
    &vbf_helvR16,
    &vbf_helvR21,
    &vbf_helvR27,
#endif
};

#define NR_VBFONTS  (sizeof (incore_vbfonts) /sizeof (VBFINFO*))

static DEVFONT* incore_vbf_dev_font;

static CHARSETOPS* vbfGetCharsetOps (VBFINFO* vbfont)
{
    int count = 0;
    const char* font_name = vbfont->name;

    while (*font_name) {
        if (*font_name == '-') count ++;
        if (count == 4) break;

        font_name ++;
    }

    if (*font_name != '-') return NULL;
    font_name ++;

    return GetCharsetOps (font_name);
}

BOOL InitIncoreVBFonts (void)
{
    int i;

    if ((incore_vbf_dev_font = malloc (NR_VBFONTS * sizeof (DEVFONT))) == NULL)
        return FALSE;

    for (i = 0; i < NR_VBFONTS; i++) {
        if ((incore_vbf_dev_font [i].charset_ops 
                = vbfGetCharsetOps (incore_vbfonts [i])) == NULL) {
            fprintf (stderr, 
                "GDI: Not supported charset for var-bitmap font %s.\n",
                incore_vbfonts[i]->name);
            free (incore_vbf_dev_font);
            return FALSE;
        }

        strncpy (incore_vbf_dev_font [i].name, incore_vbfonts [i]->name, LEN_DEVFONT_NAME);
        incore_vbf_dev_font [i].name [LEN_DEVFONT_NAME] = '\0';
        incore_vbf_dev_font [i].font_ops = &var_bitmap_font_ops;
        incore_vbf_dev_font [i].data     = incore_vbfonts [i];
    }

    for (i = 0; i < NR_VBFONTS; i++)
        AddSBDevFont (incore_vbf_dev_font + i);

    return TRUE;
}

void TermIncoreVBFonts (void)
{
    free (incore_vbf_dev_font);
    incore_vbf_dev_font = NULL;
}

#ifndef _INCORE_RES

/********************** Load/Unload of var bitmap font ***********************/
static BOOL LoadVarBitmapFont (const char* file, VBFINFO* info)
{
#ifdef HAVE_MMAP
    int fd;
#else
    FILE* fp;
#endif
    char* temp = NULL;
    char version [LEN_VERSION_INFO + 1];
    int len_header, len_offsets, len_widths, len_bits;
    int font_size;

#ifdef HAVE_MMAP
    if ((fd = open (file, O_RDONLY)) < 0)
        return FALSE;

    if (read (fd, version, LEN_VERSION_INFO) == -1)
        goto error;
    version [LEN_VERSION_INFO] = '\0'; 

    if (strcmp (version, VBF_VERSION))
        fprintf (stderr, "Error on loading vbf: %s, version: %s, invalid version.\n", file, version);

    if (read (fd, &len_header, sizeof (int)) == -1)
        goto error;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
    len_header = ArchSwap32 (len_header);
#endif

    if (read (fd, &info->max_width, sizeof (char) * 2) == -1) goto error;
    if (read (fd, &info->height, sizeof (int) * 2) == -1) goto error;
    if (read (fd, &info->first_char, sizeof (char) * 3) == -1) goto error;

    if (lseek (fd, len_header - (4 * sizeof (int)), SEEK_SET) == -1)
        goto error;
    if (read (fd, &len_offsets, sizeof (int)) == -1
            || read (fd, &len_widths, sizeof (int)) == -1
            || read (fd, &len_bits, sizeof (int)) == -1
            || read (fd, &font_size, sizeof (int)) == -1)
        goto error;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
    len_offsets = ArchSwap32 (len_offsets);
    len_widths = ArchSwap32 (len_widths);
    len_bits = ArchSwap32 (len_bits);
    font_size = ArchSwap32 (font_size);
#endif

    if ((temp = mmap (NULL, font_size, PROT_READ, MAP_SHARED, 
            fd, 0)) == MAP_FAILED)
        goto error;

    temp += len_header;
    close (fd);
#else
    // Open font file and read information of font.
    if (!(fp = fopen (file, "rb")))
        return FALSE;

    if (fread (version, sizeof (char), LEN_VERSION_INFO, fp) < LEN_VERSION_INFO)
        goto error;
    version [LEN_VERSION_INFO] = '\0'; 

    if (strcmp (version, VBF_VERSION))
        fprintf (stderr, "Error on loading vbf: %s, version: %s, invalid version.\n", file, version);

    if (fread (&len_header, sizeof (int), 1, fp) < 1)
        goto error;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
    len_header = ArchSwap32 (len_header);
#endif

    if (fread (&info->max_width, sizeof (char), 2, fp) < 2) goto error;
    if (fread (&info->height, sizeof (int), 2, fp) < 2) goto error;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
    info->height = ArchSwap32 (info->height);
    info->descent = ArchSwap32 (info->descent);
#endif
    if (fread (&info->first_char, sizeof (char), 3, fp) < 3) goto error;

    if (fseek (fp, len_header - (4*sizeof (int)), SEEK_SET) != 0)
        goto error;

    if (fread (&len_offsets, sizeof (int), 1, fp) < 1
            || fread (&len_widths, sizeof (int), 1, fp) < 1
            || fread (&len_bits, sizeof (int), 1, fp) < 1
            || fread (&font_size, sizeof (int), 1, fp) < 1)
        goto error;
#if MGUI_BYTEORDER == MGUI_BIG_ENDIAN
    len_offsets = ArchSwap32 (len_offsets);
    len_widths = ArchSwap32 (len_widths);
    len_bits = ArchSwap32 (len_bits);
    font_size = ArchSwap32 (font_size);
#endif

    // Allocate memory for font data.
    font_size -= len_header;
    if ((temp = (char *)malloc (font_size)) == NULL)
        goto error;

    if (fseek (fp, len_header, SEEK_SET) != 0)
        goto error;

    if (fread (temp, sizeof (char), font_size, fp) < font_size)
        goto error;

    fclose (fp);
#endif
    info->name = temp;
    info->offset = (unsigned short*) (temp + LEN_DEVFONT_NAME + 1);
    info->width = (unsigned char*) (temp + LEN_DEVFONT_NAME + 1 + len_offsets);
    info->bits = (unsigned char*) (temp + LEN_DEVFONT_NAME + 1 + len_offsets + len_widths);
    info->font_size = font_size;

#if 0
    fprintf (stderr, "VBF: %s-%dx%d-%d (%d~%d:%d).\n", 
            info->name, info->max_width, info->height, info->descent,
            info->first_char, info->last_char, info->def_char);
#endif

    return TRUE;

error:
#ifdef HAVE_MMAP
    if (temp)
        munmap (temp, font_size);
    close (fd);
#else
    free (temp);
    fclose (fp);
#endif
    
    return FALSE;
}

static void UnloadVarBitmapFont (VBFINFO* info)
{
#ifdef HAVE_MMAP
    if (info->name)
        munmap ((void*)(info->name), info->font_size);
#else
    free ((void*)info->name);
#endif
}

/******************** Init/Term of var bitmap font in file *******************/
static int nr_fonts;
static VBFINFO* file_vbf_infos;
static DEVFONT* file_vbf_dev_fonts;

#define SECTION_NAME    "varbitmapfonts"

BOOL InitVarBitmapFonts (void)
{
    int i;
    char font_name [LEN_DEVFONT_NAME + 1];

    if (GetMgEtcIntValue (SECTION_NAME, "font_number", 
                           &nr_fonts) < 0 )
        return FALSE;
    if ( nr_fonts < 1) return TRUE;

    file_vbf_infos = calloc (nr_fonts, sizeof (VBFINFO));
    file_vbf_dev_fonts = calloc (nr_fonts, sizeof (DEVFONT));
    if (file_vbf_infos == NULL || file_vbf_dev_fonts == NULL) {
        free (file_vbf_infos);
        free (file_vbf_dev_fonts);
        return FALSE;
    }

    for (i = 0; i < nr_fonts; i++)
        file_vbf_infos [i].name = NULL;

    for (i = 0; i < nr_fonts; i++) {
        char key [11];
        char charset [LEN_FONT_NAME + 1];
        char file [MAX_PATH + 1];
        CHARSETOPS* charset_ops;

        sprintf (key, "name%d", i);
        if (GetMgEtcValue (SECTION_NAME, key, 
                           font_name, LEN_DEVFONT_NAME) < 0 )
            goto error_load;
        if (!fontGetCharsetFromName (font_name, charset)) {
            fprintf (stderr, "GDI: Invalid font name (charset): %s.\n", 
                    font_name);
            goto error_load;
        }

        if ((charset_ops = GetCharsetOps (charset)) == NULL) {
            fprintf (stderr, "GDI: Not supported charset: %s.\n", charset);
            goto error_load;
        }

        sprintf (key, "fontfile%d", i);
        if (GetMgEtcValue (SECTION_NAME, key, 
                           file, MAX_PATH) < 0)
            goto error_load;

        if (!LoadVarBitmapFont (file, file_vbf_infos + i))
            goto error_load;

        strncpy (file_vbf_dev_fonts[i].name, font_name, LEN_DEVFONT_NAME);
        file_vbf_dev_fonts[i].name [LEN_DEVFONT_NAME] = '\0';
        file_vbf_dev_fonts[i].font_ops = &var_bitmap_font_ops;
        file_vbf_dev_fonts[i].charset_ops = charset_ops;
        file_vbf_dev_fonts[i].data = file_vbf_infos + i;
#if 0
        fprintf (stderr, "GDI: VBFDevFont %i: %s.\n", i, file_vbf_dev_fonts[i].name);
#endif
    }

    for (i = 0; i < nr_fonts; i++) {
        if (file_vbf_dev_fonts [i].charset_ops->bytes_maxlen_char > 1)
            AddMBDevFont (file_vbf_dev_fonts + i);
        else
            AddSBDevFont (file_vbf_dev_fonts + i);
    }

    return TRUE;

error_load:
    fprintf (stderr, "GDI: Error in loading vbf fonts!\n");
    for (i = 0; i < nr_fonts; i++)
        UnloadVarBitmapFont (file_vbf_infos + i);
    
    free (file_vbf_infos);
    free (file_vbf_dev_fonts);
    file_vbf_infos = NULL;
    file_vbf_dev_fonts = NULL;
    return FALSE;
}

void TermVarBitmapFonts (void)
{
    int i;

    for (i = 0; i < nr_fonts; i++)
        UnloadVarBitmapFont (file_vbf_infos + i);
    
    free (file_vbf_infos);
    free (file_vbf_dev_fonts);

    file_vbf_infos = NULL;
    file_vbf_dev_fonts = NULL;
}

#endif /* _INCORE_RES */

#endif /* _VBF_SUPPORT */

⌨️ 快捷键说明

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