1/* $NetBSD: rasops1-4_putchar.h,v 1.3 2019/08/10 01:24:17 rin Exp $ */
2
3/* NetBSD: rasops_bitops.h,v 1.23 2019/08/02 04:39:09 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#define	PIXEL_BITS	RASOPS_DEPTH
34
35#if   RASOPS_DEPTH == 1
36#define	PIXEL_SHIFT	0
37#elif RASOPS_DEPTH == 2
38#define	PIXEL_SHIFT	1
39#elif RASOPS_DEPTH == 4
40#define	PIXEL_SHIFT	2
41#else
42#error "Depth not supported"
43#endif
44
45#ifndef RASOPS_AA
46#define	COLOR_MASK	__BITS(32 - PIXEL_BITS, 31)
47#else
48#  if RASOPS_DEPTH == 2
49#define	COLOR_MASK	0x3
50#  else
51#error "Anti-aliasing not supported"
52#  endif
53#endif
54
55#ifndef RASOPS_AA
56#define	PIXEL_OR(tmp)							\
57	do {								\
58		(tmp) |= clr[(fb >> 31) & 1] >> bit;			\
59		fb <<= 1;						\
60	} while (0 /* CONSTCOND */)
61#else
62#define	PIXEL_OR(tmp)							\
63	do {								\
64		uint8_t c, w = *fr++;					\
65		if (w == 0xff)						\
66			c = clr[1];					\
67		else if (w == 0)					\
68			c = clr[0];					\
69		else							\
70			c = (w * clr[1] + (0xff - w) * clr[0]) >> 8;	\
71		(tmp) |= c << (32 - PIXEL_BITS - bit);			\
72	} while (0 /* CONSTCOND */)
73#endif
74
75#define	NAME(depth)	NAME1(depth)
76#ifndef RASOPS_AA
77#define	NAME1(depth)	rasops ## depth ## _ ## putchar
78#else
79#define	NAME1(depth)	rasops ## depth ## _ ## putchar_aa
80#endif
81
82/*
83 * Paint a single character. This function is also applicable to
84 * monochrome, but that in rasops1.c is much simpler and faster.
85 */
86static void
87NAME(RASOPS_DEPTH)(void *cookie, int row, int col, u_int uc, long attr)
88{
89	struct rasops_info *ri = (struct rasops_info *)cookie;
90	struct wsdisplay_font *font = PICK_FONT(ri, uc);
91	int height, width, full, cnt, bit;
92	uint32_t bg, fg, lbg, rbg, clr[2], lmask, rmask, tmp;
93	uint32_t *rp, *bp, *hp;
94	uint8_t *fr;
95	bool space;
96
97	hp = NULL;	/* XXX GCC */
98
99	if (__predict_false(!CHAR_IN_FONT(uc, font)))
100		return;
101
102#ifdef RASOPS_CLIPPING
103	/* Catches 'row < 0' case too */
104	if ((unsigned)row >= (unsigned)ri->ri_rows)
105		return;
106
107	if ((unsigned)col >= (unsigned)ri->ri_cols)
108		return;
109#endif
110
111	height = font->fontheight;
112	width = font->fontwidth << PIXEL_SHIFT;
113	col *= width;
114
115	rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
116	    ((col >> 3) & ~3));
117	if (ri->ri_hwbits)
118		hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
119		    ((col >> 3) & ~3));
120
121	col &= 31;
122
123	bg = ATTR_BG(ri, attr);
124	fg = ATTR_FG(ri, attr);
125
126	/* If fg and bg match this becomes a space character */
127	if (uc == ' ' || __predict_false(fg == bg)) {
128		space = true;
129		fr = NULL;	/* XXX GCC */
130	} else {
131		space = false;
132		fr = FONT_GLYPH(uc, font, ri);
133	}
134
135	if (col + width <= 32) {
136		/* Single word, only one mask */
137		rmask = rasops_pmask[col][width & 31];
138		lmask = ~rmask;
139
140		if (space) {
141			bg &= rmask;
142			while (height--) {
143				tmp = (*rp & lmask) | bg;
144				*rp = tmp;
145				if (ri->ri_hwbits) {
146					*hp = tmp;
147					DELTA(hp, ri->ri_stride, uint32_t *);
148				}
149				DELTA(rp, ri->ri_stride, uint32_t *);
150			}
151		} else {
152			clr[0] = bg & COLOR_MASK;
153			clr[1] = fg & COLOR_MASK;
154
155			while (height--) {
156#ifndef RASOPS_AA
157				uint32_t fb = rasops_be32uatoh(fr);
158				fr += ri->ri_font->stride;
159#endif
160
161				tmp = 0;
162				for (bit = col; bit < col + width;
163				    bit += PIXEL_BITS)
164					PIXEL_OR(tmp);
165				tmp = (*rp & lmask) | MBE(tmp);
166				*rp = tmp;
167
168				if (ri->ri_hwbits) {
169					*hp = tmp;
170					DELTA(hp, ri->ri_stride, uint32_t *);
171				}
172
173				DELTA(rp, ri->ri_stride, uint32_t *);
174			}
175		}
176
177		/* Do underline */
178		if ((attr & WSATTR_UNDERLINE) != 0) {
179			DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
180			if (ri->ri_hwbits)
181				DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
182				    uint32_t *);
183
184			for (height = ri->ri_ul.height; height; height--) {
185				DELTA(rp, - ri->ri_stride, uint32_t *);
186				tmp = (*rp & lmask) | (fg & rmask);
187				*rp = tmp;
188				if (ri->ri_hwbits) {
189					DELTA(hp, - ri->ri_stride, uint32_t *);
190					*hp = tmp;
191				}
192			}
193		}
194
195		return;
196	}
197
198	/* Word boundary, two masks needed */
199	lmask = ~rasops_lmask[col];
200	rmask = ~rasops_rmask[(col + width) & 31];
201
202	if (lmask != -1)
203		width -= 32 - col;
204
205	full = width / 32;
206	width -= full * 32;
207
208	if (space) {
209		lbg = bg & ~lmask;
210		rbg = bg & ~rmask;
211
212		while (height--) {
213			bp = rp;
214
215			if (lmask != -1) {
216				*bp = (*bp & lmask) | lbg;
217				bp++;
218			}
219
220			for (cnt = full; cnt; cnt--)
221				*bp++ = bg;
222
223			if (rmask != -1)
224				*bp = (*bp & rmask) | rbg;
225
226			if (ri->ri_hwbits) {
227				memcpy(hp, rp, ((lmask != -1) + full +
228				    (rmask != -1)) << 2);
229				DELTA(hp, ri->ri_stride, uint32_t *);
230			}
231
232			DELTA(rp, ri->ri_stride, uint32_t *);
233		}
234	} else {
235		clr[0] = bg & COLOR_MASK;
236		clr[1] = fg & COLOR_MASK;
237
238		while (height--) {
239			bp = rp;
240
241#ifndef RASOPS_AA
242			uint32_t fb = rasops_be32uatoh(fr);
243			fr += ri->ri_font->stride;
244#endif
245
246			if (lmask != -1) {
247				tmp = 0;
248				for (bit = col; bit < 32; bit += PIXEL_BITS)
249					PIXEL_OR(tmp);
250				*bp = (*bp & lmask) | MBE(tmp);
251				bp++;
252			}
253
254			for (cnt = full; cnt; cnt--) {
255				tmp = 0;
256				for (bit = 0; bit < 32; bit += PIXEL_BITS)
257					PIXEL_OR(tmp);
258				*bp++ = MBE(tmp);
259			}
260
261			if (rmask != -1) {
262				tmp = 0;
263				for (bit = 0; bit < width; bit += PIXEL_BITS)
264					PIXEL_OR(tmp);
265				*bp = (*bp & rmask) | MBE(tmp);
266			}
267
268			if (ri->ri_hwbits) {
269				memcpy(hp, rp, ((lmask != -1) + full +
270				    (rmask != -1)) << 2);
271				DELTA(hp, ri->ri_stride, uint32_t *);
272			}
273
274			DELTA(rp, ri->ri_stride, uint32_t *);
275		}
276	}
277
278	/* Do underline */
279	if ((attr & WSATTR_UNDERLINE) != 0) {
280		DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
281		if (ri->ri_hwbits)
282			DELTA(hp, - ri->ri_stride * ri->ri_ul.off, uint32_t *);
283
284		for (height = ri->ri_ul.height; height; height--) {
285			DELTA(rp, - ri->ri_stride, uint32_t *);
286			bp = rp;
287			if (lmask != -1) {
288				*bp = (*bp & lmask) | (fg & ~lmask);
289				bp++;
290			}
291			for (cnt = full; cnt; cnt--)
292				*bp++ = fg;
293			if (rmask != -1)
294				*bp = (*bp & rmask) | (fg & ~rmask);
295			if (ri->ri_hwbits) {
296				DELTA(hp, - ri->ri_stride, uint32_t *);
297				memcpy(hp, rp, ((lmask != -1) + full +
298				    (rmask != -1)) << 2);
299			}
300		}
301	}
302}
303
304#undef	PIXEL_BITS
305#undef	PIXEL_SHIFT
306#undef	COLOR_MASK
307
308#undef	PIXEL_OR
309
310#undef	NAME
311#undef	NAME1
312