Chinaunix首页 | 论坛 | 博客
  • 博客访问: 483053
  • 博文数量: 120
  • 博客积分: 3052
  • 博客等级: 中校
  • 技术积分: 1755
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-01 09:43
文章分类

全部博文(120)

文章存档

2011年(20)

2010年(3)

2009年(52)

2008年(45)

我的朋友

分类: C/C++

2008-04-09 15:56:50

昨天突然有个想法,就是记得见过有些人在论坛上的签名是这样一种格式:
用一个汉字用为“背景”,用另一个汉字作为“前景”,然后显示出来。
既然是写程序嘛,应该不是很难,今天就写了这样一个东西。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <iconv.h>

FILE* cclibfp;

void read_cclib( unsigned char high, unsigned char low, unsigned char *buf )
{
        long p;
        high = high - 0xa0; /* change high byte to domain_code */
        low = low - 0xa0; /* change low byte */
        /* if(high >= 15){ */
        /* high -= 6; */
        /* } /\* some code compress the charset at 10-15 domain *\/ */
        /* p = ((long)((high - 1) * 94 + low -1)) * 32 - 16; /* get the wrong position */
        p = ((long)((high - 1) * 94 + low + 16)) * 32 + 16; /* get the position */
        fseek(cclibfp, p, SEEK_SET);
        fread(buf, 32, 1, cclibfp);
}
void itoa(int value, char* buf, int base){

        int i = strlen(buf);
        for(; value || i ;){
                buf[--i] = "0123456789abcdef"[value % base];
                value /= base;
        }
}

int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
{
        iconv_t cd;
        int rc;
        char **pin = &inbuf;
        char **pout = &outbuf;

        cd = iconv_open(to_charset,from_charset);
        if (cd==0) return -1;
        memset(outbuf,0,outlen);
        if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
        iconv_close(cd);
        return 0;
}
//UNICODE码转为GB2312码

int u2g(char *inbuf,int inlen,char *outbuf,int outlen)
{
        return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}
//GB2312码转为UNICODE码

int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
        return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}


int chinese_magic(char* aim, char* back, char* fore)
{

        char* in_utf8 = aim;
        char chn[2];

        u2g(in_utf8,strlen(in_utf8),chn,2);
        unsigned char buf[32];
        /* char string[5]; */
        /* string[4] = '\0'; */


        long i16;
        int i, j;

        if((cclibfp = fopen("font.gz","rb")) == NULL){
                printf("\n 不能打开字库文件 font.ft \n");
                exit(1);
        }

        read_cclib(chn[0],chn[1],buf);
        printf("\n\n\n");

        /* i = 12; */

        /* printf("----------------\n"); */
        /* itoa(i, string, 16); */
        /* printf("%d is %s here\n", i, string); */
        /* printf("----------------\n"); */

        for(i = 0; i < 32; i += 2){
                i16 = buf[i]<<8 | buf[i+1];
                /* itoa(i16, string, 16); */
                /* for(j = strlen(string); j < 4; j++){ */
                /* printf("0"); */
                /* } */
                /* printf("%s", string); */
                for(j = 0; j < 16; j++){
                        if(i16 & (0x8000>>j)){
                                printf("%s", fore);
                        } else {
                                printf("%s", back);
                        }
                }
             printf("\n");
        }
        fclose(cclibfp);
        return 0;
}


int main()
{
        return chinese_magic("好","一","李");
}


效果如下:

用到的字体文件:
文件:font.gz
大小:752KB
下载:下载

总结一下:

1,大部分代码是参考网上的,但是:
    1)网上给的找汉字在字体表中位置的办法,



在我的的系统(LFS 6.2.5) 上都是错误的,参见代码中的注释(wrong position 一行):第一个表现是能看出来显示的是一个字的下半部分和另一个字的上半部分,于是我给它加 16(一个字的一半)。但是这时字还是不对的。于是对字作手脚,虽然发现汉字在表里是按字典序排列的,于是用二分法,很快找到了正确的地址。
2) linux gcc 下没有找到 itoa() 这个函数,只好上网去找,在
~slowe/cpp/itoa.html
找到了自己写的实现方法,但是到我这还是不好用,于是我自己又改了一个可以用的。可以比较一下我的 itoa() 和 上面的链接里的 my_itoa()。
3) 我的系统都是用的 locale=zh_CN.utf8,但是字库里是 gbk 的,要做一个编码的转换,iconv() 这个系统调用我不太会用,于是参考
 http://blog.csdn.net/kunp/archive/2005/02/05/281469.aspx
用了他的两个函数,可以转换了。


阅读(1212) | 评论(0) | 转发(0) |
0

上一篇:java 的兼容性

下一篇:疯话

给主人留下些什么吧!~~