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