mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-17 14:16:10 -06:00
234 lines
4.5 KiB
C++
234 lines
4.5 KiB
C++
#include "ScanLine.h"
|
|
|
|
ScanLine And0(const ScanLine& a, const ScanLine& b)
|
|
{
|
|
ScanLine r;
|
|
r.len = 0;
|
|
r.x = b.x;
|
|
byte aval = 0;
|
|
int acount = 0;
|
|
byte bval = 0;
|
|
int ai = 0;
|
|
int bi = 0;
|
|
int bcount = b.x - a.x;
|
|
while(bcount) {
|
|
if(ai >= a.data.GetCount())
|
|
return r;
|
|
aval = a.data[ai++];
|
|
if(aval > 128) {
|
|
acount = aval - 128;
|
|
aval = a.data[ai++];
|
|
int n = min(acount, bcount);
|
|
acount -= n;
|
|
bcount -= n;
|
|
}
|
|
else
|
|
bcount--;
|
|
}
|
|
while(ai < a.data.GetCount() && bi < b.data.GetCount()) {
|
|
if(acount == 0) {
|
|
aval = a.data[ai++];
|
|
if(aval > 128) {
|
|
acount = aval - 128;
|
|
aval = a.data[ai++];
|
|
}
|
|
}
|
|
if(bcount == 0) {
|
|
bval = b.data[bi++];
|
|
if(bval > 128) {
|
|
bcount = bval - 128;
|
|
bval = b.data[bi++];
|
|
}
|
|
}
|
|
if(acount && bcount) {
|
|
int l = min(acount, bcount);
|
|
acount -= l;
|
|
bcount -= l;
|
|
r.len += l;
|
|
while(l) {
|
|
int n = min(l, 127);
|
|
r.data.Cat(n + 128);
|
|
r.data.Cat((aval * bval) >> 7);
|
|
l -= n;
|
|
}
|
|
}
|
|
else {
|
|
r.data.Cat((aval * bval) >> 7);
|
|
r.len++;
|
|
if(acount) acount--;
|
|
if(bcount) bcount--;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
ScanLine And(const ScanLine& a, const ScanLine& b)
|
|
{
|
|
return a.x < b.x ? And0(a, b) : And0(b, a);
|
|
}
|
|
|
|
ScanLine Pack(int x, const byte *data, int len)
|
|
{
|
|
ScanLine r;
|
|
int i = 0;
|
|
r.x = x;
|
|
r.len = 0;
|
|
while(i < len) {
|
|
int n = i;
|
|
byte val = data[i++];
|
|
while(i < len && data[i] == val)
|
|
i++;
|
|
n = i - n;
|
|
if(n > 1) {
|
|
r.len += n;
|
|
while(n) {
|
|
int q = min(n, 127);
|
|
r.data.Cat(q + 128);
|
|
r.data.Cat(val);
|
|
n -= q;
|
|
}
|
|
}
|
|
else {
|
|
r.data.Cat(val);
|
|
r.len++;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
String ScanLine::ToString() const
|
|
{
|
|
String s;
|
|
s << "datalen: " << data.GetCount() << "x = " << x << ", len = " << len << ", right = " << len + x << ": ";
|
|
for(int i = 0; i < data.GetCount(); i++) {
|
|
byte val = data[i];
|
|
if(val > 128) {
|
|
int n = val - 128;
|
|
val = data[++i];
|
|
while(n--)
|
|
s << (int)val << ", ";
|
|
}
|
|
else
|
|
s << (int)val << ", ";
|
|
}
|
|
return s;
|
|
}
|
|
|
|
void Apply(RGBA *t, int len, const RGBA& c, const ScanLine& s)
|
|
{
|
|
PAINTER_TIMING("Apply");
|
|
RGBA *e = t + len;
|
|
const char *q = ~s.data;
|
|
const char *qe = s.data.End();
|
|
t += s.x;
|
|
while(t < e && q < qe) {
|
|
byte val = *q++;
|
|
if(val > 128) {
|
|
RGBA *e1 = min(e, t + val - 128);
|
|
byte val = *q++;
|
|
if(val == 128 && c.a == 255) {
|
|
int l = e1 - t;
|
|
while(l >= 16) {
|
|
t[0] = c; t[1] = c; t[2] = c; t[3] = c;
|
|
t[4] = c; t[5] = c; t[6] = c; t[7] = c;
|
|
t[8] = c; t[9] = c; t[10] = c; t[11] = c;
|
|
t[12] = c; t[13] = c; t[14] = c; t[15] = c;
|
|
t += 16;
|
|
l -= 16;
|
|
}
|
|
switch(l) {
|
|
case 15: t[14] = c;
|
|
case 14: t[13] = c;
|
|
case 13: t[12] = c;
|
|
case 12: t[11] = c;
|
|
case 11: t[10] = c;
|
|
case 10: t[9] = c;
|
|
case 9: t[8] = c;
|
|
case 8: t[7] = c;
|
|
case 7: t[6] = c;
|
|
case 6: t[5] = c;
|
|
case 5: t[4] = c;
|
|
case 4: t[3] = c;
|
|
case 3: t[2] = c;
|
|
case 2: t[1] = c;
|
|
case 1: t[0] = c;
|
|
}
|
|
t = e1;
|
|
}
|
|
else {
|
|
RGBA c1;
|
|
if(val != 128)
|
|
c1 = Mul7(c, val);
|
|
else
|
|
c1 = c;
|
|
while(t < e1)
|
|
AlphaBlend(*t++, c1);
|
|
}
|
|
}
|
|
else
|
|
AlphaBlendCover7(*t++, c, val);
|
|
// DDUMP(t - e);
|
|
}
|
|
}
|
|
|
|
struct SolidFiller {
|
|
RGBA *t;
|
|
RGBA c;
|
|
|
|
void Start(int x) { t += x; }
|
|
void Render(byte val) { AlphaBlendCover7(*t++, c, val); }
|
|
void Render(byte val, int len);
|
|
};
|
|
|
|
void SolidFiller::Render(byte val, int len)
|
|
{
|
|
if(((val - 128) | (c.a - 255)) == 0) {
|
|
while(len >= 16) {
|
|
t[0] = c; t[1] = c; t[2] = c; t[3] = c;
|
|
t[4] = c; t[5] = c; t[6] = c; t[7] = c;
|
|
t[8] = c; t[9] = c; t[10] = c; t[11] = c;
|
|
t[12] = c; t[13] = c; t[14] = c; t[15] = c;
|
|
t += 16;
|
|
len -= 16;
|
|
}
|
|
switch(len) {
|
|
case 15: t[14] = c;
|
|
case 14: t[13] = c;
|
|
case 13: t[12] = c;
|
|
case 12: t[11] = c;
|
|
case 11: t[10] = c;
|
|
case 10: t[9] = c;
|
|
case 9: t[8] = c;
|
|
case 8: t[7] = c;
|
|
case 7: t[6] = c;
|
|
case 6: t[5] = c;
|
|
case 5: t[4] = c;
|
|
case 4: t[3] = c;
|
|
case 3: t[2] = c;
|
|
case 2: t[1] = c;
|
|
case 1: t[0] = c;
|
|
}
|
|
t += len;
|
|
}
|
|
else {
|
|
RGBA c1;
|
|
if(val != 128)
|
|
c1 = Mul7(c, val);
|
|
else
|
|
c1 = c;
|
|
RGBA *e = t + len;
|
|
while(t < e)
|
|
AlphaBlend(*t++, c1);
|
|
}
|
|
}
|
|
|
|
void Render(ImageBuffer& ib, Rasterizer& r, const RGBA& color)
|
|
{
|
|
Size sz = ib.GetSize();
|
|
SolidFiller f;
|
|
f.c = color;
|
|
for(int y = r.MinY(); y <= r.MaxY(); y++) {
|
|
f.t = ib[y];
|
|
r.Render(y, f);
|
|
}
|
|
}
|