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

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