Fixed 'scale to fit' functionality of WidgetImage
This commit is contained in:
parent
c626578557
commit
17f73211a9
@ -16,7 +16,6 @@ m_valign(valign),
|
|||||||
m_bg_color(bg_color)
|
m_bg_color(bg_color)
|
||||||
{
|
{
|
||||||
m_image_surface = IMG_Load(m_filename.c_str());
|
m_image_surface = IMG_Load(m_filename.c_str());
|
||||||
|
|
||||||
if (nullptr == m_image_surface)
|
if (nullptr == m_image_surface)
|
||||||
{
|
{
|
||||||
// TODO: Print errors
|
// TODO: Print errors
|
||||||
@ -39,16 +38,23 @@ void WidgetImage::draw()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Rect align = surface_align(m_surface, m_image_surface, m_halign, m_valign);
|
SDL_Rect align;
|
||||||
|
SDL_Surface* scaled_image = nullptr;
|
||||||
switch (m_resize_type)
|
switch (m_resize_type)
|
||||||
{
|
{
|
||||||
case RESIZE_NONE:
|
case RESIZE_NONE:
|
||||||
|
align = surface_align(m_surface, m_image_surface, m_halign, m_valign);
|
||||||
SDL_BlitSurface(m_image_surface, nullptr, m_surface, &align);
|
SDL_BlitSurface(m_image_surface, nullptr, m_surface, &align);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RESIZE_FIT:
|
case RESIZE_FIT:
|
||||||
// TODO: This currently stretches
|
scaled_image = image_scale_fit();
|
||||||
SDL_BlitScaled(m_image_surface, nullptr, m_surface, nullptr);
|
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;
|
break;
|
||||||
|
|
||||||
case RESIZE_STRETCH:
|
case RESIZE_STRETCH:
|
||||||
@ -82,3 +88,41 @@ std::unique_ptr<Widget> WidgetImage::builder(const nlohmann::json& j)
|
|||||||
return std::make_unique<WidgetImage>(x, y, width, height, filename,
|
return std::make_unique<WidgetImage>(x, y, width, height, filename,
|
||||||
resize_type, halign, valign, bg_color);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@ -42,6 +42,11 @@ public:
|
|||||||
virtual void draw() override;
|
virtual void draw() override;
|
||||||
|
|
||||||
static std::unique_ptr<Widget> builder(const nlohmann::json& j);
|
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_
|
#endif // WIDGET_IMAGE_H_
|
||||||
|
|||||||
@ -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};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user