2009年10月31日 星期六

點陣字

 
以前的 DOS,或仿 DOS 環境,可以在 BIOS 的 F000:FA6E 取得
ASCII bitmap,在 WinXP上可以 LoadLibrary("ntdll.dll"),
用裡頭的 ZwOpenSection 與 ZwMapViewOfSection 取得此
section 的映射,但此法在 Vista 下不能用。

DOS 倚天中文下則由 B800:0000 開始取 (Big5, color) pair,
再對到 16 or 24 號字形檔 (.15 or .24x) 取出 bitmap。
Windows 上有許多 true type font,這些向量字不存在 bitmap,
只能用 GetGlyphOutline 或 TextOut 去轉出點陣圖。

現今由於字型檔繁多,較便捷的做法是用 Win32 API 指定字型檔與字樣,
將字畫到 canvas 上,再把座標數出來,譬如:

#include <windows.h>
#include <stdio.h>

//輸出文字 s, 字體=face, 字形大小=size

void show_text (HDC hdc, wchar_t* s, int size=16, wchar_t* face= L"細明體")
{
    int  x,y, len = wcslen(s);  
    HFONT   font    = CreateFont (size,0,0,0,400,0,0,0,0,0,0,0,0,face);
    HGDIOBJ oldFont = SelectObject (hdc, font);
    SetBkColor (hdc,RGB(255,255,255));
    SetTextColor (hdc, 0);                 //黑色
    TextOut (hdc, 0,0, s, len);

    for (y=0; y<size; y++, puts(""))
        for (x=0; x<len*size; x++)
            printf (GetPixel (hdc,x,y)? "  ":"█");
    SelectObject (hdc, oldFont);     
    DeleteObject (font);   
}

int main ()
{
    SetConsoleTitle (L"Conso");
    HDC hdc = GetDC (FindWindow (0, L"Conso"));

    show_text (hdc, L"選擇");

    DeleteDC (hdc);
    return system ("pause");
}
輸出:
█      ████  ████        ██
      ██  █    █  █    █        █      █████████
            ████  ████        █      █    █  █    █
  █        █        █          █████  █████████
    ██    █    █  █    █        █              █
              ███    ███        █        ███████
                                      █              █
      █          █    █            █  █  █████████
  ████    ████████        ██        █      █
      █          █    █        ███            █  █
      █    ██████████  █  █        ███████
      █          █    █            █              █
      ██    ██        ██        █      █████████
  ██    ██                    ███              █
  █          █████████    █                █



底下是另一種 ttf 轉點陣的寫法,需用 Unicode mode 編譯:

//將文字 ch 的點陣圖存入 buf 中, 點陣圖大小記錄於 bytes 中傳回
//字體=face, 字形大小=size, [此函式在 Unicode 模式下測試正常]

int text_bitmap (HDC hdc, UINT ch, char* buf, GLYPHMETRICS& gm,
                int size=16, wchar_t* face= L"細明體")
{
    MAT2    mat     = {{0,1},{0,0},{0,0},{0,1}};    //轉置矩陣
    HFONT   font    = CreateFont (size,0,0,0,400,0,0,0,0,0,0,0,0,face);
    HGDIOBJ oldFont = SelectObject (hdc, font);
    int bytes = GetGlyphOutline (hdc, ch, 1, &gm, 0, 0, &mat);
    if (bytes != GDI_ERROR)
        GetGlyphOutline (hdc, ch, 1, &gm, bytes, buf, &mat);
    SelectObject (hdc, oldFont);     
    DeleteObject (font);   
    return bytes;
}

int main ()
{
    SetConsoleTitle (L"Conso");
    HDC hdc = GetDC (FindWindow (0, L"Conso"));

    GLYPHMETRICS gm;
    char a[512];
    int sz = text_bitmap (hdc, L'選', a, gm);
    int nx = sz/gm.gmBlackBoxY;     //每行占幾Byte, gmBlackBoxX=位元寬度
                                    //亦即 ((gm.gmBlackBoxX+31)>>5)<<2   
    for (int x,j,i=0; i<sz; puts(""))
        for (x=0; x<nx; x++, i++)
            for (j=1<<8; j; j>>=1)
                printf (a[i]&j? "█":"  ");
   
    DeleteDC (hdc);
    return system ("pause");
}
輸出:
█      █████  ████
      ██  █    ██  █    █
            █████  ████
██        █          █
    ██    █    ██  █    █
              ████    ███

      █          ██    █
█████    █████████
      █          ██    █
      █    ███████████
      █          ██    █
      ██    ██          ██
███    ██
██          ██████████

沒有留言:

張貼留言