Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GL.DrawText gives wrong characters #168

Open
Azzar2 opened this issue Feb 15, 2020 · 13 comments
Open

GL.DrawText gives wrong characters #168

Azzar2 opened this issue Feb 15, 2020 · 13 comments

Comments

@Azzar2
Copy link

Azzar2 commented Feb 15, 2020

Hi Dave:
I am using GL.DrawText to display values in a SharpGL control: problem is that the text comes out garbled rather than what I send to DrawText - see the attached screenshot. Wondering what I may be doing wrong. The code is below. Thanks for any help. Claude. 15 Feb 2020

Note: The SharpGL control is used on a ChildWindow in a MDI environment.

Dim iR, iG, iB As Int32
Dim R, G, B As Single
Dim FontStr As String = "Arial"
Dim FontSize As Single = 10.0
Dim iX As Int32 = 0
Dim iY As Int32 = 0
Dim Gl As SharpGL.OpenGL = GLControl1.OpenGL
' ====================================

' Position where to start the Text
iX = CInt(PosX)
iY = CInt(PosY)

' Convert text color
Call GetRgbFt(Graf.IColorTxt, iR, iG, iB)
R = CSng(iR / 255)
G = CSng(iG / 255)
B = CSng(iB / 255)

' Display the text
Gl.DrawText(iX, iY, R, G, B, FontStr, FontSize, TxtStr)

DrawText

@dwmkerr
Copy link
Owner

dwmkerr commented Feb 23, 2020

What's the type for TxtStr? Also, does the TextRenderingSample run successfully on your machine (this would help us identify if it might be an issue with the driver and SharpGL not being in sync)

@Azzar2
Copy link
Author

Azzar2 commented Feb 23, 2020 via email

@Azzar2
Copy link
Author

Azzar2 commented Mar 15, 2020

Good day Dave,

Any movement on that front ?

@nzain
Copy link

nzain commented Mar 17, 2020

It seems that only ASCII+Codepage characters are rendered correctly, but Unicode is not supported. C# internally represents all strings as UTF-16 (2 bytes, see System.Text.Encoding.Unicode), but only the higher byte is really displayed.

Example: string txt = "абцдеф" gets displayed as 01F45D.

System.Text.Encoding.Unicode.GetBytes("абцдеф")	
	[00]	48	byte
	[01]	4	byte
	[02]	49	byte
	[03]	4	byte
	[04]	70	byte
	[05]	4	byte
	[06]	52	byte
	[07]	4	byte
	[08]	53	byte
	[09]	4	byte
	[10]	68	byte
	[11]	4	byte
System.Text.Encoding.Unicode.GetBytes("01F45D")
	[00]	48	byte
	[01]	0	byte
	[02]	49	byte
	[03]	0	byte
	[04]	70	byte
	[05]	0	byte
	[06]	52	byte
	[07]	0	byte
	[08]	53	byte
	[09]	0	byte
	[10]	68	byte
	[11]	0	byte

@nzain
Copy link

nzain commented Mar 17, 2020

Unicode characters (characters > 256) are lost in the call to FontBitMap.DrawText:

var lists = text.Select(c => (byte) c).ToArray();

text.ToCharArray()
	[0]	1072 'а'	char
	[1]	1073 'б'	char
	[2]	1094 'ц'	char
	[3]	1076 'д'	char
	[4]	1077 'е'	char
	[5]	1092 'ф'	char
byte[] lists
	[0]	48	byte
	[1]	49	byte
	[2]	70	byte
	[3]	52	byte
	[4]	53	byte
	[5]	68	byte

@nzain
Copy link

nzain commented Mar 17, 2020

Just to clarify: this problem is not at all related to the OPs manual rendering. Instead, this is the oh-so-old text encoding problem. One byte is not enough to encode international characters, only 7bit ASCII plus one bit for the code page.

The P/Invoke into Gdi32.dll here

var hFont = Win32.CreateFont(height, 0, 0, 0, Win32.FW_DONTCARE, 0, 0, 0, Win32.DEFAULT_CHARSET,

only supports ancient char sets; docs:
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createfontw

I'm not at all familiar with Gdi32.dll - if anyone knows how to get unicode glyph metrics please comment!

@Azzar2
Copy link
Author

Azzar2 commented Mar 17, 2020 via email

@EvgeniyKishov
Copy link

Good day, everyone!

In order to correctly draw unicode characters (e.g. text in russian) I did some modifications of sharpGL source code described below which are work well for me.

  • Modification of "win32.cs"

Add constant RUSSIAN_CHARSET = 204 (after 870 line)

  • Modification of "FontBitmaps.cs"

Modification of CreateFontOutlineEntry() function

  1. Change 9th argument of Win32.CreateFont() call from Win32.DEFAULT_CHARSET to Win32.RUSSIAN_CHARSET (line 206).
  2. Increase size of glyphMetrics array from 255 to 256. So 216 line now looks like var glyphMetrics = new GLYPHMETRICSFLOAT[256];
  3. Change 3rd argument of wglUseFontOutlines() call from 255 to 256 (line 219).
  4. Change ListCount member of foe object from 255 to 256 (line 236).

Modification of DrawText() function (line 277)

Change line 303 from var lists = text.Select(c => (byte) c).ToArray(); to var lists = Encoding.Default.GetBytes(text);

  • Modification of "FontOutlines.cs"

(very similar to modifications mentioned above)

Modification of CreateFontBitmapEntry() function

  1. Change 9th argument of Win32.CreateFont() call from Win32.DEFAULT_CHARSET to Win32.RUSSIAN_CHARSET (line 62).
  2. Change 3rd argument of wglUseFontBitmaps() call from 255 to 256 (line 72).
  3. Change ListCount member of fbe object from 255 to 256 (line 88).

Modification of DrawText() function (line 277)

Change line 160 from var lists = text.Select(c => (byte) c).ToArray(); to var lists = Encoding.Default.GetBytes(text);

That's all! After rebuilding SharpGL-project I got new *.dll libraries which able to draw unicode characters. Please, see attached picture for demonstration of results:

(https://user-images.githubusercontent.com/58272248/77472138-eb172380-6e2c-11ea-8829-04f7029ba7b5.png)

--
Regards,
Evgeniy Kishov

@Azzar2
Copy link
Author

Azzar2 commented Mar 24, 2020 via email

@nzain
Copy link

nzain commented Mar 24, 2020

This way you enable the Russian code page (up to 256 different characters), but not Unicode (all international characters, many thousand). Nevertheless, a noteworthy piece of code.

My sample was Russian (like one of my colleagues) but our customers come from many countries all over the world. Unfortunately, this is not a solution for me.

@EvgeniyKishov
Copy link

Hello, Claude,

As Patrick (aka "nzain") mentioned, it seems like there is no obvious way to use Unicode enconging withing SharpGL text rendering. But you can try different codepages with 256 symbols which available for Windows and described in "wingdi.h" - header file of Windows SDK (see, e.g. https://github.com/tpn/winsdk-7/blob/master/v7.1A/Include/WinGDI.h).

Some constants from "wingdi.h" see below:
#define ANSI_CHARSET 0
#define DEFAULT_CHARSET 1
#define SYMBOL_CHARSET 2
#define SHIFTJIS_CHARSET 128
#define HANGEUL_CHARSET 129
#define HANGUL_CHARSET 129
#define GB2312_CHARSET 134
#define CHINESEBIG5_CHARSET 136
#define OEM_CHARSET 255
#define JOHAB_CHARSET 130
#define HEBREW_CHARSET 177
#define ARABIC_CHARSET 178
#define GREEK_CHARSET 161
#define TURKISH_CHARSET 162
#define VIETNAMESE_CHARSET 163
#define THAI_CHARSET 222
#define EASTEUROPE_CHARSET 238
#define RUSSIAN_CHARSET 204

@Florian-Krax
Copy link

Hi @Azzar2,

I had the same issue and found a workaround.
It seems like the first created font doesn't work.

So to work around this issue you can first render an empty text with another FontStr or another FontSize. This will create the first font an all following fonts worked well for me.

Best regards,
Florian Krax

@Azzar2
Copy link
Author

Azzar2 commented Apr 12, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants