mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
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:
parent
daf2cece0d
commit
e16d4ea2da
6 changed files with 48 additions and 39 deletions
|
|
@ -128,10 +128,9 @@ void SubpixelFiller::Render(int val)
|
||||||
v++;
|
v++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubpixelFiller::RenderN(int val, int n)
|
void SubpixelFiller::RenderN(int val, int h, int n)
|
||||||
{
|
{
|
||||||
int16 *w = v;
|
int16 *w = v;
|
||||||
int h = val / 9;
|
|
||||||
int h2 = h + h;
|
int h2 = h + h;
|
||||||
int hv2 = val - h2 - h2;
|
int hv2 = val - h2 - h2;
|
||||||
int h3 = h2 + h;
|
int h3 = h2 + h;
|
||||||
|
|
@ -214,11 +213,12 @@ void SubpixelFiller::RenderN(int val, int n)
|
||||||
|
|
||||||
void SubpixelFiller::Render(int val, int len)
|
void SubpixelFiller::Render(int val, int len)
|
||||||
{
|
{
|
||||||
|
int h = val / 9;
|
||||||
if(len > 6) {
|
if(len > 6) {
|
||||||
int q = (3333333 - (v + 2 - begin)) % 3;
|
int q = (3333333 - (v + 2 - begin)) % 3;
|
||||||
len -= q + 2;
|
len -= q + 2;
|
||||||
int l = v + 2 + q - begin;
|
int l = v + 2 + q - begin;
|
||||||
RenderN(val, q + 4);
|
RenderN(val, h, q + 4);
|
||||||
Write(l / 3);
|
Write(l / 3);
|
||||||
l = len / 3;
|
l = len / 3;
|
||||||
len -= 3 * l;
|
len -= 3 * l;
|
||||||
|
|
@ -235,12 +235,11 @@ void SubpixelFiller::Render(int val, int len)
|
||||||
while(t < e)
|
while(t < e)
|
||||||
AlphaBlendCover8(*t++, ss ? Mul8(*s++, alpha) : color, val);
|
AlphaBlendCover8(*t++, ss ? Mul8(*s++, alpha) : color, val);
|
||||||
v = begin = sbuffer + 3;
|
v = begin = sbuffer + 3;
|
||||||
int h = val / 9;
|
|
||||||
v[0] = h + h + h;
|
v[0] = h + h + h;
|
||||||
v[1] = h;
|
v[1] = h;
|
||||||
v[2] = 0;
|
v[2] = 0;
|
||||||
}
|
}
|
||||||
RenderN(val, len);
|
RenderN(val, h, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubpixelFiller::Write(int len)
|
void SubpixelFiller::Write(int len)
|
||||||
|
|
@ -249,29 +248,22 @@ void SubpixelFiller::Write(int len)
|
||||||
int16 *q = begin;
|
int16 *q = begin;
|
||||||
while(t < e) {
|
while(t < e) {
|
||||||
RGBA c = ss ? Mul8(*s++, alpha) : color;
|
RGBA c = ss ? Mul8(*s++, alpha) : color;
|
||||||
int a, alpha;
|
int a;
|
||||||
if(t->a != 255)
|
if(t->a != 255)
|
||||||
AlphaBlendCover8(*t, c, (q[0] + q[1] + q[2]) / 3);
|
AlphaBlendCover8(*t, c, (q[0] + q[1] + q[2]) / 3);
|
||||||
else {
|
else
|
||||||
if(c.a == 255) {
|
if(c.a == 255) {
|
||||||
alpha = 256 - q[0];
|
t->r = (c.r * q[0] >> 8) + ((257 - q[0]) * t->r >> 8);
|
||||||
t->r = (c.r * q[0] >> 8) + (alpha * t->r >> 8);
|
t->g = (c.g * q[1] >> 8) + ((257 - q[1]) * t->g >> 8);
|
||||||
alpha = 256 - q[1];
|
t->b = (c.b * q[2] >> 8) + ((257 - q[2]) * t->b >> 8);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
a = c.a * q[0] >> 8;
|
a = c.a * q[0] >> 8;
|
||||||
alpha = 256 - a - (a >> 7);
|
t->r = (c.r * q[0] >> 8) + ((256 - a - (a >> 7)) * t->r >> 8);
|
||||||
t->r = (c.r * q[0] >> 8) + (alpha * t->r >> 8);
|
|
||||||
a = c.a * q[1] >> 8;
|
a = c.a * q[1] >> 8;
|
||||||
alpha = 256 - a - (a >> 7);
|
t->g = (c.g * q[1] >> 8) + ((256 - a - (a >> 7)) * t->g >> 8);
|
||||||
t->g = (c.g * q[1] >> 8) + (alpha * t->g >> 8);
|
|
||||||
a = c.a * q[2] >> 8;
|
a = c.a * q[2] >> 8;
|
||||||
alpha = 256 - a - (a >> 7);
|
t->b = (c.b * q[2] >> 8) + ((256 - a - (a >> 7)) * t->b >> 8);
|
||||||
t->b = (c.b * q[2] >> 8) + (alpha * t->b >> 8);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
t++;
|
t++;
|
||||||
q += 3;
|
q += 3;
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ struct SubpixelFiller : Rasterizer::Filler {
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
void Write(int len);
|
void Write(int len);
|
||||||
void RenderN(int val, int n);
|
void RenderN(int val, int h, int n);
|
||||||
void Render2(int val);
|
void Render2(int val);
|
||||||
void Render1(int val);
|
void Render1(int val);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,38 +21,37 @@ NAMESPACE_UPP
|
||||||
|
|
||||||
#ifdef PLATFORM_WIN32
|
#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);
|
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)
|
void RenderCharPath(const char* gbuf, unsigned total_size, Painter& sw, double xx, double yy)
|
||||||
{
|
{
|
||||||
PAINTER_TIMING("RenderCharPath");
|
PAINTER_TIMING("RenderCharPath");
|
||||||
const char* cur_glyph = gbuf;
|
const char* cur_glyph = gbuf;
|
||||||
const char* end_glyph = gbuf + total_size;
|
const char* end_glyph = gbuf + total_size;
|
||||||
|
Pointf pp(xx, yy);
|
||||||
while(cur_glyph < end_glyph) {
|
while(cur_glyph < end_glyph) {
|
||||||
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
|
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
|
||||||
const char* end_poly = cur_glyph + th->cb;
|
const char* end_poly = cur_glyph + th->cb;
|
||||||
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
|
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) {
|
while(cur_poly < end_poly) {
|
||||||
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
|
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
|
||||||
if (pc->wType == TT_PRIM_LINE)
|
if (pc->wType == TT_PRIM_LINE)
|
||||||
for(int i = 0; i < pc->cpfx; i++)
|
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));
|
sw.Line(fx_to_dbl(pp, pc->apfx[i]));
|
||||||
if (pc->wType == TT_PRIM_QSPLINE) {
|
if (pc->wType == TT_PRIM_QSPLINE)
|
||||||
int u;
|
for(int u = 0; u < pc->cpfx - 1; u++) {
|
||||||
for (u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
|
Pointf b = fx_to_dbl(pp, pc->apfx[u]);
|
||||||
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
|
Pointf c = fx_to_dbl(pp, pc->apfx[u + 1]);
|
||||||
POINTFX pnt_c = pc->apfx[u+1];
|
if (u < pc->cpfx - 2)
|
||||||
if (u < pc->cpfx - 2) { // If not on last spline, compute C
|
c = Mid(b, c);
|
||||||
*(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
|
sw.Quadratic(b, c);
|
||||||
*(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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
|
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ file
|
||||||
Image.cpp optimize_speed,
|
Image.cpp optimize_speed,
|
||||||
Mask.cpp optimize_speed,
|
Mask.cpp optimize_speed,
|
||||||
Gradient.cpp optimize_speed,
|
Gradient.cpp optimize_speed,
|
||||||
RadialGradient.cpp optimize_speed;
|
RadialGradient.cpp optimize_speed,
|
||||||
|
srcimp.tpp;
|
||||||
|
|
||||||
mainconfig
|
mainconfig
|
||||||
"" = "GUI";
|
"" = "GUI";
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#define _Painter_icpp_init_stub
|
#define _Painter_icpp_init_stub
|
||||||
#include "Core/init"
|
#include "Core/init"
|
||||||
#include "CtrlLib/init"
|
#include "CtrlLib/init"
|
||||||
#define BLITZ_INDEX__ F135B9991BD270784ACE22BD4FFB4267E
|
#define BLITZ_INDEX__ F1F279540D3FE6AF9024371A0E93C1FBB
|
||||||
#include "PaintPainting.icpp"
|
#include "PaintPainting.icpp"
|
||||||
#undef BLITZ_INDEX__
|
#undef BLITZ_INDEX__
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
17
uppsrc/Painter/srcimp.tpp/SubpixelFiller$en-us.tpp
Normal file
17
uppsrc/Painter/srcimp.tpp/SubpixelFiller$en-us.tpp
Normal 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; ]
|
||||||
Loading…
Add table
Add a link
Reference in a new issue