Annotation of nono/wx/wxtextpanel.cpp, revision 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.