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