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

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "wxtextscreen.h"
1.1.1.5   root        8: #include "wxcolor.h"
1.1.1.3   root        9: #include "wxmainframe.h"
1.1       root       10: #include "cgrom.h"
1.1.1.5   root       11: #include "sjis.h"
1.1       root       12: 
                     13: //
1.1.1.3   root       14: // テキストスクリーンを表示するパネル
1.1       root       15: //
                     16: 
                     17: // イベントテーブル
                     18: wxBEGIN_EVENT_TABLE(WXTextScreen, inherited)
                     19:        EVT_PAINT(WXTextScreen::OnPaint)
                     20:        EVT_SIZE(WXTextScreen::OnSize)
1.1.1.3   root       21:        EVT_TIMER(wxID_ANY, WXTextScreen::OnTimer)
1.1       root       22: wxEND_EVENT_TABLE()
                     23: 
                     24: // コンストラクタ
1.1.1.6   root       25: WXTextScreen::WXTextScreen(wxWindow *parent, Monitor& monitor_)
1.1       root       26:        : inherited(parent)
1.1.1.3   root       27:        , monitor(monitor_)
1.1       root       28: {
1.1.1.3   root       29:        // モニタサイズから初期サイズを決定
1.1.1.6   root       30:        nnSize ms = monitor.GetSize();
1.1.1.5   root       31:        Init(ms.width, ms.height);
                     32: 
1.1.1.3   root       33:        wxSize size = wxSize(ms.width * font_width, ms.height * font_height);
                     34:        SetClientSize(size);
1.1.1.5   root       35:        SetMinClientSize(size);
1.1.1.3   root       36: 
                     37:        timer.SetOwner(this);
1.1       root       38: 
1.1.1.3   root       39:        // 現在の設定値を適用
                     40:        SetRate(gMainFrame->GetMonitorRate());
                     41: 
                     42:        // 最初に一回描画を起こす
                     43:        wxTimerEvent dummy;
                     44:        AddPendingEvent(dummy);
1.1       root       45: }
                     46: 
                     47: // デストラクタ
                     48: WXTextScreen::~WXTextScreen()
                     49: {
1.1.1.5   root       50: }
                     51: 
                     52: // (再)初期化
                     53: void
                     54: WXTextScreen::Init(int col, int row)
                     55: {
                     56:        ts.Init(col, row);
                     57:        prevbuf.resize(col * row);
                     58:        std::fill(prevbuf.begin(), prevbuf.end(), 0xffff);
1.1       root       59: }
                     60: 
1.1.1.3   root       61: // 画面更新頻度を Hz で設定する。
1.1       root       62: void
1.1.1.3   root       63: WXTextScreen::SetRate(int hz)
1.1       root       64: {
1.1.1.3   root       65:        timer.Start(1000 / hz);
1.1       root       66: }
                     67: 
                     68: // フォントサイズ変更 (外部インタフェース)
                     69: void
1.1.1.3   root       70: WXTextScreen::SetFontSize(FontId new_fontid)
1.1       root       71: {
                     72:        // 同じなら何もしない
1.1.1.3   root       73:        if (fontid == new_fontid) {
1.1       root       74:                return;
                     75:        }
                     76: 
                     77:        // フォントを更新
1.1.1.3   root       78:        UpdateFont(new_fontid);
1.1       root       79: 
                     80:        // 再描画を強制する。
                     81:        // テキストの桁数行数は変わってないので再確保はしなくていい。
1.1.1.5   root       82:        std::fill(prevbuf.begin(), prevbuf.end(), 0xffff);
1.1       root       83: 
                     84:        // コントロールの大きさを変更
1.1.1.5   root       85:        wxSize size = wxSize(ts.GetCol() * font_width, ts.GetRow() * font_height);
1.1       root       86:        SetClientSize(size);
1.1.1.5   root       87:        SetMinClientSize(size);
1.1       root       88: }
                     89: 
                     90: // サイズ変更イベント
                     91: void
                     92: WXTextScreen::OnSize(wxSizeEvent& event)
                     93: {
                     94:        // Mac ではウィンドウ作成時に 0 以下の値が来ることがある
                     95:        // GTK では 1 で来ることがある
1.1.1.3   root       96:        const wxSize& size = event.GetSize();
1.1       root       97:        if (size.x <= 1 || size.y <= 1) {
                     98:                return;
                     99:        }
                    100: 
1.1.1.3   root      101:        // テキストサイズが変わった時だけテキストバッファを再構成。
                    102:        // (フォントサイズを変えると桁数×行数が変わらず画面サイズが変わる
                    103:        // ということは起きることに注意)
                    104:        int col = size.x / font_width;
                    105:        int row = size.y / font_height;
                    106:        if (col != ts.GetCol() || row != ts.GetRow()) {
1.1.1.5   root      107:                Init(col, row);
1.1.1.3   root      108:        }
                    109: 
                    110:        // ビットマップサイズが変わった時だけビットマップバッファを再構成。
1.1.1.5   root      111:        wxSize bmpsize = bitmap.GetSize();
                    112:        wxSize newsize = wxSize(col * font_width, row * font_height);
                    113:        if (bmpsize != newsize) {
1.1.1.3   root      114:                // ビットマップ作成
1.1.1.5   root      115:                bitmap.Create(newsize);
1.1.1.3   root      116:        }
                    117: }
1.1       root      118: 
1.1.1.3   root      119: // タイマーイベント
                    120: void
                    121: WXTextScreen::OnTimer(wxTimerEvent& event)
                    122: {
1.1.1.6   root      123:        DoRefresh();
1.1.1.3   root      124: }
1.1       root      125: 
1.1.1.6   root      126: // 画面を更新して再描画する。
                    127: //
                    128: // 通常はタイマーイベントにより更新間隔ごとに呼ばれるが、
                    129: // ユーザ操作により画面の更新が必要ならその都度直接これを呼ぶ。
1.1.1.3   root      130: void
1.1.1.6   root      131: WXTextScreen::DoRefresh()
1.1.1.3   root      132: {
1.1.1.6   root      133:        // モニタースクリーンを更新して
                    134:        MONITOR_UPDATE(monitor, ts);
                    135:        // 必要なら再描画
1.1.1.5   root      136:        if (ts.GetBuf() != prevbuf) {
1.1.1.3   root      137:                Refresh();
                    138:        }
1.1       root      139: }
                    140: 
                    141: // 描画イベント (UI スレッドから呼ばれる)
                    142: void
                    143: WXTextScreen::OnPaint(wxPaintEvent& event)
                    144: {
1.1.1.3   root      145:        // メモリ DC に描画
1.1       root      146:        wxMemoryDC memDC;
1.1.1.5   root      147:        memDC.SelectObject(bitmap);
1.1.1.3   root      148:        // 基本的には RefreshIfUpdated() により更新があった時だけ呼ばれる
                    149:        Draw(memDC);
1.1       root      150: 
                    151:        // 実画面 DC にコピー
                    152:        wxPaintDC dstDC(this);
1.1.1.5   root      153:        wxSize size = bitmap.GetSize();
                    154:        dstDC.Blit(0, 0, size.x, size.y, &memDC, 0, 0);
1.1       root      155: }
                    156: 
                    157: // テキストバッファの内容をパネルのバックグラウンドバッファに描画する。
                    158: void
                    159: WXTextScreen::Draw(wxDC& dc)
                    160: {
1.1.1.5   root      161:        auto text = ts.GetBuf().begin();
                    162:        auto prev = prevbuf.begin();
                    163: 
1.1.1.3   root      164:        int col = ts.GetCol();
                    165:        int row = ts.GetRow();
1.1       root      166:        int px = 0;
                    167:        int py = 0;
1.1.1.5   root      168:        uint prevattr = (uint)-1;
                    169: 
1.1       root      170:        for (int y = 0; y < row; y++, py += font_height) {
                    171:                px = 0;
                    172:                for (int x = 0; x < col; ) {
                    173:                        uint16 data = *text;
                    174:                        uint attr = (data & 0xff00);
                    175:                        uint chr  = (data & 0xff);
1.1.1.5   root      176: 
                    177:                        // 属性(色)を変更
                    178:                        if (__predict_false(attr != prevattr)) {
                    179:                                switch (attr) {
                    180:                                 case TA::On:
                    181:                                        SetTextColor(BGPANEL, *wxBLACK);
                    182:                                        break;
1.1.1.7 ! root      183:                                 case TA::Off:
        !           184:                                        SetTextColor(*wxBLACK, UD_LIGHT_GREY);
        !           185:                                        break;
1.1.1.5   root      186:                                 case TA::Disable:
                    187:                                        SetTextColor(UD_GREY, BGPANEL);
                    188:                                        break;
                    189:                                 default:
                    190:                                        ResetTextColor();
                    191:                                        break;
                    192:                                }
                    193:                                prevattr = attr;
                    194:                        }
                    195: 
                    196:                        if (__predict_true(SJIS::IsHankaku(chr))) {
                    197:                                // 半角文字
1.1       root      198:                                if (*prev != data) {
1.1.1.5   root      199:                                        DrawChar1(dc, px, py, chr, attr);
                    200:                                        if (SJIS::IsZenkaku(*prev) && x < col - 1) {
                    201:                                                // 変更前が全角文字だったら 2 バイト目も消す
1.1.1.4   root      202:                                                prev[1] = 0;
                    203:                                        }
1.1       root      204:                                        *prev = data;
                    205:                                }
1.1.1.5   root      206:                                prev += 1;
                    207:                                text += 1;
                    208:                                x += 1;
                    209:                                px += font_width * 1;
1.1       root      210:                        } else {
1.1.1.5   root      211:                                // 全角文字
1.1.1.6   root      212:                                // XXX: 最右カラムだったら?
1.1.1.5   root      213:                                if (*prev != data || prev[1] != text[1]) {
                    214:                                        uint code = (chr << 8) | (text[1] & 0xff);
1.1       root      215:                                        DrawChar2(dc, px, py, code, attr);
1.1.1.5   root      216:                                        if (SJIS::IsASCII(*prev) && SJIS::IsZenkaku(prev[1])
                    217:                                         && x < col - 2) {
1.1.1.6   root      218:                                                // 変更前が 'Aあ' だったら'あ'の2バイト目も消す
1.1.1.5   root      219:                                                prev[2] = 0;
                    220:                                        }
                    221:                                        prev[0] = data;
                    222:                                        prev[1] = text[1];
1.1       root      223:                                }
1.1.1.5   root      224:                                prev += 2;
                    225:                                text += 2;
1.1       root      226:                                x += 2;
                    227:                                px += font_width * 2;
                    228:                        }
                    229:                }
                    230:        }
                    231: }

unix.superglobalmegacorp.com

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