xref: /netbsd-src/sys/dev/rasops/rasops_putchar_width.h (revision f48f7ada9d22e3ff89ebff44f0a21e8c445b5344)
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