commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
420
include/framework/picture/pict_blit.cpp
Normal file
420
include/framework/picture/pict_blit.cpp
Normal file
@ -0,0 +1,420 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include "picture/pict.h"
|
||||
#include "color/color.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Picture::Reframe(int offset_sx, int offset_sy, int offset_ex, int offset_ey, const Color *fill)
|
||||
{
|
||||
if (!GetData() || (GetPixelFormat().GetBpp() != 32))
|
||||
return false;
|
||||
|
||||
int _width = GetWidth() - offset_sx + offset_ex,
|
||||
_height = GetHeight() - offset_sy + offset_ey;
|
||||
|
||||
uint *new_data = (uint *)AllocMemory(sizeof(uint) * _width * _height), *_d = new_data;
|
||||
|
||||
if (!new_data)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate destination buffer.\n", false)
|
||||
|
||||
// Fill color.
|
||||
uint _fill = fill ? GetPixelFormat().Format(fill->x, fill->y, fill->z, fill->w) : GetPixelFormat().Format(0, 0, 0);
|
||||
|
||||
// Top framing.
|
||||
for (int y = offset_sy; y < 0; ++y)
|
||||
for (int x = 0; x < _width; ++x)
|
||||
*_d++ = _fill;
|
||||
|
||||
// Blit + left/right framing.
|
||||
int blit_ex = offset_ex > 0 ? GetWidth() : GetWidth() + offset_ex,
|
||||
blit_ey = offset_ey > 0 ? GetHeight() : GetHeight() + offset_ey;
|
||||
|
||||
uint *s = (uint *)GetData();
|
||||
if (offset_sy > 0)
|
||||
s += GetWidth() * offset_sy;
|
||||
|
||||
for (int y = offset_sy > 0 ? offset_sy : 0; y < blit_ey; ++y)
|
||||
{
|
||||
uint *_s = s;
|
||||
|
||||
for (int x = offset_sx; x < 0; ++x)
|
||||
*_d++ = _fill; // Left framing
|
||||
for (int x = offset_sx > 0 ? offset_sx : 0; x < blit_ex; ++x)
|
||||
*_d++ = _s[x]; // Blit
|
||||
for (int x = 0; x < offset_ex; ++x)
|
||||
*_d++ = _fill; // Right framing
|
||||
|
||||
s += GetWidth();
|
||||
}
|
||||
|
||||
// Bottom framing.
|
||||
for (int y = 0; y < offset_ey; ++y)
|
||||
for (int x = 0; x < _width; ++x)
|
||||
*_d++ = _fill;
|
||||
|
||||
SetData(new_data, _width, _height, GetPixelFormat().GetDesc(), true);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Picture::Flip(bool flip_h, bool flip_v)
|
||||
{
|
||||
if (!GetData() || (GetPixelFormat().GetBpp() != 32))
|
||||
return false;
|
||||
|
||||
uint *s = (uint *)GetData(),
|
||||
*d = s, t;
|
||||
|
||||
if (flip_h)
|
||||
{
|
||||
if (flip_v)
|
||||
{
|
||||
d += GetWidth() * GetHeight() - 1;
|
||||
|
||||
while (d > s)
|
||||
{
|
||||
t = *s;
|
||||
*s++ = *d;
|
||||
*d-- = t;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint n = 0; n < GetHeight(); ++n)
|
||||
{
|
||||
uint *_s = s, *_d = d + GetWidth() - 1;
|
||||
|
||||
while (_d > _s)
|
||||
{
|
||||
t = *_s;
|
||||
*_s++ = *_d;
|
||||
*_d-- = t;
|
||||
}
|
||||
s += GetWidth();
|
||||
d += GetWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (flip_v)
|
||||
{
|
||||
d += GetWidth() * (GetHeight() - 1);
|
||||
while (d > s)
|
||||
{
|
||||
for (uint n = 0; n < GetWidth(); ++n)
|
||||
{
|
||||
t = s[n];
|
||||
s[n] = d[n];
|
||||
d[n] = t;
|
||||
}
|
||||
s += GetWidth();
|
||||
d -= GetWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void WindowClip(const Rect <int> *a, Rect <int> *fa, const Rect <int> *b, Rect <int> *fb)
|
||||
{
|
||||
Rect <int> _b(*b);
|
||||
_b.ex = _b.sx + a->GetWidth();
|
||||
_b.ey = _b.sy + a->GetHeight();
|
||||
|
||||
// Clip source rectangle and correct destination rectangle.
|
||||
*fa = fa->Intersection(*a);
|
||||
_b.sx += fa->sx - a->sx;
|
||||
_b.sy += fa->sy - a->sy;
|
||||
_b.ex += fa->ex - a->ex;
|
||||
_b.ey += fa->ey - a->ey;
|
||||
|
||||
// Clip destination rectangle and correct source rectangle.
|
||||
*fb = fb->Intersection(_b);
|
||||
fa->sx += fb->sx - _b.sx;
|
||||
fa->sy += fb->sy - _b.sy;
|
||||
fa->ex += fb->ex - _b.ex;
|
||||
fa->ey += fb->ey - _b.ey;
|
||||
}
|
||||
static void WindowStretch(Rect <float> *a, Rect <float> *fa, Rect <float> *b, Rect <float> *fb)
|
||||
{
|
||||
float ku = (float)b->GetWidth() / (float)a->GetWidth(),
|
||||
kv = (float)b->GetHeight() / (float)a->GetHeight();
|
||||
|
||||
// Clip source rectangle and correct destination rectangle.
|
||||
fa[0] = fa->Intersection(a[0]);
|
||||
b->sx += (fa->sx - a->sx) * ku;
|
||||
b->sy += (fa->sy - a->sy) * kv;
|
||||
b->ex += (fa->ex - a->ex) * ku;
|
||||
b->ey += (fa->ey - a->ey) * kv;
|
||||
|
||||
// Clip destination rectangle and correct source rectangle.
|
||||
fb[0] = fb->Intersection(b[0]);
|
||||
ku = 1 / ku;
|
||||
kv = 1 / kv;
|
||||
fa->sx += (fb->sx - b->sx) * ku;
|
||||
fa->sy += (fb->sy - b->sy) * kv;
|
||||
fa->ex += (fb->ex - b->ex) * ku;
|
||||
fa->ey += (fb->ey - b->ey) * kv;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool Picture::BlitMask(const Picture &src, Picture &dst, Picture &msk, const Rect <int> *src_rect, const Rect <int> *dst_rect)
|
||||
{
|
||||
if (!src.GetData() || !dst.GetData())
|
||||
return false;
|
||||
|
||||
// Default blit rectangles.
|
||||
Rect <int> default_a(src.GetRect()), default_b(dst.GetRect());
|
||||
if (!src_rect)
|
||||
src_rect = &default_a;
|
||||
if (!dst_rect)
|
||||
dst_rect = &default_b;
|
||||
|
||||
// Compute blit window.
|
||||
Rect <int> frame_a(src.GetRect()), frame_b(dst.GetRect());
|
||||
WindowClip(src_rect, &frame_a, dst_rect, &frame_b);
|
||||
|
||||
// Limit to mask dimensions.
|
||||
if (frame_b.GetWidth() > (int)msk.GetWidth())
|
||||
frame_b.SetWidth(msk.GetWidth());
|
||||
if (frame_b.GetHeight() > (int)msk.GetHeight())
|
||||
frame_b.SetHeight(msk.GetHeight());
|
||||
|
||||
if ((frame_b.GetWidth() <= 0) || (frame_b.GetHeight() <= 0))
|
||||
return false;
|
||||
|
||||
PixelFormatDescription initial = dst.GetPixelFormat().GetDesc();
|
||||
dst.Convert(src.GetPixelFormat().GetDesc());
|
||||
|
||||
// Perform blit.
|
||||
uchar *psrc = src.GetDataOffset(frame_a.sx, frame_a.sy),
|
||||
*pdst = dst.GetDataOffset(frame_b.sx, frame_b.sy),
|
||||
*pmsk = msk.GetData();
|
||||
|
||||
for (int n = 0; n < frame_b.GetHeight(); n++)
|
||||
{
|
||||
uchar *_pdst = pdst, *_psrc = psrc, *_pmsk = pmsk;
|
||||
|
||||
for (int x = frame_b.GetWidth(); x--; )
|
||||
{
|
||||
uchar alpha = _pmsk[3];
|
||||
|
||||
uchar a_blend = AlphaCompositeAlpha(_pdst[3], alpha);
|
||||
_pdst[0] = AlphaCompositeColor(_pdst[0], _psrc[0], _pdst[3], alpha, a_blend);
|
||||
_pdst[1] = AlphaCompositeColor(_pdst[1], _psrc[1], _pdst[3], alpha, a_blend);
|
||||
_pdst[2] = AlphaCompositeColor(_pdst[2], _psrc[2], _pdst[3], alpha, a_blend);
|
||||
_pdst[3] = a_blend;
|
||||
|
||||
_psrc += 4;
|
||||
_pdst += 4;
|
||||
_pmsk += 4;
|
||||
}
|
||||
|
||||
psrc += src.GetPitch();
|
||||
pdst += dst.GetPitch();
|
||||
pmsk += msk.GetPitch();
|
||||
}
|
||||
dst.Convert(initial);
|
||||
return true;
|
||||
}
|
||||
bool Picture::Blit(const Picture &src, Picture &dst, const Rect <int> *src_rect, const Rect <int> *dst_rect, BlendMode mode)
|
||||
{
|
||||
if (!src.GetData() || !dst.GetData())
|
||||
return false;
|
||||
|
||||
// Default blit rectangles.
|
||||
Rect <int> default_a(src.GetRect()), default_b(dst.GetRect());
|
||||
if (!src_rect)
|
||||
src_rect = &default_a;
|
||||
if (!dst_rect)
|
||||
dst_rect = &default_b;
|
||||
|
||||
// Compute blit window.
|
||||
Rect <int> frame_a(src.GetRect()), frame_b(dst.GetRect());
|
||||
WindowClip(src_rect, &frame_a, dst_rect, &frame_b);
|
||||
|
||||
if ((frame_b.GetWidth() <= 0) || (frame_b.GetHeight() <= 0))
|
||||
return false;
|
||||
|
||||
PixelFormatDescription initial = dst.GetPixelFormat().GetDesc();
|
||||
dst.Convert(src.GetPixelFormat().GetDesc());
|
||||
|
||||
// Perform blit.
|
||||
uchar *psrc = src.GetDataOffset(frame_a.sx, frame_a.sy),
|
||||
*pdst = dst.GetDataOffset(frame_b.sx, frame_b.sy);
|
||||
|
||||
for (int n = 0; n < frame_b.GetHeight(); n++)
|
||||
{
|
||||
uchar *_pdst = pdst, *_psrc = psrc;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case RgbToAlpha:
|
||||
for (int x = frame_b.GetWidth(); x--; )
|
||||
{
|
||||
_pdst[3] = (_psrc[0] + _psrc[1] + _psrc[2]) / 3;
|
||||
_psrc += 4;
|
||||
_pdst += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case BlendReplace:
|
||||
memmove(pdst, psrc, frame_b.GetWidth() * dst.GetBpp() / 8);
|
||||
break;
|
||||
|
||||
case BlendComposeFast:
|
||||
for (int x = frame_b.GetWidth(); x--; )
|
||||
{
|
||||
int a = _psrc[3], ia = 255 - a;
|
||||
_pdst[0] = uchar((_psrc[0] * a + _pdst[0] * ia) >> 8);
|
||||
_pdst[1] = uchar((_psrc[1] * a + _pdst[1] * ia) >> 8);
|
||||
_pdst[2] = uchar((_psrc[2] * a + _pdst[2] * ia) >> 8);
|
||||
_pdst[3] = uchar(Types::Max <int> (_pdst[3], a));
|
||||
|
||||
_psrc += 4;
|
||||
_pdst += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case BlendCompose:
|
||||
for (int x = frame_b.GetWidth(); x--; )
|
||||
{
|
||||
uchar a_blend = AlphaCompositeAlpha(_pdst[3], _psrc[3]);
|
||||
_pdst[0] = AlphaCompositeColor(_pdst[0], _psrc[0], _pdst[3], _psrc[3], a_blend);
|
||||
_pdst[1] = AlphaCompositeColor(_pdst[1], _psrc[1], _pdst[3], _psrc[3], a_blend);
|
||||
_pdst[2] = AlphaCompositeColor(_pdst[2], _psrc[2], _pdst[3], _psrc[3], a_blend);
|
||||
_pdst[3] = a_blend;
|
||||
|
||||
_psrc += 4;
|
||||
_pdst += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
psrc += src.GetPitch();
|
||||
pdst += dst.GetPitch();
|
||||
}
|
||||
dst.Convert(initial);
|
||||
return true;
|
||||
}
|
||||
bool Picture::ScaleBlit(Picture &src, Picture &dst, Rect <float> *src_rect, Rect <float> *dst_rect)
|
||||
{
|
||||
if (!src.GetData() || !dst.GetData())
|
||||
return false;
|
||||
|
||||
// Default blitting rectangles.
|
||||
Rect <float> default_a(src.GetRect().AsFloat()), default_b(dst.GetRect().AsFloat());
|
||||
if (!src_rect)
|
||||
src_rect = &default_a;
|
||||
if (!dst_rect)
|
||||
dst_rect = &default_b;
|
||||
|
||||
Rect <float> frame_a(src.GetRect().AsFloat()), frame_b(dst.GetRect().AsFloat());
|
||||
WindowStretch(src_rect, &frame_a, dst_rect, &frame_b);
|
||||
|
||||
if ((frame_b.GetWidth() <= 0) || (frame_b.GetHeight() <= 0))
|
||||
return false;
|
||||
|
||||
// Apply sub-pixel/sub-texel correction.
|
||||
float ku = frame_a.GetWidth() / frame_b.GetWidth(),
|
||||
kv = frame_a.GetHeight() / frame_b.GetHeight();
|
||||
|
||||
float fb_isx = Math::Floor(frame_b.sx),
|
||||
fb_isy = Math::Floor(frame_b.sy),
|
||||
fb_iex = Math::Floor(frame_b.ex),
|
||||
fb_iey = Math::Floor(frame_b.ey);
|
||||
|
||||
float dt_su = (frame_b.sx - fb_isx),
|
||||
dt_sv = (frame_b.sy - fb_isy),
|
||||
dt_eu = (frame_b.ex - fb_iex),
|
||||
dt_ev = (frame_b.ey - fb_iey);
|
||||
|
||||
frame_a.sx -= dt_su * ku;
|
||||
frame_a.sy -= dt_sv * kv;
|
||||
frame_a.ex -= dt_eu * ku;
|
||||
frame_a.ey -= dt_ev * kv;
|
||||
|
||||
frame_b.sx = fb_isx;
|
||||
frame_b.sy = fb_isy;
|
||||
frame_b.ex = fb_iex;
|
||||
frame_b.ey = fb_iey;
|
||||
|
||||
// Convert sub pixel deltas to blending coefficients.
|
||||
dt_su = 1 - dt_su;
|
||||
dt_sv = 1 - dt_sv;
|
||||
|
||||
uint *pdst = (uint *)dst.GetDataOffset((uint)frame_b.sx, (uint)frame_b.sy);
|
||||
|
||||
int src_width = (int)frame_b.GetWidth(),
|
||||
src_height = (int)frame_b.GetHeight();
|
||||
|
||||
float v = frame_a.sy;
|
||||
for (int y = 0; y < src_height; y++)
|
||||
{
|
||||
float u = frame_a.sx;
|
||||
|
||||
// Blended or opaque scanline.
|
||||
if ((!y) || (y == (src_height - 1)))
|
||||
{
|
||||
float kfrst, kscan, klast;
|
||||
|
||||
// Set blend coefficients.
|
||||
if (!y)
|
||||
{
|
||||
kfrst = dt_su * dt_sv; // top-left
|
||||
kscan = dt_sv; // top
|
||||
klast = dt_eu * dt_sv; // top-right
|
||||
}
|
||||
else
|
||||
{
|
||||
kfrst = dt_su * dt_ev; // bottom-left
|
||||
kscan = dt_ev; // bottom
|
||||
klast = dt_eu * dt_ev; // bottom-right
|
||||
}
|
||||
|
||||
// 1st pixel, scanline, last pixel.
|
||||
pdst[0] = ColorBlend(pdst[0], src.SampleInteger(u, v), kfrst);
|
||||
u += ku;
|
||||
|
||||
int x;
|
||||
for (x = 1; x < (src_width - 1); x++)
|
||||
{
|
||||
pdst[x] = ColorBlend(pdst[x], src.SampleInteger(u, v), kscan);
|
||||
u += ku;
|
||||
}
|
||||
pdst[x] = ColorBlend(pdst[x], src.SampleInteger(u, v), klast);
|
||||
}
|
||||
else
|
||||
{
|
||||
pdst[0] = ColorBlend(pdst[0], src.SampleInteger(u, v), dt_su);
|
||||
u += ku;
|
||||
|
||||
int x;
|
||||
for (x = 1; x < (src_width - 1); x++)
|
||||
{
|
||||
pdst[x] = src.SampleInteger(u, v);
|
||||
u += ku;
|
||||
}
|
||||
pdst[x] = ColorBlend(pdst[x], src.SampleInteger(u, v), dt_eu);
|
||||
}
|
||||
|
||||
pdst += dst.GetWidth();
|
||||
v += kv;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user