fixed up markdown-esque text algorithms

markdown-subset
Jonathan Williamson 2021-01-25 07:22:59 +00:00
rodzic f90f103da8
commit 6d0f359a91
2 zmienionych plików z 128 dodań i 72 usunięć

Wyświetl plik

@ -97,26 +97,25 @@ int main() {
};
std::vector<pt> shapes;
for(int i = 0; i < 1000; i++) {
for(int i = 0; i < 250; i++) {
pt shape;
shape.x = rand() % 240;
shape.y = rand() % 135;
shape.r = (rand() % 10) + 3;
shape.r = (rand() % 10) + 5;
shape.dx = float(rand() % 255) / 128.0f;
shape.dy = float(rand() % 255) / 128.0f;
shape.pen = pico_display.create_pen(rand() % 255, rand() % 255, rand() % 255);
shape.pen = pico_display.create_pen(rand() % 100, rand() % 100, rand() % 100);
shapes.push_back(shape);
}
uint32_t i = 0;
while(true) {
pico_display.remove_clip();
pico_display.set_pen(20, 30, 40);
pico_display.clear();
pico_display.set_pen(200, 220, 240);
pico_display.text("Markdown? *Zoiks!*\n\nIt _helps_ to /emphasize/.\n\n-a bulleted list?\n-sure, why not!?\n\nMade a mistake? ~Fix it~.", Point(5, 5), 230);
/*
for(auto &shape : shapes) {
shape.x += shape.dx;
shape.y += shape.dy;
@ -129,11 +128,41 @@ int main() {
pico_display.circle(Point(shape.x, shape.y), shape.r);
}
pico_display.set_pen(200, 220, 240);
std::string text =
"We've sourced a new LCD screen especially for our Pico Display Pack - "
"it's a lovely, bright *18-bit capable 240x135 pixel IPS display* and fits "
"the Pico perfectly.\n\nWe've surrounded it with *four tactile buttons* so you "
"can easily interface your Pico with your human fingers and an *RGB LED* that "
"you can use as an indicator, for notifications or just for adding extra rainbows."
"\n\n"
"*Features:*\n\n"
"-1.14\" 240x135 pixel IPS LCD screen\n"
"-4 x tactile buttons\n"
"-RGB LED\n"
"-Pre-soldered female headers for attaching to Pico\n"
"-Compatible with Raspberry Pi Pico.\n"
"-Fully assembled\n"
"-No soldering required (as long as your Pico has header pins attached).\n"
"-Dimensions: approx 53mm x 25mm x 9mm (L x W x H)\n"
"-Programmable with C/C++ and MicroPython"
;
pico_display.set_clip(Rect(10, 10, 220, 115));
int32_t y = cos(float(i) / 100.0f) * 200.0f - 200.0f;
pico_display.text(text, Point(10, y + 10), pico_display.clip.w - 2);
// "Markdown? *Zoiks!*\n\nIt _helps_ to /emphasize/.\n\n-a bulleted list?\n-sure, why not!?\n\nMade a mistake? ~Fix it~."
float led_step = fmod(i / 20.0f, M_PI * 2.0f);
int r = (sin(led_step) * 25.0f) + 25.0f;
pico_display.set_led(r, r / 1.2f, r);
/*
std::vector<Point> poly;
poly.push_back(Point(30, 30));
poly.push_back(Point(50, 35));

Wyświetl plik

@ -104,7 +104,7 @@ namespace pimoroni {
}
}
enum flags {BOLD = 1, ITALIC = 2, UNDERLINE = 4, STRIKETHROUGH = 8};
enum flags {BOLD = 1, ITALIC = 2, UNDERLINE = 4, STRIKETHROUGH = 8, BULLET = 16};
uint8_t *character_data(uint8_t i) {
uint32_t bytes_per_character = (font_data[0] * font_data[1]) + 1;
@ -112,7 +112,11 @@ namespace pimoroni {
}
uint8_t character_width(uint8_t i) {
return character_data(i)[0];
return character_data(i)[0] + 2;
}
uint8_t character_height() {
return font_data[1] - 2;
}
void PicoGraphics::character(const char c, const Point &p, uint32_t flags) {
@ -142,7 +146,6 @@ namespace pimoroni {
pixel(Point(p.x + cx + italic, p.y + cy));
if(flags & flags::BOLD) {
pixel(Point(p.x + cx + 1, p.y + cy));
pixel(Point(p.x + cx - 1, p.y + cy));
}
}
@ -153,7 +156,7 @@ namespace pimoroni {
if(flags & flags::UNDERLINE || flags & flags::STRIKETHROUGH) {
for(int8_t cx = -1; cx < character_width(c) + 1; cx++) {
if(flags & flags::UNDERLINE) {
pixel(Point(p.x + cx, p.y + character_height));
pixel(Point(p.x + cx, p.y + character_height - 1));
}
if(flags & flags::STRIKETHROUGH) {
@ -163,74 +166,98 @@ namespace pimoroni {
}
}
void PicoGraphics::text(const std::string &t, const Point &p, int32_t wrap) {
void PicoGraphics::text(const std::string &text, const Point &p, int32_t wrap) {
uint32_t flags = 0; // style flags
uint32_t co = 0, lo = 0; // character and line (if wrapping) offset
uint32_t character_height = font_data[1] - 2;
size_t i = 0;
uint32_t flags = 0;
while(i < t.length()) {
if(t[i] == '\n') {
co = 0;
lo += character_height;
i++;
continue;
}else if(t[i] == ' '){
i++;
}
// find length of current word
size_t next_space = std::min(t.find(' ', i + 1), t.find('\n', i + 1));
if(next_space == std::string::npos) {
next_space = t.length();
}
uint16_t word_width = 0;
for(size_t j = i; j < next_space; j++) {
char c = t[j];
if(c != '*' && c != '_' && c != '/' && c != '~') {
uint8_t bold = flags & flags::BOLD ? 1 : 0;
word_width += (character_width(c) + bold);
}
}
// if this word would exceed the wrap limit then
// move to the next line
if(co != 0 && co + word_width > wrap) {
co = 0;
lo += character_height;
}
// draw word
for(size_t j = i; j < next_space; j++) {
char c = t[j];
if(c == '*') {
for (std::string::size_type i = 0; i < text.size(); i++) {
char c = text[i];
// handle special characters
switch(c) {
case '\n': { // line break
co = 0;
lo += character_height();
flags &= ~flags::BULLET;
continue;
} break;
case '-': { // bulleted list
if(co == 0) { // only if first character on line
co += character_height(); // line height as indent for bullet
character(249, Point(p.x + co, p.y + lo), flags); // kinda bullet point thingy
co += character_width(249) + character_width(32); // bullet + space
flags |= flags::BULLET;
continue;
}
} break;
case '*': { // bold
flags ^= flags::BOLD;
}else if(c == '_') {
flags ^= flags::UNDERLINE;
}else if(c == '/') {
continue;
} break;
case '/': { // italic
flags ^= flags::ITALIC;
}else if(c == '~') {
continue;
} break;
case '_': { // underline
flags ^= flags::UNDERLINE;
continue;
} break;
case '~': { // strikethrough
flags ^= flags::STRIKETHROUGH;
}else if(c == '-') {
character(249, Point(p.x + co, p.y + lo), flags); // kinda bullet point thingy
co += 7;
i++;
}else{
character(t[j], Point(p.x + co, p.y + lo), flags);
uint8_t bold = flags & flags::BOLD ? 1 : 0;
co += (character_width(c) + bold) + 2;
}
continue;
} break;
case '\\': { // escaped character
// skip forward to escaped character so that it is
// rendered in this iteration of the loop and
// isn't evaluated for special behaviour
if(i < text.size() - 1) {
i++;
c = text[i + 1];
}
} break;
case ' ': { // space
// determine if we need to wordwrap
size_t next_whitespace = std::min(text.find(' ', i + 1), text.find('\n', i + 1));
if(next_whitespace == std::string::npos) { // not found, use end of text
next_whitespace = text.size();
}
// calculate width of the word including this leading space
uint16_t word_width = character_width(' ');
for(std::string::size_type j = i + 1; j < next_whitespace; j++) {
if(text[j] == '\\') {
if(j < next_whitespace - 1) {
j++;
// skip forward to escaped character so that it is
// rendered in this iteration of the loop and
// isn't evaluated for special behaviour
word_width += character_width(text[j]);
continue;
}
}
if(text[j] == '*' || text[j] == '~') {
continue;
}
word_width += character_width(c);
}
// if word too long for this line then wrap
if(co + word_width >= wrap) {
if(flags & flags::BULLET) {
co = character_height() + character_width(249) + character_width(32); // bullet + space
}else{
co = 0;
}
lo += character_height();
continue;
}
} break;
}
// move character offset to end of word and add a space
character(' ', Point(p.x + co, p.y + lo), flags);
co += (character_width(' '));
i = next_space;
character(text[i], Point(p.x + co, p.y + lo), flags);
co += character_width(c);
}
}