|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.