如何根据字符(某种编码的编码值)取得字符的点阵数据

几罗星人 2016-05-11 10:12:35
在CSDN那么多年,第一次遇到不知道该发往哪里的帖子。这是一个刨根问底的帖子,各位对此有深刻了解的人尽管说吧。

问题的重点应该不是如何取得点阵数据的问题。稍微想一下可以想出一个办法:TextOut之类的函数输出字符到一个DC上,然后取这个DC上的像素值。虽然没实际做过,但是按道理是可以实现通过字符编码(在你用TextOut输出一个字符的时候,参数指定的就是字符的编码或字符编码的地址)取得字符的点阵数据。

好奇的是,我们在Windows系统上安装TTF等字体,我们写代码时指定以某种编码描述的一个字符的编码值,指明字体和其他的一些特征,就可以调用API显示出这个字符,那么Windows是如何根据字符的编码值,到什么地方找出字符的点阵/矢量数据,然后渲染和显示的呢?

是TTF这类字体文件就包含了字符的点阵/矢量数据吗?如果是对于不同编码,字体文件是如何处理的?
...全文
238 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-05-18
  • 打赏
  • 举报
回复
引用 3 楼 JiLuoXingRen 的回复:
大致了解了。不过最初的初衷是做一个点阵式的字模库,供汇编使用,我对GB2312编码的所有字符用一个软件批量取模,但是发现一些字符取出来的形态不对,例如字符1,取出来的字模点阵用汇编一画是2,就是这样的情况,想知道为什么会这样,另外就是自己有没有可能做一个取模软件,当然暂时没考虑真的自己做一个取模软件
仅供参考:
#pragma comment(lib,"gdi32")
#include <windows.h>
#include <stdio.h>

int main() {
    const DWORD uWidth = 18 + 17 * 256, uHeight = 18 + 17 * 128;

    PBITMAPINFO pbmi = (PBITMAPINFO) LocalAlloc (LPTR, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2);
    pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = uWidth;
    pbmi->bmiHeader.biHeight = uHeight;
    pbmi->bmiHeader.biPlanes = 1;
    pbmi->bmiHeader.biBitCount = 1;
    pbmi->bmiHeader.biSizeImage = ((uWidth + 31) & ~31) / 8 * uHeight;
    pbmi->bmiColors[0].rgbBlue = 0;
    pbmi->bmiColors[0].rgbGreen = 0;
    pbmi->bmiColors[0].rgbRed = 0;
    pbmi->bmiColors[1].rgbBlue = 255;
    pbmi->bmiColors[1].rgbGreen = 255;
    pbmi->bmiColors[1].rgbRed = 255;

    HDC hDC = CreateCompatibleDC (0);
    void * pvBits;
    HBITMAP hBitmap = CreateDIBSection (hDC, pbmi, 0, &pvBits, NULL, 0);
    SelectObject (hDC, hBitmap);
    HFONT hFont = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "宋体");
//  HFONT hFont = CreateFont (16, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0, 0, "宋体");
    SelectObject (hDC, hFont);
    BitBlt (hDC, 0, 0, uWidth, uHeight, NULL, 0, 0, WHITENESS);

    char c[4];
    int i, j;
    for (i = 128; i < 256; i++) {
        sprintf (c, "%02X", i);
        TextOut (hDC, 1, (i - 127) * 17 + 1, c, 2);
    }
    for (j = 0; j < 256; j++) {
        sprintf (c, "%02X", j);
        TextOut (hDC, (j + 1)* 17 + 1, 1, c, 2);
    }
    for (i = 128; i < 256; i++) {
        for (j = 0; j < 256; j++) {
            c[0] = (char) i;
            c[1] = (char) j;
            TextOut (hDC, (j + 1) * 17 + 1, (i - 127) * 17 + 1, c, 2);
        }
    }
    for (i = 0; i < 130; i++) {
        MoveToEx (hDC, 0, i * 17, NULL);
        LineTo (hDC, uWidth, i * 17);
    }
    for (j = 0; j < 258; j++) {
        MoveToEx (hDC, j * 17, 0, NULL);
        LineTo (hDC, j * 17, uHeight);
    }

    BITMAPFILEHEADER bmfh;
    bmfh.bfType = *(PWORD) "BM";
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2;
    bmfh.bfSize = bmfh.bfOffBits + pbmi->bmiHeader.biSizeImage;

    HANDLE hFile = CreateFile ("goal.bmp", GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwWritten;
        WriteFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), &dwWritten, NULL);
        WriteFile (hFile, pbmi, sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * 2, &dwWritten, NULL);
        WriteFile (hFile, pvBits, pbmi->bmiHeader.biSizeImage, &dwWritten, NULL);

        CloseHandle (hFile);
    }

    DeleteObject (hFont);
    DeleteObject (hBitmap);
    DeleteDC (hDC);
    LocalFree (pbmi);

    return 0;
}
几罗星人 2016-05-17
  • 打赏
  • 举报
回复
大致了解了。不过最初的初衷是做一个点阵式的字模库,供汇编使用,我对GB2312编码的所有字符用一个软件批量取模,但是发现一些字符取出来的形态不对,例如字符1,取出来的字模点阵用汇编一画是2,就是这样的情况,想知道为什么会这样,另外就是自己有没有可能做一个取模软件,当然暂时没考虑真的自己做一个取模软件
dustpg 2016-05-11
  • 打赏
  • 举报
回复
统一为Unicode(UCS-4)编码,Windows上面一个稍微低级的一个字体API库DirectWrite可以充分地利用这些矢量字体。 字体通过矢量模型描述,freetype之类的库就是可以光栅化这些矢量数据到像素。 而DirectWrite获取的数据是矢量模型方便3D图形接口(D3D)显示

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧