rasops_putchar_width.h revision 1.15.8.2 1 1.15.8.2 martin /* $NetBSD: rasops_putchar_width.h,v 1.15.8.2 2020/04/13 08:04:47 martin Exp $ */
2 1.15.8.2 martin
3 1.15.8.2 martin /* NetBSD: rasops8.c,v 1.41 2019/07/25 03:02:44 rin Exp */
4 1.15.8.2 martin /*-
5 1.15.8.2 martin * Copyright (c) 1999 The NetBSD Foundation, Inc.
6 1.15.8.2 martin * All rights reserved.
7 1.15.8.2 martin *
8 1.15.8.2 martin * This code is derived from software contributed to The NetBSD Foundation
9 1.15.8.2 martin * by Andrew Doran.
10 1.15.8.2 martin *
11 1.15.8.2 martin * Redistribution and use in source and binary forms, with or without
12 1.15.8.2 martin * modification, are permitted provided that the following conditions
13 1.15.8.2 martin * are met:
14 1.15.8.2 martin * 1. Redistributions of source code must retain the above copyright
15 1.15.8.2 martin * notice, this list of conditions and the following disclaimer.
16 1.15.8.2 martin * 2. Redistributions in binary form must reproduce the above copyright
17 1.15.8.2 martin * notice, this list of conditions and the following disclaimer in the
18 1.15.8.2 martin * documentation and/or other materials provided with the distribution.
19 1.15.8.2 martin *
20 1.15.8.2 martin * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 1.15.8.2 martin * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.15.8.2 martin * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.15.8.2 martin * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.15.8.2 martin * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.15.8.2 martin * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.15.8.2 martin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.15.8.2 martin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.15.8.2 martin * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.15.8.2 martin * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.15.8.2 martin * POSSIBILITY OF SUCH DAMAGE.
31 1.15.8.2 martin */
32 1.15.8.2 martin
33 1.15.8.2 martin #if RASOPS_DEPTH != 2 && RASOPS_DEPTH != 4 && RASOPS_DEPTH != 8 && \
34 1.15.8.2 martin RASOPS_DEPTH != 15 && RASOPS_DEPTH != 24 && RASOPS_DEPTH != 32
35 1.15.8.2 martin #error "Depth not supported"
36 1.15.8.2 martin #endif
37 1.15.8.2 martin
38 1.15.8.2 martin #if RASOPS_WIDTH != 8 && RASOPS_WIDTH != 12 && RASOPS_WIDTH != 16
39 1.15.8.2 martin #error "Width not supported"
40 1.15.8.2 martin #endif
41 1.15.8.2 martin
42 1.15.8.2 martin #if RASOPS_DEPTH == 2
43 1.15.8.2 martin #define STAMP_TYPE uint8_t
44 1.15.8.2 martin #elif RASOPS_DEPTH == 4
45 1.15.8.2 martin #define STAMP_TYPE uint16_t
46 1.15.8.2 martin #else
47 1.15.8.2 martin #define STAMP_TYPE uint32_t
48 1.15.8.2 martin #endif
49 1.15.8.2 martin
50 1.15.8.2 martin #if RASOPS_DEPTH <= 8
51 1.15.8.2 martin #define SUBST_UNIT 1
52 1.15.8.2 martin #elif RASOPS_DEPTH == 15
53 1.15.8.2 martin #define SUBST_UNIT 2
54 1.15.8.2 martin #elif RASOPS_DEPTH == 24
55 1.15.8.2 martin #define SUBST_UNIT 3
56 1.15.8.2 martin #elif RASOPS_DEPTH == 32
57 1.15.8.2 martin #define SUBST_UNIT 4
58 1.15.8.2 martin #endif
59 1.15.8.2 martin
60 1.15.8.2 martin #define SUBST_BYTES (SUBST_UNIT * (RASOPS_WIDTH / 4) * sizeof(STAMP_TYPE))
61 1.15.8.2 martin
62 1.15.8.2 martin #if RASOPS_DEPTH <= 8
63 1.15.8.2 martin #define FILLED_STAMP 15
64 1.15.8.2 martin #elif RASOPS_DEPTH == 15
65 1.15.8.2 martin #define FILLED_STAMP 30
66 1.15.8.2 martin #else
67 1.15.8.2 martin #define FILLED_STAMP 60
68 1.15.8.2 martin #endif
69 1.15.8.2 martin
70 1.15.8.2 martin /* ################################################################### */
71 1.15.8.2 martin
72 1.15.8.2 martin #if RASOPS_DEPTH <= 8
73 1.15.8.2 martin
74 1.15.8.2 martin #define SUBST_STAMP1(off, base) \
75 1.15.8.2 martin rp[(off) * 1 + 0] = stamp[base]
76 1.15.8.2 martin
77 1.15.8.2 martin #define SUBST_GLYPH1(index, nibble, off) \
78 1.15.8.2 martin do { \
79 1.15.8.2 martin int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
80 1.15.8.2 martin rp[(off) * 1 + 0] = STAMP_READ(so); \
81 1.15.8.2 martin } while (0 /* CONSTCOND */)
82 1.15.8.2 martin
83 1.15.8.2 martin #endif /* RASOPS_DEPTH <= 8 */
84 1.15.8.2 martin
85 1.15.8.2 martin /* ################################################################### */
86 1.15.8.2 martin
87 1.15.8.2 martin #if RASOPS_DEPTH == 15
88 1.15.8.2 martin
89 1.15.8.2 martin #define SUBST_STAMP1(off, base) \
90 1.15.8.2 martin rp[(off) * 2 + 0] = rp[(off) * 2 + 1] = stamp[base]
91 1.15.8.2 martin
92 1.15.8.2 martin #define SUBST_GLYPH1(index, nibble, off) \
93 1.15.8.2 martin do { \
94 1.15.8.2 martin int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
95 1.15.8.2 martin rp[(off) * 2 + 0] = STAMP_READ(so); \
96 1.15.8.2 martin rp[(off) * 2 + 1] = STAMP_READ(so + 4); \
97 1.15.8.2 martin } while (0 /* CONSTCOND */)
98 1.15.8.2 martin
99 1.15.8.2 martin #endif /* RASOPS_DEPTH == 15 */
100 1.15.8.2 martin
101 1.15.8.2 martin /* ################################################################### */
102 1.15.8.2 martin
103 1.15.8.2 martin #if RASOPS_DEPTH == 24
104 1.15.8.2 martin
105 1.15.8.2 martin #define SUBST_STAMP1(off, base) \
106 1.15.8.2 martin do { \
107 1.15.8.2 martin rp[(off) * 3 + 0] = stamp[(base) + 0]; \
108 1.15.8.2 martin rp[(off) * 3 + 1] = stamp[(base) + 1]; \
109 1.15.8.2 martin rp[(off) * 3 + 2] = stamp[(base) + 2]; \
110 1.15.8.2 martin } while (0 /* CONSTCOND */)
111 1.15.8.2 martin
112 1.15.8.2 martin #define SUBST_GLYPH1(index, nibble, off) \
113 1.15.8.2 martin do { \
114 1.15.8.2 martin int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
115 1.15.8.2 martin rp[(off) * 3 + 0] = STAMP_READ(so); \
116 1.15.8.2 martin rp[(off) * 3 + 1] = STAMP_READ(so + 4); \
117 1.15.8.2 martin rp[(off) * 3 + 2] = STAMP_READ(so + 8); \
118 1.15.8.2 martin } while (0 /* CONSTCOND */)
119 1.15.8.2 martin
120 1.15.8.2 martin #endif /* RASOPS_DEPTH == 24 */
121 1.15.8.2 martin
122 1.15.8.2 martin /* ################################################################### */
123 1.15.8.2 martin
124 1.15.8.2 martin #if RASOPS_DEPTH == 32
125 1.15.8.2 martin
126 1.15.8.2 martin #define SUBST_STAMP1(off, base) \
127 1.15.8.2 martin rp[(off) * 4 + 0] = rp[(off) * 4 + 1] = \
128 1.15.8.2 martin rp[(off) * 4 + 2] = rp[(off) * 4 + 3] = stamp[base]
129 1.15.8.2 martin
130 1.15.8.2 martin #define SUBST_GLYPH1(index, nibble, off) \
131 1.15.8.2 martin do { \
132 1.15.8.2 martin int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
133 1.15.8.2 martin rp[(off) * 4 + 0] = STAMP_READ(so); \
134 1.15.8.2 martin rp[(off) * 4 + 1] = STAMP_READ(so + 4); \
135 1.15.8.2 martin rp[(off) * 4 + 2] = STAMP_READ(so + 8); \
136 1.15.8.2 martin rp[(off) * 4 + 3] = STAMP_READ(so + 12); \
137 1.15.8.2 martin } while (0 /* CONSTCOND */)
138 1.15.8.2 martin
139 1.15.8.2 martin #endif /* RASOPS_DEPTH == 32 */
140 1.15.8.2 martin
141 1.15.8.2 martin /* ################################################################### */
142 1.15.8.2 martin
143 1.15.8.2 martin #if RASOPS_WIDTH == 8
144 1.15.8.2 martin #define SUBST_STAMP(base) \
145 1.15.8.2 martin do { \
146 1.15.8.2 martin SUBST_STAMP1(0, base); \
147 1.15.8.2 martin SUBST_STAMP1(1, base); \
148 1.15.8.2 martin } while (0 /* CONSTCOND */)
149 1.15.8.2 martin #elif RASOPS_WIDTH == 12
150 1.15.8.2 martin #define SUBST_STAMP(base) \
151 1.15.8.2 martin do { \
152 1.15.8.2 martin SUBST_STAMP1(0, base); \
153 1.15.8.2 martin SUBST_STAMP1(1, base); \
154 1.15.8.2 martin SUBST_STAMP1(2, base); \
155 1.15.8.2 martin } while (0 /* CONSTCOND */)
156 1.15.8.2 martin #elif RASOPS_WIDTH == 16
157 1.15.8.2 martin #define SUBST_STAMP(base) \
158 1.15.8.2 martin do { \
159 1.15.8.2 martin SUBST_STAMP1(0, base); \
160 1.15.8.2 martin SUBST_STAMP1(1, base); \
161 1.15.8.2 martin SUBST_STAMP1(2, base); \
162 1.15.8.2 martin SUBST_STAMP1(3, base); \
163 1.15.8.2 martin } while (0 /* CONSTCOND */)
164 1.15.8.2 martin #endif
165 1.15.8.2 martin
166 1.15.8.2 martin /* ################################################################### */
167 1.15.8.2 martin
168 1.15.8.2 martin #if RASOPS_WIDTH == 8
169 1.15.8.2 martin #define SUBST_GLYPH \
170 1.15.8.2 martin do { \
171 1.15.8.2 martin SUBST_GLYPH1(0, 1, 0); \
172 1.15.8.2 martin SUBST_GLYPH1(0, 0, 1); \
173 1.15.8.2 martin } while (0 /* CONSTCOND */)
174 1.15.8.2 martin #elif RASOPS_WIDTH == 12
175 1.15.8.2 martin #define SUBST_GLYPH \
176 1.15.8.2 martin do { \
177 1.15.8.2 martin SUBST_GLYPH1(0, 1, 0); \
178 1.15.8.2 martin SUBST_GLYPH1(0, 0, 1); \
179 1.15.8.2 martin SUBST_GLYPH1(1, 1, 2); \
180 1.15.8.2 martin } while (0 /* CONSTCOND */)
181 1.15.8.2 martin #elif RASOPS_WIDTH == 16
182 1.15.8.2 martin #define SUBST_GLYPH \
183 1.15.8.2 martin do { \
184 1.15.8.2 martin SUBST_GLYPH1(0, 1, 0); \
185 1.15.8.2 martin SUBST_GLYPH1(0, 0, 1); \
186 1.15.8.2 martin SUBST_GLYPH1(1, 1, 2); \
187 1.15.8.2 martin SUBST_GLYPH1(1, 0, 3); \
188 1.15.8.2 martin } while (0 /* CONSTCOND */)
189 1.15.8.2 martin #endif
190 1.15.8.2 martin
191 1.15.8.2 martin /* ################################################################### */
192 1.15.8.2 martin
193 1.15.8.2 martin #define NAME(depth, width) NAME1(depth, width)
194 1.15.8.2 martin #define NAME1(depth, width) rasops ## depth ## _putchar ## width
195 1.15.8.2 martin
196 1.15.8.2 martin #define PUTCHAR(depth) PUTCHAR1(depth)
197 1.15.8.2 martin #define PUTCHAR1(depth) rasops ## depth ## _putchar
198 1.15.8.2 martin
199 1.15.8.2 martin #define MAKESTAMP(depth) MAKESTAMP1(depth)
200 1.15.8.2 martin #define MAKESTAMP1(depth) rasops ## depth ## _makestamp
201 1.15.8.2 martin
202 1.15.8.2 martin /*
203 1.15.8.2 martin * Width-optimized putchar function.
204 1.15.8.2 martin */
205 1.15.8.2 martin static void
206 1.15.8.2 martin NAME(RASOPS_DEPTH, RASOPS_WIDTH)(void *cookie, int row, int col, u_int uc,
207 1.15.8.2 martin long attr)
208 1.15.8.2 martin {
209 1.15.8.2 martin struct rasops_info *ri = (struct rasops_info *)cookie;
210 1.15.8.2 martin struct wsdisplay_font *font = PICK_FONT(ri, uc);
211 1.15.8.2 martin int height;
212 1.15.8.2 martin uint8_t *fr;
213 1.15.8.2 martin bool do_ul;
214 1.15.8.2 martin STAMP_TYPE *rp, *hp;
215 1.15.8.2 martin
216 1.15.8.2 martin hp = NULL; /* XXX GCC */
217 1.15.8.2 martin
218 1.15.8.2 martin /* check if character fits into font limits */
219 1.15.8.2 martin if (__predict_false(!CHAR_IN_FONT(uc, font)))
220 1.15.8.2 martin return;
221 1.15.8.2 martin
222 1.15.8.2 martin #ifdef RASOPS_CLIPPING
223 1.15.8.2 martin /* Catches 'row < 0' case too */
224 1.15.8.2 martin if ((unsigned)row >= (unsigned)ri->ri_rows)
225 1.15.8.2 martin return;
226 1.15.8.2 martin
227 1.15.8.2 martin if ((unsigned)col >= (unsigned)ri->ri_cols)
228 1.15.8.2 martin return;
229 1.15.8.2 martin #endif
230 1.15.8.2 martin
231 1.15.8.2 martin /*
232 1.15.8.2 martin * We don't care attributions other than back/foreground
233 1.15.8.2 martin * colors when using stamp.
234 1.15.8.2 martin */
235 1.15.8.2 martin do_ul = (attr & WSATTR_UNDERLINE) != 0;
236 1.15.8.2 martin attr &= (ATTR_MASK_BG | ATTR_MASK_FG);
237 1.15.8.2 martin
238 1.15.8.2 martin /* Recompute stamp? */
239 1.15.8.2 martin if (attr != stamp_attr || __predict_false(ri != stamp_ri))
240 1.15.8.2 martin MAKESTAMP(RASOPS_DEPTH)(ri, attr);
241 1.15.8.2 martin
242 1.15.8.2 martin height = font->fontheight;
243 1.15.8.2 martin
244 1.15.8.2 martin rp = (STAMP_TYPE *)(ri->ri_bits + FBOFFSET(ri, row, col));
245 1.15.8.2 martin if (ri->ri_hwbits)
246 1.15.8.2 martin hp = (STAMP_TYPE *)(ri->ri_hwbits + FBOFFSET(ri, row, col));
247 1.15.8.2 martin
248 1.15.8.2 martin if (uc == ' ') {
249 1.15.8.2 martin while (height--) {
250 1.15.8.2 martin SUBST_STAMP(0);
251 1.15.8.2 martin if (ri->ri_hwbits) {
252 1.15.8.2 martin memcpy(hp, rp, SUBST_BYTES);
253 1.15.8.2 martin DELTA(hp, ri->ri_stride, STAMP_TYPE *);
254 1.15.8.2 martin }
255 1.15.8.2 martin DELTA(rp, ri->ri_stride, STAMP_TYPE *);
256 1.15.8.2 martin }
257 1.15.8.2 martin } else {
258 1.15.8.2 martin fr = FONT_GLYPH(uc, font, ri);
259 1.15.8.2 martin while (height--) {
260 1.15.8.2 martin SUBST_GLYPH;
261 1.15.8.2 martin fr += font->stride;
262 1.15.8.2 martin if (ri->ri_hwbits) {
263 1.15.8.2 martin memcpy(hp, rp, SUBST_BYTES);
264 1.15.8.2 martin DELTA(hp, ri->ri_stride, STAMP_TYPE *);
265 1.15.8.2 martin }
266 1.15.8.2 martin DELTA(rp, ri->ri_stride, STAMP_TYPE *);
267 1.15.8.2 martin }
268 1.15.8.2 martin }
269 1.15.8.2 martin
270 1.15.8.2 martin /* Do underline */
271 1.15.8.2 martin if (do_ul) {
272 1.15.8.2 martin DELTA(rp, - ri->ri_stride * ri->ri_ul.off, STAMP_TYPE *);
273 1.15.8.2 martin if (ri->ri_hwbits)
274 1.15.8.2 martin DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
275 1.15.8.2 martin STAMP_TYPE *);
276 1.15.8.2 martin
277 1.15.8.2 martin for (height = ri->ri_ul.height; height; height--) {
278 1.15.8.2 martin DELTA(rp, - ri->ri_stride, STAMP_TYPE *);
279 1.15.8.2 martin SUBST_STAMP(FILLED_STAMP);
280 1.15.8.2 martin if (ri->ri_hwbits) {
281 1.15.8.2 martin DELTA(hp, - ri->ri_stride, STAMP_TYPE *);
282 1.15.8.2 martin memcpy(hp, rp, SUBST_BYTES);
283 1.15.8.2 martin }
284 1.15.8.2 martin }
285 1.15.8.2 martin }
286 1.15.8.2 martin }
287 1.15.8.2 martin
288 1.15.8.2 martin #undef STAMP_TYPE
289 1.15.8.2 martin
290 1.15.8.2 martin #undef SUBST_UNIT
291 1.15.8.2 martin #undef SUBST_BYTES
292 1.15.8.2 martin
293 1.15.8.2 martin #undef FILLED_STAMP
294 1.15.8.2 martin
295 1.15.8.2 martin #undef SUBST_STAMP1
296 1.15.8.2 martin #undef SUBST_STAMP
297 1.15.8.2 martin
298 1.15.8.2 martin #undef SUBST_GLYPH1
299 1.15.8.2 martin #undef SUBST_GLYPH
300 1.15.8.2 martin
301 1.15.8.2 martin #undef NAME
302 1.15.8.2 martin #undef NAME1
303 1.15.8.2 martin
304 1.15.8.2 martin #undef PUTCHAR
305 1.15.8.2 martin #undef PUTCHAR1
306 1.15.8.2 martin
307 1.15.8.2 martin #undef MAKESTAMP
308 1.15.8.2 martin #undef MAKESTAMP1
309