Compare commits

...

4 Commits

6 changed files with 79 additions and 38 deletions

View File

@@ -9,20 +9,36 @@ You will need the following packages: `build-essential` `libsdl2-dev` `libsdl2-i
Just run `make` and an executable called `trmnl_sdl` should be produced. Just run `make` and an executable called `trmnl_sdl` should be produced.
# How to use # How to use
1. You will need to write a JSON config file. ### General use
It can either be named `config.json` or you will need to pass it as the first command line parameter to the executable. 1. You will need to write a JSON config file named `config.json`.
An example structure of the config file can be found in `config_example.json`. An example structure of the config file can be found in `config_example.json`.
You can find more info on the available Widgets and their parameters at the end of this file. You can find more info on the available Widgets and their parameters at the end of this file.
2. Run the executable 2. Run the executable
3. Convert the image to a suitable format via an ImageMagick command from below. 3. Convert the image to a suitable format via an ImageMagick command from below.
### Different ways to supply JSON
1. Default
* Command: `./trmnl_sdl`
* JSON Used: `config.json`
2. Specified file
* Command: `./trmnl_sdl path/to/json/file.json`
* JSON Used: `path/to/json/file.json`
3. Standard input
* Command: `./trmnl_sdl -`
* JSON Used: Supplied on the standard input for the process.
# ImageMagick commands to prepare image for TRMNL device # ImageMagick commands to prepare image for TRMNL device
### Convert image without dithering ### Convert image without dithering
`convert trmnl.png -monochrome -colors 2 -depth 1 -strip png:output.png` `convert trmnl.png -monochrome -colors 2 -depth 1 -strip png:output.png`
### Convert image with dithering ### Convert image with Floyd Steinberg dithering (For normal images)
`convert trmnl.png -dither FloydSteinberg -remap pattern:gray50 -depth 1 -strip png:output.png` `convert trmnl.png -dither FloydSteinberg -remap pattern:gray50 -depth 1 -strip png:output.png`
### Convert image with Ordered dithering (For flat colors)
`convert trmnl.png -ordered-dither o2x2 -remap pattern:gray50 -depth 1 -strip png:output.png`
### Resize image to fit with dithering ### Resize image to fit with dithering
`convert image.png -resize 800x480 -background white -compose Copy -gravity center -extent 800x480 -dither FloydSteinberg -remap pattern:gray50 -depth 1 -strip png:output.png` `convert image.png -resize 800x480 -background white -compose Copy -gravity center -extent 800x480 -dither FloydSteinberg -remap pattern:gray50 -depth 1 -strip png:output.png`

View File

@@ -31,7 +31,7 @@ void WidgetRect::set_color(SDL_Color color)
void WidgetRect::set_stroke_size(int stroke_size) void WidgetRect::set_stroke_size(int stroke_size)
{ {
m_stroke_size = stroke_size m_stroke_size = stroke_size;
} }
void WidgetRect::set_radius(int radius) void WidgetRect::set_radius(int radius)

View File

@@ -172,6 +172,7 @@ void WidgetText::set_halign_via_visible(bool value)
{ {
m_halign_via_visible = value; m_halign_via_visible = value;
} }
void WidgetText::set_valign_via_visible(bool value) void WidgetText::set_valign_via_visible(bool value)
{ {
m_valign_via_visible = value; m_valign_via_visible = value;
@@ -179,6 +180,7 @@ void WidgetText::set_valign_via_visible(bool value)
void WidgetText::draw() void WidgetText::draw()
{ {
int current_text_size = m_size;
if (nullptr == m_surface) if (nullptr == m_surface)
{ {
return; return;
@@ -193,7 +195,7 @@ void WidgetText::draw()
font_name = default_font_name; font_name = default_font_name;
} }
TTF_Font* font = get_font(m_size, font_name); TTF_Font* font = get_font(current_text_size, font_name);
if (nullptr == font) if (nullptr == font)
{ {
// TODO: Message printing // TODO: Message printing
@@ -209,40 +211,42 @@ void WidgetText::draw()
return; return;
} }
// Check if text fits // Enlarge text until it becomes too big
if (FIT_AUTO == m_fit)
{
while ((txt_surface->w < m_surface->w) && (txt_surface->h < m_surface->h))
{
// Increase size and try again
++current_text_size;
// Re-render text
SDL_FreeSurface(txt_surface);
font = get_font(current_text_size, font_name);
if (nullptr == font)
{
// TODO: Message printing
return;
}
txt_surface = render_text(m_should_wrap, font, m_text, m_text_color, m_rect.w);
if (nullptr == txt_surface)
{
// TODO: Message printing
return;
}
}
}
// Shrink if it doesn't fit
if (m_fit != FIT_NONE) if (m_fit != FIT_NONE)
{ {
double x_scale; while ((txt_surface->w > m_surface->w) || (txt_surface->h > m_surface->h))
double y_scale;
x_scale = m_surface->w;
x_scale /= txt_surface->w;
y_scale = m_surface->h;
y_scale /= txt_surface->h;
// Find the scale needed to shrink or enlarge with
double min_scale = x_scale;
if (y_scale < min_scale)
{ {
min_scale = y_scale; // Decrease size and try again
} --current_text_size;
// Do not scale up if only shrinkage is allowed // Re-render text
if ((min_scale > 1.0) && (FIT_SHRINK == m_fit))
{
min_scale = 1.0;
}
// Find new font size
int new_text_size = m_size;
new_text_size *= min_scale;
// Re-render text
if (new_text_size != m_size)
{
SDL_FreeSurface(txt_surface); SDL_FreeSurface(txt_surface);
font = get_font(new_text_size, font_name); font = get_font(current_text_size, font_name);
if (nullptr == font) if (nullptr == font)
{ {
// TODO: Message printing // TODO: Message printing

View File

@@ -60,8 +60,18 @@ int main(int argc, char **argv)
cfg_filename = argv[1]; cfg_filename = argv[1];
} }
// Read JSON CFG // Read config
ok = read_config_json(cfg, cfg_filename); if ("-" == cfg_filename)
{
// Read JSON from std input
ok = read_config_json(cfg, std::cin);
}
else
{
// Read JSON from config file
ok = read_config_json(cfg, cfg_filename);
}
if (!ok) if (!ok)
{ {
result = -1; result = -1;

View File

@@ -141,15 +141,20 @@ bool read_config_json(json& cfg, const string& filename, ostream* log)
{ {
if (nullptr != log) if (nullptr != log)
{ {
*log << "Could not open config.json" << endl; *log << "Could not open config file" << endl;
} }
return false; return false;
} }
return read_config_json(cfg, cfg_file, log);
}
bool read_config_json(json& cfg, istream& in, ostream* log)
{
// Parse with comments // Parse with comments
try try
{ {
cfg = json::parse(cfg_file, nullptr, true, true); cfg = json::parse(in, nullptr, true, true);
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {

View File

@@ -90,6 +90,12 @@ SDL_Rect surface_align(const SDL_Surface* base, const SDL_Surface* applied,
// log - output errors to this ostream, silent if NULL // log - output errors to this ostream, silent if NULL
bool read_config_json(nlohmann::json& cfg, const std::string& filename, std::ostream* log = &std::cout); bool read_config_json(nlohmann::json& cfg, const std::string& filename, std::ostream* log = &std::cout);
// Reads the stream and tries to parse JSON from it with comments
// cfg - output json struct
// in - input stream to read
// log - output errors to this ostream, silent if NULL
bool read_config_json(nlohmann::json& cfg, std::istream& in, std::ostream* log = &std::cout);
// JSON Extractors - They do not override already set values if key is not present // JSON Extractors - They do not override already set values if key is not present
void json_extract(const nlohmann::json& j, const std::string& key, std::string& out); void json_extract(const nlohmann::json& j, const std::string& key, std::string& out);