nx_x11_paint.nx source
↩ module page · 219 lines · 7311 B
1// nx_x11_paint.nx -- bits-up X11 painting primitives.
2//
3// Session 3 of the bits-up browser arc. Adds the wire opcodes that
4// actually draw inside a window: CreateGC, ChangeGC, PolyFillRectangle,
5// ImageText8. Composes nx_x11_connect + nx_x11_window.
6//
7// Opcodes (X Protocol ยง10):
8// 55 CreateGC
9// 56 ChangeGC
10// 70 PolyFillRectangle
11// 76 ImageText8
12//
13// GC value mask bits we use:
14// GCForeground = 0x00000004
15//
16// Event mask bits (for the CreateWindow value list):
17// ExposureMask = 0x00008000
18// KeyPressMask = 0x00000001
19// ButtonPressMask = 0x00000004
20// StructureNotifyMask = 0x00020000
21//
22// license_tier: ORIGINAL
23// genealogy_id: international-research-sources/x_org/xproto_v11_r0
24// lineage_id: nishi_x11_paint_q10
25
26import "nx_syscalls.nx"
27import "nx_x11_connect.nx"
28import "nx_x11_window.nx"
29
30const NX_X11_EVENT_EXPOSURE: i64 = 0x00008000
31const NX_X11_EVENT_KEY_PRESS: i64 = 0x00000001
32const NX_X11_EVENT_BUTTON_PRESS: i64 = 0x00000004
33const NX_X11_EVENT_BUTTON_RELEASE: i64 = 0x00000008
34const NX_X11_EVENT_POINTER_MOTION: i64 = 0x00000040
35const NX_X11_EVENT_STRUCTURE: i64 = 0x00020000
36
37const NX_X11_GC_FOREGROUND: i64 = 0x00000004
38
39// CreateGC (opcode 55). Sets foreground pixel. Returns gc_id.
40func nx_x11_create_gc(conn: *X11Conn, drawable: i64, fg_pixel: i64) -> i64 {
41 let gc: i64 = nx_x11_alloc_id(conn)
42
43 // 16 bytes core + 4 bytes value (1 value = foreground)
44 let total: i64 = 20
45 let words: i64 = total / 4
46
47 let req: *u8 = sys_mmap(32)
48 var i: i64 = 0
49 while i < 32 { req[i] = 0; i = i + 1 }
50
51 req[0] = 55
52 req[1] = 0
53 _x11_wr_u16(req, 2, words)
54 _x11_wr_u32(req, 4, gc)
55 _x11_wr_u32(req, 8, drawable)
56 _x11_wr_u32(req, 12, NX_X11_GC_FOREGROUND)
57 _x11_wr_u32(req, 16, fg_pixel)
58
59 if _x11_send(conn, req, total) < 0 { return 0 - 1 }
60 return gc
61}
62
63// ChangeGC (opcode 56) -- update an existing GC's foreground.
64func nx_x11_set_gc_foreground(conn: *X11Conn, gc: i64, fg_pixel: i64) -> i64 {
65 let total: i64 = 16
66 let words: i64 = total / 4
67 let req: *u8 = sys_mmap(32)
68 var i: i64 = 0
69 while i < 32 { req[i] = 0; i = i + 1 }
70 req[0] = 56
71 req[1] = 0
72 _x11_wr_u16(req, 2, words)
73 _x11_wr_u32(req, 4, gc)
74 _x11_wr_u32(req, 8, NX_X11_GC_FOREGROUND)
75 _x11_wr_u32(req, 12, fg_pixel)
76 return _x11_send(conn, req, total)
77}
78
79// PolyFillRectangle (opcode 70) -- one rectangle.
80func nx_x11_fill_rect(conn: *X11Conn, drawable: i64, gc: i64,
81 x: i64, y: i64, w: i64, h: i64) -> i64 {
82 let total: i64 = 20
83 let words: i64 = total / 4
84 let req: *u8 = sys_mmap(32)
85 var i: i64 = 0
86 while i < 32 { req[i] = 0; i = i + 1 }
87 req[0] = 70
88 req[1] = 0
89 _x11_wr_u16(req, 2, words)
90 _x11_wr_u32(req, 4, drawable)
91 _x11_wr_u32(req, 8, gc)
92 _x11_wr_u16(req, 12, x)
93 _x11_wr_u16(req, 14, y)
94 _x11_wr_u16(req, 16, w)
95 _x11_wr_u16(req, 18, h)
96 return _x11_send(conn, req, total)
97}
98
99// ImageText8 (opcode 76) -- draw text using the server's default font.
100// Up to 255 bytes of string; we cap at 254 to be safe.
101func nx_x11_image_text8(conn: *X11Conn, drawable: i64, gc: i64,
102 x: i64, y: i64, text: *u8, text_len: i64) -> i64 {
103 var n: i64 = text_len
104 if n > 254 { n = 254 }
105 // request body: 16 bytes core + n bytes string padded to 4
106 var padded: i64 = n
107 if (padded & 3) != 0 { padded = padded + 4 - (padded & 3) }
108 let total: i64 = 16 + padded
109 let words: i64 = total / 4
110
111 let req: *u8 = sys_mmap(total + 16)
112 var i: i64 = 0
113 while i < total + 16 { req[i] = 0; i = i + 1 }
114 req[0] = 76
115 req[1] = n as u8 // string length
116 _x11_wr_u16(req, 2, words)
117 _x11_wr_u32(req, 4, drawable)
118 _x11_wr_u32(req, 8, gc)
119 _x11_wr_u16(req, 12, x)
120 _x11_wr_u16(req, 14, y)
121 var k: i64 = 0
122 while k < n { req[16 + k] = text[k]; k = k + 1 }
123 return _x11_send(conn, req, total)
124}
125
126// PolyText8 (opcode 74) -- draws text WITHOUT filling the glyph-cell background, so the
127// already-painted page/element background shows through (transparent text). This is what a real
128// browser needs: ImageText8 paints an opaque box (the GC background, default black) behind every
129// glyph, which is what made the page look like "black background + colored text". One TEXTITEM8:
130// [length][delta=0][string].
131func nx_x11_poly_text8(conn: *X11Conn, drawable: i64, gc: i64,
132 x: i64, y: i64, text: *u8, text_len: i64) -> i64 {
133 var n: i64 = text_len
134 if n > 254 { n = 254 }
135 // 16-byte core + TEXTITEM8 (1 len + 1 delta + n string), padded to a 4-byte boundary
136 var total: i64 = 18 + n
137 if (total & 3) != 0 { total = total + 4 - (total & 3) }
138 let words: i64 = total / 4
139 let req: *u8 = sys_mmap(total + 16)
140 var i: i64 = 0
141 while i < total + 16 { req[i] = 0; i = i + 1 }
142 req[0] = 74
143 req[1] = 0
144 _x11_wr_u16(req, 2, words)
145 _x11_wr_u32(req, 4, drawable)
146 _x11_wr_u32(req, 8, gc)
147 _x11_wr_u16(req, 12, x)
148 _x11_wr_u16(req, 14, y)
149 req[16] = n as u8 // TEXTITEM8 string length
150 req[17] = 0 as u8 // delta
151 var k: i64 = 0
152 while k < n { req[18 + k] = text[k]; k = k + 1 }
153 return _x11_send(conn, req, total)
154}
155
156// OpenFont (opcode 45) -- load a server font by name (e.g. "9x15", "fixed", or an XLFD).
157// Returns the font id, or -1. Set it on a GC with nx_x11_set_gc_font before ImageText8.
158func nx_x11_open_font(conn: *X11Conn, name: *u8, name_len: i64) -> i64 {
159 let fid: i64 = nx_x11_alloc_id(conn)
160 var padded: i64 = name_len
161 if (padded & 3) != 0 { padded = padded + 4 - (padded & 3) }
162 let total: i64 = 12 + padded
163 let req: *u8 = sys_mmap(total + 16)
164 var i: i64 = 0
165 while i < total + 16 { req[i] = 0; i = i + 1 }
166 req[0] = 45
167 _x11_wr_u16(req, 2, total / 4)
168 _x11_wr_u32(req, 4, fid)
169 _x11_wr_u16(req, 8, name_len)
170 var k: i64 = 0
171 while k < name_len { req[12 + k] = name[k]; k = k + 1 }
172 if _x11_send(conn, req, total) < 0 { return 0 - 1 }
173 return fid
174}
175
176// ChangeGC (opcode 56) -- set the GC's FONT (GCFont value mask 0x4000), so ImageText8 has a font.
177func nx_x11_set_gc_font(conn: *X11Conn, gc: i64, fid: i64) -> i64 {
178 let total: i64 = 16
179 let req: *u8 = sys_mmap(32)
180 var i: i64 = 0
181 while i < 32 { req[i] = 0; i = i + 1 }
182 req[0] = 56
183 _x11_wr_u16(req, 2, total / 4)
184 _x11_wr_u32(req, 4, gc)
185 _x11_wr_u32(req, 8, 0x00004000)
186 _x11_wr_u32(req, 12, fid)
187 return _x11_send(conn, req, total)
188}
189
190// Read ONE 32-byte X11 event/error/reply. Caller dispatches by
191// out[0] (kind byte).
192//
193// kind:
194// 0 = Error reply (out[1] = error code)
195// 1 = (regular Reply)
196// 2 = KeyPress
197// 3 = KeyRelease
198// 4 = ButtonPress
199// 5 = ButtonRelease
200// 6 = MotionNotify
201// 12 = Expose
202// 17 = DestroyNotify
203// 22 = ConfigureNotify
204// ...
205//
206// Returns 0 on success, negative on read failure.
207func nx_x11_read_event(conn: *X11Conn, out: *u8) -> i64 {
208 var got: i64 = 0
209 while got < 32 {
210 let r: i64 = sys_read(conn.fd, ((out as i64) + got) as *u8, 32 - got)
211 if r <= 0 { return 0 - 1 }
212 got = got + r
213 }
214 return 0
215}
216
217func main() -> i64 {
218 return 0
219}