Home | History | Annotate | Line # | Download | only in rasops
      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
    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