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