#if RASOPS_DEPTH != 2 && RASOPS_DEPTH != 4 && RASOPS_DEPTH != 8 && \
RASOPS_DEPTH != 15 && RASOPS_DEPTH != 24 && RASOPS_DEPTH != 32
#error "Depth not supported"
#endif
#if RASOPS_WIDTH != 8 && RASOPS_WIDTH != 12 && RASOPS_WIDTH != 16
#error "Width not supported"
#endif
#if RASOPS_DEPTH == 2
#define STAMP_TYPE uint8_t
#elif RASOPS_DEPTH == 4
#define STAMP_TYPE uint16_t
#else
#define STAMP_TYPE uint32_t
#endif
#if RASOPS_DEPTH <= 8
#define SUBST_UNIT 1
#elif RASOPS_DEPTH == 15
#define SUBST_UNIT 2
#elif RASOPS_DEPTH == 24
#define SUBST_UNIT 3
#elif RASOPS_DEPTH == 32
#define SUBST_UNIT 4
#endif
#define SUBST_BYTES (SUBST_UNIT * (RASOPS_WIDTH / 4) * sizeof(STAMP_TYPE))
#if RASOPS_DEPTH <= 8
#define FILLED_STAMP 15
#elif RASOPS_DEPTH == 15
#define FILLED_STAMP 30
#else
#define FILLED_STAMP 60
#endif
#if RASOPS_DEPTH <= 8
#define SUBST_STAMP1(off, base) \
rp[(off) * 1 + 0] = stamp[base]
#define SUBST_GLYPH1(index, nibble, off) \
do { \
int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
rp[(off) * 1 + 0] = STAMP_READ(so); \
} while (0 )
#endif
#if RASOPS_DEPTH == 15
#define SUBST_STAMP1(off, base) \
rp[(off) * 2 + 0] = rp[(off) * 2 + 1] = stamp[base]
#define SUBST_GLYPH1(index, nibble, off) \
do { \
int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
rp[(off) * 2 + 0] = STAMP_READ(so); \
rp[(off) * 2 + 1] = STAMP_READ(so + 4); \
} while (0 )
#endif
#if RASOPS_DEPTH == 24
#define SUBST_STAMP1(off, base) \
do { \
rp[(off) * 3 + 0] = stamp[(base) + 0]; \
rp[(off) * 3 + 1] = stamp[(base) + 1]; \
rp[(off) * 3 + 2] = stamp[(base) + 2]; \
} while (0 )
#define SUBST_GLYPH1(index, nibble, off) \
do { \
int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
rp[(off) * 3 + 0] = STAMP_READ(so); \
rp[(off) * 3 + 1] = STAMP_READ(so + 4); \
rp[(off) * 3 + 2] = STAMP_READ(so + 8); \
} while (0 )
#endif
#if RASOPS_DEPTH == 32
#define SUBST_STAMP1(off, base) \
rp[(off) * 4 + 0] = rp[(off) * 4 + 1] = \
rp[(off) * 4 + 2] = rp[(off) * 4 + 3] = stamp[base]
#define SUBST_GLYPH1(index, nibble, off) \
do { \
int so = STAMP_SHIFT(fr[index], nibble) & STAMP_MASK; \
rp[(off) * 4 + 0] = STAMP_READ(so); \
rp[(off) * 4 + 1] = STAMP_READ(so + 4); \
rp[(off) * 4 + 2] = STAMP_READ(so + 8); \
rp[(off) * 4 + 3] = STAMP_READ(so + 12); \
} while (0 )
#endif
#if RASOPS_WIDTH == 8
#define SUBST_STAMP(base) \
do { \
SUBST_STAMP1(0, base); \
SUBST_STAMP1(1, base); \
} while (0 )
#elif RASOPS_WIDTH == 12
#define SUBST_STAMP(base) \
do { \
SUBST_STAMP1(0, base); \
SUBST_STAMP1(1, base); \
SUBST_STAMP1(2, base); \
} while (0 )
#elif RASOPS_WIDTH == 16
#define SUBST_STAMP(base) \
do { \
SUBST_STAMP1(0, base); \
SUBST_STAMP1(1, base); \
SUBST_STAMP1(2, base); \
SUBST_STAMP1(3, base); \
} while (0 )
#endif
#if RASOPS_WIDTH == 8
#define SUBST_GLYPH \
do { \
SUBST_GLYPH1(0, 1, 0); \
SUBST_GLYPH1(0, 0, 1); \
} while (0 )
#elif RASOPS_WIDTH == 12
#define SUBST_GLYPH \
do { \
SUBST_GLYPH1(0, 1, 0); \
SUBST_GLYPH1(0, 0, 1); \
SUBST_GLYPH1(1, 1, 2); \
} while (0 )
#elif RASOPS_WIDTH == 16
#define SUBST_GLYPH \
do { \
SUBST_GLYPH1(0, 1, 0); \
SUBST_GLYPH1(0, 0, 1); \
SUBST_GLYPH1(1, 1, 2); \
SUBST_GLYPH1(1, 0, 3); \
} while (0 )
#endif
#define NAME(depth, width) NAME1(depth, width)
#define NAME1(depth, width) rasops ## depth ## _putchar ## width
#define PUTCHAR(depth) PUTCHAR1(depth)
#define PUTCHAR1(depth) rasops ## depth ## _putchar
#define MAKESTAMP(depth) MAKESTAMP1(depth)
#define MAKESTAMP1(depth) rasops ## depth ## _makestamp
static void
NAME(RASOPS_DEPTH, RASOPS_WIDTH)(void *cookie, int row, int col, u_int uc,
long attr)
{
struct rasops_info *ri = (struct rasops_info *)cookie;
struct wsdisplay_font *font = PICK_FONT(ri, uc);
int height;
uint8_t *fr;
bool do_ul;
STAMP_TYPE *rp, *hp;
hp = NULL;
if (__predict_false(!CHAR_IN_FONT(uc, font)))
return;
#ifdef RASOPS_CLIPPING
if ((unsigned)row >= (unsigned)ri->ri_rows)
return;
if ((unsigned)col >= (unsigned)ri->ri_cols)
return;
#endif
do_ul = (attr & WSATTR_UNDERLINE) != 0;
attr &= (ATTR_MASK_BG | ATTR_MASK_FG);
if (attr != stamp_attr || __predict_false(ri != stamp_ri))
MAKESTAMP(RASOPS_DEPTH)(ri, attr);
height = font->fontheight;
rp = (STAMP_TYPE *)(ri->ri_bits + FBOFFSET(ri, row, col));
if (ri->ri_hwbits)
hp = (STAMP_TYPE *)(ri->ri_hwbits + FBOFFSET(ri, row, col));
if (uc == ' ') {
while (height--) {
SUBST_STAMP(0);
if (ri->ri_hwbits) {
memcpy(hp, rp, SUBST_BYTES);
DELTA(hp, ri->ri_stride, STAMP_TYPE *);
}
DELTA(rp, ri->ri_stride, STAMP_TYPE *);
}
} else {
fr = FONT_GLYPH(uc, font, ri);
while (height--) {
SUBST_GLYPH;
fr += font->stride;
if (ri->ri_hwbits) {
memcpy(hp, rp, SUBST_BYTES);
DELTA(hp, ri->ri_stride, STAMP_TYPE *);
}
DELTA(rp, ri->ri_stride, STAMP_TYPE *);
}
}
if (do_ul) {
DELTA(rp, - ri->ri_stride * ri->ri_ul.off, STAMP_TYPE *);
if (ri->ri_hwbits)
DELTA(hp, - ri->ri_stride * ri->ri_ul.off,
STAMP_TYPE *);
for (height = ri->ri_ul.height; height; height--) {
DELTA(rp, - ri->ri_stride, STAMP_TYPE *);
SUBST_STAMP(FILLED_STAMP);
if (ri->ri_hwbits) {
DELTA(hp, - ri->ri_stride, STAMP_TYPE *);
memcpy(hp, rp, SUBST_BYTES);
}
}
}
}
#undef STAMP_TYPE
#undef SUBST_UNIT
#undef SUBST_BYTES
#undef FILLED_STAMP
#undef SUBST_STAMP1
#undef SUBST_STAMP
#undef SUBST_GLYPH1
#undef SUBST_GLYPH
#undef NAME
#undef NAME1
#undef PUTCHAR
#undef PUTCHAR1
#undef MAKESTAMP
#undef MAKESTAMP1