Skip to content

Commit e996a89

Browse files
committed
migrate dib from rust to c++
1 parent f384208 commit e996a89

File tree

5 files changed

+226
-313
lines changed

5 files changed

+226
-313
lines changed

cli/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ fn main() -> anyhow::Result<ExitCode> {
182182
machine.dump_state(0);
183183
1
184184
}
185-
_ => unreachable!(),
185+
_ => unreachable!("{status:?}"),
186186
};
187187
Ok(ExitCode::from(exit_code as u8))
188188
}

exe/cpp/build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ link_flags="/subsystem:console ddraw.lib gdi32.lib kernel32.lib user32.lib"
1212
# https://devblogs.microsoft.com/cppblog/introducing-the-universal-crt/
1313
link_flags="$link_flags libcmt.lib libvcruntime.lib libucrt.lib"
1414

15-
for src in cmdline.cc ddraw.cc errors.cc gdi.cc metrics.cc thread.cc; do
15+
for src in cmdline.cc ddraw.cc dib.cc errors.cc gdi.cc metrics.cc thread.cc; do
1616
echo $src
1717
clang-cl $clang_flags $cflags $sdk_flags $src /link $link_flags
1818
done

exe/cpp/dib.cc

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
// Draw some bitmaps in different ways.
2+
3+
#include "util.h"
4+
#include <windows.h>
5+
#include <cstdint>
6+
7+
// Upward-pointing arrow, 16x16 monochrome.
8+
const uint8_t ARROW[16 * 2] = {
9+
0b00000000, 0b00000000,
10+
0b00000001, 0b10000000,
11+
0b00000011, 0b11000000,
12+
0b00000111, 0b11100000,
13+
0b00001111, 0b11110000,
14+
0b00011111, 0b11111000,
15+
0b00111111, 0b11111100,
16+
0b01111111, 0b11111110,
17+
0b00000011, 0b11000000,
18+
0b00000011, 0b11000000,
19+
0b00000011, 0b11000000,
20+
0b00000011, 0b11000000,
21+
0b00000011, 0b11000000,
22+
0b00000011, 0b11000000,
23+
0b00000011, 0b11000000,
24+
0b00000000, 0b00000000,
25+
};
26+
27+
uint32_t* arrow_rgba() {
28+
static uint32_t pixels[16 * 16];
29+
for (size_t row = 0; row < sizeof(ARROW); ++row) {
30+
uint8_t b = ARROW[row];
31+
for (int i = 0; i < 8; ++i) {
32+
uint8_t bit = (b >> (7 - i)) & 1;
33+
uint32_t color = (bit == 0) ? 0xFF000000 : 0xFFFFFFFF;
34+
pixels[row * 8 + i] = color;
35+
}
36+
}
37+
return pixels;
38+
}
39+
40+
struct State {
41+
HBITMAP mono;
42+
HBITMAP dib;
43+
uint32_t* dib_pixels;
44+
45+
State() {
46+
mono = nullptr;
47+
dib = nullptr;
48+
dib_pixels = nullptr;
49+
}
50+
51+
void init(HDC hdc) {
52+
create_mono();
53+
create_dib(hdc, dib);
54+
}
55+
56+
void create_mono() {
57+
mono = CreateBitmap(16, 16, 1, 1, ARROW);
58+
}
59+
60+
void create_dib(HDC hdc, HBITMAP& dib) {
61+
BITMAPINFO info = {
62+
.bmiHeader = {
63+
.biSize = sizeof(BITMAPINFOHEADER),
64+
.biWidth = 16,
65+
.biHeight = 16,
66+
.biPlanes = 1,
67+
.biBitCount = 32,
68+
.biCompression = BI_RGB,
69+
},
70+
};
71+
72+
dib = CreateDIBSection(hdc, &info, DIB_RGB_COLORS, (void**)&dib_pixels, nullptr, 0);
73+
memcpy(dib_pixels, arrow_rgba(), sizeof(uint32_t) * 16 * 16);
74+
}
75+
};
76+
77+
static State state = {};
78+
79+
void paint_SetDIBitsToDevice(HDC hdc, int y, uint32_t* rgba) {
80+
struct Cfg {
81+
uint32_t startScan;
82+
bool invertY;
83+
};
84+
Cfg cfgs[] = {
85+
{0, false},
86+
{0, true},
87+
};
88+
89+
for (size_t i = 0; i < sizeof(cfgs) / sizeof(cfgs[0]); ++i) {
90+
BITMAPINFOHEADER info = {};
91+
info.biSize = sizeof(BITMAPINFOHEADER);
92+
info.biWidth = 16;
93+
info.biHeight = cfgs[i].invertY ? -16 : 16;
94+
info.biPlanes = 1;
95+
info.biBitCount = 32;
96+
info.biCompression = BI_RGB;
97+
98+
int x = 32 + static_cast<int>(i) * 32;
99+
SetDIBitsToDevice(
100+
hdc,
101+
x,
102+
y,
103+
16,
104+
16,
105+
0,
106+
static_cast<int>(cfgs[i].startScan),
107+
cfgs[i].startScan,
108+
16,
109+
rgba,
110+
reinterpret_cast<BITMAPINFO*>(&info),
111+
DIB_RGB_COLORS
112+
);
113+
}
114+
}
115+
116+
void paint_StretchDIBits(HDC hdc, int y, uint32_t* rgba) {
117+
BITMAPINFOHEADER info = {};
118+
info.biSize = sizeof(BITMAPINFOHEADER);
119+
info.biWidth = 16;
120+
info.biHeight = 16;
121+
info.biPlanes = 1;
122+
info.biBitCount = 32;
123+
info.biCompression = BI_RGB;
124+
125+
StretchDIBits(
126+
hdc,
127+
32,
128+
y,
129+
32,
130+
32,
131+
0,
132+
0,
133+
16,
134+
16,
135+
rgba,
136+
reinterpret_cast<BITMAPINFO*>(&info),
137+
DIB_RGB_COLORS,
138+
SRCCOPY
139+
);
140+
}
141+
142+
void paint(HDC hdc) {
143+
if (!state.mono) {
144+
state.init(hdc);
145+
}
146+
147+
HDC hdc_bitmap = CreateCompatibleDC(hdc);
148+
149+
int row = 1;
150+
SelectObject(hdc_bitmap, state.mono);
151+
BitBlt(hdc, 32, row * 32, 16, 16, hdc_bitmap, 0, 0, SRCCOPY);
152+
row++;
153+
154+
SelectObject(hdc_bitmap, state.dib);
155+
BitBlt(hdc, 32, row * 32, 16, 16, hdc_bitmap, 0, 0, SRCCOPY);
156+
row++;
157+
158+
uint32_t* rgba = arrow_rgba();
159+
paint_SetDIBitsToDevice(hdc, row * 32, rgba);
160+
row++;
161+
162+
paint_StretchDIBits(hdc, row * 32, rgba);
163+
164+
DeleteDC(hdc_bitmap);
165+
}
166+
167+
LRESULT CALLBACK wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
168+
switch (msg) {
169+
case WM_DESTROY:
170+
PostQuitMessage(0);
171+
return 0;
172+
case WM_LBUTTONDOWN:
173+
for (int i = 0; i < 32 * 2; ++i) {
174+
state.dib_pixels[i] = 0xFF0000FF;
175+
}
176+
InvalidateRect(hwnd, nullptr, FALSE);
177+
return 0;
178+
case WM_PAINT: {
179+
PAINTSTRUCT ps;
180+
HDC hdc = BeginPaint(hwnd, &ps);
181+
paint(hdc);
182+
EndPaint(hwnd, &ps);
183+
return 0;
184+
}
185+
default:
186+
return DefWindowProc(hwnd, msg, wparam, lparam);
187+
}
188+
}
189+
190+
HWND create_window() {
191+
const char* class_name = "dibs";
192+
WNDCLASS wc = {
193+
.lpfnWndProc = wndproc,
194+
.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1),
195+
.lpszClassName = class_name,
196+
};
197+
RegisterClass(&wc);
198+
199+
HWND hwnd = CreateWindowEx(
200+
0,
201+
class_name,
202+
"title",
203+
WS_OVERLAPPEDWINDOW,
204+
CW_USEDEFAULT,
205+
CW_USEDEFAULT,
206+
400,
207+
300,
208+
nullptr,
209+
nullptr,
210+
nullptr,
211+
nullptr
212+
);
213+
ShowWindow(hwnd, SW_NORMAL);
214+
return hwnd;
215+
}
216+
217+
extern "C" void mainCRTStartup() {
218+
HWND hwnd = create_window();
219+
MSG msg;
220+
while (GetMessage(&msg, nullptr, 0, 0)) {
221+
TranslateMessage(&msg);
222+
DispatchMessage(&msg);
223+
}
224+
}

exe/cpp/dib.exe

5.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)