Fixed rounding problem in subpixel rendering

git-svn-id: svn://ultimatepp.org/upp/trunk@899 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-02-23 17:49:45 +00:00
parent daf2cece0d
commit e16d4ea2da
6 changed files with 48 additions and 39 deletions

View file

@ -128,10 +128,9 @@ void SubpixelFiller::Render(int val)
v++;
}
void SubpixelFiller::RenderN(int val, int n)
void SubpixelFiller::RenderN(int val, int h, int n)
{
int16 *w = v;
int h = val / 9;
int h2 = h + h;
int hv2 = val - h2 - h2;
int h3 = h2 + h;
@ -214,11 +213,12 @@ void SubpixelFiller::RenderN(int val, int n)
void SubpixelFiller::Render(int val, int len)
{
int h = val / 9;
if(len > 6) {
int q = (3333333 - (v + 2 - begin)) % 3;
len -= q + 2;
int l = v + 2 + q - begin;
RenderN(val, q + 4);
RenderN(val, h, q + 4);
Write(l / 3);
l = len / 3;
len -= 3 * l;
@ -235,12 +235,11 @@ void SubpixelFiller::Render(int val, int len)
while(t < e)
AlphaBlendCover8(*t++, ss ? Mul8(*s++, alpha) : color, val);
v = begin = sbuffer + 3;
int h = val / 9;
v[0] = h + h + h;
v[1] = h;
v[2] = 0;
}
RenderN(val, len);
RenderN(val, h, len);
}
void SubpixelFiller::Write(int len)
@ -249,30 +248,23 @@ void SubpixelFiller::Write(int len)
int16 *q = begin;
while(t < e) {
RGBA c = ss ? Mul8(*s++, alpha) : color;
int a, alpha;
int a;
if(t->a != 255)
AlphaBlendCover8(*t, c, (q[0] + q[1] + q[2]) / 3);
else {
else
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);
t->r = (c.r * q[0] >> 8) + ((257 - q[0]) * t->r >> 8);
t->g = (c.g * q[1] >> 8) + ((257 - q[1]) * t->g >> 8);
t->b = (c.b * q[2] >> 8) + ((257 - q[2]) * t->b >> 8);
}
else {
a = c.a * q[0] >> 8;
alpha = 256 - a - (a >> 7);
t->r = (c.r * q[0] >> 8) + (alpha * t->r >> 8);
t->r = (c.r * q[0] >> 8) + ((256 - a - (a >> 7)) * 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);
t->g = (c.g * q[1] >> 8) + ((256 - a - (a >> 7)) * 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);
t->b = (c.b * q[2] >> 8) + ((256 - a - (a >> 7)) * t->b >> 8);
}
}
t++;
q += 3;
}

View file

@ -35,7 +35,7 @@ struct SubpixelFiller : Rasterizer::Filler {
int y;
void Write(int len);
void RenderN(int val, int n);
void RenderN(int val, int h, int n);
void Render2(int val);
void Render1(int val);

View file

@ -21,39 +21,38 @@ NAMESPACE_UPP
#ifdef PLATFORM_WIN32
inline double fx_to_dbl(const FIXED& p) {
double fx_to_dbl(const FIXED& p) {
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
}
Pointf fx_to_dbl(const Pointf& pp, const POINTFX& p) {
return Pointf(pp.x + fx_to_dbl(p.x), pp.y - fx_to_dbl(p.y));
}
void RenderCharPath(const char* gbuf, unsigned total_size, Painter& sw, double xx, double yy)
{
PAINTER_TIMING("RenderCharPath");
const char* cur_glyph = gbuf;
const char* end_glyph = gbuf + total_size;
Pointf pp(xx, yy);
while(cur_glyph < end_glyph) {
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
const char* end_poly = cur_glyph + th->cb;
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
sw.Move(xx + fx_to_dbl(th->pfxStart.x), yy - fx_to_dbl(th->pfxStart.y));
sw.Move(fx_to_dbl(pp, th->pfxStart));
while(cur_poly < end_poly) {
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
if (pc->wType == TT_PRIM_LINE)
for(int i = 0; i < pc->cpfx; i++)
sw.Line(xx + fx_to_dbl(pc->apfx[i].x), yy - fx_to_dbl(pc->apfx[i].y));
if (pc->wType == TT_PRIM_QSPLINE) {
int u;
for (u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
POINTFX pnt_c = pc->apfx[u+1];
if (u < pc->cpfx - 2) { // If not on last spline, compute C
*(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
*(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2;
}
sw.Quadratic(xx + fx_to_dbl(pnt_b.x), yy - fx_to_dbl(pnt_b.y),
xx + fx_to_dbl(pnt_c.x), yy - fx_to_dbl(pnt_c.y));
sw.Line(fx_to_dbl(pp, pc->apfx[i]));
if (pc->wType == TT_PRIM_QSPLINE)
for(int u = 0; u < pc->cpfx - 1; u++) {
Pointf b = fx_to_dbl(pp, pc->apfx[u]);
Pointf c = fx_to_dbl(pp, pc->apfx[u + 1]);
if (u < pc->cpfx - 2)
c = Mid(b, c);
sw.Quadratic(b, c);
}
}
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
}
sw.Close();

View file

@ -34,7 +34,8 @@ file
Image.cpp optimize_speed,
Mask.cpp optimize_speed,
Gradient.cpp optimize_speed,
RadialGradient.cpp optimize_speed;
RadialGradient.cpp optimize_speed,
srcimp.tpp;
mainconfig
"" = "GUI";

View file

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

View file

@ -0,0 +1,17 @@
topic "";
[ $$0,0#00000000000000000000000000000000:Default]
[H6;0 $$1,0#05600065144404261032431302351956:begin]
[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem]
[l288;2 $$3,0#27521748481378242620020725143825:desc]
[0 $$4,0#96390100711032703541132217272105:end]
[{_}%EN-US
[s1;%- &]
[s2;:SubpixelFiller`:`:Write`(int`):%- [@(0.0.255) void]_[* Write]([@(0.0.255) int]_[*@3 len])
&]
[s3; This function flushes the content of filtered subpixel buffer.&]
[s0; Important note: due to rounding errors during filtering, sometimes
the subpixel value can be 257. This is remedied by using 257
instead of 256 in the pixel blending command.&]
[s0; &]
[s4; &]
[s0; ]