Pico Graphics: Move bitmap fonts into generic library.

* Add bitmap font support into Badger 2040
pull/326/head
Phil Howard 2022-03-29 15:13:14 +01:00
rodzic 24819734b7
commit 3b8dcecd8e
17 zmienionych plików z 160 dodań i 78 usunięć

Wyświetl plik

@ -1,4 +1,5 @@
add_subdirectory(hershey_fonts)
add_subdirectory(bitmap_fonts)
add_subdirectory(breakout_dotmatrix)
add_subdirectory(breakout_encoder)
add_subdirectory(breakout_ioexpander)

Wyświetl plik

@ -8,4 +8,4 @@ target_sources(${LIB_NAME} INTERFACE
target_include_directories(${LIB_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
# Pull in pico libraries that we need
target_link_libraries(${LIB_NAME} INTERFACE hershey_fonts pico_stdlib hardware_pwm uc8151)
target_link_libraries(${LIB_NAME} INTERFACE bitmap_fonts hershey_fonts pico_stdlib hardware_pwm uc8151)

Wyświetl plik

@ -327,29 +327,61 @@ namespace pimoroni {
}
int32_t Badger2040::glyph(unsigned char c, int32_t x, int32_t y, float s, float a) {
return hershey::glyph(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
line(x1, y1, x2, y2);
}, c, x, y, s, a);
if (_bitmap_font) {
bitmap::character(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) {
for(auto px = 0; px < w; px++) {
for(auto py = 0; py < h; py++) {
pixel(x + px, y + py);
}
}
}, c, x, y, int(s));
return 0;
} else {
return hershey::glyph(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
line(x1, y1, x2, y2);
}, c, x, y, s, a);
}
}
void Badger2040::text(std::string message, int32_t x, int32_t y, float s, float a) {
hershey::text(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
line(x1, y1, x2, y2);
}, message, x, y, s, a);
if (_bitmap_font) {
bitmap::text(_bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) {
for(auto px = 0; px < w; px++) {
for(auto py = 0; py < h; py++) {
pixel(x + px, y + py);
}
}
}, message, x, y, 296 - x, int(s));
} else {
hershey::text(_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
line(x1, y1, x2, y2);
}, message, x, y, s, a);
}
}
int32_t Badger2040::measure_text(std::string message, float s) {
if (_bitmap_font) return 0;
return hershey::measure_text(_font, message, s);
}
int32_t Badger2040::measure_glyph(unsigned char c, float s) {
if (_bitmap_font) return 0;
return hershey::measure_glyph(_font, c, s);
}
void Badger2040::font(std::string name) {
// check that font exists and assign it
if(hershey::fonts.find(name) != hershey::fonts.end()) {
_font = hershey::fonts[name];
if (name == "bitmap6") {
_bitmap_font = &font6;
_font = nullptr;
} else if (name == "bitmap8") {
_bitmap_font = &font8;
_font = nullptr;
} else {
// check that font exists and assign it
if(hershey::fonts.find(name) != hershey::fonts.end()) {
_bitmap_font = nullptr;
_font = hershey::fonts[name];
}
}
}

Wyświetl plik

@ -5,6 +5,9 @@
#include "drivers/uc8151/uc8151.hpp"
#include "libraries/hershey_fonts/hershey_fonts.hpp"
#include "libraries/bitmap_fonts/bitmap_fonts.hpp"
#include "libraries/bitmap_fonts/font6_data.hpp"
#include "libraries/bitmap_fonts/font8_data.hpp"
namespace pimoroni {
@ -12,6 +15,7 @@ namespace pimoroni {
protected:
UC8151 uc8151;
const hershey::font_t *_font = &hershey::futural;
const bitmap::font_t *_bitmap_font = nullptr;
uint8_t _pen = 0;
uint8_t _thickness = 1;
uint32_t _button_states = 0;

Wyświetl plik

@ -0,0 +1 @@
include(bitmap_fonts.cmake)

Wyświetl plik

@ -0,0 +1,6 @@
add_library(bitmap_fonts
${CMAKE_CURRENT_LIST_DIR}/bitmap_fonts.cpp
)
target_include_directories(bitmap_fonts INTERFACE ${CMAKE_CURRENT_LIST_DIR})

Wyświetl plik

@ -0,0 +1,54 @@
#include "bitmap_fonts.hpp"
namespace bitmap {
void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale) {
uint8_t char_index = c - 32;
const uint8_t *d = &font->data[char_index * font->max_width];
for(uint8_t cx = 0; cx < font->widths[char_index]; cx++) {
for(uint8_t cy = 0; cy < font->height; cy++) {
if((1U << cy) & *d) {
rectangle(x + (cx * scale), y + (cy * scale), scale, scale);
}
}
d++;
}
}
void text(const font_t *font, rect_func rectangle, const std::string &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale) {
uint32_t co = 0, lo = 0; // character and line (if wrapping) offset
size_t i = 0;
while(i < t.length()) {
// find length of current word
size_t next_space = t.find(' ', 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++) {
word_width += font->widths[t[j] - 32] * scale;
}
// if this word would exceed the wrap limit then
// move to the next line
if(co != 0 && co + word_width > (uint32_t)wrap) {
co = 0;
lo += (font->height + 1) * scale;
}
// draw word
for(size_t j = i; j < next_space; j++) {
character(font, rectangle, t[j], x + co, y + lo, scale);
co += font->widths[t[j] - 32] * scale;
}
// move character offset to end of word and add a space
co += font->widths[0] * scale;
i = next_space + 1;
}
}
}

Wyświetl plik

@ -0,0 +1,19 @@
#pragma once
#include <functional>
#include <string>
#include <cstdint>
namespace bitmap {
struct font_t {
const uint8_t height;
const uint8_t max_width;
const uint8_t widths[96];
const uint8_t data[];
};
typedef std::function<void(int32_t x, int32_t y, int32_t w, int32_t h)> rect_func;
void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale = 2);
void text(const font_t *font, rect_func rectangle, const std::string &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale = 2);
}

Wyświetl plik

@ -1,8 +1,8 @@
#pragma once
#include "font.hpp"
#include "bitmap_fonts.hpp"
const pimoroni::Font font6 {
const bitmap::font_t font6 {
.height = 6,
.max_width = 6,
.widths = {

Wyświetl plik

@ -1,8 +1,8 @@
#pragma once
#include "font.hpp"
#include "bitmap_fonts.hpp"
const pimoroni::Font font8 {
const bitmap::font_t font8 {
.height = 8,
.max_width = 6,
.widths = {

Wyświetl plik

@ -1,12 +0,0 @@
#pragma once
#include <cstdint>
namespace pimoroni {
struct Font {
const uint8_t height;
const uint8_t max_width;
const uint8_t widths[96];
const uint8_t data[];
};
}

Wyświetl plik

@ -5,3 +5,4 @@ add_library(pico_graphics
target_include_directories(pico_graphics INTERFACE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(pico_graphics bitmap_fonts)

Wyświetl plik

@ -6,7 +6,7 @@ namespace pimoroni {
set_font(&font6);
};
void PicoGraphics::set_font(const Font *font){
void PicoGraphics::set_font(const bitmap::font_t *font){
this->font = font;
}
@ -110,57 +110,15 @@ namespace pimoroni {
}
void PicoGraphics::character(const char c, const Point &p, uint8_t scale) {
uint8_t char_index = c - 32;
Rect char_bounds(p.x, p.y, font->widths[char_index] * scale, font->height * scale);
if(!clip.intersects(char_bounds)) return;
const uint8_t *d = &font->data[char_index * font->max_width];
for(uint8_t cx = 0; cx < font->widths[char_index]; cx++) {
for(uint8_t cy = 0; cy < font->height; cy++) {
if((1U << cy) & *d) {
rectangle(Rect(p.x + (cx * scale), p.y + (cy * scale), scale, scale));
}
}
d++;
}
bitmap::character(font, [this](int32_t x, int32_t y, int32_t w, int32_t h){
rectangle(Rect(x, y, w, h));
}, c, p.x, p.y, scale);
}
void PicoGraphics::text(const std::string &t, const Point &p, int32_t wrap, uint8_t scale) {
uint32_t co = 0, lo = 0; // character and line (if wrapping) offset
size_t i = 0;
while(i < t.length()) {
// find length of current word
size_t next_space = t.find(' ', 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++) {
word_width += font->widths[t[j] - 32] * scale;
}
// if this word would exceed the wrap limit then
// move to the next line
if(co != 0 && co + word_width > (uint32_t)wrap) {
co = 0;
lo += (font->height + 1) * scale;
}
// draw word
for(size_t j = i; j < next_space; j++) {
character(t[j], Point(p.x + co, p.y + lo), scale);
co += font->widths[t[j] - 32] * scale;
}
// move character offset to end of word and add a space
co += font->widths[0] * scale;
i = next_space + 1;
}
bitmap::text(font, [this](int32_t x, int32_t y, int32_t w, int32_t h){
rectangle(Rect(x, y, w, h));
}, t, p.x, p.y, wrap, scale);
}
int32_t orient2d(Point p1, Point p2, Point p3) {

Wyświetl plik

@ -4,7 +4,7 @@
#include <cstdint>
#include <algorithm>
#include <vector>
#include "font6_data.hpp"
#include "libraries/bitmap_fonts/font6_data.hpp"
// a tiny little graphics library for our Pico products
// supports only 16-bit (565) RGB framebuffers
@ -52,11 +52,11 @@ namespace pimoroni {
Pen pen;
const Font *font;
const bitmap::font_t *font;
public:
PicoGraphics(uint16_t width, uint16_t height, uint16_t *frame_buffer);
void set_font(const Font *font);
void set_font(const bitmap::font_t *font);
void set_pen(uint8_t r, uint8_t g, uint8_t b);
void set_pen(Pen p);

Wyświetl plik

@ -30,6 +30,8 @@ include(breakout_icp10125/micropython)
include(breakout_scd41/micropython)
include(hershey_fonts/micropython)
include(bitmap_fonts/micropython)
include(badger2040/micropython)
include(micropython/examples/badger2040/micropython-builtins)
include(plasma/micropython)

Wyświetl plik

@ -0,0 +1,14 @@
set(MOD_NAME bitmap_fonts)
string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER)
add_library(usermod_${MOD_NAME} INTERFACE)
target_sources(usermod_${MOD_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/../../../libraries/bitmap_fonts/bitmap_fonts.cpp
)
target_include_directories(usermod_${MOD_NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/../../../libraries/bitmap_fonts
)
target_link_libraries(usermod INTERFACE usermod_${MOD_NAME})

Wyświetl plik

@ -38,6 +38,8 @@ include(pico_display_2/micropython)
include(pico_explorer/micropython)
include(pico_wireless/micropython)
include(bitmap_fonts/micropython)
include(plasma/micropython)
include(hub75/micropython)
include(servo/micropython)