Annotation of nono/wx/wxtextpanel.cpp, revision 1.1.1.3

1.1       root        1: //
                      2: // nono
1.1.1.3 ! root        3: // Copyright (C) 2020 nono project
        !             4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "wxtextpanel.h"
1.1.1.3 ! root        8: #include "wxcolor.h"
1.1       root        9: #include "bitrev.h"
1.1.1.3 ! root       10: #include "cgrom.h"
        !            11: #include "kaname12.h"
1.1       root       12: 
                     13: // wxOSX(-3.0.2) の wxLIGHT_GREY は値が(色も透明度も)正しくない。
                     14: // wxGTK の wxLIGHT_GREY は 0xffd3d3d3 だけどこれを Mac で見ると
                     15: // (Mac の統一感としては) 暗く見えるので色コード自体を変える。
                     16: #if defined(__WXOSX__)
                     17: #define LIGHT_GREY     wxColour(0xffe0e0e0)
                     18: #else
                     19: #define LIGHT_GREY     *wxLIGHT_GREY
                     20: #endif
                     21: 
                     22: //
                     23: // テキストフォントを管理するクラス
                     24: //
                     25: 
1.1.1.3 ! root       26: static struct fontinfo {
1.1       root       27:        int width;
                     28:        int height;
                     29: } fontinfo[] = {
                     30:        // 順序はヘッダの FONT_* 識別子の順と揃えること
                     31:        {  6, 12 },
                     32:        {  8, 16 },
                     33: };
                     34: static_assert(countof(fontinfo) == FONT_MAX, "");
                     35: 
                     36: // コンストラクタ
                     37: WXTextPanel::WXTextPanel(wxWindow *parent)
                     38:        : inherited(parent, wxID_ANY)
                     39: {
                     40:        UpdateFont(global_fontsize);
                     41: 
                     42:        // デフォルト色
                     43:        SetTextColor(*wxBLACK, LIGHT_GREY, wxColour(0x50, 0x50, 0x50));
                     44: }
                     45: 
                     46: // デストラクタ
                     47: WXTextPanel::~WXTextPanel()
                     48: {
                     49:        FreeFont(fontsize);
                     50: }
                     51: 
                     52: // フォント関連の内部情報をよしなに更新する
                     53: void
                     54: WXTextPanel::UpdateFont(fontsize_t new_fontsize)
                     55: {
                     56:        assert(fontsize != new_fontsize);
                     57: 
                     58:        // フォントデータを更新
                     59:        FreeFont(fontsize);
                     60:        AllocFont(new_fontsize);
                     61: 
                     62:        // 内部変数を更新
                     63:        fontsize = new_fontsize;
                     64:        font_width  = fontinfo[fontsize].width;
                     65:        font_height = fontinfo[fontsize].height;
                     66:        ascii_glyph = ascii_glyph_table[fontsize];
                     67:        bold_glyph = bold_glyph_table[fontsize];
                     68: }
                     69: 
                     70: // 必要ならフォントを用意する
                     71: /*static*/ void
                     72: WXTextPanel::AllocFont(fontsize_t fontsize)
                     73: {
                     74:        const uint8 *base;
                     75: 
                     76:        std::unique_lock<std::mutex> lock(global_font_mutex);
                     77:        if (font_refcnt[fontsize]++ != 0) {
                     78:                return;
                     79:        }
                     80: 
1.1.1.3 ! root       81:        // 6x12, 8x16 半角は X68030 CGROM にあるのでそれを使う
1.1       root       82:        switch (fontsize) {
                     83:         case FONT_6x12:
1.1.1.3 ! root       84:                base = BuiltinCGROM::Get6x12();
1.1       root       85:                break;
                     86:         case FONT_8x16:
1.1.1.3 ! root       87:                base = BuiltinCGROM::Get8x16();
1.1       root       88:                break;
                     89:         default:
1.1.1.2   root       90:                assertmsg(0, "fontsize=%d", fontsize);
1.1       root       91:        }
                     92: 
                     93:        // フォントの行ストライド[byte]
                     94:        int font_width = fontinfo[fontsize].width;
                     95:        int font_height = fontinfo[fontsize].height;
                     96:        int font_stride = (font_width + 7) / 8;
                     97:        int bytes = font_stride * font_height;
1.1.1.3 ! root       98:        std::vector<char> buf(bytes);
1.1       root       99: 
                    100:        wxBitmap **ascii_glyph = ascii_glyph_table[fontsize];
                    101:        wxBitmap **bold_glyph = bold_glyph_table[fontsize];
                    102:        // ASCII というか半角というかは通常 0x7f までだが
                    103:        // X680x0 の CGROM の 0x80, 0x81, 0x82 には '\\', '~', '|' が
                    104:        // 収納されているのでここまで含めてデータを作っておく。
                    105:        for (int ch = 0; ch < countof(ascii_glyph_table[0]); ch++) {
                    106:                const uint8 *ptr = base + ch * bytes;
                    107: 
                    108:                // wxBitmap は XBM 形式で 1bpp ビットマップを受け取る。
                    109:                // XBM は MSB が右なので、ビット左右を反転する
                    110:                for (int i = 0; i < bytes; i++) {
                    111:                        uint8 src = ptr[i];
                    112:                        buf[i] = bitrev(src);
                    113:                }
                    114:                // その XBM データから1文字分のビットマップオブジェクトを作成
1.1.1.3 ! root      115:                ascii_glyph[ch] = new wxBitmap(&buf[0], font_width, font_height, 1);
1.1       root      116: 
                    117:                // 続いてボールドに加工
                    118:                for (int i = 0; i < bytes; i++) {
                    119:                        // XBM 形式は MSB が右なので左シフトすると一般的なボールド。
                    120:                        buf[i] |= ((uint8)buf[i] << 1);
                    121:                }
1.1.1.3 ! root      122:                bold_glyph[ch] = new wxBitmap(&buf[0], font_width, font_height, 1);
1.1       root      123:        }
                    124: }
                    125: 
                    126: // 最後の一人ならフォントを解放する
                    127: /*static*/ void
                    128: WXTextPanel::FreeFont(fontsize_t fontsize)
                    129: {
                    130:        std::unique_lock<std::mutex> lock(global_font_mutex);
                    131: 
                    132:        if (fontsize < 0 || fontsize >= FONT_MAX) {
                    133:                return;
                    134:        }
                    135:        if (--font_refcnt[fontsize] != 0) {
                    136:                return;
                    137:        }
                    138: 
                    139:        wxBitmap **ascii_glyph = ascii_glyph_table[fontsize];
                    140:        wxBitmap **bold_glyph = bold_glyph_table[fontsize];
                    141:        for (int i = 0; i < countof(ascii_glyph_table[0]); i++) {
                    142:                if (ascii_glyph[i]) {
                    143:                        delete ascii_glyph[i];
                    144:                        ascii_glyph[i] = NULL;
                    145:                }
                    146:                if (bold_glyph[i]) {
                    147:                        delete bold_glyph[i];
                    148:                        bold_glyph[i] = NULL;
                    149:                }
                    150:        }
                    151: }
                    152: 
                    153: // テキスト色を指定する
                    154: void
                    155: WXTextPanel::SetTextColor(const wxColour& fg, const wxColour& bg,
                    156:        const wxColour& dc)
                    157: {
                    158:        text_fgcolor = fg;
                    159:        text_bgcolor = bg;
                    160:        text_disable_color = dc;
                    161: }
                    162: 
                    163: // (px, py) を左上とする座標から Shift_JIS 文字列を属性 attr で描画する。
                    164: // 文字列中で属性を変えることはできない。
                    165: // キャンバスをはみ出すかどうかについてはこちらでは関知しない。
                    166: // フォントサイズは現行のフォント。
                    167: void
                    168: WXTextPanel::DrawStringSJIS(wxDC& dc, int px, int py, const char *sjis,
                    169:        uint attr)
                    170: {
                    171:        const uint8 *s;
                    172: 
                    173:        for (s = (const uint8 *)sjis; *s; ) {
1.1.1.3 ! root      174:                if (__predict_true(*s < 0x80)) {
        !           175:                        // ASCII
1.1       root      176:                        DrawChar1(dc, px, py, *s++, attr);
                    177:                        px += font_width;
1.1.1.3 ! root      178:                } else if (0xa0 <= *s && *s < 0xe0) {
        !           179:                        // 半角カナ
        !           180:                        DrawCharKana(dc, px, py, *s++, attr);
        !           181:                        px += font_width;
1.1       root      182:                } else {
                    183:                        // 全角
                    184:                        int code;
                    185:                        code = (*s++ << 8);
                    186:                        code |= *s++;
                    187:                        DrawChar2(dc, px, py, code, attr);
                    188:                        px += font_width * 2;
                    189:                }
                    190:        }
                    191: }
                    192: 
                    193: // (px, py) を左上とする座標からASCII文字 code を属性 attr で描画する。
                    194: // code は 0x80 未満。
                    195: // フォントサイズは現行のフォント。
                    196: void
                    197: WXTextPanel::DrawChar1(wxDC& dc, int px, int py, uint code, uint attr)
                    198: {
                    199:        wxBitmap **glyph;
                    200: 
1.1.1.2   root      201:        assertmsg(code < 0x80, "code=0x%x", code);
1.1       root      202: 
                    203:        // ボールドかどうかでテーブルが別
                    204:        if ((attr & TA::Em)) {
                    205:                glyph = bold_glyph;
                    206:        } else {
                    207:                glyph = ascii_glyph;
                    208:        }
                    209: 
                    210:        // 変更可能なグリフ
                    211:        if (__predict_false(code == 0x5c)) {
                    212:                if (glyph_5c) {
                    213:                        code = 0x80;
                    214:                }
                    215:        } else if (__predict_false(code == 0x7e)) {
                    216:                if (glyph_7e) {
                    217:                        code = 0x81;
                    218:                }
                    219:        } else if (__predict_false(code == 0x7c)) {
                    220:                if (glyph_7c) {
                    221:                        code = 0x82;
                    222:                }
                    223:        }
                    224:        DrawBitmap(dc, px, py, *glyph[code], attr);
                    225: }
                    226: 
1.1.1.3 ! root      227: // (px, py) を左上とする座標から半角カナ1文字を出力する。
        !           228: // フォントサイズは現行のフォント。
        !           229: void
        !           230: WXTextPanel::DrawCharKana(wxDC& dc, int px, int py, uint sjiscode, uint attr)
        !           231: {
        !           232:        std::unique_ptr<wxBitmap> kana;
        !           233:        kana.reset(KanaBitmap(sjiscode, attr));
        !           234:        DrawBitmap(dc, px, py, *kana, attr);
        !           235: }
        !           236: 
1.1       root      237: // (px, py) を左上とする座標から漢字1文字を出力する。
                    238: // sjiscode は Shift_JIS。
                    239: // フォントサイズは現行のフォント。
                    240: void
                    241: WXTextPanel::DrawChar2(wxDC& dc, int px, int py, uint sjiscode, uint attr)
                    242: {
1.1.1.3 ! root      243:        std::unique_ptr<wxBitmap> kanji;
        !           244:        kanji.reset(KanjiBitmap(sjiscode, attr));
1.1       root      245:        DrawBitmap(dc, px, py, *kanji, attr);
                    246: }
                    247: 
                    248: // (px, py) を左上とする座標に bitmap を描画する。
                    249: // この DrawBitmap() は dc のペン色を設定して dc.DrawBitmap() を呼ぶ。
                    250: // ちょっと紛らわしいので注意。
                    251: void
                    252: WXTextPanel::DrawBitmap(wxDC& dc, int px, int py, const wxBitmap& bitmap,
                    253:        uint attr)
                    254: {
                    255:        // 文字の背景は透過ではなく背景色で塗りつぶす
                    256:        // XXX もっと初期化時に近いところへ移してよさそうだが
                    257:        dc.SetBackgroundMode(wxSOLID);
                    258: 
                    259:        // 属性を設定
                    260:        switch (attr) {
                    261:         case TA::On:
                    262:                dc.SetTextForeground(text_bgcolor);
                    263:                dc.SetTextBackground(text_fgcolor);
                    264:                break;
                    265:         case TA::Disable:
                    266:                dc.SetTextForeground(text_disable_color);
                    267:                dc.SetTextBackground(text_bgcolor);
                    268:                break;
                    269:         default:
                    270:                dc.SetTextForeground(text_fgcolor);
                    271:                dc.SetTextBackground(text_bgcolor);
                    272:                break;
                    273:        }
                    274: 
                    275:        // 1文字出力
                    276:        dc.DrawBitmap(bitmap, px, py);
                    277: 
                    278:        // 1文字ずつ属性を元に戻す
                    279:        dc.SetTextForeground(text_fgcolor);
                    280:        dc.SetTextBackground(text_bgcolor);
                    281: }
                    282: 
1.1.1.3 ! root      283: // Shift_JIS の半角カナ1文字分のビットマップを作成する。
        !           284: wxBitmap *
        !           285: WXTextPanel::KanaBitmap(uint16 sjiscode, uint attr)
        !           286: {
        !           287:        const uint8 *base;
        !           288:        // X680x0 CGROM
        !           289:        switch (fontsize) {
        !           290:         case FONT_6x12:
        !           291:                base = BuiltinCGROM::Get6x12();
        !           292:                break;
        !           293:         case FONT_8x16:
        !           294:                base = BuiltinCGROM::Get8x16();
        !           295:                break;
        !           296:         default:
        !           297:                __unreachable();
        !           298:        }
        !           299: 
        !           300:        int bytes = ((font_width + 7) / 8) * font_height;
        !           301:        std::vector<char> buf(bytes);
        !           302: 
        !           303:        const uint8 *ptr;
        !           304:        ptr = base + sjiscode * bytes;
        !           305: 
        !           306:        for (int i = 0; i < bytes; i++) {
        !           307:                buf[i] = bitrev(ptr[i]);
        !           308:        }
        !           309:        if (attr == TA::Em) {
        !           310:                for (int i = 0; i < bytes; i++) {
        !           311:                        buf[i] |= buf[i] >> 1;
        !           312:                }
        !           313:        }
        !           314: 
        !           315:        // その XBM データから1文字分のビットマップオブジェクトを作成
        !           316:        return new wxBitmap(&buf[0], font_width, font_height, 1);
        !           317: }
        !           318: 
1.1       root      319: // Shift_JIS の漢字1文字のビットマップを作成する。
                    320: wxBitmap *
                    321: WXTextPanel::KanjiBitmap(uint16 sjiscode, uint attr)
                    322: {
                    323:        // Shift_JIS を JIS というかコードポイントに変換
                    324:        uint sh = (sjiscode >> 8);
                    325:        uint sl = sjiscode & 0xff;
                    326:        uint jh;
                    327:        uint jl;
                    328:        if (sh < 0xa0) {
                    329:                jh = sh - 0x71;
                    330:        } else {
                    331:                jh = sh - 0xb1;
                    332:        }
                    333:        jh = jh * 2 + 1;
                    334:        jl = sl;
                    335:        if (sl > 0x7f) {
                    336:                jl--;
                    337:        }
                    338:        if (jl < 0x9e) {
                    339:                jl -= 0x1f;
                    340:        } else {
                    341:                jl -= 0x7d;
                    342:                jh++;
                    343:        }
                    344:        // ここで JIS。これを CGROM 格納コードポイントに変換。
                    345:        jh -= 0x21;
                    346:        jl -= 0x21;
                    347:        if (jh >= 15) {
                    348:                jh -= 7;
                    349:        }
                    350:        int code = jh * 94 + jl;
                    351: 
                    352:        // XXX 見付からなかったらゲタ文字にしたい
                    353:        if (code <0) code=0x6b;
                    354: 
                    355:        // フォント領域
                    356:        const uint8 *base;
                    357:        switch (fontsize) {
                    358:         case FONT_6x12:
                    359:                // 12x12 は内蔵フォントデータ
                    360:                base = builtin_kanji12;
                    361:                break;
                    362:         case FONT_8x16:
                    363:                // 16x16 は X680x0 CGROM のを使う。
1.1.1.3 ! root      364:                base = BuiltinCGROM::Get16x16();
1.1       root      365:                break;
                    366:         default:
                    367:                // ここより先に必ず半角のほうでエラーが出るはず
                    368:                __unreachable();
                    369:        }
                    370: 
                    371:        int bytes = (((font_width * 2) + 7) / 8) * font_height;
1.1.1.3 ! root      372:        std::vector<char> buf(bytes);
1.1       root      373: 
                    374:        const uint8 *ptr;
                    375:        ptr = base + code * bytes;
                    376: 
                    377:        for (int i = 0; i < bytes; i++) {
                    378:                buf[i] = bitrev(ptr[i]);
                    379:        }
                    380:        if (attr == TA::Em) {
                    381:                for (int i = 0; i < bytes; i++) {
                    382:                        buf[i] |= buf[i] >> 1;
                    383:                }
                    384:        }
                    385: 
                    386:        // その XBM データから1文字分のビットマップオブジェクトを作成
1.1.1.3 ! root      387:        return new wxBitmap(&buf[0], font_width * 2, font_height, 1);
1.1       root      388: }
                    389: 
                    390: // スタティック変数
                    391: fontsize_t WXTextPanel::global_fontsize;
                    392: std::mutex WXTextPanel::global_font_mutex;
                    393: u_int WXTextPanel::font_refcnt[FONT_MAX];
                    394: wxBitmap *WXTextPanel::ascii_glyph_table[FONT_MAX][0x83];
                    395: wxBitmap *WXTextPanel::bold_glyph_table[FONT_MAX][0x83];

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.