mirror of
https://github.com/Dejvino/lilybook.git
synced 2024-12-04 19:58:50 +00:00
Implemented typesetter to allow exact paging. Improved spacing between chars.
This commit is contained in:
parent
05f1856a10
commit
f343983184
@ -44,6 +44,7 @@ uint8_t font_transparent; // if not 0 draw fonts transparent
|
|||||||
uint8_t font_forceFixed; // if not zero force drawing proportional fonts with fixed width
|
uint8_t font_forceFixed; // if not zero force drawing proportional fonts with fixed width
|
||||||
uint8_t font_buffered_char;
|
uint8_t font_buffered_char;
|
||||||
uint8_t font_line_space; // additional spacing between text lines; added to font height
|
uint8_t font_line_space; // additional spacing between text lines; added to font height
|
||||||
|
uint8_t font_x_space; // additional spacing between characters in x axis
|
||||||
uint8_t text_wrap; // if not 0 wrap long text to the new line, else clip
|
uint8_t text_wrap; // if not 0 wrap long text to the new line, else clip
|
||||||
color_t _fg; // current foreground color for fonts
|
color_t _fg; // current foreground color for fonts
|
||||||
color_t _bg; // current background for non transparent fonts
|
color_t _bg; // current background for non transparent fonts
|
||||||
@ -1732,10 +1733,10 @@ int EPD_getStringWidth(char* str)
|
|||||||
char* tempStrptr = str;
|
char* tempStrptr = str;
|
||||||
while (*tempStrptr != 0) {
|
while (*tempStrptr != 0) {
|
||||||
if (getCharPtr(*tempStrptr++)) {
|
if (getCharPtr(*tempStrptr++)) {
|
||||||
strWidth += (((fontChar.width > fontChar.xDelta) ? fontChar.width : fontChar.xDelta) + 1);
|
strWidth += (((fontChar.width > fontChar.xDelta) ? fontChar.width : fontChar.xDelta) + font_x_space);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strWidth--;
|
strWidth -= font_x_space;
|
||||||
}
|
}
|
||||||
return strWidth;
|
return strWidth;
|
||||||
}
|
}
|
||||||
@ -1980,7 +1981,7 @@ void EPD_print(char *st, int x, int y) {
|
|||||||
// Let's print the character
|
// Let's print the character
|
||||||
if (cfont.x_size == 0) {
|
if (cfont.x_size == 0) {
|
||||||
// == proportional font
|
// == proportional font
|
||||||
if (font_rotate == 0) EPD_X += printProportionalChar( EPD_X, EPD_Y) + 1;
|
if (font_rotate == 0) EPD_X += printProportionalChar( EPD_X, EPD_Y) + font_x_space;
|
||||||
else {
|
else {
|
||||||
// rotated proportional font
|
// rotated proportional font
|
||||||
offset += rotatePropChar(x, y, offset);
|
offset += rotatePropChar(x, y, offset);
|
||||||
|
@ -45,6 +45,7 @@ extern uint8_t font_transparent; // if not 0 draw fonts transparent
|
|||||||
extern uint8_t font_forceFixed; // if not zero force drawing proportional fonts with fixed width
|
extern uint8_t font_forceFixed; // if not zero force drawing proportional fonts with fixed width
|
||||||
extern uint8_t font_buffered_char;
|
extern uint8_t font_buffered_char;
|
||||||
extern uint8_t font_line_space; // additional spacing between text lines; added to font height
|
extern uint8_t font_line_space; // additional spacing between text lines; added to font height
|
||||||
|
extern uint8_t font_x_space; // additional spacing between characters in x axis
|
||||||
extern uint8_t text_wrap; // if not 0 wrap long text to the new line, else clip
|
extern uint8_t text_wrap; // if not 0 wrap long text to the new line, else clip
|
||||||
extern color_t _fg; // current foreground color for fonts
|
extern color_t _fg; // current foreground color for fonts
|
||||||
extern color_t _bg; // current background for non transparent fonts
|
extern color_t _bg; // current background for non transparent fonts
|
||||||
|
@ -7,6 +7,7 @@ class Page
|
|||||||
public:
|
public:
|
||||||
Page();
|
Page();
|
||||||
|
|
||||||
|
size_t start;
|
||||||
char* text;
|
char* text;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
static const char *TAG = "PagePrinter";
|
static const char *TAG = "PagePrinter";
|
||||||
|
|
||||||
int font = DEJAVU18_FONT;//DEFAULT_FONT;
|
//int pageFont = DEFAULT_FONT;
|
||||||
|
int pageFont = DEJAVU18_FONT;
|
||||||
|
|
||||||
PagePrinter::PagePrinter()
|
PagePrinter::PagePrinter()
|
||||||
{}
|
{}
|
||||||
@ -19,7 +20,7 @@ void PagePrinter::print(Page* page)
|
|||||||
if (page->len == 0) {
|
if (page->len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EPD_setFont(font, NULL);
|
EPD_setFont(pageFont, NULL);
|
||||||
text_wrap = 1;
|
text_wrap = 1;
|
||||||
EPD_print(page->text, 0, 0);
|
EPD_print(page->text, 0, 0);
|
||||||
//EPD_UpdateScreen();
|
//EPD_UpdateScreen();
|
||||||
|
@ -6,6 +6,4 @@ public:
|
|||||||
PagePrinter();
|
PagePrinter();
|
||||||
|
|
||||||
void print(Page* page);
|
void print(Page* page);
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
48
main/PageSettingsProvider.cpp
Normal file
48
main/PageSettingsProvider.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "PageSettingsProvider.h"
|
||||||
|
#include "EPD.h"
|
||||||
|
#include "EPDspi.h" // TODO: remove after display config is extracted
|
||||||
|
|
||||||
|
int PageSettingsProvider::getWidth()
|
||||||
|
{
|
||||||
|
return EPD_DISPLAY_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PageSettingsProvider::getHeight()
|
||||||
|
{
|
||||||
|
return EPD_DISPLAY_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PageSettingsProvider::getCharWidth(char c)
|
||||||
|
{
|
||||||
|
char txt[2] = { c, 0x00 };
|
||||||
|
return this->getStringWidth(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int pageFont;
|
||||||
|
void activatePageFont()
|
||||||
|
{
|
||||||
|
EPD_setFont(pageFont, NULL); // TODO: hack to get the same font as the printer
|
||||||
|
}
|
||||||
|
|
||||||
|
int PageSettingsProvider::getStringWidth(char* string)
|
||||||
|
{
|
||||||
|
activatePageFont();
|
||||||
|
int ret = EPD_getStringWidth(string);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PageSettingsProvider::getCharSpace()
|
||||||
|
{
|
||||||
|
return font_x_space;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PageSettingsProvider::getLineHeight()
|
||||||
|
{
|
||||||
|
activatePageFont();
|
||||||
|
return EPD_getfontheight();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PageSettingsProvider::getLineSpace()
|
||||||
|
{
|
||||||
|
return font_line_space;
|
||||||
|
}
|
12
main/PageSettingsProvider.h
Normal file
12
main/PageSettingsProvider.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
class PageSettingsProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int getWidth();
|
||||||
|
int getHeight();
|
||||||
|
|
||||||
|
int getCharWidth(char c);
|
||||||
|
int getStringWidth(char* string);
|
||||||
|
int getCharSpace();
|
||||||
|
int getLineHeight();
|
||||||
|
int getLineSpace();
|
||||||
|
};
|
@ -32,7 +32,7 @@ size_t TextReader::read(long pos, char* text, size_t len)
|
|||||||
fseek(this->f, pos, SEEK_SET);
|
fseek(this->f, pos, SEEK_SET);
|
||||||
size_t read = fread(text, 1, len, this->f);
|
size_t read = fread(text, 1, len, this->f);
|
||||||
if (read > 0) {
|
if (read > 0) {
|
||||||
ESP_LOGI(TAG, "Read content: %s", text);
|
//ESP_LOGI(TAG, "Read content: %s", text);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "End of file. Closing.");
|
ESP_LOGI(TAG, "End of file. Closing.");
|
||||||
fclose(this->f);
|
fclose(this->f);
|
||||||
|
@ -1,27 +1,38 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "Typesetter.h"
|
#include "Typesetter.h"
|
||||||
|
|
||||||
Typesetter::Typesetter()
|
#include "esp_log.h"
|
||||||
{}
|
static const char *TAG = "Typesetter";
|
||||||
|
|
||||||
Page* Typesetter::preparePage(char* text, size_t len)
|
Typesetter::Typesetter()
|
||||||
|
{
|
||||||
|
this->pageSettingsProvider = new PageSettingsProvider(); // TODO: make it a param
|
||||||
|
}
|
||||||
|
|
||||||
|
Typesetter::~Typesetter()
|
||||||
|
{
|
||||||
|
delete this->pageSettingsProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Page* extractPage(char* text, size_t len)
|
||||||
{
|
{
|
||||||
Page* page = new Page;
|
Page* page = new Page;
|
||||||
page->text = new char[len+1];
|
page->text = new char[len+1];
|
||||||
memcpy(page->text, text, len);
|
memcpy(page->text, text, len);
|
||||||
page->text[len] = 0;
|
page->text[len] = 0;
|
||||||
page->len = len;
|
page->len = len;
|
||||||
|
ESP_LOGI(TAG, "Extracted page (%d bytes):\n%s\n----", page->len, page->text);
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Page* Typesetter::preparePage(char* text, size_t len)
|
||||||
|
{
|
||||||
|
return this->preparePageInternal(text, len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
Page* Typesetter::preparePreviousPage(char* text, size_t len)
|
Page* Typesetter::preparePreviousPage(char* text, size_t len)
|
||||||
{
|
{
|
||||||
Page* page = new Page;
|
return this->preparePageInternal(text, len, 1);
|
||||||
page->text = new char[len+1];
|
|
||||||
memcpy(page->text, text, len);
|
|
||||||
page->text[len] = 0;
|
|
||||||
page->len = len;
|
|
||||||
return page;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Typesetter::destroyPage(Page* page)
|
void Typesetter::destroyPage(Page* page)
|
||||||
@ -32,3 +43,40 @@ void Typesetter::destroyPage(Page* page)
|
|||||||
delete page->text;
|
delete page->text;
|
||||||
delete page;
|
delete page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Page* Typesetter::preparePageInternal(char* text, size_t len, int reverse)
|
||||||
|
{
|
||||||
|
int page_width = this->pageSettingsProvider->getWidth();
|
||||||
|
int page_height = this->pageSettingsProvider->getHeight();
|
||||||
|
int line_height = this->pageSettingsProvider->getLineHeight()
|
||||||
|
+ this->pageSettingsProvider->getLineSpace();
|
||||||
|
int line_count = page_height / line_height;
|
||||||
|
|
||||||
|
char buf[len+1];
|
||||||
|
memset(buf, 0, len+1);
|
||||||
|
|
||||||
|
int line_start = 0;
|
||||||
|
ESP_LOGI(TAG, " === Typesetting%s page === ", reverse ? " reversed" : "");
|
||||||
|
for (int line = 0; line < line_count && line_start < len; line++) {
|
||||||
|
int i;
|
||||||
|
for (i = line_start; i < len; i++) {
|
||||||
|
buf[i] = text[reverse ? (len - i) : (i)];
|
||||||
|
if (buf[i] == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int line_width = this->pageSettingsProvider->getStringWidth(&buf[line_start]);
|
||||||
|
if (line_width > page_width) {
|
||||||
|
// backtrack
|
||||||
|
buf[i] = 0;
|
||||||
|
i--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Line %d | %s", line, &buf[line_start]);
|
||||||
|
//ESP_LOGI(TAG, "Line %d [%04d:%04d] | %s | %03d / %03d", line, line_start, i, &buf[line_start],
|
||||||
|
// this->pageSettingsProvider->getStringWidth(&buf[line_start]), page_width);
|
||||||
|
line_start = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return extractPage(text, line_start);
|
||||||
|
}
|
@ -1,12 +1,20 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "Page.h"
|
#include "Page.h"
|
||||||
|
#include "PageSettingsProvider.h"
|
||||||
|
|
||||||
class Typesetter
|
class Typesetter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Typesetter();
|
Typesetter();
|
||||||
|
~Typesetter();
|
||||||
|
|
||||||
Page* preparePage(char* text, size_t len);
|
Page* preparePage(char* text, size_t len);
|
||||||
Page* preparePreviousPage(char* text, size_t len);
|
Page* preparePreviousPage(char* text, size_t len);
|
||||||
void destroyPage(Page* page);
|
void destroyPage(Page* page);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Page* preparePageInternal(char* text, size_t len, int direction);
|
||||||
|
|
||||||
|
PageSettingsProvider* pageSettingsProvider; // TODO: expose so it may be changed
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,11 +70,20 @@ extern "C" void app_main()
|
|||||||
if (textReader != NULL) {
|
if (textReader != NULL) {
|
||||||
if (pageCurrent == NULL) {
|
if (pageCurrent == NULL) {
|
||||||
size_t read = textReader->read(bookmark, text, sizeof(text));
|
size_t read = textReader->read(bookmark, text, sizeof(text));
|
||||||
pageCurrent = typesetter.preparePage(text, sizeof(text));
|
pageCurrent = typesetter.preparePage(text, read);
|
||||||
|
pageCurrent->start = bookmark;
|
||||||
}
|
}
|
||||||
if (pageLast == NULL) {
|
if (pageLast == NULL) {
|
||||||
size_t read = textReader->read(bookmark - sizeof(text), text, sizeof(text));
|
// align with the start?
|
||||||
pageLast = typesetter.preparePreviousPage(text, sizeof(text));
|
if (bookmark < sizeof(text)) {
|
||||||
|
size_t read = textReader->read(0, text, sizeof(text));
|
||||||
|
pageLast = typesetter.preparePage(text, read);
|
||||||
|
pageLast->start = 0;
|
||||||
|
} else {
|
||||||
|
size_t read = textReader->read((bookmark - sizeof(text)), text, sizeof(text));
|
||||||
|
pageLast = typesetter.preparePreviousPage(text, read);
|
||||||
|
pageLast->start = bookmark - pageLast->len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
typesetter.destroyPage(pageCurrent);
|
typesetter.destroyPage(pageCurrent);
|
||||||
@ -97,7 +106,8 @@ extern "C" void app_main()
|
|||||||
if (buttons_pressed_plus()) {
|
if (buttons_pressed_plus()) {
|
||||||
ESP_LOGI(TAG, "Turn page PLUS.");
|
ESP_LOGI(TAG, "Turn page PLUS.");
|
||||||
if (pageCurrent != NULL) {
|
if (pageCurrent != NULL) {
|
||||||
bookmark += pageCurrent->len;
|
bookmark = pageCurrent->start + pageCurrent->len;
|
||||||
|
// TODO: limit bookmark to file size
|
||||||
typesetter.destroyPage(pageLast);
|
typesetter.destroyPage(pageLast);
|
||||||
pageLast = pageCurrent;
|
pageLast = pageCurrent;
|
||||||
pageCurrent = NULL;
|
pageCurrent = NULL;
|
||||||
@ -109,7 +119,7 @@ extern "C" void app_main()
|
|||||||
if (buttons_pressed_minus()) {
|
if (buttons_pressed_minus()) {
|
||||||
ESP_LOGI(TAG, "Turn page MINUS.");
|
ESP_LOGI(TAG, "Turn page MINUS.");
|
||||||
if (pageLast != NULL) {
|
if (pageLast != NULL) {
|
||||||
bookmark -= pageLast->len;
|
bookmark = pageLast->start;
|
||||||
typesetter.destroyPage(pageCurrent);
|
typesetter.destroyPage(pageCurrent);
|
||||||
pageCurrent = pageLast;
|
pageCurrent = pageLast;
|
||||||
pageLast = NULL;
|
pageLast = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user