From bc032c21d3b4ab5a670eab33f1a3df00238435dd Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 22 Feb 2009 09:31:25 +0000 Subject: [PATCH] Painter: Working on subpixel rendering git-svn-id: svn://ultimatepp.org/upp/trunk@885 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Painter/BufferPainter.h | 8 +- uppsrc/Painter/Context.cpp | 15 +--- uppsrc/Painter/Fillers.cpp | 144 ++++++++++++++++++++---------- uppsrc/Painter/Fillers.h | 1 + uppsrc/Painter/PaintPainting.icpp | 9 +- uppsrc/Painter/Painter.h | 6 +- uppsrc/Painter/Painter.hpp | 6 -- uppsrc/Painter/Painting.cpp | 6 -- uppsrc/Painter/Painting.h | 2 - uppsrc/Painter/Render.cpp | 2 +- uppsrc/Painter/init | 2 +- 11 files changed, 115 insertions(+), 86 deletions(-) diff --git a/uppsrc/Painter/BufferPainter.h b/uppsrc/Painter/BufferPainter.h index d41b99042..0566a435b 100644 --- a/uppsrc/Painter/BufferPainter.h +++ b/uppsrc/Painter/BufferPainter.h @@ -259,7 +259,6 @@ protected: virtual void MiterLimitOp(double l); virtual void EvenOddOp(bool evenodd); virtual void DashOp(const Vector& 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 subpixel; int render_cx; @@ -312,7 +311,6 @@ public: Array attrstack; Vector< Buffer > clip; Array< ImageBuffer > mask; - Image gradient; RGBA gradient1, gradient2; @@ -324,7 +322,7 @@ public: Rasterizer rasterizer; Buffer span; - + void *PathAddRaw(int type, int size); template T& PathAdd(int type) { return *(T *)PathAddRaw(type, sizeof(T)); } @@ -343,5 +341,5 @@ public: void FinishMask(); public: - BufferPainter(ImageBuffer& ib, bool subpixel = false); + BufferPainter(ImageBuffer& ib, int quality = 0); }; diff --git a/uppsrc/Painter/Context.cpp b/uppsrc/Painter/Context.cpp index 65e943e27..c2de3c2f0 100644 --- a/uppsrc/Painter/Context.cpp +++ b/uppsrc/Painter/Context.cpp @@ -73,13 +73,6 @@ void BufferPainter::DashOp(const Vector& 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; diff --git a/uppsrc/Painter/Fillers.cpp b/uppsrc/Painter/Fillers.cpp index bb8625c39..3b42a9206 100644 --- a/uppsrc/Painter/Fillers.cpp +++ b/uppsrc/Painter/Fillers.cpp @@ -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; } diff --git a/uppsrc/Painter/Fillers.h b/uppsrc/Painter/Fillers.h index d83b07c3b..f44b759b2 100644 --- a/uppsrc/Painter/Fillers.h +++ b/uppsrc/Painter/Fillers.h @@ -24,6 +24,7 @@ struct SpanFiller : Rasterizer::Filler { struct SubpixelFiller : Rasterizer::Filler { int16 *sbuffer; + int16 *begin; RGBA *t; int16 *v; RGBA *s; diff --git a/uppsrc/Painter/PaintPainting.icpp b/uppsrc/Painter/PaintPainting.icpp index 01ba02b86..1eef486c1 100644 --- a/uppsrc/Painter/PaintPainting.icpp +++ b/uppsrc/Painter/PaintPainting.icpp @@ -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); diff --git a/uppsrc/Painter/Painter.h b/uppsrc/Painter/Painter.h index e27b82d74..c74f6e08b 100644 --- a/uppsrc/Painter/Painter.h +++ b/uppsrc/Painter/Painter.h @@ -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& 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& 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); diff --git a/uppsrc/Painter/Painter.hpp b/uppsrc/Painter/Painter.hpp index f71782592..c4007946a 100644 --- a/uppsrc/Painter/Painter.hpp +++ b/uppsrc/Painter/Painter.hpp @@ -192,12 +192,6 @@ inline Painter& Painter::Dash(const Vector& dash, double start) return *this; } -inline Painter& Painter::NoAA(bool noaa) -{ - NoAAOp(noaa); - return *this; -} - inline Painter& Painter::Transform(const Xform2D& m) { TransformOp(m); diff --git a/uppsrc/Painter/Painting.cpp b/uppsrc/Painter/Painting.cpp index 9e3eac914..8a4043fee 100644 --- a/uppsrc/Painter/Painting.cpp +++ b/uppsrc/Painter/Painting.cpp @@ -235,12 +235,6 @@ void PaintingPainter::DashOp(const Vector& dash, double start) Putf(start); } -void PaintingPainter::NoAAOp(bool noaa) -{ - Put(PAINTING_NOAA); - Put(noaa); -} - void PaintingPainter::TransformOp(const Xform2D& m) { Put(PAINTING_TRANSFORM); diff --git a/uppsrc/Painter/Painting.h b/uppsrc/Painter/Painting.h index 09fc3bcd2..8cd7b3326 100644 --- a/uppsrc/Painter/Painting.h +++ b/uppsrc/Painter/Painting.h @@ -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& dash, double start); - virtual void NoAAOp(bool noaa); virtual void TransformOp(const Xform2D& m); diff --git a/uppsrc/Painter/Render.cpp b/uppsrc/Painter/Render.cpp index 98aa2a809..ee610e4b7 100644 --- a/uppsrc/Painter/Render.cpp +++ b/uppsrc/Painter/Render.cpp @@ -80,7 +80,7 @@ Buffer 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; } diff --git a/uppsrc/Painter/init b/uppsrc/Painter/init index e5a2008f0..77e82d94b 100644 --- a/uppsrc/Painter/init +++ b/uppsrc/Painter/init @@ -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