quickwin 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +7 -7
- package/README.md +7 -7
- package/constants.ts +1070 -0
- package/enum_map.d.ts +130 -0
- package/examples/PdfCanvas.js +2 -2
- package/examples/PdfCanvas.tsx +3 -2
- package/examples/{execd.js → execd/main.js} +717 -148
- package/examples/execd/tray.js +192 -0
- package/examples/{execd_worker.js → execd/worker.js} +7 -7
- package/examples/pdf_preview2.js +46 -46
- package/examples/pdf_preview2.ts +55 -54
- package/examples/pdf_viewer.js +34 -19
- package/examples/pdf_viewer.tsx +6 -5
- package/examples/test_gallery.js +35 -20
- package/examples/test_gallery.tsx +9 -8
- package/examples/test_react_lazy.js +34 -19
- package/examples/test_react_lazy.tsx +7 -6
- package/examples/test_react_listbox.js +34 -19
- package/examples/test_react_listbox.tsx +8 -7
- package/examples/test_root_window.js +34 -19
- package/examples/test_root_window.tsx +5 -5
- package/examples/test_tab.js +34 -19
- package/examples/test_tab.tsx +7 -6
- package/examples/tray_demo.js +8 -8
- package/examples/tray_demo.tsx +9 -8
- package/lib/dumpRects.js +2 -2
- package/lib/dumpRects.ts +3 -2
- package/lib/fetch.js +15 -15
- package/lib/fetch.ts +16 -15
- package/lib/ffi/bind.js +3 -3
- package/lib/ffi/bind.ts +3 -3
- package/lib/http-server.js +54 -29
- package/lib/http-server.ts +56 -27
- package/lib/react-qw/components/Button.js +2 -2
- package/lib/react-qw/components/CheckBox.js +4 -4
- package/lib/react-qw/components/ComboBox.js +10 -10
- package/lib/react-qw/components/DateTimePicker.js +12 -12
- package/lib/react-qw/components/Input.js +7 -7
- package/lib/react-qw/components/Link.js +4 -4
- package/lib/react-qw/components/ListBox.js +12 -12
- package/lib/react-qw/components/ListView.js +35 -35
- package/lib/react-qw/components/PathPicker.js +3 -3
- package/lib/react-qw/components/ProgressBar.js +4 -4
- package/lib/react-qw/components/RadioButton.js +4 -4
- package/lib/react-qw/components/ScrollView.js +28 -28
- package/lib/react-qw/components/Slider.js +11 -11
- package/lib/react-qw/components/Tab.js +10 -10
- package/lib/react-qw/components/Tooltip.js +8 -8
- package/lib/react-qw/components/TreeView.js +20 -20
- package/lib/react-qw/index.js +5 -5
- package/lib/react-qw/index.ts +6 -5
- package/lib/react-qw/props.js +4 -4
- package/lib/react-qw/props.ts +5 -4
- package/lib/react-qw/reconciler.js +10 -10
- package/lib/react-qw/reconciler.ts +11 -10
- package/lib/text-measure.js +3 -3
- package/lib/text-measure.ts +4 -3
- package/lib/websocket.js +17 -17
- package/lib/websocket.ts +18 -17
- package/lib/windows/advapi32.js +7 -7
- package/lib/windows/advapi32.ts +7 -7
- package/lib/windows/gdi32.js +16 -16
- package/lib/windows/gdi32.ts +16 -16
- package/lib/windows/kernel32.js +41 -2
- package/lib/windows/kernel32.ts +45 -2
- package/lib/windows/shell32.js +24 -3
- package/lib/windows/shell32.ts +27 -4
- package/lib/windows/structs.js +54 -0
- package/lib/windows/structs.ts +63 -1
- package/lib/windows/user32.js +18 -6
- package/lib/windows/user32.ts +18 -6
- package/lib/windows/winspool.js +3 -3
- package/lib/windows/winspool.ts +3 -3
- package/package.json +4 -3
- package/quickwin.d.ts +32 -10
- package/qwin-nowasm-x86.exe +0 -0
- package/qwin-nowasm.exe +0 -0
- package/qwin-x86.exe +0 -0
- package/qwin.exe +0 -0
- package/test/test_ffi_bind.js +7 -7
- package/test/test_ffi_bind.ts +8 -8
- package/test/test_ffi_struct.js +2 -2
- package/test/test_ffi_struct.ts +3 -3
- package/test/test_ffi_windows.js +1 -1
- package/test/test_ffi_windows.ts +1 -1
- package/test/test_files.js +7 -7
- package/test/test_files.ts +8 -8
- package/test/test_gdi_draw.js +51 -51
- package/test/test_gdi_draw.ts +57 -57
- package/test/test_http_server.js +3 -3
- package/test/test_http_server.ts +4 -3
- package/test/test_ipv6.js +3 -3
- package/test/test_ipv6.ts +4 -3
- package/test/test_net_event.js +3 -3
- package/test/test_net_event.ts +4 -3
- package/test/test_printer.js +4 -4
- package/test/test_printer.ts +5 -5
- package/test/test_react_complex.js +36 -21
- package/test/test_react_counter.js +34 -19
- package/test/test_react_flex.js +36 -21
- package/test/test_react_hidden.js +34 -19
- package/test/test_react_listview_link.js +35 -20
- package/test/test_react_notify.js +52 -37
- package/test/test_react_render.js +34 -19
- package/test/test_registry.js +6 -6
- package/test/test_registry.ts +8 -8
- package/test/test_wolfssl_read.js +8 -8
- package/test/test_wolfssl_read.ts +9 -8
- package/examples/execd.tsx +0 -798
- package/examples/execd_worker.ts +0 -127
- package/quickwin_const.d.ts +0 -1063
package/test/test_gdi_draw.js
CHANGED
|
@@ -14,7 +14,7 @@ const H = 240;
|
|
|
14
14
|
export const suite = {
|
|
15
15
|
name: 'gdi-draw',
|
|
16
16
|
run: (t) => {
|
|
17
|
-
// —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与
|
|
17
|
+
// —— 基座:屏幕 DC → 内存 DC + 32bpp 位图(与 execd/worker 截屏同型)——
|
|
18
18
|
t.section('setup: memory DC + 32bpp bitmap');
|
|
19
19
|
const screen = GetDC(NULL);
|
|
20
20
|
const mem = CreateCompatibleDC(screen);
|
|
@@ -47,16 +47,16 @@ export const suite = {
|
|
|
47
47
|
return (pxU8[i] << 16) | (pxU8[i + 1] << 8) | pxU8[i + 2]; // B,G,R → COLORREF
|
|
48
48
|
};
|
|
49
49
|
const clearWhite = () => {
|
|
50
|
-
PatBlt(mem, 0, 0, W, H, 16711778 /*
|
|
50
|
+
PatBlt(mem, 0, 0, W, H, 16711778 /* RasterOp.WHITENESS */); // 与画刷无关的整白
|
|
51
51
|
readPx();
|
|
52
52
|
};
|
|
53
53
|
clearWhite();
|
|
54
54
|
t.check('baseline = white', WHITE, px(5, 5));
|
|
55
55
|
t.checkTrue('GetDIBits full read', pxOk);
|
|
56
56
|
t.section('state: return-previous semantics');
|
|
57
|
-
t.check('fresh DC default bkMode = OPAQUE', 2 /*
|
|
58
|
-
t.check('SetBkMode returns previous', 2 /*
|
|
59
|
-
SetBkMode(mem, 2 /*
|
|
57
|
+
t.check('fresh DC default bkMode = OPAQUE', 2 /* BackgroundMode.OPAQUE */, SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */));
|
|
58
|
+
t.check('SetBkMode returns previous', 2 /* BackgroundMode.OPAQUE */, SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */));
|
|
59
|
+
SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
|
|
60
60
|
SetTextColor(mem, RED); // 返回默认色(不假设)
|
|
61
61
|
t.check('SetTextColor returns previous', RED, SetTextColor(mem, BLUE));
|
|
62
62
|
SetTextColor(mem, 0);
|
|
@@ -66,7 +66,7 @@ export const suite = {
|
|
|
66
66
|
// 类型专用块(只过 tsc、不执行)
|
|
67
67
|
const typeOnly = () => {
|
|
68
68
|
// @ts-expect-error 跨枚举 nominal:BackgroundMode 成员进不了 PenStyle 位
|
|
69
|
-
CreatePen(1 /*
|
|
69
|
+
CreatePen(1 /* BackgroundMode.TRANSPARENT */, 1, 0);
|
|
70
70
|
// @ts-expect-error '<HDC>ptr!' 禁空位不收 NULL
|
|
71
71
|
Rectangle(NULL, 0, 0, 1, 1);
|
|
72
72
|
// @ts-expect-error encoder 数组位不收裸对象(单对象对 C 是越界基址)
|
|
@@ -76,37 +76,37 @@ export const suite = {
|
|
|
76
76
|
// @ts-expect-error <WCHAR>ptr 文本位收 string / NULL,不收裸数字
|
|
77
77
|
TextOut(0, 0, 0, 123, 1);
|
|
78
78
|
// @ts-expect-error 跨枚举 nominal:PenStyle 成员进不了 StockObject 位
|
|
79
|
-
GetStockObject(0 /*
|
|
79
|
+
GetStockObject(0 /* PenStyle.SOLID */);
|
|
80
80
|
// @ts-expect-error 跨枚举 nominal:HatchStyle 成员进不了 PolyFillMode 位
|
|
81
|
-
SetPolyFillMode(0, 4 /*
|
|
81
|
+
SetPolyFillMode(0, 4 /* HatchStyle.CROSS */);
|
|
82
82
|
// @ts-expect-error u32@RasterOp 标注拦枚举外光栅码(字面量不匹配成员值)
|
|
83
83
|
PatBlt(0, 0, 0, 1, 1, 0x123456);
|
|
84
84
|
// @ts-expect-error '<SIZE>ptr!' 出参位不收 NULL
|
|
85
85
|
GetTextExtentPoint32(0, 'x', 1, NULL);
|
|
86
86
|
// @ts-expect-error 跨枚举 nominal:StretchBltMode 成员进不了 ArcDirection 位
|
|
87
|
-
SetArcDirection(0, 4 /*
|
|
87
|
+
SetArcDirection(0, 4 /* StretchBltMode.HALFTONE */);
|
|
88
88
|
};
|
|
89
89
|
t.checkTrue('type-only block wired', typeof typeOnly === 'function');
|
|
90
90
|
t.section('SaveDC/RestoreDC: state stack rollback');
|
|
91
91
|
// 先定基态(断言不依赖前面 section 的收尾值)
|
|
92
92
|
SetTextColor(mem, 0);
|
|
93
|
-
SetBkMode(mem, 2 /*
|
|
93
|
+
SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
|
|
94
94
|
SetBkColor(mem, WHITE);
|
|
95
95
|
const saved = SaveDC(mem);
|
|
96
96
|
t.checkTrue(`SaveDC state id ≠ 0 (${saved})`, saved !== 0);
|
|
97
97
|
// 打乱:三项绘图状态 + 换一支笔
|
|
98
98
|
SetTextColor(mem, RED);
|
|
99
|
-
SetBkMode(mem, 1 /*
|
|
99
|
+
SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */);
|
|
100
100
|
SetBkColor(mem, BLUE);
|
|
101
|
-
const junkPen = CreatePen(1 /*
|
|
101
|
+
const junkPen = CreatePen(1 /* PenStyle.DASH */, 1, GREEN);
|
|
102
102
|
SelectObject(mem, junkPen);
|
|
103
103
|
t.checkTrue('RestoreDC ok', RestoreDC(mem, saved) !== 0);
|
|
104
104
|
DeleteObject(junkPen); // 恢复后已卸下,可安全删
|
|
105
105
|
// 逐项回滚断言:各 Set 返回的就是回滚后的当前值
|
|
106
106
|
t.check('text color rolled back', 0, SetTextColor(mem, RED));
|
|
107
107
|
SetTextColor(mem, 0);
|
|
108
|
-
t.check('bkMode rolled back', 2 /*
|
|
109
|
-
SetBkMode(mem, 2 /*
|
|
108
|
+
t.check('bkMode rolled back', 2 /* BackgroundMode.OPAQUE */, SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */));
|
|
109
|
+
SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
|
|
110
110
|
t.check('bkColor rolled back', WHITE, SetBkColor(mem, RED));
|
|
111
111
|
SetBkColor(mem, WHITE);
|
|
112
112
|
t.section('Rectangle: brush fill (inside/outside pixels)');
|
|
@@ -123,7 +123,7 @@ export const suite = {
|
|
|
123
123
|
DeleteObject(brush);
|
|
124
124
|
t.section('Polyline: encoder array position + NULL passthrough');
|
|
125
125
|
clearWhite();
|
|
126
|
-
const pen = CreatePen(0 /*
|
|
126
|
+
const pen = CreatePen(0 /* PenStyle.SOLID */, 1, GREEN);
|
|
127
127
|
t.checkTrue('pen created', !!pen);
|
|
128
128
|
const oldPen = SelectObject(mem, pen);
|
|
129
129
|
t.checkTrue('Polyline success', Polyline(mem, [{ x: 0, y: 100 }, { x: 100, y: 100 }], 2) !== 0);
|
|
@@ -161,9 +161,9 @@ export const suite = {
|
|
|
161
161
|
SelectObject(mem, oldPen);
|
|
162
162
|
DeleteObject(pen);
|
|
163
163
|
t.section('SetROP2: R2_XORPEN reversible');
|
|
164
|
-
PatBlt(mem, 0, 0, W, H, 66 /*
|
|
165
|
-
t.check('default raster mode = R2_COPYPEN', 13 /*
|
|
166
|
-
const xorPen = CreatePen(0 /*
|
|
164
|
+
PatBlt(mem, 0, 0, W, H, 66 /* RasterOp.BLACKNESS */); // 黑底:黑^绿=绿,绿^绿=黑
|
|
165
|
+
t.check('default raster mode = R2_COPYPEN', 13 /* RasterMode.R2_COPYPEN */, SetROP2(mem, 7 /* RasterMode.R2_XORPEN */)); // 返回旧值 = 默认,同时设为 XOR
|
|
166
|
+
const xorPen = CreatePen(0 /* PenStyle.SOLID */, 1, GREEN);
|
|
167
167
|
const xorOld = SelectObject(mem, xorPen);
|
|
168
168
|
MoveToEx(mem, 10, 200, NULL);
|
|
169
169
|
LineTo(mem, 100, 200);
|
|
@@ -175,7 +175,7 @@ export const suite = {
|
|
|
175
175
|
t.check('second pass cancels back to black', BLACK, px(50, 200));
|
|
176
176
|
SelectObject(mem, xorOld);
|
|
177
177
|
DeleteObject(xorPen);
|
|
178
|
-
SetROP2(mem, 13 /*
|
|
178
|
+
SetROP2(mem, 13 /* RasterMode.R2_COPYPEN */); // 恢复
|
|
179
179
|
t.section('Polygon: fill + outline (auto-close)');
|
|
180
180
|
clearWhite();
|
|
181
181
|
const pBrush = CreateSolidBrush(BLUE);
|
|
@@ -205,7 +205,7 @@ export const suite = {
|
|
|
205
205
|
// 圆 (100,100)-(200,200) 心 (150,150) r=50;起 12 点 (150,100) → 终 9 点 (100,150):
|
|
206
206
|
// GDI 默认逆时针 12→11→10→9 = 左上 90° 弧(SetArcDirection 可改,见 MSDN Arc)
|
|
207
207
|
clearWhite();
|
|
208
|
-
const arcPen = CreatePen(0 /*
|
|
208
|
+
const arcPen = CreatePen(0 /* PenStyle.SOLID */, 1, RED);
|
|
209
209
|
const arcOldPen = SelectObject(mem, arcPen);
|
|
210
210
|
Arc(mem, 100, 100, 200, 200, 150, 100, 100, 150);
|
|
211
211
|
readPx();
|
|
@@ -247,13 +247,13 @@ export const suite = {
|
|
|
247
247
|
clearWhite();
|
|
248
248
|
const dirBrush = CreateSolidBrush(RED);
|
|
249
249
|
const dirOldB = SelectObject(mem, dirBrush);
|
|
250
|
-
t.check('default arc direction = counterclockwise', 1 /*
|
|
251
|
-
t.check('SetArcDirection returns previous', 1 /*
|
|
250
|
+
t.check('default arc direction = counterclockwise', 1 /* ArcDirection.COUNTERCLOCKWISE */, GetArcDirection(mem));
|
|
251
|
+
t.check('SetArcDirection returns previous', 1 /* ArcDirection.COUNTERCLOCKWISE */, SetArcDirection(mem, 2 /* ArcDirection.CLOCKWISE */));
|
|
252
252
|
Pie(mem, 100, 100, 200, 200, 150, 100, 100, 150); // 起 12 点终 9 点:顺时针 → 右下 270°
|
|
253
253
|
readPx();
|
|
254
254
|
t.check('clockwise sweep fills opposite side', RED, px(180, 180));
|
|
255
255
|
t.check('clockwise sweep skips upper-left', WHITE, px(118, 128));
|
|
256
|
-
SetArcDirection(mem, 1 /*
|
|
256
|
+
SetArcDirection(mem, 1 /* ArcDirection.COUNTERCLOCKWISE */); // 恢复默认
|
|
257
257
|
SelectObject(mem, dirOldB);
|
|
258
258
|
DeleteObject(dirBrush);
|
|
259
259
|
t.section('SetPolyFillMode: ALTERNATE vs WINDING (pentagram)');
|
|
@@ -265,7 +265,7 @@ export const suite = {
|
|
|
265
265
|
V.push({ x: Math.round(150 + 55 * Math.cos(a)), y: Math.round(150 + 55 * Math.sin(a)) });
|
|
266
266
|
}
|
|
267
267
|
const star = [V[0], V[2], V[4], V[1], V[3]];
|
|
268
|
-
t.check('default fill mode = ALTERNATE', 1 /*
|
|
268
|
+
t.check('default fill mode = ALTERNATE', 1 /* PolyFillMode.ALTERNATE */, SetPolyFillMode(mem, 1 /* PolyFillMode.ALTERNATE */));
|
|
269
269
|
const starBrush = CreateSolidBrush(RED);
|
|
270
270
|
const starOldB = SelectObject(mem, starBrush);
|
|
271
271
|
Polygon(mem, star, 5);
|
|
@@ -279,18 +279,18 @@ export const suite = {
|
|
|
279
279
|
}
|
|
280
280
|
t.checkTrue(`ALTERNATE: star drawn (${starRed}px)`, starRed > 200);
|
|
281
281
|
t.check('ALTERNATE: center hollow (even-odd)', WHITE, px(150, 150));
|
|
282
|
-
SetPolyFillMode(mem, 2 /*
|
|
282
|
+
SetPolyFillMode(mem, 2 /* PolyFillMode.WINDING */);
|
|
283
283
|
clearWhite();
|
|
284
284
|
Polygon(mem, star, 5);
|
|
285
285
|
readPx();
|
|
286
286
|
t.check('WINDING: center filled (nonzero)', RED, px(150, 150));
|
|
287
287
|
SelectObject(mem, starOldB);
|
|
288
288
|
DeleteObject(starBrush);
|
|
289
|
-
SetPolyFillMode(mem, 1 /*
|
|
289
|
+
SetPolyFillMode(mem, 1 /* PolyFillMode.ALTERNATE */); // 恢复默认
|
|
290
290
|
t.section('GetStockObject: stock objects, outline-only shape');
|
|
291
291
|
clearWhite();
|
|
292
|
-
const hollow = GetStockObject(5 /*
|
|
293
|
-
const stkPen = GetStockObject(7 /*
|
|
292
|
+
const hollow = GetStockObject(5 /* StockObject.NULL_BRUSH */);
|
|
293
|
+
const stkPen = GetStockObject(7 /* StockObject.BLACK_PEN */);
|
|
294
294
|
t.checkTrue(`stock handles non-zero (0x${hollow.toString(16)}, 0x${stkPen.toString(16)})`, hollow !== 0 && stkPen !== 0);
|
|
295
295
|
const stockOldBrush = SelectObject(mem, hollow);
|
|
296
296
|
const stockOldPen = SelectObject(mem, stkPen);
|
|
@@ -318,8 +318,8 @@ export const suite = {
|
|
|
318
318
|
// stock 对象是系统共享的,不 DeleteObject
|
|
319
319
|
t.section('CreateHatchBrush: textured fill');
|
|
320
320
|
clearWhite();
|
|
321
|
-
SetBkMode(mem, 1 /*
|
|
322
|
-
const hatch = CreateHatchBrush(0 /*
|
|
321
|
+
SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */); // 间隙透底 = 白
|
|
322
|
+
const hatch = CreateHatchBrush(0 /* HatchStyle.HORIZONTAL */, RED);
|
|
323
323
|
t.checkTrue('hatch brush created', hatch !== 0);
|
|
324
324
|
const hatchOldB = SelectObject(mem, hatch);
|
|
325
325
|
Rectangle(mem, 20, 20, 120, 60);
|
|
@@ -343,7 +343,7 @@ export const suite = {
|
|
|
343
343
|
t.check('no other colors in hatch', 0, hOther);
|
|
344
344
|
SelectObject(mem, hatchOldB);
|
|
345
345
|
DeleteObject(hatch);
|
|
346
|
-
SetBkMode(mem, 2 /*
|
|
346
|
+
SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
|
|
347
347
|
t.section('FrameRect/InvertRect: border and invert (user32)');
|
|
348
348
|
clearWhite();
|
|
349
349
|
const frBrush = CreateSolidBrush(RED);
|
|
@@ -372,15 +372,15 @@ export const suite = {
|
|
|
372
372
|
const stOldBmp = SelectObject(stTmp, stBmp);
|
|
373
373
|
const stFill = CreateSolidBrush(RED);
|
|
374
374
|
SelectObject(stTmp, stFill);
|
|
375
|
-
PatBlt(stTmp, 0, 0, 4, 4, 15728673 /*
|
|
376
|
-
t.checkTrue('StretchBlt ok', StretchBlt(mem, 10, 10, 40, 40, stTmp, 0, 0, 4, 4, 13369376 /*
|
|
375
|
+
PatBlt(stTmp, 0, 0, 4, 4, 15728673 /* RasterOp.PATCOPY */); // 源 4×4 全红
|
|
376
|
+
t.checkTrue('StretchBlt ok', StretchBlt(mem, 10, 10, 40, 40, stTmp, 0, 0, 4, 4, 13369376 /* RasterOp.SRCCOPY */) !== 0);
|
|
377
377
|
readPx();
|
|
378
378
|
t.check('scaled center red', RED, px(30, 30));
|
|
379
379
|
t.check('scaled near-origin red', RED, px(11, 11));
|
|
380
380
|
t.check('outside target untouched', WHITE, px(60, 30));
|
|
381
381
|
const stMode0 = GetStretchBltMode(mem);
|
|
382
|
-
t.check('SetStretchBltMode returns current', stMode0, SetStretchBltMode(mem, 4 /*
|
|
383
|
-
t.check('GetStretchBltMode = HALFTONE', 4 /*
|
|
382
|
+
t.check('SetStretchBltMode returns current', stMode0, SetStretchBltMode(mem, 4 /* StretchBltMode.HALFTONE */));
|
|
383
|
+
t.check('GetStretchBltMode = HALFTONE', 4 /* StretchBltMode.HALFTONE */, GetStretchBltMode(mem));
|
|
384
384
|
SelectObject(stTmp, stOldBmp);
|
|
385
385
|
DeleteObject(stFill);
|
|
386
386
|
DeleteObject(stBmp);
|
|
@@ -396,11 +396,11 @@ export const suite = {
|
|
|
396
396
|
const pkOldBmp = SelectObject(pkTmp, pkBmp);
|
|
397
397
|
const pkRed = CreateSolidBrush(RED);
|
|
398
398
|
SelectObject(pkTmp, pkRed);
|
|
399
|
-
PatBlt(pkTmp, 0, 0, 4, 4, 15728673 /*
|
|
399
|
+
PatBlt(pkTmp, 0, 0, 4, 4, 15728673 /* RasterOp.PATCOPY */); // 红底
|
|
400
400
|
const pkWhite = CreateSolidBrush(WHITE);
|
|
401
401
|
SelectObject(pkTmp, pkWhite);
|
|
402
|
-
PatBlt(pkTmp, 2, 0, 2, 2, 15728673 /*
|
|
403
|
-
PatBlt(pkTmp, 0, 2, 2, 2, 15728673 /*
|
|
402
|
+
PatBlt(pkTmp, 2, 0, 2, 2, 15728673 /* RasterOp.PATCOPY */); // 挖两白角 = 2×2 棋盘
|
|
403
|
+
PatBlt(pkTmp, 0, 2, 2, 2, 15728673 /* RasterOp.PATCOPY */);
|
|
404
404
|
SelectObject(pkTmp, pkOldBmp); // 位图退出选入状态
|
|
405
405
|
const pkPat = CreatePatternBrush(pkBmp);
|
|
406
406
|
t.checkTrue('pattern brush created', pkPat !== 0);
|
|
@@ -441,7 +441,7 @@ export const suite = {
|
|
|
441
441
|
t.check('dib bottom rows blue', BLUE, px(21, 23));
|
|
442
442
|
t.check('dib outside untouched', WHITE, px(30, 21));
|
|
443
443
|
clearWhite();
|
|
444
|
-
t.checkTrue('StretchDIBits ok', StretchDIBits(mem, 20, 20, 40, 40, 0, 0, 4, 4, dibBits, dibBmi, 0, 13369376 /*
|
|
444
|
+
t.checkTrue('StretchDIBits ok', StretchDIBits(mem, 20, 20, 40, 40, 0, 0, 4, 4, dibBits, dibBmi, 0, 13369376 /* RasterOp.SRCCOPY */) === 4);
|
|
445
445
|
readPx();
|
|
446
446
|
t.check('stretched top half red', RED, px(40, 30));
|
|
447
447
|
t.check('stretched bottom half blue', BLUE, px(40, 50));
|
|
@@ -457,7 +457,7 @@ export const suite = {
|
|
|
457
457
|
const plgOldB = SelectObject(plgTmp, plgBmp);
|
|
458
458
|
const plgRed = CreateSolidBrush(RED);
|
|
459
459
|
SelectObject(plgTmp, plgRed);
|
|
460
|
-
PatBlt(plgTmp, 0, 0, 40, 40, 15728673 /*
|
|
460
|
+
PatBlt(plgTmp, 0, 0, 40, 40, 15728673 /* RasterOp.PATCOPY */); // 源 40×40 全红
|
|
461
461
|
// 三点 TL(40,60) TR(160,60) BL(70,160) → 方向 s(120,0)+t(30,100),中心 (115,110)
|
|
462
462
|
t.checkTrue('PlgBlt ok', PlgBlt(mem, [{ x: 40, y: 60 }, { x: 160, y: 60 }, { x: 70, y: 160 }], plgTmp, 0, 0, 40, 40, NULL, 0, 0) !== 0);
|
|
463
463
|
readPx();
|
|
@@ -478,7 +478,7 @@ export const suite = {
|
|
|
478
478
|
const mkOldB = SelectObject(mkTmp, mkBmp);
|
|
479
479
|
const mkRed = CreateSolidBrush(RED);
|
|
480
480
|
SelectObject(mkTmp, mkRed);
|
|
481
|
-
PatBlt(mkTmp, 0, 0, 4, 4, 15728673 /*
|
|
481
|
+
PatBlt(mkTmp, 0, 0, 4, 4, 15728673 /* RasterOp.PATCOPY */); // 源 4×4 全红
|
|
482
482
|
// 1bpp 掩码 4×4:行按 word(2B) 对齐(CreateBitmap 惯例,非 DIB 的 4B)——
|
|
483
483
|
// 行 0/2 = 0xFF(白)、行 1/3 = 0x00(黑)
|
|
484
484
|
const mkBits = new PtrArrayBuffer(8);
|
|
@@ -487,9 +487,9 @@ export const suite = {
|
|
|
487
487
|
mkU8[4] = 0xFF;
|
|
488
488
|
const mask = CreateBitmap(4, 4, 1, 1, mkBits);
|
|
489
489
|
t.checkTrue('CreateBitmap(1bpp) ok', mask !== 0);
|
|
490
|
-
PatBlt(mem, 30, 30, 4, 4, 66 /*
|
|
490
|
+
PatBlt(mem, 30, 30, 4, 4, 66 /* RasterOp.BLACKNESS */); // 目标底黑 → back 白可辨
|
|
491
491
|
// MAKEROP4(fore=SRCCOPY 取源, back=WHITENESS 画白):back 码在 bit31..24、fore 在 bit23..16
|
|
492
|
-
const rop4 = (((16711778 /*
|
|
492
|
+
const rop4 = (((16711778 /* RasterOp.WHITENESS */ << 8) & 0xFF000000) | 13369376 /* RasterOp.SRCCOPY */) >>> 0;
|
|
493
493
|
t.checkTrue('MaskBlt ok', MaskBlt(mem, 30, 30, 4, 4, mkTmp, 0, 0, mask, 0, 0, rop4) !== 0);
|
|
494
494
|
readPx();
|
|
495
495
|
t.check('mask row0 = fore (red)', RED, px(31, 30));
|
|
@@ -512,10 +512,10 @@ export const suite = {
|
|
|
512
512
|
const trOldB = SelectObject(trTmp, trBmp);
|
|
513
513
|
const trRed = CreateSolidBrush(RED);
|
|
514
514
|
SelectObject(trTmp, trRed);
|
|
515
|
-
PatBlt(trTmp, 0, 0, 20, 16, 15728673 /*
|
|
515
|
+
PatBlt(trTmp, 0, 0, 20, 16, 15728673 /* RasterOp.PATCOPY */); // 左半红
|
|
516
516
|
const trBlue = CreateSolidBrush(BLUE);
|
|
517
517
|
SelectObject(trTmp, trBlue);
|
|
518
|
-
PatBlt(trTmp, 20, 0, 20, 16, 15728673 /*
|
|
518
|
+
PatBlt(trTmp, 20, 0, 20, 16, 15728673 /* RasterOp.PATCOPY */); // 右半蓝 = 键色
|
|
519
519
|
t.checkTrue('TransparentBlt ok', TransparentBlt(mem, 20, 20, 40, 16, trTmp, 0, 0, 40, 16, BLUE) !== 0);
|
|
520
520
|
readPx();
|
|
521
521
|
t.check('non-key pixels copied (red)', RED, px(25, 25));
|
|
@@ -538,7 +538,7 @@ export const suite = {
|
|
|
538
538
|
const abOldB = SelectObject(abTmp, abBmp);
|
|
539
539
|
const abGreen = CreateSolidBrush(GREEN);
|
|
540
540
|
SelectObject(abTmp, abGreen);
|
|
541
|
-
PatBlt(abTmp, 0, 0, 40, 16, 15728673 /*
|
|
541
|
+
PatBlt(abTmp, 0, 0, 40, 16, 15728673 /* RasterOp.PATCOPY */); // 源 = 纯绿(不透明)
|
|
542
542
|
// 完全覆盖:SourceConstantAlpha=255、无调制(BlendFlags=0)、BlendOp=AC_SRC_OVER(0)
|
|
543
543
|
t.checkTrue('AlphaBlend full alpha ok', AlphaBlend(mem, 20, 20, 40, 16, abTmp, 0, 0, 40, 16, { BlendOp: 0, BlendFlags: 0, SourceConstantAlpha: 255, AlphaFormat: 0 }) !== 0);
|
|
544
544
|
readPx();
|
|
@@ -565,7 +565,7 @@ export const suite = {
|
|
|
565
565
|
t.section('TextOut: transparent background + text color');
|
|
566
566
|
clearWhite();
|
|
567
567
|
SetBkColor(mem, BLUE); // 衬底设蓝:若 TRANSPARENT 未生效,字底必现蓝块
|
|
568
|
-
SetBkMode(mem, 1 /*
|
|
568
|
+
SetBkMode(mem, 1 /* BackgroundMode.TRANSPARENT */);
|
|
569
569
|
SetTextColor(mem, RED);
|
|
570
570
|
t.checkTrue('TextOut success', TextOut(mem, 20, 100, 'Hello GDI', 9) !== 0);
|
|
571
571
|
readPx();
|
|
@@ -583,7 +583,7 @@ export const suite = {
|
|
|
583
583
|
}
|
|
584
584
|
t.checkTrue(`glyph pixels rendered (red=${redPx})`, redPx > 20);
|
|
585
585
|
t.checkTrue(`transparent bg: zero blue backdrop (blue=${bluePx})`, bluePx === 0);
|
|
586
|
-
SetBkMode(mem, 2 /*
|
|
586
|
+
SetBkMode(mem, 2 /* BackgroundMode.OPAQUE */);
|
|
587
587
|
SetBkColor(mem, WHITE);
|
|
588
588
|
SetTextColor(mem, 0);
|
|
589
589
|
t.section('text metrics/align: extent + SetTextAlign + ExtTextOut');
|
|
@@ -603,7 +603,7 @@ export const suite = {
|
|
|
603
603
|
t.checkTrue(`tmAveCharWidth sane (${tmv.tmAveCharWidth})`, (tmv.tmAveCharWidth ?? 0) >= 4 && (tmv.tmAveCharWidth ?? 0) <= 48);
|
|
604
604
|
// (c) SetTextAlign 右对齐:字形全部落在锚点左侧
|
|
605
605
|
SetTextColor(mem, RED);
|
|
606
|
-
t.check('default align = 0 (LEFT|TOP|NOUPDATECP)', 0, SetTextAlign(mem, 2 /*
|
|
606
|
+
t.check('default align = 0 (LEFT|TOP|NOUPDATECP)', 0, SetTextAlign(mem, 2 /* TextAlign.TA_RIGHT */));
|
|
607
607
|
TextOut(mem, 200, 100, 'Right', 5);
|
|
608
608
|
readPx();
|
|
609
609
|
let rRight = 0;
|
|
@@ -621,12 +621,12 @@ export const suite = {
|
|
|
621
621
|
}
|
|
622
622
|
t.checkTrue(`right-aligned glyphs left of anchor (red=${rRight})`, rRight > 10);
|
|
623
623
|
t.check('no glyphs right of anchor', 0, rWrong);
|
|
624
|
-
SetTextAlign(mem, 0 /*
|
|
624
|
+
SetTextAlign(mem, 0 /* TextAlign.TA_LEFT */); // 恢复 0
|
|
625
625
|
SetTextColor(mem, 0);
|
|
626
626
|
// (d) ExtTextOut ETO_OPAQUE 衬底(lprc 对象形直传 = encoder 入参位)
|
|
627
627
|
SetTextColor(mem, RED);
|
|
628
628
|
SetBkColor(mem, BLUE);
|
|
629
|
-
t.checkTrue('ExtTextOut ETO_OPAQUE ok', ExtTextOut(mem, 20, 100, 2 /*
|
|
629
|
+
t.checkTrue('ExtTextOut ETO_OPAQUE ok', ExtTextOut(mem, 20, 100, 2 /* TextOutOptions.ETO_OPAQUE */, { left: 18, top: 98, right: 100, bottom: 118 }, 'Opaque', 6, NULL) !== 0);
|
|
630
630
|
readPx();
|
|
631
631
|
let oBlue = 0;
|
|
632
632
|
let oRed = 0;
|