mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
DTIMING and Minor fixed in Painter and Oci8
git-svn-id: svn://ultimatepp.org/upp/trunk@878 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
a3b7d313db
commit
d1411d55a6
3 changed files with 242 additions and 240 deletions
|
|
@ -1,238 +1,238 @@
|
|||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#if 0 // does not seem to help...
|
||||
|
||||
Image MipMap(const Image& img)
|
||||
{
|
||||
Size ssz = img.GetSize() / 2;
|
||||
Size msz = (img.GetSize() + 1) / 2;
|
||||
ImageBuffer ib(msz);
|
||||
for(int y = 0; y < ssz.cy; y++) {
|
||||
const RGBA *s1 = img[2 * y];
|
||||
const RGBA *s2 = img[2 * y + 1];
|
||||
const RGBA *e = s1 + 2 * ssz.cx;
|
||||
RGBA *t = ib[y];
|
||||
while(s1 < e) {
|
||||
t->r = (s1[0].r + s1[1].r + s2[0].r + s2[1].r) >> 2;
|
||||
t->g = (s1[0].g + s1[1].g + s2[0].g + s2[1].g) >> 2;
|
||||
t->b = (s1[0].b + s1[1].b + s2[0].b + s2[1].b) >> 2;
|
||||
t->a = (s1[0].a + s1[1].a + s2[0].a + s2[1].a) >> 2;
|
||||
t++;
|
||||
s1 += 2;
|
||||
s2 += 2;
|
||||
}
|
||||
if(ssz.cx < msz.cx) {
|
||||
t->r = (s1[0].r + s2[0].r) >> 2;
|
||||
t->g = (s1[0].g + s2[0].g) >> 2;
|
||||
t->b = (s1[0].b + s2[0].b) >> 2;
|
||||
t->a = (s1[0].a + s2[0].a) >> 2;
|
||||
}
|
||||
}
|
||||
if(ssz.cy < msz.cy) {
|
||||
const RGBA *s1 = img[img.GetSize().cy - 1];
|
||||
const RGBA *e = s1 + 2 * ssz.cx;
|
||||
RGBA *t = ib[msz.cy - 1];
|
||||
while(s1 < e) {
|
||||
t->r = (s1[0].r + s1[1].r) >> 2;
|
||||
t->g = (s1[0].g + s1[1].g) >> 2;
|
||||
t->b = (s1[0].b + s1[1].b) >> 2;
|
||||
t->a = (s1[0].a + s1[1].a) >> 2;
|
||||
t++;
|
||||
s1 += 2;
|
||||
}
|
||||
if(ssz.cx < msz.cx) {
|
||||
t->r = s1[0].r >> 2;
|
||||
t->g = s1[0].g >> 2;
|
||||
t->b = s1[0].b >> 2;
|
||||
t->a = s1[0].a >> 2;
|
||||
}
|
||||
}
|
||||
return ib;
|
||||
}
|
||||
|
||||
Image MakeMipMap(const Image& m, int level);
|
||||
|
||||
struct MipMapMaker : ImageMaker {
|
||||
int level;
|
||||
Image image;
|
||||
|
||||
virtual String Key() const {
|
||||
String h;
|
||||
RawCat(h, image.GetSerialId());
|
||||
RawCat(h, level);
|
||||
return h;
|
||||
}
|
||||
virtual Image Make() const {
|
||||
Size sz = image.GetSize();
|
||||
if(sz.cx && sz.cx) {
|
||||
if(level <= 0)
|
||||
return image;
|
||||
return MipMap(MakeMipMap(image, level - 1));
|
||||
}
|
||||
return Image();
|
||||
}
|
||||
};
|
||||
|
||||
Image MakeMipMap(const Image& img, int level)
|
||||
{
|
||||
MipMapMaker m;
|
||||
m.image = img;
|
||||
m.level = level;
|
||||
return MakeImage(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct PainterImageSpan : SpanSource {
|
||||
struct RGBAV {
|
||||
dword r, g, b, a;
|
||||
|
||||
void Set(dword v) { r = g = b = a = v; }
|
||||
void Put(dword weight, const RGBA& src) {
|
||||
r += weight * src.r;
|
||||
g += weight * src.g;
|
||||
b += weight * src.b;
|
||||
a += weight * src.a;
|
||||
}
|
||||
};
|
||||
|
||||
LinearInterpolator interpolator;
|
||||
int ax, ay, cx, cy, maxx, maxy;
|
||||
byte style;
|
||||
byte hstyle, vstyle;
|
||||
bool fast;
|
||||
bool fixed;
|
||||
Image image;
|
||||
|
||||
void Set(const Xform2D& m, const Image& img) {
|
||||
int level = 0;
|
||||
#if 0 // no mipmap for now
|
||||
double q = 1;
|
||||
if(!fast) {
|
||||
double q = 1;
|
||||
Pointf sc = m.GetScaleXY();
|
||||
if(sc.x >= 0.01 && sc.y >= 0.01)
|
||||
while(sc.x < 0.5 && sc.y < 0.5) {
|
||||
level++;
|
||||
sc.x *= 2;
|
||||
sc.y *= 2;
|
||||
q /= 2;
|
||||
}
|
||||
}
|
||||
if(q != 1)
|
||||
interpolator.Set(Inverse(m) * Xform2D::Scale(q));
|
||||
else
|
||||
#endif
|
||||
interpolator.Set(Inverse(m));
|
||||
image = img;
|
||||
// image = MakeMipMap(img, level);
|
||||
cx = image.GetWidth();
|
||||
cy = image.GetHeight();
|
||||
maxx = cx - 1;
|
||||
maxy = cy - 1;
|
||||
ax = 6000000 / cx * cx * 2;
|
||||
ay = 6000000 / cy * cy * 2;
|
||||
}
|
||||
|
||||
RGBA Pixel(int x, int y) { return image[y][x]; }
|
||||
|
||||
RGBA GetPixel(int x, int y) {
|
||||
if(hstyle == FILL_HPAD)
|
||||
x = minmax(x, 0, maxx);
|
||||
else
|
||||
if(hstyle == FILL_HREFLECT)
|
||||
x = (x + ax) / cx & 1 ? (ax - x - 1) % cx : (x + ax) % cx;
|
||||
else
|
||||
if(hstyle == FILL_HREPEAT)
|
||||
x = (x + ax) % cx;
|
||||
if(vstyle == FILL_VPAD)
|
||||
y = minmax(y, 0, maxy);
|
||||
else
|
||||
if(vstyle == FILL_VREFLECT)
|
||||
y = (y + ay) / cy & 1 ? (ay - y - 1) % cy : (y + ay) % cy;
|
||||
else
|
||||
if(vstyle == FILL_VREPEAT)
|
||||
y = (y + ay) % cy;
|
||||
return fixed || (x >= 0 && x < cx && y >= 0 && y < cy) ? image[y][x] : RGBAZero();
|
||||
}
|
||||
|
||||
virtual void Get(RGBA *span, int x, int y, unsigned len)
|
||||
{
|
||||
interpolator.Begin(x, y, len);
|
||||
fixed = hstyle && vstyle;
|
||||
while(len--) {
|
||||
Point h = interpolator.Get();
|
||||
// h -= 128;
|
||||
Point l = h >> 8;
|
||||
if(hstyle == FILL_HREPEAT)
|
||||
l.x = (l.x + ax) % cx;
|
||||
if(vstyle == FILL_VREPEAT)
|
||||
l.y = (l.y + ay) % cy;
|
||||
if(fast) {
|
||||
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy)
|
||||
*span = Pixel(l.x, l.y);
|
||||
else
|
||||
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy))
|
||||
*span = RGBAZero();
|
||||
else
|
||||
*span = GetPixel(l.x, l.y);
|
||||
}
|
||||
else {
|
||||
RGBAV v;
|
||||
v.Set(0);
|
||||
// v.Set(256 * 256 / 2);
|
||||
h.x &= 255;
|
||||
h.y &= 255;
|
||||
Point u = -h + 256;
|
||||
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy) {
|
||||
v.Put(u.x * u.y, Pixel(l.x, l.y));
|
||||
v.Put(h.x * u.y, Pixel(l.x + 1, l.y));
|
||||
v.Put(u.x * h.y, Pixel(l.x, l.y + 1));
|
||||
v.Put(h.x * h.y, Pixel(l.x + 1, l.y + 1));
|
||||
}
|
||||
else
|
||||
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy))
|
||||
v.Set(0);
|
||||
else {
|
||||
v.Put(u.x * u.y, GetPixel(l.x, l.y));
|
||||
v.Put(h.x * u.y, GetPixel(l.x + 1, l.y));
|
||||
v.Put(u.x * h.y, GetPixel(l.x, l.y + 1));
|
||||
v.Put(h.x * h.y, GetPixel(l.x + 1, l.y + 1));
|
||||
}
|
||||
span->r = byte(v.r >> 16);
|
||||
span->g = byte(v.g >> 16);
|
||||
span->b = byte(v.b >> 16);
|
||||
span->a = byte(v.a >> 16);
|
||||
}
|
||||
++span;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void BufferPainter::RenderImage(double width, const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
if(image.GetWidth() == 0 || image.GetHeight() == 0)
|
||||
return;
|
||||
PainterImageSpan ss;
|
||||
ss.style = flags & 15;
|
||||
ss.hstyle = flags & 3;
|
||||
ss.vstyle = flags & 12;
|
||||
ss.fast = flags & FILL_FAST;
|
||||
ss.Set(transsrc * pathattr.mtx, image);
|
||||
RenderPath(width, &ss, RGBAZero());
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
Close();
|
||||
RenderImage(-1, image, transsrc, flags);
|
||||
}
|
||||
|
||||
void BufferPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
RenderImage(width, image, transsrc, flags);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#include "Painter.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#if 0 // does not seem to help...
|
||||
|
||||
Image MipMap(const Image& img)
|
||||
{
|
||||
Size ssz = img.GetSize() / 2;
|
||||
Size msz = (img.GetSize() + 1) / 2;
|
||||
ImageBuffer ib(msz);
|
||||
for(int y = 0; y < ssz.cy; y++) {
|
||||
const RGBA *s1 = img[2 * y];
|
||||
const RGBA *s2 = img[2 * y + 1];
|
||||
const RGBA *e = s1 + 2 * ssz.cx;
|
||||
RGBA *t = ib[y];
|
||||
while(s1 < e) {
|
||||
t->r = (s1[0].r + s1[1].r + s2[0].r + s2[1].r) >> 2;
|
||||
t->g = (s1[0].g + s1[1].g + s2[0].g + s2[1].g) >> 2;
|
||||
t->b = (s1[0].b + s1[1].b + s2[0].b + s2[1].b) >> 2;
|
||||
t->a = (s1[0].a + s1[1].a + s2[0].a + s2[1].a) >> 2;
|
||||
t++;
|
||||
s1 += 2;
|
||||
s2 += 2;
|
||||
}
|
||||
if(ssz.cx < msz.cx) {
|
||||
t->r = (s1[0].r + s2[0].r) >> 2;
|
||||
t->g = (s1[0].g + s2[0].g) >> 2;
|
||||
t->b = (s1[0].b + s2[0].b) >> 2;
|
||||
t->a = (s1[0].a + s2[0].a) >> 2;
|
||||
}
|
||||
}
|
||||
if(ssz.cy < msz.cy) {
|
||||
const RGBA *s1 = img[img.GetSize().cy - 1];
|
||||
const RGBA *e = s1 + 2 * ssz.cx;
|
||||
RGBA *t = ib[msz.cy - 1];
|
||||
while(s1 < e) {
|
||||
t->r = (s1[0].r + s1[1].r) >> 2;
|
||||
t->g = (s1[0].g + s1[1].g) >> 2;
|
||||
t->b = (s1[0].b + s1[1].b) >> 2;
|
||||
t->a = (s1[0].a + s1[1].a) >> 2;
|
||||
t++;
|
||||
s1 += 2;
|
||||
}
|
||||
if(ssz.cx < msz.cx) {
|
||||
t->r = s1[0].r >> 2;
|
||||
t->g = s1[0].g >> 2;
|
||||
t->b = s1[0].b >> 2;
|
||||
t->a = s1[0].a >> 2;
|
||||
}
|
||||
}
|
||||
return ib;
|
||||
}
|
||||
|
||||
Image MakeMipMap(const Image& m, int level);
|
||||
|
||||
struct MipMapMaker : ImageMaker {
|
||||
int level;
|
||||
Image image;
|
||||
|
||||
virtual String Key() const {
|
||||
String h;
|
||||
RawCat(h, image.GetSerialId());
|
||||
RawCat(h, level);
|
||||
return h;
|
||||
}
|
||||
virtual Image Make() const {
|
||||
Size sz = image.GetSize();
|
||||
if(sz.cx && sz.cx) {
|
||||
if(level <= 0)
|
||||
return image;
|
||||
return MipMap(MakeMipMap(image, level - 1));
|
||||
}
|
||||
return Image();
|
||||
}
|
||||
};
|
||||
|
||||
Image MakeMipMap(const Image& img, int level)
|
||||
{
|
||||
MipMapMaker m;
|
||||
m.image = img;
|
||||
m.level = level;
|
||||
return MakeImage(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct PainterImageSpan : SpanSource {
|
||||
struct RGBAV {
|
||||
dword r, g, b, a;
|
||||
|
||||
void Set(dword v) { r = g = b = a = v; }
|
||||
void Put(dword weight, const RGBA& src) {
|
||||
r += weight * src.r;
|
||||
g += weight * src.g;
|
||||
b += weight * src.b;
|
||||
a += weight * src.a;
|
||||
}
|
||||
};
|
||||
|
||||
LinearInterpolator interpolator;
|
||||
int ax, ay, cx, cy, maxx, maxy;
|
||||
byte style;
|
||||
byte hstyle, vstyle;
|
||||
bool fast;
|
||||
bool fixed;
|
||||
Image image;
|
||||
|
||||
void Set(const Xform2D& m, const Image& img) {
|
||||
int level = 0;
|
||||
#if 0 // no mipmap for now
|
||||
double q = 1;
|
||||
if(!fast) {
|
||||
double q = 1;
|
||||
Pointf sc = m.GetScaleXY();
|
||||
if(sc.x >= 0.01 && sc.y >= 0.01)
|
||||
while(sc.x < 0.5 && sc.y < 0.5) {
|
||||
level++;
|
||||
sc.x *= 2;
|
||||
sc.y *= 2;
|
||||
q /= 2;
|
||||
}
|
||||
}
|
||||
if(q != 1)
|
||||
interpolator.Set(Inverse(m) * Xform2D::Scale(q));
|
||||
else
|
||||
#endif
|
||||
interpolator.Set(Inverse(m));
|
||||
image = img;
|
||||
// image = MakeMipMap(img, level);
|
||||
cx = image.GetWidth();
|
||||
cy = image.GetHeight();
|
||||
maxx = cx - 1;
|
||||
maxy = cy - 1;
|
||||
ax = 6000000 / cx * cx * 2;
|
||||
ay = 6000000 / cy * cy * 2;
|
||||
}
|
||||
|
||||
RGBA Pixel(int x, int y) { return image[y][x]; }
|
||||
|
||||
RGBA GetPixel(int x, int y) {
|
||||
if(hstyle == FILL_HPAD)
|
||||
x = minmax(x, 0, maxx);
|
||||
else
|
||||
if(hstyle == FILL_HREFLECT)
|
||||
x = (x + ax) / cx & 1 ? (ax - x - 1) % cx : (x + ax) % cx;
|
||||
else
|
||||
if(hstyle == FILL_HREPEAT)
|
||||
x = (x + ax) % cx;
|
||||
if(vstyle == FILL_VPAD)
|
||||
y = minmax(y, 0, maxy);
|
||||
else
|
||||
if(vstyle == FILL_VREFLECT)
|
||||
y = (y + ay) / cy & 1 ? (ay - y - 1) % cy : (y + ay) % cy;
|
||||
else
|
||||
if(vstyle == FILL_VREPEAT)
|
||||
y = (y + ay) % cy;
|
||||
return fixed || (x >= 0 && x < cx && y >= 0 && y < cy) ? image[y][x] : RGBAZero();
|
||||
}
|
||||
|
||||
virtual void Get(RGBA *span, int x, int y, unsigned len)
|
||||
{
|
||||
interpolator.Begin(x, y, len);
|
||||
fixed = hstyle && vstyle;
|
||||
while(len--) {
|
||||
Point h = interpolator.Get();
|
||||
// h -= 128;
|
||||
Point l = h >> 8;
|
||||
if(hstyle == FILL_HREPEAT)
|
||||
l.x = (l.x + ax) % cx;
|
||||
if(vstyle == FILL_VREPEAT)
|
||||
l.y = (l.y + ay) % cy;
|
||||
if(fast) {
|
||||
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy)
|
||||
*span = Pixel(l.x, l.y);
|
||||
else
|
||||
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy))
|
||||
*span = RGBAZero();
|
||||
else
|
||||
*span = GetPixel(l.x, l.y);
|
||||
}
|
||||
else {
|
||||
RGBAV v;
|
||||
v.Set(0);
|
||||
// v.Set(256 * 256 / 2);
|
||||
h.x &= 255;
|
||||
h.y &= 255;
|
||||
Point u = -h + 256;
|
||||
if(l.x > 0 && l.x < maxx && l.y > 0 && l.y < maxy) {
|
||||
v.Put(u.x * u.y, Pixel(l.x, l.y));
|
||||
v.Put(h.x * u.y, Pixel(l.x + 1, l.y));
|
||||
v.Put(u.x * h.y, Pixel(l.x, l.y + 1));
|
||||
v.Put(h.x * h.y, Pixel(l.x + 1, l.y + 1));
|
||||
}
|
||||
else
|
||||
if(style == 0 && (l.x < -1 || l.x > cx || l.y < -1 || l.y > cy))
|
||||
v.Set(0);
|
||||
else {
|
||||
v.Put(u.x * u.y, GetPixel(l.x, l.y));
|
||||
v.Put(h.x * u.y, GetPixel(l.x + 1, l.y));
|
||||
v.Put(u.x * h.y, GetPixel(l.x, l.y + 1));
|
||||
v.Put(h.x * h.y, GetPixel(l.x + 1, l.y + 1));
|
||||
}
|
||||
span->r = byte(v.r >> 16);
|
||||
span->g = byte(v.g >> 16);
|
||||
span->b = byte(v.b >> 16);
|
||||
span->a = byte(v.a >> 16);
|
||||
}
|
||||
++span;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void BufferPainter::RenderImage(double width, const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
if(image.GetWidth() == 0 || image.GetHeight() == 0)
|
||||
return;
|
||||
PainterImageSpan ss;
|
||||
ss.style = byte(flags & 15);
|
||||
ss.hstyle = byte(flags & 3);
|
||||
ss.vstyle = byte(flags & 12);
|
||||
ss.fast = flags & FILL_FAST;
|
||||
ss.Set(transsrc * pathattr.mtx, image);
|
||||
RenderPath(width, &ss, RGBAZero());
|
||||
}
|
||||
|
||||
void BufferPainter::FillOp(const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
Close();
|
||||
RenderImage(-1, image, transsrc, flags);
|
||||
}
|
||||
|
||||
void BufferPainter::StrokeOp(double width, const Image& image, const Xform2D& transsrc, dword flags)
|
||||
{
|
||||
RenderImage(width, image, transsrc, flags);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue