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

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