Add a new image tiling mode: "tile_highres" for high-DPI tiled images.

The other options "tile" and "tile_center" work in draw space,
which is consistent with past behaviour, but doesn't look as nice.
This commit is contained in:
Tommy 2022-06-05 21:27:20 +12:00
parent 352236a094
commit ebcae03e48
7 changed files with 56 additions and 5 deletions

View file

@ -23,7 +23,7 @@
w = "(width)"
h = "(height)"
name = "dialogs/opaque-background.png"
resize_mode = "tile"
resize_mode = "tile_highres"
[/image]
{_BACKGROUND_DRAW}

View file

@ -48,7 +48,7 @@
w = "(width - 4)"
h = "(height - 4)"
name = "dialogs/{BASE_NAME}-background.png"
resize_mode = "tile"
resize_mode = "tile_highres"
[/image]
[/draw]
@ -152,7 +152,7 @@
w = "(width)"
h = "(height)"
name = "dialogs/menu-background.png"
resize_mode = "tile"
resize_mode = "tile_highres"
[/image]
[rectangle]

View file

@ -31,7 +31,7 @@
[/type]
[type]
name=resize_mode
value="scale|scale_sharp|stretch|tile|tile_center"
value="scale|scale_sharp|stretch|tile|tile_center|tile_highres"
[/type]
[type]
name=scrollbar_mode

View file

@ -270,11 +270,11 @@ void draw::flipped(const texture& tex, bool flip_h, bool flip_v)
}
// TODO: highdpi - maybe expose this mirrored mode to WML somehow
void draw::tiled(const texture& tex, const SDL_Rect& dst, bool centered,
bool mirrored)
{
if (!tex) { return; }
// TODO: highdpi - should this draw at full res? Or game res? For now it's using game res. To draw in higher res, width and height would have to be specified.
// Reduce clip to dst.
auto clipper = draw::reduce_clip(dst);
@ -297,6 +297,38 @@ void draw::tiled(const texture& tex, const SDL_Rect& dst, bool centered,
}
}
void draw::tiled_highres(const texture& tex, const SDL_Rect& dst,
bool centered, bool mirrored)
{
if (!tex) { return; }
const int pixel_scale = CVideo::get_singleton().get_pixel_scale();
// Reduce clip to dst.
auto clipper = draw::reduce_clip(dst);
const auto info = tex.get_info();
const float w = float(info.w) / float(pixel_scale);
const float h = float(info.h) / float(pixel_scale);
const float xoff = centered ? (dst.w - w) / 2 : 0.0f;
const float yoff = centered ? (dst.h - h) / 2 : 0.0f;
// Just blit the image however many times is necessary.
bool vf = false;
SDL_FRect t{dst.x - xoff, dst.y - yoff, w, h};
for (; t.y < dst.y + dst.h; t.y += t.h, vf = !vf) {
bool hf = false;
for (t.x = dst.x - xoff; t.x < dst.x + dst.w; t.x += t.w, hf = !hf) {
if (mirrored) {
SDL_RendererFlip flip = get_flip(hf, vf);
SDL_RenderCopyExF(renderer(), tex, nullptr, &t, 0.0, nullptr, flip);
} else {
SDL_RenderCopyF(renderer(), tex, nullptr, &t);
}
}
}
}
/***************************/
/* RAII state manipulation */

View file

@ -238,6 +238,8 @@ void flipped(const texture& tex, bool flip_h = true, bool flip_v = false);
/**
* Tile a texture to fill a region.
*
* This function tiles the texture in draw-space.
*
* The texture may be aligned either with its center at the center
* of the region, or with its top-left corner at the top-left corner
* of the region.
@ -256,6 +258,17 @@ void tiled(const texture& tex,
bool mirrored = false
);
/** Tile a texture to fill a region.
*
* This function tiles the texture in output space. It is otherwise
* identical to draw::tiled().
*/
void tiled_highres(const texture& tex,
const SDL_Rect& dst,
bool centered = false,
bool mirrored = false
);
/***************************/
/* RAII state manipulation */

View file

@ -431,6 +431,9 @@ void image_shape::draw(
case (resize_mode::tile_center):
draw::tiled(tex, adjusted_draw_loc, true, mirror_(variables));
break;
case resize_mode::tile_highres:
draw::tiled_highres(tex, adjusted_draw_loc, false, mirror_(variables));
break;
case resize_mode::stretch:
// Stretching is identical to scaling in terms of handling.
// Is this intended? That's what previous code was doing.
@ -456,6 +459,8 @@ image_shape::resize_mode image_shape::get_resize_mode(const std::string& resize_
return resize_mode::tile;
} else if(resize_mode == "tile_center") {
return resize_mode::tile_center;
} else if(resize_mode == "tile_highres") {
return resize_mode::tile_highres;
} else if(resize_mode == "stretch") {
return resize_mode::stretch;
} else if(resize_mode == "scale_sharp") {

View file

@ -386,6 +386,7 @@ private:
stretch,
tile,
tile_center,
tile_highres,
};
/** Converts a string to a resize mode. */