ultimatepp/uppsrc/Draw/Raster.cpp
cxl 8ebdcbb0d5 uppsrc: NAMESPACE_UPP / END_UPP_NAMESPACE removed
git-svn-id: svn://ultimatepp.org/upp/trunk@10186 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-08-26 17:15:30 +00:00

281 lines
5.5 KiB
C++

#include "Draw.h"
namespace Upp {
Raster::Info::Info()
{
bpp = 24;
colors = 1 << 24;
dots = Size(0, 0);
hotspot = Point(0, 0);
kind = IMAGE_OPAQUE;
}
const RasterFormat *Raster::GetFormat()
{
return NULL;
}
void Raster::SeekPage(int page)
{
ASSERT(page == 0);
}
int Raster::GetActivePage() const
{
return 0;
}
int Raster::GetPageCount()
{
return 1;
}
int Raster::GetPageAspect(int page)
{
return 0;
}
int Raster::GetPageDelay(int page)
{
return 0;
}
Rect Raster::GetPageRect(int n)
{
Size sz = GetSize();
return Rect(0, 0, sz.cx, sz.cy);
}
int Raster::GetPageDisposal(int n)
{
return 0;
}
void Raster::Line::Pick(Line&& b)
{
data = b.data;
fmtdata = b.fmtdata;
raster = b.raster;
free = b.free;
fmtfree = b.fmtfree;
const_cast<Line *>(&b)->free = const_cast<Line *>(&b)->fmtfree = false;
#ifdef _DEBUG
const_cast<Line *>(&b)->data = NULL;
const_cast<Line *>(&b)->fmtdata = NULL;
#endif
}
void Raster::Line::MakeRGBA() const
{
ASSERT(fmtdata && raster);
int cx = raster->GetWidth();
const RasterFormat *f = raster->GetFormat();
if(f) {
RGBA *rgba = new RGBA[cx];
free = true;
f->Read(rgba, fmtdata, cx, raster->GetPalette());
data = rgba;
}
else
data = (const RGBA *)fmtdata;
}
Raster::Info Raster::GetInfo()
{
Info f;
f.bpp = 32;
f.colors = 256*256*256;
f.dots = Size(0, 0);
f.hotspot = Point(0, 0);
f.kind = IMAGE_ALPHA;
return f;
}
bool Raster::Create() { return true; }
bool Raster::IsError() { return false; }
int Raster::GetPaletteCount() { return 0; }
const RGBA *Raster::GetPalette() { return NULL; }
Image Raster::GetImage(int x, int y, int cx, int cy, const Gate2<int, int> progress)
{
Size size = GetSize();
y = minmax(y, 0, size.cy);
int yy = minmax(y + cy, y, size.cy);
x = minmax(x, 0, size.cx);
cx = minmax(x + cx, x, size.cx) - x;
ImageBuffer b(cx, yy - y);
RGBA* t = b;
int y0 = y;
while(y < yy) {
if(progress(y - y0, yy - y0))
return Null;
memcpy(t, ~GetLine(y) + x, cx * sizeof(RGBA));
t += cx;
y++;
}
Info f = GetInfo();
b.SetHotSpot(f.hotspot - Point(x, y0));
if(size.cx && size.cy)
b.SetDots(Size(f.dots.cx * cx / size.cx, f.dots.cy * cy / size.cy));
return IsError() ? Image() : Image(b);
}
Image Raster::GetImage(const Gate2<int, int> progress)
{
Size sz = GetSize();
return GetImage(0, 0, sz.cx, sz.cy, progress);
}
Raster::~Raster() {}
Raster::Line ImageRaster::GetLine(int line)
{
return Line(img[line], false);
}
Size ImageRaster::GetSize()
{
return img.GetSize();
}
Raster::Info ImageRaster::GetInfo()
{
Raster::Info f = Raster::GetInfo();
f.dots = img.GetDots();
f.hotspot = img.GetHotSpot();
f.kind = img.GetKind();
return f;
}
MemoryRaster::MemoryRaster()
: size(0, 0)
{
}
void MemoryRaster::Load(Raster& raster)
{
info = raster.GetInfo();
size = raster.GetSize();
palette.SetCount(raster.GetPaletteCount());
if(!palette.IsEmpty())
memcpy(palette, raster.GetPalette(), palette.GetCount() * sizeof(RGBA));
lines.SetCount(size.cy);
if(const RasterFormat *fmt = raster.GetFormat()) {
format = *fmt;
int rowbytes = format.GetByteCount(size.cx);
for(int i = 0; i < size.cy; i++) {
lines[i].Alloc(rowbytes);
memcpy(~lines[i], raster.GetLine(i).GetRawData(), rowbytes);
}
}
else {
format.SetRGBA();
int rowbytes = sizeof(RGBA) * size.cx;
for(int i = 0; i < size.cy; i++) {
lines[i].Alloc(rowbytes);
memcpy(~lines[i], raster.GetLine(i).GetRGBA(), rowbytes);
}
}
}
Raster::Line MemoryRaster::GetLine(int line)
{
if(format.IsRGBA())
return Line((const RGBA *)~lines[line], false);
else
return Line(~lines[line], this, false);
}
int MemoryRaster::GetLength() const
{
return size.cy * (format.IsRGBA()
? size.cx * sizeof(RGBA)
: ((size.cx * info.bpp + 31) >> 5) * 4);
}
bool StreamRaster::Open(Stream& _s)
{
s = &_s;
error = !Create();
return !error;
}
bool StreamRaster::IsError()
{
return error || !s || s->IsError();
}
Image StreamRaster::Load(Stream& s, const Gate2<int, int> progress)
{
if(Open(s)) {
Image img = GetImage(progress);
if(!IsError())
return img;
}
return Image();
}
Image StreamRaster::LoadFile(const char *fn, const Gate2<int, int> progress)
{
FileIn in(fn);
return in ? Load(in, progress) : Image();
}
Image StreamRaster::LoadString(const String& s, const Gate2<int, int> progress)
{
StringStream ss(s);
return Load(ss, progress);
}
static StaticCriticalSection sAnyRaster;
Vector<void *>& StreamRaster::Map()
{
static Vector<void *> x;
return x;
}
void StreamRaster::AddFormat(RasterFactory factory)
{
INTERLOCKED_(sAnyRaster)
Map().Add((void *)factory);
}
One<StreamRaster> StreamRaster::OpenAny(Stream& s)
{
INTERLOCKED_(sAnyRaster)
for(int i = 0; i < Map().GetCount(); i++) {
int64 p = s.GetPos();
One<StreamRaster> raster = (*RasterFactory(Map()[i]))();
s.ClearError();
if(raster->Open(s))
return raster;
s.ClearError();
s.Seek(p);
}
return NULL;
}
Image StreamRaster::LoadAny(Stream& s, const Gate2<int, int> progress)
{
One<StreamRaster> r = OpenAny(s);
return r ? r->GetImage(progress) : Image();
}
Image StreamRaster::LoadFileAny(const char *fn, const Gate2<int, int> progress)
{
FileIn in(fn);
return LoadAny(in, progress);
}
Image StreamRaster::LoadStringAny(const String& s, const Gate2<int, int> progress)
{
StringStream ss(s);
return LoadAny(ss, progress);
}
}