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

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