kopia lustrzana https://github.com/pimoroni/pimoroni-pico
PicoVector: C++ basic bringup.
rodzic
469833670e
commit
8a719c214e
|
@ -25,6 +25,3 @@
|
|||
[submodule "drivers/mlx90640/src"]
|
||||
path = drivers/mlx90640/src
|
||||
url = https://github.com/melexis/mlx90640-library
|
||||
[submodule "libraries/pico_vector/pretty_poly"]
|
||||
path = libraries/pico_vector/pretty_poly
|
||||
url = https://github.com/lowfatcode/pretty-poly/
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
add_subdirectory(mandelbrot)
|
||||
|
||||
set(OUTPUT_NAME pico_display2_demo)
|
||||
|
||||
add_executable(
|
||||
${OUTPUT_NAME}
|
||||
pico_display_2_demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${OUTPUT_NAME} pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button pico_display_2 st7789 pico_graphics)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(${OUTPUT_NAME})
|
||||
include(pico_display_2_demo.cmake)
|
||||
include(pico_display_2_vector.cmake)
|
|
@ -0,0 +1,10 @@
|
|||
add_executable(
|
||||
pico_display_2_demo
|
||||
pico_display_2_demo.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(pico_display_2_demo pico_stdlib hardware_spi hardware_pwm hardware_dma rgbled button pico_display_2 st7789 pico_graphics)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(pico_display_2_demo)
|
|
@ -0,0 +1,41 @@
|
|||
function(static_asset NAME PATH)
|
||||
get_filename_component(PATH ${PATH} ABSOLUTE)
|
||||
get_filename_component(ASSET ${PATH} NAME)
|
||||
get_filename_component(PATH ${PATH} DIRECTORY)
|
||||
set(OBJNAME ${ASSET}.o)
|
||||
add_custom_command(OUTPUT ${OBJNAME}
|
||||
DEPENDS ${PATH}/${ASSET}
|
||||
COMMENT "Building ${OBJNAME}"
|
||||
WORKING_DIRECTORY "${PATH}"
|
||||
COMMAND ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME} ${ASSET}
|
||||
COMMAND ${CMAKE_OBJDUMP} -t ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME}
|
||||
)
|
||||
# TODO figure out how to make static resources work
|
||||
## COMMAND ${CMAKE_OBJCOPY} --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME} ${CMAKE_CURRENT_BINARY_DIR}/${OBJNAME})
|
||||
target_sources(${NAME} PRIVATE ${OBJNAME})
|
||||
endfunction()
|
||||
|
||||
add_executable(
|
||||
pico_display_2_vector
|
||||
pico_display_2_vector.cpp
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(pico_display_2_vector
|
||||
pico_stdlib
|
||||
hardware_spi
|
||||
hardware_pwm
|
||||
hardware_dma
|
||||
pico_display_2
|
||||
st7789
|
||||
pico_graphics
|
||||
pico_vector
|
||||
)
|
||||
|
||||
static_asset(pico_display_2_vector ${CMAKE_CURRENT_LIST_DIR}/vector/DynaPuff-Medium.af)
|
||||
|
||||
pico_enable_stdio_usb(pico_display_2_vector 0)
|
||||
pico_enable_stdio_uart(pico_display_2_vector 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(pico_display_2_vector)
|
|
@ -0,0 +1,66 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "libraries/pico_display_2/pico_display_2.hpp"
|
||||
#include "drivers/st7789/st7789.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
#include "libraries/pico_vector/pico_vector.hpp"
|
||||
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
ST7789 st7789(320, 240, ROTATE_180, false, get_spi_pins(BG_SPI_FRONT));
|
||||
PicoGraphics_PenRGB332 graphics(st7789.width, st7789.height, nullptr);
|
||||
|
||||
uint8_t vector_mem[PicoVector::pretty_poly_buffer_size()];
|
||||
|
||||
PicoVector vector(&graphics);
|
||||
|
||||
extern char _binary_DynaPuff_Medium_af_start[];
|
||||
extern size_t _binary_DynaPuff_Medium_af_size;
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
Pen BG = graphics.create_pen(120, 40, 60);
|
||||
Pen TEXT = graphics.create_pen(255, 255, 255);
|
||||
|
||||
st7789.set_backlight(255);
|
||||
|
||||
vector.set_font(_binary_DynaPuff_Medium_af_start, 30);
|
||||
|
||||
unsigned int a = 0;
|
||||
|
||||
while (true) {
|
||||
Point text_location(0, 0);
|
||||
graphics.set_pen(BG);
|
||||
graphics.clear();
|
||||
graphics.set_pen(TEXT);
|
||||
graphics.text("Hello World", text_location, 320);
|
||||
|
||||
pp_point_t outline[] = {{-64, -64}, {64, -64}, {64, 64}, {-64, 64}};
|
||||
pp_point_t hole[] = {{ -32, 32}, { 32, 32}, { 32, -32}, { -32, -32}};
|
||||
pp_path_t paths[] = {
|
||||
{.points = outline, .count = 4},
|
||||
{.points = hole, .count = 4}
|
||||
};
|
||||
pp_poly_t poly = {.paths = paths, .count = 2};
|
||||
|
||||
pp_mat3_t pos = pp_mat3_identity();
|
||||
pp_mat3_translate(&pos, 50, 50);
|
||||
pp_mat3_rotate(&pos, a);
|
||||
vector.draw(&poly);
|
||||
vector.text("Hello World", &pos);
|
||||
|
||||
// update screen
|
||||
st7789.update(&graphics);
|
||||
a += 1;
|
||||
if (a > 359) {
|
||||
a = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Plik binarny nie jest wyświetlany.
|
@ -0,0 +1,36 @@
|
|||
#include "af-file-io.h"
|
||||
#include "string.h"
|
||||
|
||||
static size_t ptr = 0;
|
||||
|
||||
void* fileio_open(const char* filename) {
|
||||
ptr = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fileio_close(void* fhandle) {
|
||||
ptr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t fileio_read(void* fhandle, void *buf, size_t len) {
|
||||
memcpy(buf, fhandle + ptr, len);
|
||||
ptr += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
int fileio_getc(void* fhandle) {
|
||||
uint8_t *f = fhandle;
|
||||
int c = f[ptr];
|
||||
ptr += 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t fileio_tell(void* fhandle) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
size_t fileio_seek(void* fhandle, size_t pos) {
|
||||
ptr = pos;
|
||||
return ptr;
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void* fileio_open(const char* filename);
|
||||
|
||||
void fileio_close(void* fhandle);
|
||||
|
@ -13,4 +15,6 @@ int fileio_getc(void* fhandle);
|
|||
size_t fileio_tell(void* fhandle);
|
||||
|
||||
size_t fileio_seek(void* fhandle, size_t pos);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#include "af-memory.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void *af_malloc(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *af_realloc(void *p, size_t size) {
|
||||
return realloc(p, size);
|
||||
}
|
||||
|
||||
void af_free(void *p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
void af_debug(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int ret = printf(fmt, ap);
|
||||
va_end(ap);
|
||||
(void)ret;
|
||||
}
|
|
@ -1,6 +1,12 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void *af_malloc(size_t size);
|
||||
void *af_realloc(void *p, size_t size);
|
||||
void af_free(void *p);
|
||||
void af_debug(const char *fmt, ...);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -1,136 +0,0 @@
|
|||
#include <cstdint>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <map>
|
||||
|
||||
#include "alright_fonts.hpp"
|
||||
|
||||
namespace alright_fonts {
|
||||
/*
|
||||
utility functions
|
||||
*/
|
||||
pp_rect_t measure_character(text_metrics_t &tm, uint16_t codepoint) {
|
||||
if(tm.face.glyphs.count(codepoint) == 1) {
|
||||
glyph_t glyph = tm.face.glyphs[codepoint];
|
||||
|
||||
return {0, 0, ((glyph.advance * tm.size) / 128), tm.size};
|
||||
}
|
||||
|
||||
return {0, 0, 0, 0};
|
||||
}
|
||||
|
||||
/*
|
||||
render functions
|
||||
*/
|
||||
|
||||
void render_character(text_metrics_t &tm, uint16_t codepoint, pp_point_t origin, pp_mat3_t *transform) {
|
||||
if(tm.face.glyphs.count(codepoint) == 1) {
|
||||
glyph_t glyph = tm.face.glyphs[codepoint];
|
||||
pp_transform(transform);
|
||||
pp_render(&glyph.contours);
|
||||
}
|
||||
}
|
||||
/*
|
||||
load functions
|
||||
*/
|
||||
|
||||
// big endian stream value helpers
|
||||
uint16_t ru16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
|
||||
int16_t rs16(file_io &ifs) {uint8_t w[2]; ifs.read((char *)w, 2); return w[0] << 8 | w[1];}
|
||||
uint32_t ru32(file_io &ifs) {uint8_t dw[4]; ifs.read((char *)dw, 4); return dw[0] << 24 | dw[1] << 16 | dw[2] << 8 | dw[3];}
|
||||
uint8_t ru8(file_io &ifs) {uint8_t w; ifs.read(&w, 1); return w;}
|
||||
int8_t rs8(file_io &ifs) {int8_t w; ifs.read(&w, 1); return w;}
|
||||
|
||||
bool face_t::load(file_io &ifs) {
|
||||
char marker[4];
|
||||
ifs.read(marker, sizeof(marker));
|
||||
|
||||
// check header magic bytes are present
|
||||
if(memcmp(marker, "af!?", 4) != 0) {
|
||||
// doesn't start with magic marker
|
||||
return false;
|
||||
}
|
||||
|
||||
// number of glyphs embedded in font file
|
||||
this->glyph_count = ru16(ifs);
|
||||
|
||||
// extract flags and ensure none set
|
||||
this->flags = ru16(ifs);
|
||||
if(this->flags != 0) {
|
||||
// unknown flags set
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract glyph dictionary
|
||||
uint16_t glyph_entry_size = 9;
|
||||
uint32_t contour_data_offset = 8 + this->glyph_count * glyph_entry_size;
|
||||
for(auto i = 0; i < this->glyph_count; i++) {
|
||||
glyph_t g;
|
||||
g.codepoint = ru16(ifs);
|
||||
g.bounds.x = rs8(ifs);
|
||||
g.bounds.y = rs8(ifs);
|
||||
g.bounds.w = ru8(ifs);
|
||||
g.bounds.h = ru8(ifs);
|
||||
g.advance = ru8(ifs);
|
||||
|
||||
g.contours.paths = (pp_path_t *)malloc(sizeof(pp_path_t) * 10);
|
||||
|
||||
if(ifs.fail()) {
|
||||
// could not read glyph dictionary entry
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate space for the contour data and read it from the font file
|
||||
uint16_t contour_data_length = ru16(ifs);
|
||||
|
||||
// remember where we are in the dictionary
|
||||
int pos = ifs.tell();
|
||||
|
||||
// read contour data
|
||||
ifs.seek(contour_data_offset);
|
||||
while(true) {
|
||||
// get number of points in contour
|
||||
uint16_t count = ru16(ifs);
|
||||
|
||||
// if count is zero then this is the end of contour marker
|
||||
if(count == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// allocate space to store point data for contour and read
|
||||
// from file
|
||||
g.contours.paths[g.contours.count].points = (pp_point_t *)malloc(sizeof(pp_point_t) * count);
|
||||
|
||||
ifs.read((char *)g.contours.paths[g.contours.count].points, sizeof(pp_point_t) * count);
|
||||
|
||||
g.contours.count ++;
|
||||
}
|
||||
|
||||
// return back to position in dictionary
|
||||
ifs.seek(pos);
|
||||
contour_data_offset += contour_data_length;
|
||||
|
||||
if(ifs.fail()) {
|
||||
// could not read glyph contour data
|
||||
return false;
|
||||
}
|
||||
|
||||
this->glyphs[g.codepoint] = g;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool face_t::load(std::string_view path) {
|
||||
file_io ifs(path);
|
||||
if(ifs.fail()) {
|
||||
// could not open file
|
||||
return false;
|
||||
}
|
||||
return load(ifs);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#include <cstdint>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <map>
|
||||
|
||||
#include "pretty-poly.h"
|
||||
#include "file_io.hpp"
|
||||
|
||||
namespace alright_fonts {
|
||||
|
||||
struct glyph_t {
|
||||
uint16_t codepoint;
|
||||
pp_rect_t bounds;
|
||||
uint8_t advance;
|
||||
pp_poly_t contours;
|
||||
};
|
||||
|
||||
struct face_t {
|
||||
uint16_t glyph_count;
|
||||
uint16_t flags;
|
||||
std::map<uint16_t, glyph_t> glyphs;
|
||||
|
||||
face_t() {};
|
||||
face_t(file_io &ifs) {load(ifs);}
|
||||
face_t(std::string_view path) {load(path);}
|
||||
|
||||
bool load(file_io &ifs);
|
||||
bool load(std::string_view path);
|
||||
};
|
||||
|
||||
enum alignment_t {
|
||||
left = 0,
|
||||
center = 1,
|
||||
right = 2,
|
||||
justify = 4,
|
||||
top = 8,
|
||||
bottom = 16
|
||||
};
|
||||
|
||||
struct text_metrics_t {
|
||||
face_t face; // font to write in
|
||||
int size; // text size in pixels
|
||||
uint scroll; // vertical scroll offset
|
||||
int line_height; // spacing between lines (%)
|
||||
int letter_spacing; // spacing between characters
|
||||
int word_spacing; // spacing between words
|
||||
alignment_t align; // horizontal and vertical alignment
|
||||
//optional<mat3_t> transform; // arbitrary transformation
|
||||
pp_antialias_t antialiasing = PP_AA_X4; // level of antialiasing to apply
|
||||
|
||||
void set_size(int s) {
|
||||
size = s;
|
||||
line_height = size;
|
||||
letter_spacing = 0;
|
||||
word_spacing = size / 2;
|
||||
}
|
||||
|
||||
text_metrics_t() {};
|
||||
};
|
||||
|
||||
/*
|
||||
utility functions
|
||||
*/
|
||||
pp_rect_t measure_character(text_metrics_t &tm, uint16_t codepoint);
|
||||
|
||||
/*
|
||||
render functions
|
||||
*/
|
||||
|
||||
void render_character(text_metrics_t &tm, uint16_t codepoint, pp_point_t origin, pp_mat3_t *transform);
|
||||
}
|
|
@ -4,7 +4,8 @@ endif()
|
|||
|
||||
add_library(pico_vector
|
||||
${CMAKE_CURRENT_LIST_DIR}/pico_vector.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/alright_fonts.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/af-file-io.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/af-memory.c
|
||||
)
|
||||
|
||||
target_include_directories(pico_vector INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
|
|
@ -112,7 +112,20 @@ namespace pimoroni {
|
|||
return result;
|
||||
}
|
||||
|
||||
pp_point_t text(std::string_view text, pp_mat3_t *t);
|
||||
bool set_font(void* font, unsigned int font_size) {
|
||||
if(text_metrics.face) {
|
||||
af_free(text_metrics.face->glyphs);
|
||||
af_free(text_metrics.face);
|
||||
}
|
||||
text_metrics.face = (af_face_t *)af_malloc(sizeof(af_face_t));
|
||||
bool result = af_load_font_file(font, text_metrics.face);
|
||||
|
||||
set_font_size(font_size);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
pp_point_t text(std::string_view text, pp_mat3_t *t=nullptr);
|
||||
|
||||
void transform(pp_path_t *path, pp_mat3_t *t);
|
||||
void transform(pp_poly_t *poly, pp_mat3_t *t);
|
||||
|
|
Ładowanie…
Reference in New Issue