You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
6.4 KiB
261 lines
6.4 KiB
//
|
|
// Created by MightyPork on 2022/11/12.
|
|
//
|
|
|
|
#include "framebuffer.h"
|
|
|
|
#define MIN(a,b) ((a)>(b)?(b):(a))
|
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
|
|
|
#include <string.h>
|
|
|
|
uint8_t fb[(FBH / 8) * FBW];
|
|
|
|
/** Fill with a vertical pattern, 1 byte */
|
|
void fb_fill(uint8_t pattern) {
|
|
memset(fb, pattern, sizeof(fb));
|
|
}
|
|
|
|
void fb_clear() {
|
|
fb_fill(0);
|
|
}
|
|
|
|
void fb_px(uint8_t x, uint8_t y, uint8_t color) {
|
|
if (x >= FBW || y >= FBH) return;
|
|
const uint8_t row = y / 8;
|
|
const uint8_t rowrem = y % 8;
|
|
const uint16_t cell = (uint16_t) x + (uint16_t) row * FBW;
|
|
if (color) {
|
|
fb[cell] |= (1 << rowrem);
|
|
} else {
|
|
fb[cell] &= ~(1 << rowrem);
|
|
}
|
|
}
|
|
|
|
void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color) {
|
|
if (x >= FBW || y >= FBH) return;
|
|
w = MIN(FBW - x, w);
|
|
const uint8_t row = y / 8;
|
|
const uint8_t rowrem = y % 8;
|
|
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW;
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
if (color) {
|
|
fb[cell] |= (1 << rowrem);
|
|
} else {
|
|
fb[cell] &= ~(1 << rowrem);
|
|
}
|
|
cell++;
|
|
}
|
|
}
|
|
|
|
void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color) {
|
|
if (x >= FBW || y >= FBH) return;
|
|
h = MIN(FBH - y - 1, h);
|
|
const uint8_t row = y / 8;
|
|
const uint8_t rowrem = y % 8;
|
|
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW;
|
|
|
|
if (rowrem + h < 8) {
|
|
// all within one cell
|
|
uint8_t mask = (0xFF << rowrem) & (0xFF >> (h-rowrem));
|
|
if (color) {
|
|
fb[cell] |= mask;
|
|
} else {
|
|
fb[cell] &= ~mask;
|
|
}
|
|
return;
|
|
} else {
|
|
// First
|
|
uint8_t mask = (0xFF << rowrem);
|
|
if (color) {
|
|
fb[cell] |= mask;
|
|
} else {
|
|
fb[cell] &= ~mask;
|
|
}
|
|
h -= rowrem;
|
|
|
|
uint8_t whole_cells = h / 8;
|
|
h -= whole_cells * 8;
|
|
for(uint8_t i = 0; i < whole_cells; i++) {
|
|
cell += FBW;
|
|
if (color) {
|
|
fb[cell] = 0xFF;
|
|
} else {
|
|
fb[cell] = 0;
|
|
}
|
|
}
|
|
|
|
// last
|
|
mask = (0xFF >> (8-h));
|
|
if (color) {
|
|
fb[cell] |= mask;
|
|
} else {
|
|
fb[cell] &= ~mask;
|
|
}
|
|
}
|
|
}
|
|
|
|
void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) {
|
|
if (x >= FBW || y >= FBH) return;
|
|
w = MIN(FBW - x - 1, w);
|
|
h = MIN(FBH - y - 1, h);
|
|
const uint8_t row = y / 8;
|
|
const uint8_t rowrem = y % 8;
|
|
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW;
|
|
|
|
if (rowrem + h <= 8) {
|
|
// all within one cell
|
|
uint8_t mask = (0xFF << rowrem) & (0xFF >> (8 - (h - rowrem)));
|
|
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
return;
|
|
} else {
|
|
// First
|
|
uint8_t mask = (0xFF << rowrem);
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
h -= 8 - rowrem;
|
|
|
|
uint8_t whole_cells = h / 8;
|
|
h -= whole_cells * 8;
|
|
for(uint8_t j = 0; j < whole_cells; j++) {
|
|
cell += FBW;
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
if (color) {
|
|
fb[cell + i] = 0xFF;
|
|
} else {
|
|
fb[cell + i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
cell += FBW;
|
|
|
|
// last
|
|
mask = (0xFF >> (8-h));
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color) {
|
|
if (x >= FBW || y >= FBH) return;
|
|
const uint8_t w0 = w;
|
|
const uint8_t h0 = h;
|
|
w = MIN(FBW - x - 1, w);
|
|
h = MIN(FBH - y - 1, h);
|
|
const uint8_t row = y / 8;
|
|
const uint8_t rowrem = y % 8;
|
|
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW;
|
|
|
|
if (rowrem + h <= 8) {
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
// all within one cell
|
|
uint8_t mask = (map[i] & (0xFF >> (8-h))) << rowrem;
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
return;
|
|
} else if (rowrem == 0) {
|
|
// Optimization
|
|
uint8_t mapc0 = 0;
|
|
|
|
// First
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
uint8_t mask = map[i];
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
h -= 8;
|
|
|
|
// Middle
|
|
uint8_t whole_cells = h / 8;
|
|
h -= whole_cells * 8;
|
|
for(uint8_t j = 0; j < whole_cells; j++) {
|
|
cell += FBW;
|
|
mapc0 += w0;
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
uint8_t mask = map[i + mapc0];
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
}
|
|
|
|
// last
|
|
mapc0 += w0;
|
|
cell += FBW;
|
|
|
|
// last
|
|
for(uint8_t i = 0; i < w; i++) {
|
|
uint8_t mask = map[i + mapc0] & (0xFF >> (8-h));
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
uint8_t mapc0 = 0;
|
|
|
|
while (h > 0) {
|
|
// First
|
|
for (uint8_t i = 0; i < w; i++) {
|
|
uint8_t mask = (map[i + mapc0] & (0xFF >> rowrem)) << rowrem;
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
|
|
//mapc0 += w0;
|
|
cell += FBW;
|
|
|
|
// leftover of the first row in map
|
|
|
|
// last
|
|
for (uint8_t i = 0; i < w; i++) {
|
|
uint8_t mask = (map[i + mapc0] & (0xFF << (8 - rowrem))) >> (8 - rowrem);
|
|
if (color) {
|
|
fb[cell + i] |= mask;
|
|
} else {
|
|
fb[cell + i] &= ~mask;
|
|
}
|
|
}
|
|
|
|
if (h > 8) {
|
|
h -= 8;
|
|
} else {
|
|
break;
|
|
}
|
|
mapc0 += w0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|