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_image_surface = IMG_Load(m_filename.c_str());
|
||||
|
||||
if (nullptr == m_image_surface)
|
||||
{
|
||||
// TODO: Print errors
|
||||
@ -39,16 +38,23 @@ void WidgetImage::draw()
|
||||
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)
|
||||
{
|
||||
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:
|
||||
// TODO: This currently stretches
|
||||
SDL_BlitScaled(m_image_surface, nullptr, m_surface, nullptr);
|
||||
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:
|
||||
@ -82,3 +88,41 @@ std::unique_ptr<Widget> WidgetImage::builder(const nlohmann::json& j)
|
||||
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;
|
||||
}
|
||||
|
||||
@ -42,6 +42,11 @@ public:
|
||||
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_
|
||||
|
||||
@ -87,6 +87,10 @@ SDL_Rect surface_align(const SDL_Surface* base, const SDL_Surface* applied,
|
||||
return align;
|
||||
}
|
||||
|
||||
// These are set in order to handle scaled blits
|
||||
align.w = applied->w;
|
||||
align.h = applied->h;
|
||||
|
||||
if (nullptr == hint_external)
|
||||
{
|
||||
hint = SDL_Rect{.x = 0, .y = 0, .w = applied->w, .h = applied->h};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user