Conduct surface manipulation in-place when possible (#9218)
This commit is contained in:
parent
fb1232e4ea
commit
457ed4bb43
6 changed files with 239 additions and 532 deletions
|
@ -664,7 +664,7 @@ bool canvas::update_blur(const rect& screen_region, bool force)
|
|||
rect read_region = screen_region;
|
||||
auto setter = draw::set_render_target({});
|
||||
surface s = video::read_pixels_low_res(&read_region);
|
||||
s = blur_surface(s, blur_depth_);
|
||||
blur_surface(s, {0, 0, s->w, s->h}, blur_depth_);
|
||||
blur_texture_ = texture(s);
|
||||
deferred_ = false;
|
||||
return true;
|
||||
|
|
|
@ -149,29 +149,24 @@ modification_queue modification::decode(const std::string& encoded_mods)
|
|||
return mods;
|
||||
}
|
||||
|
||||
surface rc_modification::operator()(const surface& src) const
|
||||
void rc_modification::operator()(surface& src) const
|
||||
{
|
||||
// unchecked
|
||||
return recolor_image(src, rc_map_);
|
||||
recolor_image(src, rc_map_);
|
||||
}
|
||||
|
||||
surface fl_modification::operator()(const surface& src) const
|
||||
void fl_modification::operator()(surface& src) const
|
||||
{
|
||||
surface ret = src;
|
||||
|
||||
if(horiz_ && vert_ ) {
|
||||
// Slightly faster than doing both a flip and a flop.
|
||||
ret = rotate_180_surface(ret);
|
||||
src = rotate_180_surface(src);
|
||||
} else if(horiz_) {
|
||||
ret = flip_surface(ret);
|
||||
flip_surface(src);
|
||||
} else if(vert_) {
|
||||
ret = flop_surface(ret);
|
||||
flop_surface(src);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
surface rotate_modification::operator()(const surface& src) const
|
||||
void rotate_modification::operator()(surface& src) const
|
||||
{
|
||||
// Convert the number of degrees to the interval [0,360].
|
||||
const int normalized = degrees_ >= 0 ?
|
||||
|
@ -180,59 +175,66 @@ surface rotate_modification::operator()(const surface& src) const
|
|||
|
||||
switch ( normalized )
|
||||
{
|
||||
case 0: return src;
|
||||
case 90: return rotate_90_surface(src, true);
|
||||
case 180: return rotate_180_surface(src);
|
||||
case 270: return rotate_90_surface(src, false);
|
||||
case 360: return src;
|
||||
case 0:
|
||||
return;
|
||||
case 90:
|
||||
src = rotate_90_surface(src, true);
|
||||
return;
|
||||
case 180:
|
||||
src = rotate_180_surface(src);
|
||||
return;
|
||||
case 270:
|
||||
src = rotate_90_surface(src, false);
|
||||
return;
|
||||
case 360:
|
||||
return;
|
||||
}
|
||||
|
||||
return rotate_any_surface(src, normalized, zoom_, offset_);
|
||||
src = rotate_any_surface(src, normalized, zoom_, offset_);
|
||||
}
|
||||
|
||||
surface gs_modification::operator()(const surface& src) const
|
||||
void gs_modification::operator()(surface& src) const
|
||||
{
|
||||
return greyscale_image(src);
|
||||
greyscale_image(src);
|
||||
}
|
||||
|
||||
surface crop_transparency_modification::operator()(const surface& src) const
|
||||
void crop_transparency_modification::operator()(surface& src) const
|
||||
{
|
||||
rect src_rect = get_non_transparent_portion(src);
|
||||
if(src_rect.w == src->w && src_rect.h == src->h) {
|
||||
return src;
|
||||
return;
|
||||
}
|
||||
|
||||
if(surface cropped = get_surface_portion(src, src_rect)) {
|
||||
return cropped;
|
||||
src = cropped;
|
||||
} else {
|
||||
ERR_DP << "Failed to either crop or scale the surface";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
surface bw_modification::operator()(const surface& src) const
|
||||
void bw_modification::operator()(surface& src) const
|
||||
{
|
||||
return monochrome_image(src, threshold_);
|
||||
monochrome_image(src, threshold_);
|
||||
}
|
||||
|
||||
surface sepia_modification::operator()(const surface &src) const
|
||||
void sepia_modification::operator()(surface& src) const
|
||||
{
|
||||
return sepia_image(src);
|
||||
sepia_image(src);
|
||||
}
|
||||
|
||||
surface negative_modification::operator()(const surface &src) const
|
||||
void negative_modification::operator()(surface& src) const
|
||||
{
|
||||
return negative_image(src, red_, green_, blue_);
|
||||
negative_image(src, red_, green_, blue_);
|
||||
}
|
||||
|
||||
surface plot_alpha_modification::operator()(const surface& src) const
|
||||
void plot_alpha_modification::operator()(surface& src) const
|
||||
{
|
||||
return alpha_to_greyscale(src);
|
||||
alpha_to_greyscale(src);
|
||||
}
|
||||
|
||||
surface wipe_alpha_modification::operator()(const surface& src) const
|
||||
void wipe_alpha_modification::operator()(surface& src) const
|
||||
{
|
||||
return wipe_alpha(src);
|
||||
wipe_alpha(src);
|
||||
}
|
||||
|
||||
// TODO: Is this useful enough to move into formula/callable_objects?
|
||||
|
@ -291,25 +293,14 @@ private:
|
|||
uint32_t w, h;
|
||||
};
|
||||
|
||||
surface adjust_alpha_modification::operator()(const surface & src) const
|
||||
void adjust_alpha_modification::operator()(surface& src) const
|
||||
{
|
||||
if(src == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if(src) {
|
||||
wfl::formula new_alpha(formula_);
|
||||
|
||||
wfl::formula new_alpha(formula_);
|
||||
|
||||
surface nsurf = src.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
surface_lock lock(nsurf);
|
||||
surface_lock lock(src);
|
||||
uint32_t* cur = lock.pixels();
|
||||
uint32_t* const end = cur + nsurf->w * src->h;
|
||||
uint32_t* const end = cur + src->w * src->h;
|
||||
uint32_t* const beg = cur;
|
||||
|
||||
while(cur != end) {
|
||||
|
@ -321,42 +312,29 @@ surface adjust_alpha_modification::operator()(const surface & src) const
|
|||
|
||||
int i = cur - beg;
|
||||
SDL_Point p;
|
||||
p.y = i / nsurf->w;
|
||||
p.x = i % nsurf->w;
|
||||
p.y = i / src->w;
|
||||
p.x = i % src->w;
|
||||
|
||||
pixel_callable px(p, pixel, nsurf->w, nsurf->h);
|
||||
pixel_callable px(p, pixel, src->w, src->h);
|
||||
pixel.a = std::min<unsigned>(new_alpha.evaluate(px).as_int(), 255);
|
||||
*cur = (pixel.a << 24) + (pixel.r << 16) + (pixel.g << 8) + pixel.b;
|
||||
|
||||
++cur;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface adjust_channels_modification::operator()(const surface & src) const
|
||||
void adjust_channels_modification::operator()(surface& src) const
|
||||
{
|
||||
if(src == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if(src) {
|
||||
wfl::formula new_red(formulas_[0]);
|
||||
wfl::formula new_green(formulas_[1]);
|
||||
wfl::formula new_blue(formulas_[2]);
|
||||
wfl::formula new_alpha(formulas_[3]);
|
||||
|
||||
wfl::formula new_red(formulas_[0]);
|
||||
wfl::formula new_green(formulas_[1]);
|
||||
wfl::formula new_blue(formulas_[2]);
|
||||
wfl::formula new_alpha(formulas_[3]);
|
||||
|
||||
surface nsurf = src.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
surface_lock lock(nsurf);
|
||||
surface_lock lock(src);
|
||||
uint32_t* cur = lock.pixels();
|
||||
uint32_t* const end = cur + nsurf->w * src->h;
|
||||
uint32_t* const end = cur + src->w * src->h;
|
||||
uint32_t* const beg = cur;
|
||||
|
||||
while(cur != end) {
|
||||
|
@ -368,10 +346,10 @@ surface adjust_channels_modification::operator()(const surface & src) const
|
|||
|
||||
int i = cur - beg;
|
||||
SDL_Point p;
|
||||
p.y = i / nsurf->w;
|
||||
p.x = i % nsurf->w;
|
||||
p.y = i / src->w;
|
||||
p.x = i % src->w;
|
||||
|
||||
pixel_callable px(p, pixel, nsurf->w, nsurf->h);
|
||||
pixel_callable px(p, pixel, src->w, src->h);
|
||||
pixel.r = std::min<unsigned>(new_red.evaluate(px).as_int(), 255);
|
||||
pixel.g = std::min<unsigned>(new_green.evaluate(px).as_int(), 255);
|
||||
pixel.b = std::min<unsigned>(new_blue.evaluate(px).as_int(), 255);
|
||||
|
@ -381,11 +359,9 @@ surface adjust_channels_modification::operator()(const surface & src) const
|
|||
++cur;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface crop_modification::operator()(const surface& src) const
|
||||
void crop_modification::operator()(surface& src) const
|
||||
{
|
||||
SDL_Rect area = slice_;
|
||||
if(area.w == 0) {
|
||||
|
@ -396,18 +372,10 @@ surface crop_modification::operator()(const surface& src) const
|
|||
area.h = src->h;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlike other image functions cut_surface does not convert the input
|
||||
* surface to a neutral surface, nor does it convert its return surface
|
||||
* to an optimised surface.
|
||||
*
|
||||
* Since it seems to work for most cases, rather change this caller instead
|
||||
* of the function signature. (The issue was discovered in bug #20876).
|
||||
*/
|
||||
return cut_surface(src, area);
|
||||
src = cut_surface(src, area);
|
||||
}
|
||||
|
||||
surface blit_modification::operator()(const surface& src) const
|
||||
void blit_modification::operator()(surface& src) const
|
||||
{
|
||||
if(x_ >= src->w) {
|
||||
std::stringstream sstr;
|
||||
|
@ -443,39 +411,36 @@ surface blit_modification::operator()(const surface& src) const
|
|||
throw imod_exception(sstr);
|
||||
}
|
||||
|
||||
surface nsrc = src.clone();
|
||||
SDL_Rect r {x_, y_, 0, 0};
|
||||
sdl_blit(surf_, nullptr, nsrc, &r);
|
||||
return nsrc;
|
||||
sdl_blit(surf_, nullptr, src, &r);
|
||||
}
|
||||
|
||||
surface mask_modification::operator()(const surface& src) const
|
||||
void mask_modification::operator()(surface& src) const
|
||||
{
|
||||
if(src->w == mask_->w && src->h == mask_->h && x_ == 0 && y_ == 0) {
|
||||
return mask_surface(src, mask_);
|
||||
if(src->w == mask_->w && src->h == mask_->h && x_ == 0 && y_ == 0) {
|
||||
mask_surface(src, mask_);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Rect r {x_, y_, 0, 0};
|
||||
surface new_mask(src->w, src->h);
|
||||
sdl_blit(mask_, nullptr, new_mask, &r);
|
||||
return mask_surface(src, new_mask);
|
||||
mask_surface(src, new_mask);
|
||||
}
|
||||
|
||||
surface light_modification::operator()(const surface& src) const {
|
||||
if(src == nullptr) { return nullptr; }
|
||||
void light_modification::operator()(surface& src) const
|
||||
{
|
||||
if(src == nullptr) { return; }
|
||||
|
||||
// light_surface wants a neutral surface having same dimensions
|
||||
surface nsurf;
|
||||
if(surf_->w != src->w || surf_->h != src->h) {
|
||||
nsurf = scale_surface(surf_, src->w, src->h);
|
||||
light_surface(src, scale_surface(surf_, src->w, src->h));
|
||||
} else {
|
||||
nsurf = surf_;
|
||||
light_surface(src, surf_);
|
||||
}
|
||||
|
||||
return light_surface(src, nsurf);
|
||||
}
|
||||
|
||||
surface scale_modification::operator()(const surface& src) const
|
||||
void scale_modification::operator()(surface& src) const
|
||||
{
|
||||
point size = target_size_;
|
||||
|
||||
|
@ -504,40 +469,31 @@ surface scale_modification::operator()(const surface& src) const
|
|||
}
|
||||
|
||||
if(flags_ & SCALE_SHARP) {
|
||||
return scale_surface_sharp(src, size.x, size.y);
|
||||
src = scale_surface_sharp(src, size.x, size.y);
|
||||
} else {
|
||||
return scale_surface_legacy(src, size.x, size.y);
|
||||
src = scale_surface_legacy(src, size.x, size.y);
|
||||
}
|
||||
}
|
||||
|
||||
surface xbrz_modification::operator()(const surface& src) const
|
||||
void xbrz_modification::operator()(surface& src) const
|
||||
{
|
||||
if(z_ == 1) {
|
||||
return src;
|
||||
if(z_ != 1) {
|
||||
src = scale_surface_xbrz(src, z_);
|
||||
}
|
||||
|
||||
return scale_surface_xbrz(src, z_);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Opacity IPF doesn't seem to work with surface-wide alpha and instead needs per-pixel alpha.
|
||||
* If this is needed anywhere else it can be moved back to sdl/utils.*pp.
|
||||
*/
|
||||
surface o_modification::operator()(const surface& src) const
|
||||
void o_modification::operator()(surface& src) const
|
||||
{
|
||||
surface nsurf = src.clone();
|
||||
if(src) {
|
||||
uint8_t alpha_mod = float_to_color(opacity_);
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t alpha_mod = float_to_color(opacity_);
|
||||
|
||||
{
|
||||
surface_lock lock(nsurf);
|
||||
surface_lock lock(src);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w * src->h;
|
||||
uint32_t* end = beg + src->w * src->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -555,40 +511,36 @@ surface o_modification::operator()(const surface& src) const
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface cs_modification::operator()(const surface& src) const
|
||||
void cs_modification::operator()(surface& src) const
|
||||
{
|
||||
return((r_ != 0 || g_ != 0 || b_ != 0)
|
||||
? adjust_surface_color(src, r_, g_, b_)
|
||||
: src
|
||||
);
|
||||
if((r_ != 0 || g_ != 0 || b_ != 0)) {
|
||||
adjust_surface_color(src, r_, g_, b_);
|
||||
}
|
||||
}
|
||||
|
||||
surface blend_modification::operator()(const surface& src) const
|
||||
void blend_modification::operator()(surface& src) const
|
||||
{
|
||||
return blend_surface(src, static_cast<double>(a_), color_t(r_, g_, b_));
|
||||
blend_surface(src, static_cast<double>(a_), color_t(r_, g_, b_));
|
||||
}
|
||||
|
||||
surface bl_modification::operator()(const surface& src) const
|
||||
void bl_modification::operator()(surface& src) const
|
||||
{
|
||||
return blur_alpha_surface(src, depth_);
|
||||
blur_alpha_surface(src, depth_);
|
||||
}
|
||||
|
||||
surface background_modification::operator()(const surface &src) const
|
||||
void background_modification::operator()(surface& src) const
|
||||
{
|
||||
surface ret = src.clone();
|
||||
SDL_FillRect(ret, nullptr, SDL_MapRGBA(ret->format, color_.r, color_.g,
|
||||
color_.b, color_.a));
|
||||
SDL_FillRect(ret, nullptr, SDL_MapRGBA(ret->format, color_.r, color_.g, color_.b, color_.a));
|
||||
sdl_blit(src, nullptr, ret, nullptr);
|
||||
return ret;
|
||||
src = ret;
|
||||
}
|
||||
|
||||
surface swap_modification::operator()(const surface &src) const
|
||||
void swap_modification::operator()(surface& src) const
|
||||
{
|
||||
return swap_channels_image(src, red_, green_, blue_, alpha_);
|
||||
swap_channels_image(src, red_, green_, blue_, alpha_);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
virtual ~modification() {}
|
||||
|
||||
/** Applies the image-path modification on the specified surface */
|
||||
virtual surface operator()(const surface& src) const = 0;
|
||||
virtual void operator()(surface& src) const = 0;
|
||||
|
||||
/** Specifies the priority of the modification */
|
||||
virtual int priority() const { return 0; }
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
rc_modification(const color_range_map& recolor_map)
|
||||
: rc_map_(recolor_map)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
// The rc modification has a higher priority
|
||||
virtual int priority() const { return 1; }
|
||||
|
@ -159,7 +159,7 @@ public:
|
|||
: horiz_(horiz)
|
||||
, vert_(vert)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
void set_horiz(bool val) { horiz_ = val; }
|
||||
void set_vert(bool val) { vert_ = val; }
|
||||
|
@ -205,7 +205,7 @@ public:
|
|||
rotate_modification(int degrees = 90, int zoom = 16, int offset = 8)
|
||||
: degrees_(degrees), zoom_(zoom), offset_(offset)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
bool no_op() const { return degrees_ % 360 == 0; }
|
||||
|
||||
|
@ -221,7 +221,7 @@ private:
|
|||
class gs_modification : public modification
|
||||
{
|
||||
public:
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -230,7 +230,7 @@ public:
|
|||
class crop_transparency_modification : public modification
|
||||
{
|
||||
public:
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -240,7 +240,7 @@ class bw_modification : public modification
|
|||
{
|
||||
public:
|
||||
bw_modification(int threshold): threshold_(threshold) {}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
private:
|
||||
int threshold_;
|
||||
};
|
||||
|
@ -250,7 +250,7 @@ private:
|
|||
*/
|
||||
struct sepia_modification : modification
|
||||
{
|
||||
virtual surface operator()(const surface &src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -260,7 +260,7 @@ class negative_modification : public modification
|
|||
{
|
||||
public:
|
||||
negative_modification(int r, int g, int b): red_(r), green_(g), blue_(b) {}
|
||||
virtual surface operator()(const surface &src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
private:
|
||||
int red_, green_, blue_;
|
||||
};
|
||||
|
@ -271,7 +271,7 @@ private:
|
|||
class plot_alpha_modification : public modification
|
||||
{
|
||||
public:
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -280,7 +280,7 @@ public:
|
|||
class wipe_alpha_modification : public modification
|
||||
{
|
||||
public:
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -293,7 +293,7 @@ public:
|
|||
: formula_(formula)
|
||||
{}
|
||||
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
private:
|
||||
std::string formula_;
|
||||
|
@ -322,7 +322,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> formulas_;
|
||||
|
@ -337,7 +337,7 @@ public:
|
|||
crop_modification(const SDL_Rect& slice)
|
||||
: slice_(slice)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
const SDL_Rect& get_slice() const
|
||||
{
|
||||
|
@ -358,7 +358,7 @@ public:
|
|||
blit_modification(const surface& surf, int x, int y)
|
||||
: surf_(surf), x_(x), y_(y)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
const surface& get_surface() const
|
||||
{
|
||||
|
@ -391,7 +391,7 @@ public:
|
|||
mask_modification(const surface& mask, int x, int y)
|
||||
: mask_(mask), x_(x), y_(y)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
const surface& get_mask() const
|
||||
{
|
||||
|
@ -424,7 +424,7 @@ public:
|
|||
light_modification(const surface& surf)
|
||||
: surf_(surf)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
const surface& get_surface() const
|
||||
{
|
||||
|
@ -456,7 +456,7 @@ public:
|
|||
, flags_(flags)
|
||||
{}
|
||||
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
int get_w() const { return target_size_.x; }
|
||||
int get_h() const { return target_size_.y; }
|
||||
|
@ -477,7 +477,7 @@ public:
|
|||
: z_(z)
|
||||
{}
|
||||
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
private:
|
||||
int z_;
|
||||
|
@ -492,7 +492,7 @@ public:
|
|||
o_modification(float opacity)
|
||||
: opacity_(opacity)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
float get_opacity() const
|
||||
{
|
||||
|
@ -512,7 +512,7 @@ public:
|
|||
cs_modification(int r, int g, int b)
|
||||
: r_(r), g_(g), b_(b)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
int get_r() const { return r_; }
|
||||
int get_g() const { return g_; }
|
||||
|
@ -531,7 +531,7 @@ public:
|
|||
blend_modification(int r, int g, int b, float a)
|
||||
: r_(r), g_(g), b_(b), a_(a)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
int get_r() const { return r_; }
|
||||
int get_g() const { return g_; }
|
||||
|
@ -552,7 +552,7 @@ public:
|
|||
bl_modification(int depth)
|
||||
: depth_(depth)
|
||||
{}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
int get_depth() const
|
||||
{
|
||||
|
@ -569,7 +569,7 @@ private:
|
|||
struct background_modification : modification
|
||||
{
|
||||
background_modification(const color_t& c): color_(c) {}
|
||||
virtual surface operator()(const surface &src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
|
||||
const color_t& get_color() const
|
||||
{
|
||||
|
@ -587,7 +587,7 @@ class swap_modification : public modification
|
|||
{
|
||||
public:
|
||||
swap_modification(channel r, channel g, channel b, channel a): red_(r), green_(g), blue_(b), alpha_(a) {}
|
||||
virtual surface operator()(const surface& src) const;
|
||||
virtual void operator()(surface& src) const;
|
||||
private:
|
||||
channel red_;
|
||||
channel green_;
|
||||
|
|
|
@ -384,7 +384,8 @@ static surface load_image_file(const image::locator& loc)
|
|||
|
||||
static surface load_image_sub_file(const image::locator& loc)
|
||||
{
|
||||
surface surf = get_surface(loc.get_filename(), UNSCALED);
|
||||
// Create a new surface in-memory on which to apply the modifications
|
||||
surface surf = get_surface(loc.get_filename(), UNSCALED).clone();
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -395,7 +396,7 @@ static surface load_image_sub_file(const image::locator& loc)
|
|||
modification* mod = mods.top();
|
||||
|
||||
try {
|
||||
surf = (*mod)(surf);
|
||||
std::invoke(*mod, surf);
|
||||
} catch(const image::modification::imod_exception& e) {
|
||||
std::ostringstream ss;
|
||||
ss << "\n";
|
||||
|
@ -428,9 +429,9 @@ static surface load_image_sub_file(const image::locator& loc)
|
|||
}
|
||||
|
||||
// cut and hex mask, but also check and cache if empty result
|
||||
surface cut(cut_surface(surf, srcrect));
|
||||
surface cut = cut_surface(surf, srcrect);
|
||||
bool is_empty = false;
|
||||
surf = mask_surface(cut, get_hexmask(), &is_empty);
|
||||
mask_surface(cut, get_hexmask(), &is_empty);
|
||||
|
||||
// discard empty images to free memory
|
||||
if(is_empty) {
|
||||
|
@ -438,6 +439,8 @@ static surface load_image_sub_file(const image::locator& loc)
|
|||
// and it filters them out.
|
||||
// A safer and more general way would be to keep only one copy of it
|
||||
surf = nullptr;
|
||||
} else {
|
||||
surf = cut;
|
||||
}
|
||||
|
||||
is_empty_hex_.add_to_cache(loc, is_empty);
|
||||
|
@ -499,7 +502,8 @@ static surface apply_light(surface surf, const light_string& ls)
|
|||
// if no lightmap (first char = -1) then we need the initial value
|
||||
//(before the halving done for lightmap)
|
||||
int m = ls[0] == -1 ? 2 : 1;
|
||||
return adjust_surface_color(surf, ls[1] * m, ls[2] * m, ls[3] * m);
|
||||
adjust_surface_color(surf, ls[1] * m, ls[2] * m, ls[3] * m);
|
||||
return surf;
|
||||
}
|
||||
|
||||
// check if the lightmap is already cached or need to be generated
|
||||
|
@ -543,7 +547,8 @@ static surface apply_light(surface surf, const light_string& ls)
|
|||
}
|
||||
|
||||
// apply the final lightmap
|
||||
return light_surface(surf, lightmap);
|
||||
light_surface(surf, lightmap);
|
||||
return surf;
|
||||
}
|
||||
|
||||
static surface load_from_disk(const locator& loc)
|
||||
|
@ -586,8 +591,8 @@ void set_color_adjustment(int r, int g, int b)
|
|||
|
||||
static surface get_hexed(const locator& i_locator, bool skip_cache = false)
|
||||
{
|
||||
surface image(get_surface(i_locator, UNSCALED, skip_cache));
|
||||
surface mask(get_hexmask());
|
||||
surface image = get_surface(i_locator, UNSCALED, skip_cache).clone();
|
||||
surface mask = get_hexmask();
|
||||
// Ensure the image is the correct size by cropping and/or centering.
|
||||
// TODO: this should probably be a function of sdl/utils
|
||||
if(image && (image->w != mask->w || image->h != mask->h)) {
|
||||
|
@ -618,15 +623,16 @@ static surface get_hexed(const locator& i_locator, bool skip_cache = false)
|
|||
}
|
||||
// hex cut tiles, also check and cache if empty result
|
||||
bool is_empty = false;
|
||||
surface res = mask_surface(image, mask, &is_empty, i_locator.get_filename());
|
||||
mask_surface(image, mask, &is_empty, i_locator.get_filename());
|
||||
is_empty_hex_.add_to_cache(i_locator, is_empty);
|
||||
return res;
|
||||
return image;
|
||||
}
|
||||
|
||||
static surface get_tod_colored(const locator& i_locator, bool skip_cache = false)
|
||||
{
|
||||
surface img = get_surface(i_locator, HEXED, skip_cache);
|
||||
return adjust_surface_color(img, red_adjust, green_adjust, blue_adjust);
|
||||
surface img = get_surface(i_locator, HEXED, skip_cache).clone();
|
||||
adjust_surface_color(img, red_adjust, green_adjust, blue_adjust);
|
||||
return img;
|
||||
}
|
||||
|
||||
/** translate type to a simpler one when possible */
|
||||
|
@ -727,7 +733,7 @@ surface get_lighted_image(const image::locator& i_locator, const light_string& l
|
|||
DBG_IMG << "lit surface cache miss: " << i_locator;
|
||||
|
||||
// not cached yet, generate it
|
||||
surface res = apply_light(get_surface(i_locator, HEXED), ls);
|
||||
surface res = apply_light(get_surface(i_locator, HEXED).clone(), ls);
|
||||
|
||||
// record the lighted surface in the corresponding variants cache
|
||||
lvar[ls] = res;
|
||||
|
@ -790,7 +796,7 @@ bool is_in_hex(const locator& i_locator)
|
|||
bool is_empty_hex(const locator& i_locator)
|
||||
{
|
||||
if(!is_empty_hex_.in_cache(i_locator)) {
|
||||
const surface surf = get_surface(i_locator, HEXED);
|
||||
surface surf = get_surface(i_locator, HEXED);
|
||||
// emptiness of terrain image is checked during hex cut
|
||||
// so, maybe in cache now, let's recheck
|
||||
if(!is_empty_hex_.in_cache(i_locator)) {
|
||||
|
|
|
@ -357,7 +357,6 @@ surface scale_surface_legacy(const surface &surf, int w, int h)
|
|||
return dst;
|
||||
}
|
||||
|
||||
|
||||
surface scale_surface_sharp(const surface& surf, int w, int h)
|
||||
{
|
||||
// Since SDL version 1.1.5 0 is transparent, before 255 was transparent.
|
||||
|
@ -408,27 +407,12 @@ surface scale_surface_sharp(const surface& surf, int w, int h)
|
|||
return dst;
|
||||
}
|
||||
|
||||
surface adjust_surface_color(const surface &surf, int red, int green, int blue)
|
||||
void adjust_surface_color(surface& nsurf, int red, int green, int blue)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
if((red == 0 && green == 0 && blue == 0)) {
|
||||
surface temp = surf; // TODO: remove temp surface
|
||||
return temp;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf && (red != 0 || green != 0 || blue != 0)) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -449,25 +433,14 @@ surface adjust_surface_color(const surface &surf, int red, int green, int blue)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface greyscale_image(const surface &surf)
|
||||
void greyscale_image(surface& nsurf)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -494,25 +467,14 @@ surface greyscale_image(const surface &surf)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface monochrome_image(const surface &surf, const int threshold)
|
||||
void monochrome_image(surface& nsurf, const int threshold)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -534,25 +496,14 @@ surface monochrome_image(const surface &surf, const int threshold)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface sepia_image(const surface &surf)
|
||||
void sepia_image(surface& nsurf)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -576,25 +527,14 @@ surface sepia_image(const surface &surf)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface negative_image(const surface &surf, const int thresholdR, const int thresholdG, const int thresholdB)
|
||||
void negative_image(surface& nsurf, const int thresholdR, const int thresholdG, const int thresholdB)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -619,25 +559,14 @@ surface negative_image(const surface &surf, const int thresholdR, const int thre
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface alpha_to_greyscale(const surface &surf)
|
||||
void alpha_to_greyscale(surface& nsurf)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -647,25 +576,14 @@ surface alpha_to_greyscale(const surface &surf)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface wipe_alpha(const surface &surf)
|
||||
void wipe_alpha(surface& nsurf)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
|
||||
|
@ -674,28 +592,21 @@ surface wipe_alpha(const surface &surf)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
|
||||
surface shadow_image(const surface &surf, int scale)
|
||||
void shadow_image(surface& surf, int scale)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
return;
|
||||
|
||||
// we blur it, and reuse the neutral surface created by the blur function
|
||||
surface nsurf (blur_alpha_surface(surf, 2*scale));
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to blur the shadow surface";
|
||||
return nullptr;
|
||||
}
|
||||
blur_alpha_surface(surf, 2*scale);
|
||||
|
||||
{
|
||||
surface_lock lock(nsurf);
|
||||
surface_lock lock(surf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + surf->w*surf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -712,24 +623,14 @@ surface shadow_image(const surface &surf, int scale)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface swap_channels_image(const surface& surf, channel r, channel g, channel b, channel a) {
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
void swap_channels_image(surface& nsurf, channel r, channel g, channel b, channel a)
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -754,7 +655,7 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
newRed = alpha;
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (g) {
|
||||
|
@ -771,7 +672,7 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
newGreen = alpha;
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (b) {
|
||||
|
@ -788,7 +689,7 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
newBlue = alpha;
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (a) {
|
||||
|
@ -805,7 +706,7 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
newAlpha = alpha;
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
*beg = (newAlpha << 24) | (newRed << 16) | (newGreen << 8) | newBlue;
|
||||
|
@ -814,28 +715,20 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface recolor_image(surface surf, const color_range_map& map_rgb)
|
||||
void recolor_image(surface& nsurf, const color_range_map& map_rgb)
|
||||
{
|
||||
if(surf == nullptr)
|
||||
return nullptr;
|
||||
if(nsurf == nullptr)
|
||||
return;
|
||||
|
||||
if(map_rgb.empty()) {
|
||||
return surf;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "failed to make neutral surface";
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -853,27 +746,14 @@ surface recolor_image(surface surf, const color_range_map& map_rgb)
|
|||
|
||||
++beg;
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface brighten_image(const surface &surf, int32_t amount)
|
||||
void brighten_image(surface& nsurf, int32_t amount)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
if (amount < 0) amount = 0;
|
||||
while(beg != end) {
|
||||
|
@ -895,8 +775,6 @@ surface brighten_image(const surface &surf, int32_t amount)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
void adjust_surface_alpha(surface& surf, uint8_t alpha_mod)
|
||||
|
@ -908,23 +786,12 @@ void adjust_surface_alpha(surface& surf, uint8_t alpha_mod)
|
|||
SDL_SetSurfaceAlphaMod(surf, alpha_mod);
|
||||
}
|
||||
|
||||
surface adjust_surface_alpha_add(const surface &surf, int amount)
|
||||
void adjust_surface_alpha_add(surface& nsurf, int amount)
|
||||
{
|
||||
if(surf== nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
while(beg != end) {
|
||||
uint8_t alpha = (*beg) >> 24;
|
||||
|
@ -942,28 +809,19 @@ surface adjust_surface_alpha_add(const surface &surf, int amount)
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface mask_surface(const surface &surf, const surface &mask, bool* empty_result, const std::string& filename)
|
||||
void mask_surface(surface& nsurf, const surface& nmask, bool* empty_result, const std::string& filename)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
if(nsurf == nullptr) {
|
||||
*empty_result = true;
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
if(mask == nullptr) {
|
||||
return surf;
|
||||
if(nmask == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
surface nmask = mask.clone();
|
||||
|
||||
if(nsurf == nullptr || nmask == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
if (nsurf->w != nmask->w) {
|
||||
if (nsurf->w != nmask->w) {
|
||||
// we don't support efficiently different width.
|
||||
// (different height is not a real problem)
|
||||
// This function is used on all hexes and usually only for that
|
||||
|
@ -974,7 +832,7 @@ surface mask_surface(const surface &surf, const surface &mask, bool* empty_resul
|
|||
ss << nsurf->w << "x" << nsurf->h;
|
||||
PLAIN_LOG << ss.str();
|
||||
PLAIN_LOG << "It will not be masked, please use: "<< nmask->w << "x" << nmask->h;
|
||||
return nsurf;
|
||||
return;
|
||||
}
|
||||
|
||||
bool empty = true;
|
||||
|
@ -983,7 +841,7 @@ surface mask_surface(const surface &surf, const surface &mask, bool* empty_resul
|
|||
const_surface_lock mlock(nmask);
|
||||
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
const uint32_t* mbeg = mlock.pixels();
|
||||
const uint32_t* mend = mbeg + nmask->w*nmask->h;
|
||||
|
||||
|
@ -1012,32 +870,22 @@ surface mask_surface(const surface &surf, const surface &mask, bool* empty_resul
|
|||
}
|
||||
if(empty_result)
|
||||
*empty_result = empty;
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
bool in_mask_surface(const surface &surf, const surface &mask)
|
||||
bool in_mask_surface(surface nsurf, surface nmask)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
if(nsurf == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if(mask == nullptr){
|
||||
if(nmask == nullptr){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (surf->w != mask->w || surf->h != mask->h ) {
|
||||
if (nsurf->w != nmask->w || nsurf->h != nmask->h ) {
|
||||
// not same size, consider it doesn't fit
|
||||
return false;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
surface nmask = mask.clone();
|
||||
|
||||
if(nsurf == nullptr || nmask == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
surface_lock lock(nsurf);
|
||||
const_surface_lock mlock(nmask);
|
||||
|
@ -1062,21 +910,15 @@ bool in_mask_surface(const surface &surf, const surface &mask)
|
|||
return true;
|
||||
}
|
||||
|
||||
surface light_surface(const surface &surf, const surface &lightmap)
|
||||
void light_surface(surface& nsurf, const surface &lightmap)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
if(nsurf == nullptr) {
|
||||
return;
|
||||
}
|
||||
if(lightmap == nullptr) {
|
||||
return surf;
|
||||
return;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
if (nsurf->w != lightmap->w) {
|
||||
// we don't support efficiently different width.
|
||||
// (different height is not a real problem)
|
||||
|
@ -1084,7 +926,7 @@ surface light_surface(const surface &surf, const surface &lightmap)
|
|||
// so better keep it simple and efficient for the normal case
|
||||
PLAIN_LOG << "Detected an image with bad dimensions: " << nsurf->w << "x" << nsurf->h;
|
||||
PLAIN_LOG << "It will not be lighted, please use: "<< lightmap->w << "x" << lightmap->h;
|
||||
return nsurf;
|
||||
return;
|
||||
}
|
||||
{
|
||||
surface_lock lock(nsurf);
|
||||
|
@ -1123,28 +965,6 @@ surface light_surface(const surface &surf, const surface &lightmap)
|
|||
++lbeg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
|
||||
surface blur_surface(const surface &surf, int depth)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface res = surf.clone();
|
||||
|
||||
if(res == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SDL_Rect rect {0, 0, surf->w, surf->h};
|
||||
blur_surface(res, rect, depth);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void blur_surface(surface& surf, SDL_Rect rect, int depth)
|
||||
|
@ -1263,17 +1083,10 @@ void blur_surface(surface& surf, SDL_Rect rect, int depth)
|
|||
}
|
||||
}
|
||||
|
||||
surface blur_alpha_surface(const surface &surf, int depth)
|
||||
void blur_alpha_surface(surface& res, int depth)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface res = surf.clone();
|
||||
|
||||
if(res == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
const int max_blur = 256;
|
||||
|
@ -1406,8 +1219,6 @@ surface blur_alpha_surface(const surface &surf, int depth)
|
|||
assert(static_cast<int>(queue.size()) == std::min(depth, res->h));
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
surface cut_surface(const surface &surf, const SDL_Rect& r)
|
||||
|
@ -1468,26 +1279,13 @@ surface cut_surface(const surface &surf, const SDL_Rect& r)
|
|||
|
||||
return res;
|
||||
}
|
||||
surface blend_surface(
|
||||
const surface &surf
|
||||
, const double amount
|
||||
, const color_t color)
|
||||
|
||||
void blend_surface(surface& nsurf, const double amount, const color_t color)
|
||||
{
|
||||
if(surf== nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* beg = lock.pixels();
|
||||
uint32_t* end = beg + nsurf->w*surf->h;
|
||||
uint32_t* end = beg + nsurf->w*nsurf->h;
|
||||
|
||||
uint16_t ratio = amount * 256;
|
||||
const uint16_t red = ratio * color.r;
|
||||
|
@ -1506,8 +1304,6 @@ surface blend_surface(
|
|||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
/* Simplified RotSprite algorithm.
|
||||
|
@ -1626,12 +1422,11 @@ uint32_t get_pixel(const surface& surf, const const_surface_lock& surf_lock, int
|
|||
}
|
||||
|
||||
// Rotates a surface 180 degrees.
|
||||
surface rotate_180_surface(const surface &surf)
|
||||
surface rotate_180_surface(const surface& surf)
|
||||
{
|
||||
if ( surf == nullptr )
|
||||
return nullptr;
|
||||
|
||||
// Work with a "neutral" surface.
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if ( nsurf == nullptr ) {
|
||||
|
@ -1666,12 +1461,11 @@ surface rotate_180_surface(const surface &surf)
|
|||
return nsurf;
|
||||
}
|
||||
|
||||
|
||||
// Rotates a surface 90 degrees, either clockwise or counter-clockwise.
|
||||
surface rotate_90_surface(const surface &surf, bool clockwise)
|
||||
surface rotate_90_surface(const surface& surf, bool clockwise)
|
||||
{
|
||||
if ( surf == nullptr )
|
||||
return nullptr;
|
||||
if(surf == nullptr)
|
||||
return surf;
|
||||
|
||||
surface dst(surf->h, surf->w); // Flipped dimensions.
|
||||
|
||||
|
@ -1680,7 +1474,7 @@ surface rotate_90_surface(const surface &surf, bool clockwise)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
{// Code block to limit the scope of the surface locks.
|
||||
{
|
||||
const_surface_lock src_lock(surf);
|
||||
surface_lock dst_lock(dst);
|
||||
|
||||
|
@ -1702,21 +1496,9 @@ surface rotate_90_surface(const surface &surf, bool clockwise)
|
|||
return dst;
|
||||
}
|
||||
|
||||
|
||||
surface flip_surface(const surface &surf)
|
||||
void flip_surface(surface& nsurf)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* const pixels = lock.pixels();
|
||||
|
||||
|
@ -1728,37 +1510,22 @@ surface flip_surface(const surface &surf)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface flop_surface(const surface &surf)
|
||||
void flop_surface(surface& nsurf)
|
||||
{
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
surface nsurf = surf.clone();
|
||||
|
||||
if(nsurf == nullptr) {
|
||||
PLAIN_LOG << "could not make neutral surface...";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
if(nsurf) {
|
||||
surface_lock lock(nsurf);
|
||||
uint32_t* const pixels = lock.pixels();
|
||||
|
||||
for(int x = 0; x != nsurf->w; ++x) {
|
||||
for(int y = 0; y != nsurf->h/2; ++y) {
|
||||
const int index1 = y*nsurf->w + x;
|
||||
const int index2 = (nsurf->h-y-1)*surf->w + x;
|
||||
const int index2 = (nsurf->h-y-1)*nsurf->w + x;
|
||||
std::swap(pixels[index1],pixels[index2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsurf;
|
||||
}
|
||||
|
||||
surface get_surface_portion(const surface &src, SDL_Rect &area)
|
||||
|
|
|
@ -101,18 +101,18 @@ surface scale_surface_legacy(const surface &surf, int w, int h);
|
|||
*/
|
||||
surface scale_surface_sharp(const surface& surf, int w, int h);
|
||||
|
||||
surface adjust_surface_color(const surface &surf, int r, int g, int b);
|
||||
surface greyscale_image(const surface &surf);
|
||||
surface monochrome_image(const surface &surf, const int threshold);
|
||||
surface sepia_image(const surface &surf);
|
||||
surface negative_image(const surface &surf, const int thresholdR, const int thresholdG, const int thresholdB);
|
||||
surface alpha_to_greyscale(const surface & surf);
|
||||
surface wipe_alpha(const surface & surf);
|
||||
void adjust_surface_color(surface& surf, int r, int g, int b);
|
||||
void greyscale_image(surface& surf);
|
||||
void monochrome_image(surface& surf, const int threshold);
|
||||
void sepia_image(surface& surf);
|
||||
void negative_image(surface& surf, const int thresholdR, const int thresholdG, const int thresholdB);
|
||||
void alpha_to_greyscale(surface& surf);
|
||||
void wipe_alpha(surface& surf);
|
||||
/** create an heavy shadow of the image, by blurring, increasing alpha and darkening */
|
||||
surface shadow_image(const surface &surf, int scale = 1);
|
||||
void shadow_image(surface& surf, int scale = 1);
|
||||
|
||||
enum channel { RED, GREEN, BLUE, ALPHA };
|
||||
surface swap_channels_image(const surface& surf, channel r, channel g, channel b, channel a);
|
||||
void swap_channels_image(surface& surf, channel r, channel g, channel b, channel a);
|
||||
|
||||
/**
|
||||
* Recolors a surface using a map with source and converted palette values.
|
||||
|
@ -121,12 +121,10 @@ surface swap_channels_image(const surface& surf, channel r, channel g, channel b
|
|||
* @param surf The source surface.
|
||||
* @param map_rgb Map of color values, with the keys corresponding to the
|
||||
* source palette, and the values to the recolored palette.
|
||||
* @return A recolored surface, or a null surface if there are
|
||||
* problems with the source.
|
||||
*/
|
||||
surface recolor_image(surface surf, const color_range_map& map_rgb);
|
||||
void recolor_image(surface& surf, const color_range_map& map_rgb);
|
||||
|
||||
surface brighten_image(const surface &surf, int32_t amount);
|
||||
void brighten_image(surface& surf, int32_t amount);
|
||||
|
||||
/** Get a portion of the screen.
|
||||
* Send nullptr if the portion is outside of the screen.
|
||||
|
@ -139,13 +137,13 @@ surface brighten_image(const surface &surf, int32_t amount);
|
|||
surface get_surface_portion(const surface &surf, SDL_Rect &rect);
|
||||
|
||||
void adjust_surface_alpha(surface& surf, uint8_t alpha_mod);
|
||||
surface adjust_surface_alpha_add(const surface &surf, int amount);
|
||||
void adjust_surface_alpha_add(surface& surf, int amount);
|
||||
|
||||
/** Applies a mask on a surface. */
|
||||
surface mask_surface(const surface &surf, const surface &mask, bool* empty_result = nullptr, const std::string& filename = std::string());
|
||||
void mask_surface(surface& surf, const surface& mask, bool* empty_result = nullptr, const std::string& filename = std::string());
|
||||
|
||||
/** Check if a surface fit into a mask */
|
||||
bool in_mask_surface(const surface &surf, const surface &mask);
|
||||
bool in_mask_surface(surface surf, surface mask);
|
||||
|
||||
/**
|
||||
* Light surf using lightmap
|
||||
|
@ -155,16 +153,7 @@ bool in_mask_surface(const surface &surf, const surface &mask);
|
|||
* to cover the full (-256,256) spectrum.
|
||||
* Should already be neutral
|
||||
*/
|
||||
surface light_surface(const surface &surf, const surface &lightmap);
|
||||
|
||||
/**
|
||||
* Cross-fades a surface.
|
||||
*
|
||||
* @param surf The source surface.
|
||||
* @param depth The depth of the blurring.
|
||||
* @return A new, blurred, neutral surface.
|
||||
*/
|
||||
surface blur_surface(const surface &surf, int depth = 1);
|
||||
void light_surface(surface& surf, const surface &lightmap);
|
||||
|
||||
/**
|
||||
* Cross-fades a surface in place.
|
||||
|
@ -180,9 +169,8 @@ void blur_surface(surface& surf, SDL_Rect rect, int depth = 1);
|
|||
*
|
||||
* @param surf The source surface.
|
||||
* @param depth The depth of the blurring.
|
||||
* @return A new, blurred, neutral surface.
|
||||
*/
|
||||
surface blur_alpha_surface(const surface &surf, int depth = 1);
|
||||
void blur_alpha_surface(surface& surf, int depth = 1);
|
||||
|
||||
/** Cuts a rectangle from a surface. */
|
||||
surface cut_surface(const surface &surf, const SDL_Rect& r);
|
||||
|
@ -199,13 +187,8 @@ surface cut_surface(const surface &surf, const SDL_Rect& r);
|
|||
* [0, 1].
|
||||
* @param color The color to blend width, note its alpha
|
||||
* channel is ignored.
|
||||
*
|
||||
* @return The blended surface.
|
||||
*/
|
||||
surface blend_surface(
|
||||
const surface &surf
|
||||
, const double amount
|
||||
, const color_t color);
|
||||
void blend_surface(surface& surf, const double amount, const color_t color);
|
||||
|
||||
/**
|
||||
* Rotates a surface by any degrees.
|
||||
|
@ -220,8 +203,7 @@ surface blend_surface(
|
|||
*
|
||||
* @return The rotated surface.
|
||||
*/
|
||||
surface rotate_any_surface(const surface& surf, float angle,
|
||||
int zoom, int offset);
|
||||
surface rotate_any_surface(const surface& surf, float angle, int zoom, int offset);
|
||||
|
||||
/**
|
||||
* Rotates a surface 180 degrees.
|
||||
|
@ -230,7 +212,7 @@ surface rotate_any_surface(const surface& surf, float angle,
|
|||
*
|
||||
* @return The rotated surface.
|
||||
*/
|
||||
surface rotate_180_surface(const surface &surf);
|
||||
surface rotate_180_surface(const surface& surf);
|
||||
|
||||
/**
|
||||
* Rotates a surface 90 degrees.
|
||||
|
@ -241,10 +223,10 @@ surface rotate_180_surface(const surface &surf);
|
|||
*
|
||||
* @return The rotated surface.
|
||||
*/
|
||||
surface rotate_90_surface(const surface &surf, bool clockwise);
|
||||
surface rotate_90_surface(const surface& surf, bool clockwise);
|
||||
|
||||
surface flip_surface(const surface &surf);
|
||||
surface flop_surface(const surface &surf);
|
||||
void flip_surface(surface& surf);
|
||||
void flop_surface(surface& surf);
|
||||
|
||||
rect get_non_transparent_portion(const surface& surf);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue