Painter: Working on subpixel rendering

git-svn-id: svn://ultimatepp.org/upp/trunk@885 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-02-22 09:31:25 +00:00
parent 6189510565
commit bc032c21d3
11 changed files with 115 additions and 86 deletions

View file

@ -259,7 +259,6 @@ protected:
virtual void MiterLimitOp(double l);
virtual void EvenOddOp(bool evenodd);
virtual void DashOp(const Vector<double>& dash, double start);
virtual void NoAAOp(bool noaa);
virtual void TransformOp(const Xform2D& m);
@ -300,10 +299,10 @@ public:
int cliplevel;
bool hasclip;
bool mask;
bool noaa;
};
ImageBuffer& ib;
int quality;
Buffer<int16> subpixel;
int render_cx;
@ -313,7 +312,6 @@ public:
Vector< Buffer<ClipLine> > clip;
Array< ImageBuffer > mask;
Image gradient;
RGBA gradient1, gradient2;
int gradientn;
@ -343,5 +341,5 @@ public:
void FinishMask();
public:
BufferPainter(ImageBuffer& ib, bool subpixel = false);
BufferPainter(ImageBuffer& ib, int quality = 0);
};

View file

@ -73,13 +73,6 @@ void BufferPainter::DashOp(const Vector<double>& dash, double start)
}
}
void BufferPainter::NoAAOp(bool noaa)
{
pathattr.noaa = noaa;
if(IsNull(current))
attr.noaa = noaa;
}
void BufferPainter::ColorStop0(Attr& a, double pos, const RGBA& color)
{
pos = minmax(pos, 0.0, 1.0);
@ -105,14 +98,15 @@ void BufferPainter::ClearStopsOp()
}
}
BufferPainter::BufferPainter(ImageBuffer& ib, bool subpixel_)
BufferPainter::BufferPainter(ImageBuffer& ib, int quality_)
: ib(ib),
rasterizer(subpixel_ ? 3 * ib.GetWidth() : ib.GetWidth(), ib.GetHeight())
quality(quality_),
rasterizer(quality_ == QUALITY_SUBPIXEL ? 3 * ib.GetWidth() : ib.GetWidth(), ib.GetHeight())
{
ClearPath();
render_cx = ib.GetWidth();
if(subpixel_) {
if(quality == QUALITY_SUBPIXEL) {
render_cx *= 3;
subpixel.Alloc(render_cx + 30);
}
@ -127,7 +121,6 @@ BufferPainter::BufferPainter(ImageBuffer& ib, bool subpixel_)
attr.dash_start = 0.0;
attr.opacity = 1.0;
attr.mask = false;
attr.noaa = false;
pathattr = attr;
gradientn = Null;

View file

@ -3,6 +3,35 @@
NAMESPACE_UPP
void FillRGBA(RGBA *t, RGBA c, int len)
{
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;
}
}
void SolidFiller::Start(int minx, int maxx)
{
t += minx;
@ -20,31 +49,7 @@ void SolidFiller::Render(int val, int len)
return;
}
if(((val - 256) | (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;
}
FillRGBA(t, c, len);
t += len;
}
else {
@ -62,12 +67,16 @@ void SolidFiller::Render(int val, int len)
void SubpixelFiller::Start(int minx, int maxx)
{
x = minx / 3;
if(x > 0) {
begin = sbuffer;
x--;
}
else
begin = sbuffer + 3;
t += x;
v = sbuffer;
int n = minx % 3 + 3;
while(n--)
*v++ = 0;
v[0] = v[1] = v[2] = v[3] = v[4] = 0;
sbuffer[0] = sbuffer[1] = sbuffer[2] = sbuffer[3] =
sbuffer[4] = sbuffer[5] = sbuffer[6] = sbuffer[7] = 0;
v = sbuffer + 3 + minx % 3;
if(ss) {
int xx = maxx / 3;
ss->Get(buffer, x, y, xx - x + 2);
@ -75,9 +84,10 @@ void SubpixelFiller::Start(int minx, int maxx)
}
}
void SubpixelFiller::Render(int val)
void SubpixelFiller::Render(int val) // Optimize: Render0
{
int h = (7282 * val) >> 16;
#if 1
int h = val / 9;
int h2 = h + h;
v[-2] += h;
v[-1] += h2;
@ -85,34 +95,78 @@ void SubpixelFiller::Render(int val)
v[1] += h2;
v[2] += h;
v[3] = 0;
#else
int h = val / 3;
v[-1] += h;
v[0] += val - h - h;
v[1] += h;
v[2] = 0;
#endif
v++;
x++;
}
void SubpixelFiller::Render(int val, int len)
{
/* if(len > 9) {
int q = (3333333 - x) % 3;
len -= q;
while(q--)
Render(val);
int16 *h = v;
Render(val);
Render(val);
Render(val);
v = h;
End();
q = len / 3 - 1;
len -= q * 3;
RGBA *e = t + q;
while(t < e)
AlphaBlendCover8(*t++, ss ? Mul8(*s++, alpha) : color, val);
v = sbuffer + 3;
v[-2] = v[-1] = v[0] = v[1] = v[2] = 0;
x = 0;
}*/
while(len--)
Render(val);
}
void SubpixelFiller::End()
{
int16 *q = sbuffer + 3;
int n = (3333333 - (v - begin)) % 3;
while(n--)
Render(0);
int16 *q = begin;
while(q < v) {
RGBA c = ss ? Mul8(*s++, alpha) : color;
int a, alpha;
a = c.a * q[0] >> 8;
alpha = 256 - (a + (a >> 7));
t->r = (c.r * q[0] >> 8) + (alpha * t->r >> 8);
a = c.a * q[1] >> 8;
alpha = 256 - (a + (a >> 7));
t->g = (c.g * q[1] >> 8) + (alpha * t->g >> 8);
a = c.a * q[2] >> 8;
alpha = 256 - (a + (a >> 7));
t->b = (c.b * q[2] >> 8) + (alpha * t->b >> 8);
a = c.a * (q[0] + q[1] + q[2]) / 3 >> 8;
alpha = 256 - (a + (a >> 7));
t->a = a + (alpha * t->a >> 8);
/* if(c.a == 255) {
alpha = 256 - q[0];
t->r = (c.r * q[0] >> 8) + (alpha * t->r >> 8);
alpha = 256 - q[1];
t->g = (c.g * q[1] >> 8) + (alpha * t->g >> 8);
alpha = 256 - q[2];
t->b = (c.b * q[2] >> 8) + (alpha * t->b >> 8);
a = (q[0] + q[1] + q[2]) / 3;
a = c.a * (q[0] + q[1] + q[2]) / 3 >> 8;
alpha = 256 - (a + (a >> 7));
t->a = a + (alpha * t->a >> 8);
}
else {*/
a = c.a * q[0] >> 8;
alpha = 256 - (a + (a >> 7));
t->r = (c.r * q[0] >> 8) + (alpha * t->r >> 8);
a = c.a * q[1] >> 8;
alpha = 256 - (a + (a >> 7));
t->g = (c.g * q[1] >> 8) + (alpha * t->g >> 8);
a = c.a * q[2] >> 8;
alpha = 256 - (a + (a >> 7));
t->b = (c.b * q[2] >> 8) + (alpha * t->b >> 8);
a = c.a * (q[0] + q[1] + q[2]) / 3 >> 8;
alpha = 256 - (a + (a >> 7));
t->a = a + (alpha * t->a >> 8);
// }
t++;
q += 3;
}

View file

@ -24,6 +24,7 @@ struct SpanFiller : Rasterizer::Filler {
struct SubpixelFiller : Rasterizer::Filler {
int16 *sbuffer;
int16 *begin;
RGBA *t;
int16 *v;
RGBA *s;

View file

@ -218,9 +218,6 @@ void Painter::Paint(const Painting& pic)
DashOp(dash, r);
}
break;
case PAINTING_NOAA:
NoAAOp(ss.Get());
break;
case PAINTING_TRANSFORM:
sGet(m, ss);
TransformOp(m);
@ -240,8 +237,7 @@ void Painter::Paint(const Painting& pic)
void PaintImageBufferPaintingFn(ImageBuffer& ib, const Painting& p, Size sz, Point pos, bool noaa)
{
BufferPainter sw(ib);
sw.NoAA(noaa);
BufferPainter sw(ib, noaa ? QUALITY_NOAA : QUALITY_ANTIALIASED);
Sizef psz = p.GetSize();
sw.Translate(-pos.x, -pos.y);
sw.Scale(sz.cx / psz.cx, sz.cy / psz.cy);
@ -250,8 +246,7 @@ void PaintImageBufferPaintingFn(ImageBuffer& ib, const Painting& p, Size sz, Poi
void PaintImageBufferDrawingFn(ImageBuffer& ib, const Drawing& iw, bool noaa)
{
BufferPainter sw(ib);
sw.NoAA(noaa);
BufferPainter sw(ib, noaa ? QUALITY_NOAA : QUALITY_ANTIALIASED);
Sizef sz = ib.GetSize();
Size isz = iw.GetSize();
sw.Scale(sz.cx / isz.cx, sz.cy / isz.cy);

View file

@ -57,6 +57,10 @@ enum {
GRADIENT_PAD = 0,
GRADIENT_REPEAT = 1,
GRADIENT_REFLECT = 2,
QUALITY_NOAA = 0,
QUALITY_ANTIALIASED = 1,
QUALITY_SUBPIXEL = 2,
};
class Painter : public Draw {
@ -133,7 +137,6 @@ protected:
virtual void MiterLimitOp(double l) = 0;
virtual void EvenOddOp(bool evenodd) = 0;
virtual void DashOp(const Vector<double>& dash, double start = 0) = 0;
virtual void NoAAOp(bool noaa) = 0;
virtual void TransformOp(const Xform2D& m) = 0;
@ -290,7 +293,6 @@ public:
Painter& EvenOdd(bool evenodd = true);
Painter& Dash(const Vector<double>& dash, double start);
Painter& Dash(const char *dash, double start = 0);
Painter& NoAA(bool noaa = true);
Painter& Transform(const Xform2D& m);
Painter& Translate(double x, double y);

View file

@ -192,12 +192,6 @@ inline Painter& Painter::Dash(const Vector<double>& dash, double start)
return *this;
}
inline Painter& Painter::NoAA(bool noaa)
{
NoAAOp(noaa);
return *this;
}
inline Painter& Painter::Transform(const Xform2D& m)
{
TransformOp(m);

View file

@ -235,12 +235,6 @@ void PaintingPainter::DashOp(const Vector<double>& dash, double start)
Putf(start);
}
void PaintingPainter::NoAAOp(bool noaa)
{
Put(PAINTING_NOAA);
Put(noaa);
}
void PaintingPainter::TransformOp(const Xform2D& m)
{
Put(PAINTING_TRANSFORM);

View file

@ -43,7 +43,6 @@ enum {
PAINTING_MITERLIMIT,
PAINTING_EVENODD,
PAINTING_DASH,
PAINTING_NOAA,
PAINTING_TRANSFORM,
PAINTING_BEGIN,
@ -113,7 +112,6 @@ protected:
virtual void MiterLimitOp(double l);
virtual void EvenOddOp(bool evenodd);
virtual void DashOp(const Vector<double>& dash, double start);
virtual void NoAAOp(bool noaa);
virtual void TransformOp(const Xform2D& m);

View file

@ -80,7 +80,7 @@ Buffer<ClipLine> BufferPainter::RenderPath(double width, SpanSource *ss, const R
rg = &solid_filler;
}
}
if(pathattr.noaa) {
if(quality == QUALITY_NOAA) {
noaa_filler.Set(rg);
rg = &noaa_filler;
}

View file

@ -2,7 +2,7 @@
#define _Painter_icpp_init_stub
#include "Core/init"
#include "CtrlLib/init"
#define BLITZ_INDEX__ F41D82715284B94932890A06EF04E4CA5
#define BLITZ_INDEX__ F135B9991BD270784ACE22BD4FFB4267E
#include "PaintPainting.icpp"
#undef BLITZ_INDEX__
#endif