mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
125 lines
2.3 KiB
C++
125 lines
2.3 KiB
C++
#include "Draw.h"
|
|
|
|
namespace Upp {
|
|
|
|
#define LTIMING(x)
|
|
// #define BENCHMARK_RLE
|
|
|
|
VectorMap<String, void *>& DataDrawer::Map()
|
|
{
|
|
static VectorMap<String, void *> x;
|
|
return x;
|
|
}
|
|
|
|
static StaticCriticalSection sDataDrawer;
|
|
|
|
void DataDrawer::AddFormat(const char *id, Factory factory)
|
|
{
|
|
Mutex::Lock __(sDataDrawer);
|
|
Map().Add(id, (void *)factory);
|
|
}
|
|
|
|
One<DataDrawer> DataDrawer::Create(const String& id)
|
|
{
|
|
Mutex::Lock __(sDataDrawer);
|
|
Factory q = (Factory) Map().Get(id, NULL);
|
|
if(q)
|
|
return (*q)();
|
|
return NULL;
|
|
}
|
|
|
|
bool IsWhiteColumn(const Image& m, int x)
|
|
{
|
|
LTIMING("IsEqColumn");
|
|
Size sz = m.GetSize();
|
|
const RGBA *s = ~m + x;
|
|
while(sz.cy > 1) {
|
|
s += sz.cx;
|
|
if((s->a & s->r & s->g & s->b) != 255)
|
|
return false;
|
|
sz.cy--;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
#ifdef BENCHMARK_RLE
|
|
static int sTotal;
|
|
static int sRle;
|
|
|
|
EXITBLOCK
|
|
{
|
|
DUMP(sTotal);
|
|
DUMP(sRle);
|
|
}
|
|
#endif
|
|
|
|
void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp)
|
|
{
|
|
int xi = 0;
|
|
int cx = m.GetWidth();
|
|
int ccy = m.GetHeight();
|
|
Buffer<bool> todo(cx, true);
|
|
#ifdef BENCHMARK_RLE
|
|
sTotal += cx;
|
|
#endif
|
|
while(xi < cx) {
|
|
int xi0 = xi;
|
|
while(w.Dots() && IsWhiteColumn(m, xi) && xi < cx)
|
|
xi++;
|
|
if(xi - xi0 >= 16) {
|
|
#ifdef BENCHMARK_RLE
|
|
sRle += xi - xi0;
|
|
#endif
|
|
w.DrawRect(x + xi0, y, xi - xi0, ccy, White);
|
|
Fill(~todo + xi0, ~todo + xi, false);
|
|
}
|
|
xi++;
|
|
}
|
|
|
|
xi = 0;
|
|
while(xi < cx)
|
|
if(todo[xi]) {
|
|
int xi0 = xi;
|
|
while(xi < cx && todo[xi] && xi - xi0 < 2000)
|
|
xi++;
|
|
w.DrawImage(x + xi0, y, m, RectC(xi0, 0, xi - xi0, ccy));
|
|
}
|
|
else
|
|
xi++;
|
|
}
|
|
|
|
void Draw::DrawDataOp(int x, int y, int cx, int cy, const String& data, const char *id)
|
|
{
|
|
bool tonative = !IsNative();
|
|
if(tonative) {
|
|
BeginNative();
|
|
Native(x, y);
|
|
Native(cx, cy);
|
|
}
|
|
One<DataDrawer> dd = DataDrawer::Create(id);
|
|
if(dd) {
|
|
dd->Open(data, cx, cy);
|
|
if((cx > 2048 || cy > 2048) && (GetInfo() & DATABANDS)) {
|
|
int yy = 0;
|
|
while(yy < cy) {
|
|
int ccy = min(cy - yy, 32); // Must be multiply of 4 because of dithering
|
|
ImageBuffer ib(cx, ccy);
|
|
dd->Render(ib);
|
|
DrawImageBandRLE(*this, x, y + yy, ib, 16);
|
|
yy += ccy;
|
|
}
|
|
}
|
|
else {
|
|
ImageBuffer m(cx, cy);
|
|
dd->Render(m);
|
|
DrawImage(x, y, m);
|
|
}
|
|
}
|
|
if(tonative)
|
|
EndNative();
|
|
}
|
|
|
|
DataDrawer::~DataDrawer() {}
|
|
|
|
}
|