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

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

unix.superglobalmegacorp.com

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