added FreeTypeDemo

This commit is contained in:
nopnop2002 2024-09-08 12:15:46 +09:00
parent 665c80c22d
commit 87219adcbc
10 changed files with 294 additions and 0 deletions

View File

@ -0,0 +1,14 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../components/ssd1306)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ssd1306)
# Create a SPIFFS image from the contents of the 'font' directory
# that fits the partition named 'storage'. FLASH_IN_PROJECT indicates that
# the generated image should be flashed when the entire project is flashed to
# the target with 'idf.py -p PORT flash
spiffs_create_partition_image(fonts fonts FLASH_IN_PROJECT)

24
FreeTypeDemo/README.md Normal file
View File

@ -0,0 +1,24 @@
# FreeTypeDemo for SSD1306
FreeType components are published in the ESP Component Registry.
The github page is [here](https://github.com/espressif/idf-extra-components/tree/master/freetype).
This component can convert a True Type Font to a bitmap image.
___Please note that if you use a proportional font, some fonts may not convert correctly.___
Monospaced fonts can be converted correctly.
You can find Monospaced fonts [here](https://en.wikipedia.org/wiki/List_of_monospaced_typefaces).
![FreeTypeDemo](https://github.com/user-attachments/assets/13892a84-8ed8-48b9-8e1e-8e1f7235f8cb)
# How to use true type font.
- Download Monospaced fonts from internet.
- Copy font file to fonts directory.
- Select font
load_font("/fonts/consola.ttf");
- Specify the display position and threshold
render_text(&dev, 0, 16, 128, "FreeType");

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,16 @@
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS "")
register_component()
#idf_component_register(SRCS "freetype-example.c" INCLUDE_DIRS "." PRIV_REQUIRES spiffs)
# Download the example font into a directory "spiffs" in the build directory
#set(URL "https://github.com/espressif/esp-docs/raw/f036a337d8bee5d1a93b2264ecd29255baec4260/src/esp_docs/fonts/DejaVuSans.ttf")
#set(FILE "DejaVuSans.ttf")
set(SPIFFS_DIR "../spiffs")
#message(SPIFFS_DIR="${SPIFFS_DIR}")
#file(MAKE_DIRECTORY ${SPIFFS_DIR})
#file(DOWNLOAD ${URL} ${SPIFFS_DIR}/${FILE} SHOW_PROGRESS)
# Create a partition named "fonts" with the example font
#spiffs_create_partition_image(fonts ${SPIFFS_DIR} FLASH_IN_PROJECT)

View File

@ -0,0 +1,4 @@
## IDF Component Manager Manifest File
dependencies:
espressif/freetype:
version: "^2.13.0~3"

222
FreeTypeDemo/main/main.c Normal file
View File

@ -0,0 +1,222 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
//#include "esp_err.h"
#include "esp_spiffs.h"
#include "ft2build.h"
#include FT_FREETYPE_H
#include "ssd1306.h"
static const char *tag = "MAIN";
#define BITMAP_WIDTH 20
#define BITMAP_HEIGHT 16
static FT_Library s_library;
static FT_Face s_face;
static uint8_t s_bitmap[BITMAP_HEIGHT][BITMAP_WIDTH];
static void load_font(char *font)
{
FT_Error error = FT_New_Face( s_library, font, 0, &s_face );
if (error) {
ESP_LOGE(tag, "Error loading font: %d", error);
abort();
}
ESP_LOGI(tag, "Font [%s] loaded", font);
}
static void render_text(SSD1306_t * dev, int xpos, int ypos, int threshold, char *text)
{
/* Configure character size. */
//const int font_size = 14;
const int font_size = 16;
const int freetype_scale = 64;
FT_Error error = FT_Set_Char_Size(s_face, 0, font_size * freetype_scale, 0, 0 );
if (error) {
ESP_LOGE(tag, "Error setting font size: %d", error);
abort();
}
int num_chars = strlen(text);
/* current drawing position */
int x = 0;
int y = 12;
for (int n = 0; n < num_chars; n++) {
memset(s_bitmap, 0, BITMAP_WIDTH*BITMAP_HEIGHT);
ESP_LOGI(tag, "Rendering char: '%c'", text[n]);
/* retrieve glyph index from character code */
FT_UInt glyph_index = FT_Get_Char_Index( s_face, text[n] );
/* load glyph image into the slot (erase previous one) */
error = FT_Load_Glyph( s_face, glyph_index, FT_LOAD_DEFAULT );
//error = FT_Load_Glyph( s_face, glyph_index, FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO);
if (error) {
ESP_LOGE(tag, "Error loading glyph: %d", error);
abort();
}
/* convert to a bitmap */
error = FT_Render_Glyph( s_face->glyph, FT_RENDER_MODE_NORMAL );
if (error) {
ESP_LOGE(tag, "Error rendering glyph: %d", error);
abort();
}
/* copy the glyph bitmap into the overall bitmap */
FT_GlyphSlot slot = s_face->glyph;
ESP_LOGD(tag, "font_size=%d", font_size);
ESP_LOGD(tag, "slot->bitmap.rows=%d", slot->bitmap.rows);
ESP_LOGD(tag, "slot->bitmap.width=%d", slot->bitmap.width);
ESP_LOGD(tag, "slot->bitmap_top=%d", slot->bitmap_top);
ESP_LOGD(tag, "slot->bitmap_left=%d", slot->bitmap_left);
ESP_LOGD(tag, "slot->advance.x/64=%"PRIi32, slot->advance.x/64);
int width = 0;
for (int iy = 0; iy < slot->bitmap.rows; iy++) {
for (int ix = 0; ix < slot->bitmap.width; ix++) {
/* bounds check */
//int res_x = ix + x;
int res_x = ix + x + slot->bitmap_left;
if (res_x < 0) res_x = 0;
int res_y = y + iy - slot->bitmap_top;
if (res_y < 0) res_y = 0;
ESP_LOGD(tag,"res_x=%d res_y=%d", res_x, res_y);
if (res_x >= BITMAP_WIDTH || res_y >= BITMAP_HEIGHT) {
ESP_LOGW(tag, "bitmap size too large. res_x=%d res_y=%d", res_x, res_y);
continue;
}
ESP_LOGD(tag, "iy=%d ix=%d res_y=%d res_x=%d", iy, ix, res_y, res_x);
s_bitmap[res_y][res_x] = slot->bitmap.buffer[ix + iy * slot->bitmap.width];
if (res_x > width) width = res_x;
}
}
uint8_t bitmap[BITMAP_HEIGHT];
memset(bitmap, 0, BITMAP_HEIGHT);
ESP_LOGD(tag, "width=%d", width);
for (int iy = 0; iy < BITMAP_HEIGHT; iy++) {
for (int ix = 0; ix < width; ix++) {
int val = s_bitmap[iy][ix];
if (val > 128) {
putchar('#');
} else if (val > 64) {
putchar('+');
} else if (val > 32) {
putchar('.');
} else {
putchar('_');
}
uint8_t wk = 0;
if (val > threshold) wk = 1;
wk = wk << ix;
bitmap[iy] = bitmap[iy] | wk;
ESP_LOGD(tag, "val=%d threshold=%d ix=%d iy=%d wk=0x%x bitmap[iy]=0x%x", val, threshold, ix, iy, wk, bitmap[iy]);
}
putchar('\n');
}
//ESP_LOG_BUFFER_HEXDUMP(tag, bitmap, BITMAP_HEIGHT, ESP_LOG_INFO);
for (int i=0;i<BITMAP_HEIGHT;i++) {
bitmap[i] = ssd1306_rotate_byte(bitmap[i]);
}
//ESP_LOG_BUFFER_HEXDUMP(tag, bitmap, BITMAP_HEIGHT, ESP_LOG_INFO);
ssd1306_bitmaps(dev, xpos, ypos, bitmap, 8, BITMAP_HEIGHT, false);
xpos += slot->advance.x / 64;
}
}
void app_main(void)
{
SSD1306_t dev;
//int top, bottom;
//char lineChar[20];
#if CONFIG_I2C_INTERFACE
ESP_LOGI(tag, "INTERFACE is i2c");
ESP_LOGI(tag, "CONFIG_SDA_GPIO=%d",CONFIG_SDA_GPIO);
ESP_LOGI(tag, "CONFIG_SCL_GPIO=%d",CONFIG_SCL_GPIO);
ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_I2C_INTERFACE
#if CONFIG_SPI_INTERFACE
ESP_LOGI(tag, "INTERFACE is SPI");
ESP_LOGI(tag, "CONFIG_MOSI_GPIO=%d",CONFIG_MOSI_GPIO);
ESP_LOGI(tag, "CONFIG_SCLK_GPIO=%d",CONFIG_SCLK_GPIO);
ESP_LOGI(tag, "CONFIG_CS_GPIO=%d",CONFIG_CS_GPIO);
ESP_LOGI(tag, "CONFIG_DC_GPIO=%d",CONFIG_DC_GPIO);
ESP_LOGI(tag, "CONFIG_RESET_GPIO=%d",CONFIG_RESET_GPIO);
spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
#endif // CONFIG_SPI_INTERFACE
#if CONFIG_FLIP
dev._flip = true;
ESP_LOGW(tag, "Flip upside down");
#endif
#if CONFIG_SSD1306_128x64
ESP_LOGI(tag, "Panel is 128x64");
ssd1306_init(&dev, 128, 64);
#endif // CONFIG_SSD1306_128x64
#if CONFIG_SSD1306_128x32
ESP_LOGI(tag, "Panel is 128x32");
ssd1306_init(&dev, 128, 32);
#endif // CONFIG_SSD1306_128x32
// Initialize SPIFFS
esp_vfs_spiffs_conf_t conf = {
.base_path = "/fonts",
.partition_label = "fonts",
.max_files = 1,
};
ESP_ERROR_CHECK(esp_vfs_spiffs_register(&conf));
// Initialize FreeType
FT_Error error = FT_Init_FreeType( &s_library );
if (error) {
ESP_LOGE(tag, "Error initializing FreeType library: %d", error);
abort();
}
ESP_LOGI(tag, "FreeType library initialized");
ssd1306_clear_screen(&dev, false);
ssd1306_contrast(&dev, 0xff);
// Bold style
load_font("/fonts/consola.ttf");
render_text(&dev, 0, 0, 32, "FreeType");
FT_Done_Face( s_face );
// Slim style
load_font("/fonts/consola.ttf");
render_text(&dev, 0, 16, 128, "FreeType");
FT_Done_Face( s_face );
#if CONFIG_SSD1306_128x64
//load_font("/fonts/FiraMono-Regular.ttf");
load_font("/fonts/monof55.ttf");
render_text(&dev, 0, 32, 32, "FreeType");
FT_Done_Face( s_face );
load_font("/fonts/FiraMono-Regular.ttf");
render_text(&dev, 0, 48, 64, "FreeType");
FT_Done_Face( s_face );
#endif
FT_Done_FreeType( s_library );
}

View File

@ -0,0 +1,5 @@
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
fonts, data, spiffs, , 0xF0000,
#fonts, data, spiffs, , 0x1F0000,
1 nvs data nvs 0x9000 0x6000
2 phy_init data phy 0xf000 0x1000
3 factory app factory 0x10000 1M
4 fonts data spiffs 0xF0000
5 #fonts data spiffs 0x1F0000

View File

@ -0,0 +1,9 @@
#
# Partition Table
#
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
#CONFIG_ESP_MAIN_TASK_STACK_SIZE=20000
#CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y