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

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

unix.superglobalmegacorp.com

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