Home » U++ Library support » Draw, Display, Images, Bitmaps, Icons » Strange issue with text in Painter
|
Re: Strange issue with text in Painter [message #50921 is a reply to message #50916] |
Mon, 14 January 2019 11:57 |
Tom1
Messages: 1277 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Mon, 14 January 2019 12:41Thinking about it, I have suspiction that maybe RawPickToValue might have to do something with all that...
What about this:
struct sMakeGlyph : LRUCache<String, GlyphKey>::Maker {
GlyphKey gk;
GlyphKey Key() const { return gk; }
int Make(String& v) const {
GlyphPainter gp;
gp.move = gp.pos = Null;
gp.tolerance = gk.tolerance;
PaintCharacter(gp, Pointf(0, 0), gk.chr, gk.fnt);
int sz = gp.glyph.GetCount() * 4;
v.Set((char *)gp.glyph.begin(), sizeof(float) * gp.glyph.GetCount());
return sz;
}
};
void ApproximateChar(LinearPathConsumer& t, Pointf at, int ch, Font fnt, double tolerance)
{
PAINTER_TIMING("ApproximateChar");
String v;
INTERLOCKED {
PAINTER_TIMING("ApproximateChar::Fetch");
static LRUCache<String, GlyphKey> cache;
cache.Shrink(500000);
sMakeGlyph h;
h.gk.fnt = fnt;
h.gk.chr = ch;
h.gk.tolerance = tolerance;
v = cache.Get(h);
}
int i = 0;
int count = v.GetCount() / sizeof(float);
const float *g = (const float *)~v;
while(i < count) {
Pointf p;
p.x = g[i++];
if(p.x > 1e30) {
p.x = g[i++];
p.y = g[i++];
t.Move(p + at);
}
else {
PAINTER_TIMING("ApproximateChar::Line");
p.y = g[i++];
t.Line(p + at);
}
}
}
The problem is still there with the above code.
BR, Tom
|
|
|
|
|
|
Re: Strange issue with text in Painter [message #50926 is a reply to message #50922] |
Mon, 14 January 2019 12:21 |
Tom1
Messages: 1277 Registered: March 2007
|
Senior Contributor |
|
|
According to Windows Task Manager, there are 30 threads running on this process. But my GUI is simply running on main thread. There should be nothing graphical going on in any of my background threads.
Here's an interesting part: I said previously that ST/MT in Painter did not make any difference. Well, it did not when I had started the program originally with Painter MT enabled and then switched 'live' to ST to test for the error effect. BUT: Now I started with Painter fixed in ST and: Error is gone... Sounds like in my original MT/ST test the font caching in Painter had already happened in MT before I switched it to ST.
I need to dig deeper on this.
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50927 is a reply to message #50924] |
Mon, 14 January 2019 12:22 |
Tom1
Messages: 1277 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Mon, 14 January 2019 13:14Have you tried this on another computer? (Blaming HW is the last thing I usually do, but this is way too weird...)
Mirek
Need to try that too.
|
|
|
|
|
Re: Strange issue with text in Painter [message #50930 is a reply to message #50929] |
Mon, 14 January 2019 13:23 |
|
mirek
Messages: 14154 Registered: November 2005
|
Ultimate Member |
|
|
Try this pls:
Buffer<ClippingLine> BufferPainter::RenderPath(double width, Event<One<SpanSource>&> ss, const RGBA& color)
{
PAINTER_TIMING("RenderPath");
Buffer<ClippingLine> newclip;
if(width == FILL)
Close();
current = Null;
if(width == 0 || !ss && color.a == 0 && width >= FILL)
return newclip;
if(pathattr.mtx_serial != preclip_mtx_serial) {
if(dopreclip) {
Pointf tl, br, a;
Xform2D imx = Inverse(pathattr.mtx);
tl = br = imx.Transform(0, 0);
a = imx.Transform(size.cx, 0);
tl = min(a, tl);
br = max(a, br);
a = imx.Transform(0, size.cy);
tl = min(a, tl);
br = max(a, br);
a = imx.Transform(size.cx, size.cy);
tl = min(a, tl);
br = max(a, br);
preclip = Rectf(tl, br);
}
else
preclip = Null;
regular = pathattr.mtx.IsRegular();
preclip_mtx_serial = pathattr.mtx_serial;
}
if(co) {
if(width >= FILL && !ss && !alt && findarg(mode, MODE_ANTIALIASED, MODE_SUBPIXEL) >= 0 && !path_info->ischar) {
(The difference is && !path_info->ischar in the last line).
Also, is there a difference DEBUG vs RELEASE?
|
|
|
Re: Strange issue with text in Painter [message #50931 is a reply to message #50924] |
Mon, 14 January 2019 13:26 |
Tom1
Messages: 1277 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Mon, 14 January 2019 13:14Have you tried this on another computer? (Blaming HW is the last thing I usually do, but this is way too weird...)
Mirek
Tried with my old reliable notebook, but it's the same.
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50932 is a reply to message #50930] |
Mon, 14 January 2019 13:53 |
Tom1
Messages: 1277 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Mon, 14 January 2019 14:23Try this pls:
Buffer<ClippingLine> BufferPainter::RenderPath(double width, Event<One<SpanSource>&> ss, const RGBA& color)
{
PAINTER_TIMING("RenderPath");
Buffer<ClippingLine> newclip;
if(width == FILL)
Close();
current = Null;
if(width == 0 || !ss && color.a == 0 && width >= FILL)
return newclip;
if(pathattr.mtx_serial != preclip_mtx_serial) {
if(dopreclip) {
Pointf tl, br, a;
Xform2D imx = Inverse(pathattr.mtx);
tl = br = imx.Transform(0, 0);
a = imx.Transform(size.cx, 0);
tl = min(a, tl);
br = max(a, br);
a = imx.Transform(0, size.cy);
tl = min(a, tl);
br = max(a, br);
a = imx.Transform(size.cx, size.cy);
tl = min(a, tl);
br = max(a, br);
preclip = Rectf(tl, br);
}
else
preclip = Null;
regular = pathattr.mtx.IsRegular();
preclip_mtx_serial = pathattr.mtx_serial;
}
if(co) {
if(width >= FILL && !ss && !alt && findarg(mode, MODE_ANTIALIASED, MODE_SUBPIXEL) >= 0 && !path_info->ischar) {
(The difference is && !path_info->ischar in the last line).
Also, is there a difference DEBUG vs RELEASE?
In RELEASE mode I could not find a single bad letter in 15 minutes. I think this is it!
Will try now with DEBUG...
BR, Tom
|
|
|
|
Re: Strange issue with text in Painter [message #50934 is a reply to message #50933] |
Mon, 14 January 2019 15:03 |
|
mirek
Messages: 14154 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Mon, 14 January 2019 14:11Not a single false character in DEBUG mode either.
I should have found something already if the problem still existed.
So, is this the fix or means for problem isolation?
Best regards,
Tom
This basically disables MT for character rendering...
So for now, please revert it and try two separate things for me:
void Painter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const double *dx)
{
if(n == 0) {
Move(0, 0);
return;
}
FontInfo fi = fnt.Info();
double x = p.x;
while(n) {
int ch = *text++;
Character(x, p.y, ch, fnt);
// Div();
if(dx)
x += *dx++;
else
x += fi[ch];
n--;
}
if(fnt.IsUnderline() || fnt.IsStrikeout()) {
double a = fnt.GetAscent();
double cy = max(a / 16, 1.0);
double cx = x - p.x;
if(fnt.IsUnderline())
Rectangle(p.x, p.y + a + cy, cx, cy);
if(fnt.IsStrikeout())
Rectangle(p.x, p.y + 2 * a / 3, cx, cy);
}
}
(This might lead to some new artifacts where characters overlap, that is expected, look for the original problem (wrong characters).
void BufferPainter::RenderPathSegments(LinearPathConsumer *g, const Vector<byte>& path,
const SimpleAttr *attr, double tolerance)
{
Pointf pos = Pointf(0, 0);
const byte *data = path.begin();
const byte *end = path.end();
while(data < end) {
const LinearData *d = (LinearData *)data;
switch(d->type) {
case MOVE: {
g->Move(pos = attr ? attr->mtx.Transform(d->p) : d->p);
data += sizeof(LinearData);
break;
}
case LINE: {
PAINTER_TIMING("LINE");
g->Line(pos = attr ? attr->mtx.Transform(d->p) : d->p);
data += sizeof(LinearData);
break;
}
case QUADRATIC: {
PAINTER_TIMING("QUADRATIC");
const QuadraticData *d = (QuadraticData *)data;
if(attr) {
Pointf p = attr->mtx.Transform(d->p);
ApproximateQuadratic(*g, pos, attr->mtx.Transform(d->p1), p, tolerance);
pos = p;
}
else {
ApproximateQuadratic(*g, pos, d->p1, d->p, tolerance);
pos = d->p;
}
data += sizeof(QuadraticData);
break;
}
case CUBIC: {
PAINTER_TIMING("CUBIC");
const CubicData *d = (CubicData *)data;
if(attr) {
Pointf p = attr->mtx.Transform(d->p);
ApproximateCubic(*g, pos, attr->mtx.Transform(d->p1),
attr->mtx.Transform(d->p2), p, tolerance);
pos = p;
}
else {
ApproximateCubic(*g, pos, d->p1, d->p2, d->p, tolerance);
pos = d->p;
}
data += sizeof(CubicData);
break;
}
case CHAR: {
const CharData *ch = (CharData *)data;
INTERLOCKED ApproximateChar(*g, ch->p, ch->ch, ch->fnt, tolerance);
data += sizeof(CharData);
break;
}
default:
NEVER();
g->End();
return;
}
}
g->End();
}
(Additional mutex in for CHAR).
Thanks,
Mirek
[Updated on: Mon, 14 January 2019 15:13] Report message to a moderator
|
|
|
|
|
|
Re: Strange issue with text in Painter [message #50938 is a reply to message #50937] |
Mon, 14 January 2019 16:08 |
|
mirek
Messages: 14154 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Mon, 14 January 2019 15:38No, false positive. The problem is still there even after the "void Painter::TextOp(const Pointf& p, const wchar *text, Font fnt, int n, const double *dx)" -fix.
BR, Tom
Well, for today I am out of ideas.... Will continue tomorrow, OK?
Perhaps one last question: This probably must have started recently, probably after the last round of optimizations. Is that correct?
Mirek
|
|
|
Re: Strange issue with text in Painter [message #50939 is a reply to message #50938] |
Mon, 14 January 2019 17:21 |
Tom1
Messages: 1277 Registered: March 2007
|
Senior Contributor |
|
|
Hi,
Yes, I'm also out of time for today. Tomorrow I will have time until about 14:00 EET.
The first time I noticed this was just last week when I reported it. I had not updated from SVN in a while before that though, so I may need to go back a bit further in time to find that.
One potential reason for finding this issue is that I had just recently reached a point in my own code where I started to rotate the texts according to the original scale and rotation, both of which change constantly over the projection surface for maps where a change from one map projection to another has been carried out.
In effect this has caused an overwhelming increase in cached fonts here in my application. I think the reason is that when tolerance changes even by the smallest fraction of a double, it necessitates a new cache entry. In my case there will be a huge amount of cache entries. Actually, if the tolerance parameter were made more discrete, e.g. through classing to slots for caching, the problem might not show up at all or at least do it extremely rarely. Then again, I think, the potential issue with caching should be corrected first, if real, and only thereafter should the optimization through classing be implemented.
I might have it all wrong here, but this is just a thought.
Anyway, Mirek, thanks for your efforts today on the task!
Best regards,
Tom
|
|
|
|
Goto Forum:
Current Time: Tue Dec 03 00:32:19 CET 2024
Total time taken to generate the page: 0.02804 seconds
|