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