Home » U++ Library support » Draw, Display, Images, Bitmaps, Icons » Strange issue with text in Painter
|
Re: Strange issue with text in Painter [message #50988 is a reply to message #50986] |
Wed, 16 January 2019 09:37   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 16 January 2019 10:18Tom1 wrote on Wed, 16 January 2019 08:54Good morning Mirek,
Removing "thread__" from "thread__ CharEntry fc_cache[512];" fixes it.
Removing "thread__" from "thread__ FontEntry fi_cache[63];" does not have any effect on the problem.
Best regards,
Tom
BTW: Why should the caches be thread_local anyway? Isn't it true that Painter will use the same fonts with a whole bunch of threads when painting in MT? Having them common for all threads would have the used fonts cached after first hit and available to all threads. (Well, I'm likely missing something important here, but you'll probably educate me on that shortly...) 
Only to avoid confusion, how the code for CharEntry exactly looks now for you? And again, the rest of the code is absolutely the same as trunk?
Mirek
I refreshed from trunk this morning and the only change is in Font.cpp:
Instead of original:
thread__ CharEntry fc_cache[512];
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50989 is a reply to message #50988] |
Wed, 16 January 2019 09:39   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Wed, 16 January 2019 09:37mirek wrote on Wed, 16 January 2019 10:18Tom1 wrote on Wed, 16 January 2019 08:54Good morning Mirek,
Removing "thread__" from "thread__ CharEntry fc_cache[512];" fixes it.
Removing "thread__" from "thread__ FontEntry fi_cache[63];" does not have any effect on the problem.
Best regards,
Tom
BTW: Why should the caches be thread_local anyway? Isn't it true that Painter will use the same fonts with a whole bunch of threads when painting in MT? Having them common for all threads would have the used fonts cached after first hit and available to all threads. (Well, I'm likely missing something important here, but you'll probably educate me on that shortly...) 
Only to avoid confusion, how the code for CharEntry exactly looks now for you? And again, the rest of the code is absolutely the same as trunk?
Mirek
I refreshed from trunk this morning and the only change is in Font.cpp:
Instead of original:
thread__ CharEntry fc_cache[512];
BR, Tom
Well,there should be additional INTERLOCKED (to replace thread__)... Anyway, that is probably not relevant..
Any chance that you see a bug there in the code? I see nothing 
|
|
|
|
Re: Strange issue with text in Painter [message #50991 is a reply to message #50989] |
Wed, 16 January 2019 10:45   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 16 January 2019 10:39Tom1 wrote on Wed, 16 January 2019 09:37mirek wrote on Wed, 16 January 2019 10:18Tom1 wrote on Wed, 16 January 2019 08:54Good morning Mirek,
Removing "thread__" from "thread__ CharEntry fc_cache[512];" fixes it.
Removing "thread__" from "thread__ FontEntry fi_cache[63];" does not have any effect on the problem.
Best regards,
Tom
BTW: Why should the caches be thread_local anyway? Isn't it true that Painter will use the same fonts with a whole bunch of threads when painting in MT? Having them common for all threads would have the used fonts cached after first hit and available to all threads. (Well, I'm likely missing something important here, but you'll probably educate me on that shortly...) 
Only to avoid confusion, how the code for CharEntry exactly looks now for you? And again, the rest of the code is absolutely the same as trunk?
Mirek
I refreshed from trunk this morning and the only change is in Font.cpp:
Instead of original:
thread__ CharEntry fc_cache[512];
BR, Tom
Well,there should be additional INTERLOCKED (to replace thread__)... Anyway, that is probably not relevant..
Any chance that you see a bug there in the code? I see nothing 
I have read the code back and forth, but I clearly do not understand what's the reason for this. I'll keep digging...
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50992 is a reply to message #50991] |
Wed, 16 January 2019 10:52   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
Now I'm even more confused. I removed the access to fc_cache entirely:
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
font.RealizeStd();
unsigned hash = GlyphHash(font, chr);
/* CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;*/
return GetGlyphEntry(font, chr, hash).info;
}
But the error is still there!
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50993 is a reply to message #50991] |
Wed, 16 January 2019 10:53   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
Can you try this (with thread__ in place)
void PaintCharacter(Painter& sw, const Pointf& p, int chr, Font font)
{
GlyphInfo gi = GetGlyphInfo(font, chr);
PaintCharPath pw;
pw.sw = &sw;
if(gi.IsNormal())
font.Render(pw, p.x, p.y, chr);
else
if(gi.IsReplaced()) {
Font fnt = font;
fnt.Face(gi.lspc);
fnt.Height(gi.rspc);
fnt.Render(pw, p.x, p.y + font.GetAscent() - fnt.GetAscent(), chr);
DLOG("Replaced " << font << " -> " << fnt << ", " << chr << " " << (char)chr);
}
else
if(gi.IsComposed()) {
DLOG("Composed " << font << ", " << chr << " " << (char)chr);
ComposedGlyph cg;
Compose(font, chr, cg);
font.Render(pw, p.x, p.y, cg.basic_char);
sw.Div();
cg.mark_font.Render(pw, p.x + cg.mark_pos.x, p.y + cg.mark_pos.y, cg.mark_char);
}
sw.EvenOdd(true);
}
bring it to error and check whether there is anything in the log?
Mirek
|
|
|
Re: Strange issue with text in Painter [message #50994 is a reply to message #50992] |
Wed, 16 January 2019 11:11   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
Maybe you can try to call GetGlyphInfoSys directly there, with Mutex::Lock __(sFontLock);
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
font.RealizeStd();
/* unsigned hash = GlyphHash(font, chr);
CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;*/
return GetGlyphEntry(font, chr, hash).info;
*/
Mutex::Lock __(sFontLock);
return GetGlyphInfoSys(font, chr);
}
Another thing to test is whether
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
font.RealizeStd();
unsigned hash = GlyphHash(font, chr);
/* CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;*/
return GetGlyphEntry(font, chr, hash).info;
}
still depends on thread__ (hopefully not
[Updated on: Wed, 16 January 2019 11:18] Report message to a moderator
|
|
|
Re: Strange issue with text in Painter [message #50995 is a reply to message #50993] |
Wed, 16 January 2019 11:31   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 16 January 2019 11:53Can you try this (with thread__ in place)
void PaintCharacter(Painter& sw, const Pointf& p, int chr, Font font)
{
GlyphInfo gi = GetGlyphInfo(font, chr);
PaintCharPath pw;
pw.sw = &sw;
if(gi.IsNormal())
font.Render(pw, p.x, p.y, chr);
else
if(gi.IsReplaced()) {
Font fnt = font;
fnt.Face(gi.lspc);
fnt.Height(gi.rspc);
fnt.Render(pw, p.x, p.y + font.GetAscent() - fnt.GetAscent(), chr);
DLOG("Replaced " << font << " -> " << fnt << ", " << chr << " " << (char)chr);
}
else
if(gi.IsComposed()) {
DLOG("Composed " << font << ", " << chr << " " << (char)chr);
ComposedGlyph cg;
Compose(font, chr, cg);
font.Render(pw, p.x, p.y, cg.basic_char);
sw.Div();
cg.mark_font.Render(pw, p.x + cg.mark_pos.x, p.y + cg.mark_pos.y, cg.mark_char);
}
sw.EvenOdd(true);
}
bring it to error and check whether there is anything in the log?
Mirek
Nothing is shown on log.
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50996 is a reply to message #50994] |
Wed, 16 January 2019 11:35   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
font.RealizeStd();
/* unsigned hash = GlyphHash(font, chr);
CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;
return GetGlyphEntry(font, chr, hash).info;
*/
Mutex::Lock __(sFontLock);
return GetGlyphInfoSys(font, chr);
}
Still fails.
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50997 is a reply to message #50996] |
Wed, 16 January 2019 11:39   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
font.RealizeStd();
unsigned hash = GlyphHash(font, chr);
/* CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;*/
return GetGlyphEntry(font, chr, hash).info;
}
This fails regardless using thread__ or not.
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #50998 is a reply to message #50997] |
Wed, 16 January 2019 11:46   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
Even this fails:
//CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
//Mutex::Lock __(sFontLock);
GlyphInfo info;
INTERLOCKED{
font.RealizeStd();
info=GetGlyphInfoSys(font, chr);
}
return info;
}
BR, Tom
|
|
|
|
Re: Strange issue with text in Painter [message #51000 is a reply to message #50999] |
Wed, 16 January 2019 12:07   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 16 January 2019 13:00...
Well, those returns some sanity...
I have found possible issue and commited to trunk, please plain trunk now.. The chance that this fixes the issue is like 5%, but it is worth trying....
Unfortunately, the issue remains.
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #51001 is a reply to message #51000] |
Wed, 16 January 2019 12:16   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
What about this:
HFONT GetWin32Font(Font fnt, int angle)
{
LTIMING("GetWin32Font");
static HFontEntry cache[FONTCACHE];
ONCELOCK {
for(int i = 0; i < FONTCACHE; i++)
cache[i].font.Height(-30000);
}
HFontEntry be;
be = cache[0];
/* for(int i = 0; i < FONTCACHE; i++) {
HFontEntry e = cache[i];
if(i)
cache[i] = be;
if(e.font == fnt && e.angle == angle) {
if(i)
cache[0] = e;
return e.hfont;
}
be = e;
}*/
LTIMING("GetWin32Font2");
if(be.hfont)
DeleteObject(be.hfont);
be.font = fnt;
be.angle = angle;
#ifdef PLATFORM_WINCE
LOGFONT lfnt;
Zero(lfnt);
lfnt.lfHeight = fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12;
lfnt.lfWeight = fnt.IsBold() ? FW_BOLD : FW_NORMAL;
lfnt.lfItalic = fnt.IsItalic();
lfnt.lfUnderline = fnt.IsUnderline();
lfnt.lfStrikeOut = fnt.IsStrikeout();
wcscpy(lfnt.lfFaceName, ToSystemCharset(fnt.GetFaceName()));
be.hfont = CreateFontIndirect(&lfnt);
#else
be.hfont = CreateFont(
fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12,
fnt.GetWidth(), angle, angle, fnt.IsBold() ? FW_BOLD : FW_NORMAL,
fnt.IsItalic(), fnt.IsUnderline(), fnt.IsStrikeout(),
fnt.GetFace() == Font::SYMBOL ? SYMBOL_CHARSET : DEFAULT_CHARSET,
fnt.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
fnt.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
fnt.GetFaceName()
);
#endif
cache[0] = be;
return be.hfont;
}
(It is actually possible that this will INCREASE the number of wrong letters, even that would be important to know)
[Updated on: Wed, 16 January 2019 12:17] Report message to a moderator
|
|
|
Re: Strange issue with text in Painter [message #51002 is a reply to message #51001] |
Wed, 16 January 2019 12:47   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 16 January 2019 13:16What about this:
HFONT GetWin32Font(Font fnt, int angle)
{
LTIMING("GetWin32Font");
static HFontEntry cache[FONTCACHE];
ONCELOCK {
for(int i = 0; i < FONTCACHE; i++)
cache[i].font.Height(-30000);
}
HFontEntry be;
be = cache[0];
/* for(int i = 0; i < FONTCACHE; i++) {
HFontEntry e = cache[i];
if(i)
cache[i] = be;
if(e.font == fnt && e.angle == angle) {
if(i)
cache[0] = e;
return e.hfont;
}
be = e;
}*/
LTIMING("GetWin32Font2");
if(be.hfont)
DeleteObject(be.hfont);
be.font = fnt;
be.angle = angle;
#ifdef PLATFORM_WINCE
LOGFONT lfnt;
Zero(lfnt);
lfnt.lfHeight = fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12;
lfnt.lfWeight = fnt.IsBold() ? FW_BOLD : FW_NORMAL;
lfnt.lfItalic = fnt.IsItalic();
lfnt.lfUnderline = fnt.IsUnderline();
lfnt.lfStrikeOut = fnt.IsStrikeout();
wcscpy(lfnt.lfFaceName, ToSystemCharset(fnt.GetFaceName()));
be.hfont = CreateFontIndirect(&lfnt);
#else
be.hfont = CreateFont(
fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12,
fnt.GetWidth(), angle, angle, fnt.IsBold() ? FW_BOLD : FW_NORMAL,
fnt.IsItalic(), fnt.IsUnderline(), fnt.IsStrikeout(),
fnt.GetFace() == Font::SYMBOL ? SYMBOL_CHARSET : DEFAULT_CHARSET,
fnt.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
fnt.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
fnt.GetFaceName()
);
#endif
cache[0] = be;
return be.hfont;
}
(It is actually possible that this will INCREASE the number of wrong letters, even that would be important to know)
It seems this fixes the issue! 
BR, Tom
|
|
|
Re: Strange issue with text in Painter [message #51003 is a reply to message #51002] |
Wed, 16 January 2019 13:09   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
How about
HFONT GetWin32Font(Font fnt, int angle)
{
LTIMING("GetWin32Font");
static HFontEntry cache[FONTCACHE];
ONCELOCK {
for(int i = 0; i < FONTCACHE; i++)
cache[i].font.Height(-30000);
}
HFontEntry be;
be = cache[0];
INTERLOCKED
for(int i = 0; i < FONTCACHE; i++) {
HFontEntry e = cache[i];
if(i)
cache[i] = be;
if(e.font == fnt && e.angle == angle) {
if(i)
cache[0] = e;
return e.hfont;
}
be = e;
}
LTIMING("GetWin32Font2");
if(be.hfont)
DeleteObject(be.hfont);
be.font = fnt;
be.angle = angle;
#ifdef PLATFORM_WINCE
LOGFONT lfnt;
Zero(lfnt);
lfnt.lfHeight = fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12;
lfnt.lfWeight = fnt.IsBold() ? FW_BOLD : FW_NORMAL;
lfnt.lfItalic = fnt.IsItalic();
lfnt.lfUnderline = fnt.IsUnderline();
lfnt.lfStrikeOut = fnt.IsStrikeout();
wcscpy(lfnt.lfFaceName, ToSystemCharset(fnt.GetFaceName()));
be.hfont = CreateFontIndirect(&lfnt);
#else
be.hfont = CreateFont(
fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12,
fnt.GetWidth(), angle, angle, fnt.IsBold() ? FW_BOLD : FW_NORMAL,
fnt.IsItalic(), fnt.IsUnderline(), fnt.IsStrikeout(),
fnt.GetFace() == Font::SYMBOL ? SYMBOL_CHARSET : DEFAULT_CHARSET,
fnt.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
fnt.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
fnt.GetFaceName()
);
#endif
cache[0] = be;
return be.hfont;
}
|
|
|
Re: Strange issue with text in Painter [message #51004 is a reply to message #51003] |
Wed, 16 January 2019 13:20   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 16 January 2019 14:09How about
HFONT GetWin32Font(Font fnt, int angle)
{
LTIMING("GetWin32Font");
static HFontEntry cache[FONTCACHE];
ONCELOCK {
for(int i = 0; i < FONTCACHE; i++)
cache[i].font.Height(-30000);
}
HFontEntry be;
be = cache[0];
INTERLOCKED
for(int i = 0; i < FONTCACHE; i++) {
HFontEntry e = cache[i];
if(i)
cache[i] = be;
if(e.font == fnt && e.angle == angle) {
if(i)
cache[0] = e;
return e.hfont;
}
be = e;
}
LTIMING("GetWin32Font2");
if(be.hfont)
DeleteObject(be.hfont);
be.font = fnt;
be.angle = angle;
#ifdef PLATFORM_WINCE
LOGFONT lfnt;
Zero(lfnt);
lfnt.lfHeight = fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12;
lfnt.lfWeight = fnt.IsBold() ? FW_BOLD : FW_NORMAL;
lfnt.lfItalic = fnt.IsItalic();
lfnt.lfUnderline = fnt.IsUnderline();
lfnt.lfStrikeOut = fnt.IsStrikeout();
wcscpy(lfnt.lfFaceName, ToSystemCharset(fnt.GetFaceName()));
be.hfont = CreateFontIndirect(&lfnt);
#else
be.hfont = CreateFont(
fnt.GetHeight() ? -abs(fnt.GetHeight()) : -12,
fnt.GetWidth(), angle, angle, fnt.IsBold() ? FW_BOLD : FW_NORMAL,
fnt.IsItalic(), fnt.IsUnderline(), fnt.IsStrikeout(),
fnt.GetFace() == Font::SYMBOL ? SYMBOL_CHARSET : DEFAULT_CHARSET,
fnt.IsTrueTypeOnly() ? OUT_TT_ONLY_PRECIS : OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
fnt.IsNonAntiAliased() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
fnt.GetFaceName()
);
#endif
cache[0] = be;
return be.hfont;
}
Works perfectly. 
BR, Tom
EDIT: I'll be back online after about one hour...
[Updated on: Wed, 16 January 2019 13:25] Report message to a moderator
|
|
|
Re: Strange issue with text in Painter [message #51005 is a reply to message #51004] |
Wed, 16 January 2019 13:26   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
We are close but not there yet... The problem is that all calls to GetWin32Font should already be serialized (locked) - the only one that was not quite properly locked I have fixed in the trunk today.
Just for sanity check, can you do Find in Files search over all project files for GetWin32Font ?
For me, it returns
C:\u\upp.src\uppsrc\Draw\FontWin32.cpp (20): HFONT GetWin32Font(Font fnt, int angle)
C:\u\upp.src\uppsrc\Draw\FontWin32.cpp (22): LTIMING("GetWin32Font");
C:\u\upp.src\uppsrc\Draw\FontWin32.cpp (41): LTIMING("GetWin32Font2");
C:\u\upp.src\uppsrc\Draw\FontWin32.cpp (106): HFONT hfont = GetWin32Font(font, 0);
C:\u\upp.src\uppsrc\Draw\FontWin32.cpp (262): HFONT hfont = GetWin32Font(font, 0);
C:\u\upp.src\uppsrc\Draw\FontWin32.cpp (344): HFONT hfont = GetWin32Font(font, 0);
C:\u\upp.src\uppsrc\Draw\FontWin32.cpp (401): HFONT hfont = GetWin32Font(fnt, 0);
C:\u\upp.src\uppsrc\CtrlCore\DrawTextWin32.cpp (9): HFONT GetWin32Font(Font fnt, int angle);
C:\u\upp.src\uppsrc\CtrlCore\DrawTextWin32.cpp (21): Mutex::Lock ___(sFontLock); // need this because of GetWin32Font
C:\u\upp.src\uppsrc\CtrlCore\DrawTextWin32.cpp (22): HGDIOBJ orgfont = ::SelectObject(handle, GetWin32Font(font, angle));
(): 10 occurrence(s) have been found.
Do you have any other occurences?
Mirek
|
|
|
Re: Strange issue with text in Painter [message #51006 is a reply to message #51005] |
Wed, 16 January 2019 14:27   |
Tom1
Messages: 1303 Registered: March 2007
|
Ultimate Contributor |
|
|
The "GetWin32Font" occurences are the same.
The bad news is that I just found one missing character error again with this last code. But this is just one, which means the frequency of errors dropped significantly because of INTERLOCKing the GetWin32Font -cache. Now I must go back and check again more thoroughly when the GetWin32Font -cache is entirely disabled.
BR, Tom
|
|
|
Goto Forum:
Current Time: Tue May 13 10:55:30 CEST 2025
Total time taken to generate the page: 0.01699 seconds
|