Compare commits
3 Commits
3d45fc89fc
...
17f73211a9
| Author | SHA1 | Date | |
|---|---|---|---|
| 17f73211a9 | |||
| c626578557 | |||
| af9ebe5fe8 |
3
Makefile
3
Makefile
@ -2,8 +2,9 @@ src_files += main.cpp
|
|||||||
src_files += sdl_helpers.cpp
|
src_files += sdl_helpers.cpp
|
||||||
|
|
||||||
src_files += Widgets/Widget.cpp
|
src_files += Widgets/Widget.cpp
|
||||||
src_files += Widgets/WidgetText.cpp
|
src_files += Widgets/WidgetImage.cpp
|
||||||
src_files += Widgets/WidgetRect.cpp
|
src_files += Widgets/WidgetRect.cpp
|
||||||
|
src_files += Widgets/WidgetText.cpp
|
||||||
|
|
||||||
all:
|
all:
|
||||||
g++ $(src_files) -Wall -lSDL2 -lSDL2_ttf -lSDL2_image -o trmnl_sdl
|
g++ $(src_files) -Wall -lSDL2 -lSDL2_ttf -lSDL2_image -o trmnl_sdl
|
||||||
|
|||||||
128
Widgets/WidgetImage.cpp
Normal file
128
Widgets/WidgetImage.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#include "WidgetImage.h"
|
||||||
|
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
WidgetImage::WidgetImage(int x, int y, int width, int height, string filename,
|
||||||
|
ImageResize resize_type, HorizontalAlign halign, VerticalAlign valign,
|
||||||
|
SDL_Color bg_color)
|
||||||
|
: Widget(x, y, width, height),
|
||||||
|
m_filename(filename),
|
||||||
|
m_image_surface(nullptr),
|
||||||
|
m_resize_type(resize_type),
|
||||||
|
m_halign(halign),
|
||||||
|
m_valign(valign),
|
||||||
|
m_bg_color(bg_color)
|
||||||
|
{
|
||||||
|
m_image_surface = IMG_Load(m_filename.c_str());
|
||||||
|
if (nullptr == m_image_surface)
|
||||||
|
{
|
||||||
|
// TODO: Print errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidgetImage::draw()
|
||||||
|
{
|
||||||
|
if (nullptr == m_surface)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear surface with BG color
|
||||||
|
SDL_FillRect(m_surface, nullptr,
|
||||||
|
SDL_MapRGBA(m_surface->format, m_bg_color.r, m_bg_color.g, m_bg_color.b, m_bg_color.a));
|
||||||
|
|
||||||
|
if (nullptr == m_image_surface)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect align;
|
||||||
|
SDL_Surface* scaled_image = nullptr;
|
||||||
|
switch (m_resize_type)
|
||||||
|
{
|
||||||
|
case RESIZE_NONE:
|
||||||
|
align = surface_align(m_surface, m_image_surface, m_halign, m_valign);
|
||||||
|
SDL_BlitSurface(m_image_surface, nullptr, m_surface, &align);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RESIZE_FIT:
|
||||||
|
scaled_image = image_scale_fit();
|
||||||
|
if (nullptr != scaled_image)
|
||||||
|
{
|
||||||
|
align = surface_align(m_surface, scaled_image, m_halign, m_valign);
|
||||||
|
SDL_BlitScaled(scaled_image, nullptr, m_surface, &align);
|
||||||
|
SDL_FreeSurface(scaled_image);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RESIZE_STRETCH:
|
||||||
|
SDL_BlitScaled(m_image_surface, nullptr, m_surface, nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Widget> WidgetImage::builder(const nlohmann::json& j)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
string filename;
|
||||||
|
ImageResize resize_type = RESIZE_FIT;
|
||||||
|
HorizontalAlign halign = HALIGN_CENTER;
|
||||||
|
VerticalAlign valign = VALIGN_CENTER;
|
||||||
|
SDL_Color bg_color = {.r = 255, .g = 255, .b = 255, .a = SDL_ALPHA_TRANSPARENT};
|
||||||
|
|
||||||
|
json_extract(j, "x", x);
|
||||||
|
json_extract(j, "y", y);
|
||||||
|
json_extract(j, "width", width);
|
||||||
|
json_extract(j, "height", height);
|
||||||
|
json_extract(j, "filename", filename);
|
||||||
|
json_extract(j, "resize_type", resize_type);
|
||||||
|
json_extract(j, "halign", halign);
|
||||||
|
json_extract(j, "valign", valign);
|
||||||
|
json_extract(j, "bg_color", bg_color);
|
||||||
|
|
||||||
|
return std::make_unique<WidgetImage>(x, y, width, height, filename,
|
||||||
|
resize_type, halign, valign, bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* WidgetImage::image_scale_fit()
|
||||||
|
{
|
||||||
|
SDL_Rect align = {.x = 0, .y = 0, .w = 0, .h = 0};
|
||||||
|
|
||||||
|
if ((nullptr == m_surface) || (nullptr == m_image_surface))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
double x_scale = m_surface->w;
|
||||||
|
x_scale /= m_image_surface->w;
|
||||||
|
|
||||||
|
double y_scale = m_surface->h;
|
||||||
|
y_scale /= m_image_surface->h;
|
||||||
|
|
||||||
|
// Find smallest scale factor
|
||||||
|
double min_scale = x_scale;
|
||||||
|
if (y_scale < min_scale)
|
||||||
|
{
|
||||||
|
min_scale = y_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale with double in the front and then clamp to int via SDL_Rect
|
||||||
|
align.w = min_scale * m_image_surface->w;
|
||||||
|
align.h = min_scale * m_image_surface->h;
|
||||||
|
|
||||||
|
SDL_Surface* scaled_image_surface =
|
||||||
|
SDL_CreateRGBSurfaceWithFormat(0, align.w, align.h, 32, SDL_PIXELFORMAT_RGBA8888);
|
||||||
|
if (nullptr == scaled_image_surface)
|
||||||
|
{
|
||||||
|
// TODO: Print Error
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_BlitScaled(m_image_surface, nullptr, scaled_image_surface, nullptr);
|
||||||
|
return scaled_image_surface;
|
||||||
|
}
|
||||||
52
Widgets/WidgetImage.h
Normal file
52
Widgets/WidgetImage.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#ifndef WIDGET_IMAGE_H_
|
||||||
|
#define WIDGET_IMAGE_H_
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "../sdl_helpers.h"
|
||||||
|
|
||||||
|
class WidgetImage : public Widget
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// Image filepath
|
||||||
|
std::string m_filename;
|
||||||
|
|
||||||
|
// Image surface
|
||||||
|
SDL_Surface* m_image_surface;
|
||||||
|
|
||||||
|
// Whether to resize the image and how
|
||||||
|
// RESIZE_NONE - Do not resize
|
||||||
|
// RESIZE_FIT - Scale the image to fit the rectangle
|
||||||
|
// RESIZE_STRETCH - Scale and stretch the image to fit the box perfectly
|
||||||
|
ImageResize m_resize_type;
|
||||||
|
|
||||||
|
// Default - center
|
||||||
|
HorizontalAlign m_halign;
|
||||||
|
|
||||||
|
// Default - center
|
||||||
|
VerticalAlign m_valign;
|
||||||
|
|
||||||
|
// Background color to be used
|
||||||
|
// Default - transparent white
|
||||||
|
SDL_Color m_bg_color;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WidgetImage(int x, int y, int width, int height, std::string filename,
|
||||||
|
ImageResize resize_type = RESIZE_FIT,
|
||||||
|
HorizontalAlign halign = HALIGN_CENTER,
|
||||||
|
VerticalAlign valign = VALIGN_CENTER,
|
||||||
|
SDL_Color bg_color = SDL_Color{.r = 255, .g = 255, .b = 255, .a = SDL_ALPHA_TRANSPARENT});
|
||||||
|
|
||||||
|
virtual void draw() override;
|
||||||
|
|
||||||
|
static std::unique_ptr<Widget> builder(const nlohmann::json& j);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Create a new surface of the image_surface that is scaled via RESIZE_FIT method
|
||||||
|
// NOTE: The user MUST free the surface when done with it
|
||||||
|
SDL_Surface* image_scale_fit();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WIDGET_IMAGE_H_
|
||||||
@ -26,6 +26,11 @@ m_radius(radius)
|
|||||||
|
|
||||||
void WidgetRect::draw()
|
void WidgetRect::draw()
|
||||||
{
|
{
|
||||||
|
if (nullptr == m_surface)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Clear surface
|
// Clear surface
|
||||||
SDL_FillRect(m_surface, nullptr, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT));
|
SDL_FillRect(m_surface, nullptr, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT));
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ public:
|
|||||||
|
|
||||||
static std::unique_ptr<Widget> builder(const nlohmann::json& j);
|
static std::unique_ptr<Widget> builder(const nlohmann::json& j);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
// x, y - center of circle
|
// x, y - center of circle
|
||||||
// quadrant - 1--4
|
// quadrant - 1--4
|
||||||
void draw_circle_corner(int x, int y, int quadrant);
|
void draw_circle_corner(int x, int y, int quadrant);
|
||||||
|
|||||||
@ -170,6 +170,11 @@ void WidgetText::set_color(SDL_Color text_color)
|
|||||||
|
|
||||||
void WidgetText::draw()
|
void WidgetText::draw()
|
||||||
{
|
{
|
||||||
|
if (nullptr == m_surface)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Clear surface
|
// Clear surface
|
||||||
SDL_FillRect(m_surface, nullptr, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT));
|
SDL_FillRect(m_surface, nullptr, SDL_MapRGBA(m_surface->format, 255, 255, 255, SDL_ALPHA_TRANSPARENT));
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
#define WIDGET_TEXT_H_
|
#define WIDGET_TEXT_H_
|
||||||
|
|
||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
#include <SDL2/SDL.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|||||||
4
main.cpp
4
main.cpp
@ -12,8 +12,9 @@
|
|||||||
|
|
||||||
#include "sdl_helpers.h"
|
#include "sdl_helpers.h"
|
||||||
#include "Widgets/Widget.h"
|
#include "Widgets/Widget.h"
|
||||||
#include "Widgets/WidgetText.h"
|
#include "Widgets/WidgetImage.h"
|
||||||
#include "Widgets/WidgetRect.h"
|
#include "Widgets/WidgetRect.h"
|
||||||
|
#include "Widgets/WidgetText.h"
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
@ -26,6 +27,7 @@ using nlohmann::json;
|
|||||||
|
|
||||||
void init_builders(map<string, unique_ptr<Widget>(*)(const json&)>& widget_builders)
|
void init_builders(map<string, unique_ptr<Widget>(*)(const json&)>& widget_builders)
|
||||||
{
|
{
|
||||||
|
widget_builders["image"] = &WidgetImage::builder;
|
||||||
widget_builders["rect"] = &WidgetRect::builder;
|
widget_builders["rect"] = &WidgetRect::builder;
|
||||||
widget_builders["text"] = &WidgetText::builder;
|
widget_builders["text"] = &WidgetText::builder;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,10 @@ SDL_Rect surface_align(const SDL_Surface* base, const SDL_Surface* applied,
|
|||||||
return align;
|
return align;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These are set in order to handle scaled blits
|
||||||
|
align.w = applied->w;
|
||||||
|
align.h = applied->h;
|
||||||
|
|
||||||
if (nullptr == hint_external)
|
if (nullptr == hint_external)
|
||||||
{
|
{
|
||||||
hint = SDL_Rect{.x = 0, .y = 0, .w = applied->w, .h = applied->h};
|
hint = SDL_Rect{.x = 0, .y = 0, .w = applied->w, .h = applied->h};
|
||||||
@ -167,7 +171,7 @@ void json_extract(const json& j, const string& key, string& out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void json_extract(const nlohmann::json& j, const string& key, int& out)
|
void json_extract(const json& j, const string& key, int& out)
|
||||||
{
|
{
|
||||||
if (j.contains(key) && j[key].is_number_integer())
|
if (j.contains(key) && j[key].is_number_integer())
|
||||||
{
|
{
|
||||||
@ -175,7 +179,7 @@ void json_extract(const nlohmann::json& j, const string& key, int& out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void json_extract(const nlohmann::json& j, const string& key, bool& out)
|
void json_extract(const json& j, const string& key, bool& out)
|
||||||
{
|
{
|
||||||
if (j.contains(key) && j[key].is_boolean())
|
if (j.contains(key) && j[key].is_boolean())
|
||||||
{
|
{
|
||||||
@ -238,10 +242,24 @@ void json_extract(const json& j, const string& key, SDL_Color& out)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void json_extract(const nlohmann::json& j, const string& key, Uint8& out)
|
void json_extract(const json& j, const string& key, Uint8& out)
|
||||||
{
|
{
|
||||||
if (j.contains(key) && j[key].is_number_unsigned())
|
if (j.contains(key) && j[key].is_number_unsigned())
|
||||||
{
|
{
|
||||||
out = j[key];
|
out = j[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void json_extract(const json& j, const string& key, ImageResize& out)
|
||||||
|
{
|
||||||
|
if (j.contains(key))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out = j[key].get<ImageResize>();
|
||||||
|
}
|
||||||
|
catch(const std::exception& e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -52,6 +52,20 @@ NLOHMANN_JSON_SERIALIZE_ENUM(TextFit,
|
|||||||
{FIT_AUTO, "auto"},
|
{FIT_AUTO, "auto"},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
enum ImageResize
|
||||||
|
{
|
||||||
|
RESIZE_NONE,
|
||||||
|
RESIZE_FIT,
|
||||||
|
RESIZE_STRETCH
|
||||||
|
};
|
||||||
|
|
||||||
|
NLOHMANN_JSON_SERIALIZE_ENUM(ImageResize,
|
||||||
|
{
|
||||||
|
{RESIZE_NONE, "none"},
|
||||||
|
{RESIZE_FIT, "fit"},
|
||||||
|
{RESIZE_STRETCH, "stretch"},
|
||||||
|
})
|
||||||
|
|
||||||
// Call this before everything
|
// Call this before everything
|
||||||
// Prints its messages
|
// Prints its messages
|
||||||
bool init_sdl();
|
bool init_sdl();
|
||||||
@ -86,5 +100,6 @@ void json_extract(const nlohmann::json& j, const std::string& key, VerticalAlign
|
|||||||
void json_extract(const nlohmann::json& j, const std::string& key, TextFit& out);
|
void json_extract(const nlohmann::json& j, const std::string& key, TextFit& out);
|
||||||
void json_extract(const nlohmann::json& j, const std::string& key, SDL_Color& out);
|
void json_extract(const nlohmann::json& j, const std::string& key, SDL_Color& out);
|
||||||
void json_extract(const nlohmann::json& j, const std::string& key, Uint8& out);
|
void json_extract(const nlohmann::json& j, const std::string& key, Uint8& out);
|
||||||
|
void json_extract(const nlohmann::json& j, const std::string& key, ImageResize& out);
|
||||||
|
|
||||||
#endif // SDL_HELPERS_H_
|
#endif // SDL_HELPERS_H_
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user