diff options
Diffstat (limited to 'sw/Core/Src/gfx.h')
| -rwxr-xr-x | sw/Core/Src/gfx.h | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/sw/Core/Src/gfx.h b/sw/Core/Src/gfx.h new file mode 100755 index 0000000..d5a33ff --- /dev/null +++ b/sw/Core/Src/gfx.h @@ -0,0 +1,371 @@ +#pragma once +typedef enum { + BOLD=16, + + F_8=0,F_12,F_16,F_20,F_24,F_28,F_32, + F_8_BOLD=BOLD,F_12_BOLD,F_16_BOLD,F_20_BOLD,F_24_BOLD,F_28_BOLD,F_32_BOLD, + +} EFont; +int strwidth(EFont f, const char *buf); + +void invertrectangle(int x1, int y1, int x2, int y2); +void fillrectangle(int x1, int y1, int x2, int y2); + +extern u8 textcol; // 0 =black, 1=white, 2=upper shadow, 3=lower shadow +int drawstr(int x, int y, EFont f, const char *buf); +int fdrawstr(int x, int y, EFont f, const char *fmt, ...); +int drawchar(int x, int y, EFont f, char c, char textcol); +void vline(int x1, int y1, int y2, int c); +void hline(int x1, int y1, int x2, int c); +void putpixel(int x, int y, int c); +void clear(); + +#define W 128 +#define H 32 + +extern u8 vrambuf[H / 8 * W + 1]; // first byte is 0x40 + +static inline u8* getvram(void) { return vrambuf + 1; } + +/////////////////////////////////////////////// + +#ifdef IMPL +#include "fontdata.h" + +u8 vrambuf[H / 8 * W + 1]; + + +void clear(void) { + vrambuf[0] = 0x40; + memset(getvram(),0,W*H/8); +} + +void putpixel(int x, int y, int c) { + if (x >= W) + return; + if (y >= H) + return; + u8 *dst = getvram() + x + ((y >> 3) << 7); + u8 b = 1 << (y & 7); + if (c) + *dst |= b; + else + *dst &= ~b; +} + +void vline(int x1, int y1, int y2, int c) { + if (x1 < 0 || x1 >= W) + return; + y1 = clampi(y1, 0, H); + y2 = clampi(y2, 0, H); + if (y1 >= y2) + return; + int y1b = y1 >> 3; + int n = (y2 >> 3) - y1b; + u8 *dst = getvram() + (x1) + (y1b << 7); + u8 b1 = 0xff << (y1 & 7), b2 = ~(0xff << (y2 & 7)); + if (c) { + u8 mask = (c == 1) ? 255 : (x1 & 1) ? 0x55 : 0xaa; + if (n == 0) { + *dst |= b1 & b2 & mask; + } else { + *dst |= b1 & mask; + dst += W; + for (; --n; dst += W) + *dst |= mask; + *dst |= b2 & mask; + } + } else { + if (n == 0) { + *dst &= ~(b1 & b2); + } else { + *dst &= ~b1; + dst += W; + for (; --n; dst += W) + *dst = 0; + *dst &= ~b2; + } + } +} + +void hline(int x1, int y1, int x2, int c) { + if (y1 < 0 || y1 >= H) + return; + x1 = clampi(x1, 0, W); + x2 = clampi(x2, 0, W); + int n = (x2 - x1); + if (n <= 0) + return; + u8 *dst = getvram() + ((y1 >> 3) << 7) + (x1); + u8 b = (1 << (y1 & 7)); + if (c) { + for (; n--; dst++) + *dst |= b; + } else { + b = ~b; + for (; n--; dst++) + *dst &= b; + } +} + + +int charwidth(EFont f, char c) { + int xsize = ((int) (f) & 15) * 2 + 4; + int ysize = xsize * 2; + if (c & 0x80) + return 20; + if (c <= 32 || c > '~') + return xsize / 2; // space + int fo = fontoffsets[f & 15][(f&BOLD) >= BOLD]; + const u8 *data = (((const u8*) fontdata) + fo); + u8 datap = (ysize + 7) / 8; + u32 mask = (2 << (ysize - 1)) - 1; + data += datap * xsize * (c - 32); + while (xsize > 0 && ((*(u32*) data) & mask) == 0) { + data += datap; + --xsize; + } // skip blank at start? + int lastset = 0; + for (int xx = 0; xx < xsize; ++xx) { + u32 d = ((*((const u32*) data)) & mask); + data += datap; + if (!d) + continue; + lastset = xx; + } + return lastset + 2; +} + +void invertrectangle(int x1, int y1, int x2, int y2) { + x1=clampi(0,x1,128); + y1=clampi(0,y1,32); + x2=clampi(0,x2,128); + y2=clampi(0,y2,32); + if (y1>=y2 || x1>=x2) return ; + u32 mask=(2<<(y2-y1-1))-1; + u8 *dst=getvram() + x1 + (y1/8)*128; + mask<<=y1&7; + int w=x2-x1; + while (mask) { + u8 bmask; + bmask=mask; for (int i=0;i<w;++i) dst[i]^=bmask; + mask>>=8; + dst+=128; + } +} + +void fillrectangle(int x1, int y1, int x2, int y2) { + x1 = clampi(0, x1, 128); + y1 = clampi(0, y1, 32); + x2 = clampi(0, x2, 128); + y2 = clampi(0, y2, 32); + if (y1 >= y2 || x1 >= x2) return; + u32 mask = (2 << (y2 - y1 - 1)) - 1; + u8* dst = getvram() + x1 + (y1 / 8) * 128; + mask <<= y1 & 7; + int w = x2 - x1; + while (mask) { + u8 bmask; + bmask = mask; for (int i = 0; i < w; ++i) dst[i] |= bmask; + mask >>= 8; + dst += 128; + } +} + +void halfrectangle(int x1, int y1, int x2, int y2) { + x1 = clampi(0, x1, 128); + y1 = clampi(0, y1, 32); + x2 = clampi(0, x2, 128); + y2 = clampi(0, y2, 32); + if (y1 >= y2 || x1 >= x2) return; + u32 mask = (2 << (y2 - y1 - 1)) - 1; + u8* dst = getvram() + x1 + (y1 / 8) * 128; + mask <<= y1 & 7; + int w = x2 - x1; + while (mask) { + u8 bmask; + u8 dither = (x1 & 1) ? 0x55 : 0xaa; + bmask = mask; for (int i = 0; i < w; ++i, dither^=255) dst[i] |= (bmask & dither); + mask >>= 8; + dst += 128; + } +} + +#include "icons.h" + +int drawicon(int x, int y, unsigned char c, int textcol) { + if (x<=-16 || x>=128 || y<=-16 || y>=32 || c>=numicons) + return 20; + const u16 *data =icons[c]; + u8 *dst = getvram() + x; + for (int xx = 0; xx < 15; ++xx, ++dst, ++x) { + if (x >= W) + break; + u32 d = *data++; + if (!d || x<0) + continue; + if (y < 0) + d >>= -y; + else + d <<= y; + if (!d) + continue; + if (textcol == 0) { + if (d & 255) dst[0] &= ~d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W] &= ~d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W * 2] &= ~d; + if ((d >>= 8) & 255) dst[W * 3] &= ~d; + } + else { + if (d & 255) dst[0] |= d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W] |= d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W * 2] |= d; + if ((d >>= 8) & 255) dst[W * 3] |= d; + } + } + return 20; +} + + +int drawchar(int x, int y, EFont f, char c, char textcol) { + if (textcol == 2) { + drawchar(x-1, y - 1, f, c, 0); + textcol = 1; + } + else if (textcol == 3) { + drawchar(x-1, y + 1, f, c, 0); + textcol = 1; + } + int xsize = ((int) (f) & 15) * 2 + 4; + int ysize = xsize * 2; + if (c&0x80) + return drawicon(x,mini(y,18),c^0x80, textcol); + if (c <= 32 || c > '~') + return xsize / 2; // space + int fo = fontoffsets[f & 15][(f&BOLD) >= BOLD]; + const u8 *data = (((const u8*) fontdata) + fo); + u8 datap = (ysize + 7) / 8; + u32 mask = (2 << (ysize - 1)) - 1; + data += datap * xsize * (c - 32); + while (xsize > 0 && ((*(u32*) data) & mask) == 0) { + data += datap; + --xsize; + } // skip blank at start? + int lastset = 0; +// u8 *vram=getvram(); + u8 *dst = getvram() + x; + for (int xx = 0; xx < xsize; ++xx, ++dst, ++x) { + if (x >= W) + break; + u32 d = ((*((const u32*) data)) & mask); + data += datap; + if (!d) + continue; + lastset = xx; + if (x < 0) + continue; + if (y < 0) + d >>= -y; + else + d <<= y; + if (!d) + continue; + if (textcol == 0) { + if (d & 255) dst[0] &= ~d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W] &= ~d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W * 2] &= ~d; + d >>= 8; + if (d & 255) dst[W * 3] &= ~d; + } + else { + if (d & 255) dst[0] |= d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W] |= d; + if (!(d >>= 8)) continue; + if (d & 255) dst[W * 2] |= d; + d >>= 8; + if (d & 255) dst[W * 3] |= d; + } + } + return lastset + 2; +} + +u8 textcol = 1; + + +int drawstr_noright(int x, int y, EFont f, const char* buf) { + if (!buf) + return 0; + + int ox = x; + int ysize = ((int) (f) & 15) * 2 + 4; + if (x>=128 || y<=-ysize || y>=32) + return 0; + for (; *buf;) { + if (*buf == '\n') { + x = ox; + y += ysize*2-2; + } else + x += drawchar(x, y, f, *buf, textcol); + buf++; + if (x>W+1) + return x; + } + return x; +} + +int drawstr(int x, int y, EFont f, const char* buf) { + if (x < 0) { + // right align! hohoho + int w = strwidth(f, buf); + x = -x - w; + } + return drawstr_noright(x, y, f, buf); +} + +int fontheight(EFont f) { + return ((int)(f) & 15) * 4 + 8; +} + +int strheight(EFont f, const char *buf) { + int lines = 1; + for (; *buf;++buf) if (*buf == '\n') lines++; + return lines * fontheight(f); +} + +int strwidth(EFont f, const char *buf) { + if (!buf) return 0; + int w=0; + int mw=0; + for (; *buf;) { + if (*buf & 0x80) + w += 20; + else if (*buf == '\n') { + mw=maxi(mw,w); + w=0; + } else + w += charwidth(f, *buf); + buf++; + } + return maxi(mw,w); +} + + +int fdrawstr(int x, int y, EFont f, const char *fmt, ...) { + if (!fmt) + return 0; + va_list args; + va_start(args, fmt); + char buf[64]; + vsnprintf(buf, 63, fmt, args); + va_end(args); + return drawstr(x, y, f, buf); +} + +#endif |
