2011年1月1日 星期六

bdf點陣字

bdf font是文字格式的點陣字型
我是將unifont(unicode bdf font),掃成我定義的bitmap格式

   1               1               1     1        1    1     1
    1        1     1               1     1        1   1      1
 1111111 1111      11111111111     1     1       1   11111  1
         1        1     1          1  1111111   1  1 1   1 1  1
  1   1  1        1     1          11    1  1   111  1   1 111
   1 1   1       1      1        1 1 1   1  1    1   11111  1
11111111 111111    1111111111    1 1     1  1   1  1 1   1 1  1
    1    1  1      1    1        1 1     1  1   1111 1   1 1111
    1    1  1      1    1       1  1 1111111111    1 11111    1
 1111111 1  1      1    1          1     1             1
    1    1  1   111111111111111    1    1 1     111111111111111
  1 1 1  1  1           1          1    1 1          1 1 1
 1  1  1 1  1           1          1   1   1        1  1  1
1   1   1   1           1          1   1   1      11   1   11
  1 1   1   1           1          1  1     1   11     1     11
   1   1    1           1          1 1       11        1

bool loadbdf(const char *path, Bitmap *chars)
{
    FILE *file = fopen(path, "r");
    if(!file) {
        return false;
    }

    char text[128];
    while(fscanf(file, "%s", text) != EOF) {
        char *pch = strstr(text, "ENCODING");
        if(pch == text) {
            unsigned int code = 0;
            fscanf(file, "%d", &code);
            createbitmap(file, chars+code);
        }
    }
    fclose(file);

    return true;
}
bool createbitmap(FILE *file, Bitmap *bitmap)
{
    char text[128];
    unsigned int i=0;
    unsigned int j=0;
    int m=0;
    int n=0;
    while(fscanf(file, "%s", text) != EOF) {
        char *pch = strstr(text, "DWIDTH");
        if(pch == text) {
            unsigned int i=0;
            fscanf(file, "%u", &i);
            bitmap->width += i;
            continue;
        }
        pch = strstr(text, "BBX");
        if(pch == text) {
            unsigned int i=0;
            unsigned int j=0;
            int m=0;
            int n=0;
            fscanf(file, "%u %u %d %d", &i, &j, &m, &n);
            bitmap->width = bitmap->width - m;
            bitmap->height = j;
            bitmap->x = m;
            bitmap->y = n;
            bitmap->pitch = i/8;
            if(i % 8 != 0) {
                bitmap->pitch += 1;
            }
            continue;
        }
        pch = strstr(text, "BITMAP");
        if(pch == text) {
            int size = bitmap->pitch * bitmap->height;
            unsigned char *data = calloc(size, sizeof(unsigned char));
            int k = 0;
            for(int p=0; p<bitmap->height; p++) {
                unsigned int value;
                fscanf(file, "%x", &value);
                for(int q=bitmap->pitch -1; q>=0; q--) {
                    data[k] = (value>>(q*8)) & 0x00FF;
                    k++;
                }
            }
            bitmap->data = data;
            return true;
        }
    }
    return false;
}

完整程式
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

typedef struct Bitmap_ {
    int             x;
    int             y;
    unsigned int    width;
    unsigned int    height;
    unsigned int    pitch;
    unsigned char*  data;

} Bitmap;

void printtext(Bitmap *bitmap)
{
    for(int j=0; j<bitmap->height; j++) {
        for(int i=0; i<bitmap->pitch; i++) {
            for(int k=7; k>=0; k--) {
                if(7-k+i*8 == bitmap->width)
                    break;
                printf("%c", (bitmap->data[i+j*bitmap->pitch] & 0x1<<k)?'1':' ');
            }
        }
        printf("\n");
    }
}

void combinetext(Bitmap *bitmap, Bitmap *font)
{
    int x1 = bitmap->x;
    int y1 = bitmap->y;
    unsigned int width1 = bitmap->width;
    unsigned int height1 = bitmap->height;
    unsigned int pitch1 = bitmap->pitch;
    unsigned char* data1 = bitmap->data;

    int x2 = x1 + width1 + font->x;
    int y2 = font->y;
    unsigned int width2 = font->width;
    unsigned int height2 = font->height;
    unsigned int pitch2 = font->pitch;
    unsigned char* data2 = font->data;

    int x3 = x1;
    if(x1 > x2) {
        x3 = x2;
    }
    unsigned int width3 = width1 + font->x + width2;
    int y3 = y1;
    unsigned int height3 = height1;
    if(y1 > y2) {
        y3 = y2;
        height3 += (y1 - y2);
    }
    if(y1+height1 < y2+height2) {
        height3 += (y2+height2) - (y1+height1);
    }
    unsigned int pitch3 = width3/8;
    if(width3 % 8 != 0) {
        pitch3 += 1;
    }

    int size3 = pitch3 * height3;
    unsigned char *data3 = calloc(size3, sizeof(unsigned char));
    int shiftX1 = 0;
    int shiftY1 = (height3+y3) - (height1+y1);
    for(int j=0; j<height1; j++) {
        int nj = j+shiftY1;
        for(int i=0; i<pitch1; i++) {
            int n = shiftX1/8+i+nj*pitch3;
            unsigned char data = data1[i+j*pitch1];
            int shift = shiftX1%8;
            if(shift == 0) {
                data3[n] |= data;
            } else {
                data3[n] |= (0x7f & data>>shift);
                data3[n+1] |= data<<(8-shift);
            }
        }
    }
    int shiftX2 = x2-x3;
    int shiftY2 = (height3+y3) - (height2+y2);
    for(int j=0; j<height2; j++) {
        int nj = j+shiftY2;
        for(int i=0; i<pitch2; i++) {
            int n = shiftX2/8+i+nj*pitch3;
            unsigned char data = data2[i+j*pitch2];
            int shift = shiftX2%8;
            if(shift == 0) {
                data3[n] |= data;
            } else {
                data3[n] |= (0x7f & data>>shift);
                data3[n+1] |= data<<(8-shift);
            }
        }
    }
    free(bitmap->data);

    bitmap->x = x3;
    bitmap->y = y3;
    bitmap->width = width3;
    bitmap->height = height3;
    bitmap->pitch = pitch3;
    bitmap->data = data3;
}

bool createbitmap(FILE *file, Bitmap *bitmap)
{
    char text[128];
    unsigned int i=0;
    unsigned int j=0;
    int m=0;
    int n=0;
    while(fscanf(file, "%s", text) != EOF) {
        char *pch = strstr(text, "DWIDTH");
        if(pch == text) {
            unsigned int i=0;
            fscanf(file, "%u", &i);
            bitmap->width += i;
            continue;
        }
        pch = strstr(text, "BBX");
        if(pch == text) {
            unsigned int i=0;
            unsigned int j=0;
            int m=0;
            int n=0;
            fscanf(file, "%u %u %d %d", &i, &j, &m, &n);
            bitmap->width = bitmap->width - m;
            bitmap->height = j;
            bitmap->x = m;
            bitmap->y = n;
            bitmap->pitch = i/8;
            if(i % 8 != 0) {
                bitmap->pitch += 1;
            }
            continue;
        }
        pch = strstr(text, "BITMAP");
        if(pch == text) {
            int size = bitmap->pitch * bitmap->height;
            unsigned char *data = calloc(size, sizeof(unsigned char));
            int k = 0;
            for(int p=0; p<bitmap->height; p++) {
                unsigned int value;
                fscanf(file, "%x", &value);
                for(int q=bitmap->pitch -1; q>=0; q--) {
                    data[k] = (value>>(q*8)) & 0x00FF;
                    k++;
                }
            }
            bitmap->data = data;
            return true;
        }
    }
    return false;
}

bool loadbdf(const char *path, Bitmap *chars)
{
    FILE *file = fopen(path, "r");
    if(!file) {
        return false;
    }

    char text[128];
    while(fscanf(file, "%s", text) != EOF) {
        char *pch = strstr(text, "ENCODING");
        if(pch == text) {
            unsigned int code = 0;
            fscanf(file, "%d", &code);
            createbitmap(file, chars+code);
        }
    }
    fclose(file);

    return true;
}

bool rasters(const wchar_t texts[], Bitmap *bitmap, Bitmap *chars)
{
    if(texts[0] == '\0') {
        return true;
    }

    for(int i=0; i<wcslen(texts); i++) {
        unsigned int ucode = texts[i];
        combinetext(bitmap, chars+ucode);
    }

    return true;
}

int main(int argc, char *argv[])
{
    Bitmap *chars = calloc(65535, sizeof(Bitmap));
    if(loadbdf("font.bdf", chars)) {
        Bitmap *bitmap = calloc(1, sizeof(Bitmap));
        if(rasters(L"新年快樂", bitmap, chars)) {
            printtext(bitmap);
        }
    } else {
        printf("load error");
    }
    return EXIT_SUCCESS;
}

沒有留言: