dwmkerr / sharpgl

Use OpenGL in .NET applications. SharpGL wraps all modern OpenGL features and offers a powerful scene graph to aid development.
MIT License
768 stars 300 forks source link

GL.DrawText gives wrong characters #168

Open Azzar2 opened 4 years ago

Azzar2 commented 4 years ago

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 commented 4 years ago

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 commented 4 years ago

Good day Dave,

Thanks for coming back on this.

public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } }

[image: image.png]

but none of these changes makes any difference.

   DirectCast(GLControl1,

System.ComponentModel.ISupportInitialize).BeginInit() SuspendLayout()

     ' SharpGLControl
     '
     GLControl1.DrawFPS           = True
     GLControl1.FrameRate         = 20
     GLControl1.Location          = New System.Drawing.Point(0, 0)
     GLControl1.Size              = New System.Drawing.Size(300, 284)
     GLControl1.Name              = "OpenGLControl1"
     GLControl1.CausesValidation  = True
     GLControl1.ForeColor         = Color.Black
     GLControl1.BackgroundImage   = Nothing

     GLControl1.OpenGLVersion     =

SharpGL.Version.OpenGLVersion.OpenGL2_1 GLControl1.RenderContextType = SharpGL.RenderContextType.FBO GLControl1.RenderTrigger = SharpGL.RenderTrigger.Manual GLControl1.BorderStyle = BorderStyle.FixedSingle GLControl1.TabIndex = 8 GLControl1.TabStop = True GLControl1.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowOnly GLControl1.Anchor = AnchorStyles.None GLControl1.AutoValidate = Windows.Forms.AutoValidate.EnablePreventFocusChange GLControl1.ImeMode = Windows.Forms.ImeMode.NoControl GLControl1.Enabled = True

    AddHandler GLControl1.OpenGLInitialized,  New

System.EventHandler (AddressOf GLControl_OpenGLInitialized) AddHandler GLControl1.OpenGLDraw, New SharpGL.RenderEventHandler(AddressOf GLControl_OpenGLDraw) AddHandler GLControl1.Resized, New System.EventHandler (AddressOf GLControl_OpenGLResize) Controls.Add(GLControl1) HDC = GLControl1.Handle

  DirectCast(GLControl1,

System.ComponentModel.ISupportInitialize).EndInit() ResumeLayout(False)

  Me.FormBorderStyle   = Windows.Forms.FormBorderStyle.Sizable
  Me.AutoSizeMode      = Windows.Forms.AutoSizeMode.GrowAndShrink
  Me.SizeGripStyle     = Windows.Forms.SizeGripStyle.Show

[image: image.png]

[image: image.png]

Thanks in advance for any suggestion.

Cordialement / Best regards - Claude Gosselin


Claude Gosselin, Ph.D., P.Eng.Involute Simulation Softwares 1139 des Laurentides Quebec, P. Quebec, Canada G1S-3C2 Email: HyGEARS@HyGEARS.com Web: www.HyGEARS.com


This e-mail message and any attachments may contain legally privileged, confidential or proprietary Information, or information otherwise protected by law of Involute Simulation Softwares Inc., its affiliates, or third parties. This notice serves as marking of its "Confidential" status as defined in any confidentiality agreements concerning the sender and recipient.

If you are not the intended recipient(s), or the employee or agent responsible for delivery of this message to the intended recipient(s), you are hereby notified that any dissemination, distribution or copying of this e-mail message is strictly prohibited. If you have received this message in error, please immediately notify the sender and delete this e-mail message from your computer.

On Sun, Feb 23, 2020 at 7:29 AM Dave Kerr notifications@github.com wrote:

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)

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/dwmkerr/sharpgl/issues/168?email_source=notifications&email_token=AKT6XJKWMMYZLWQYWTWI4SLREJT3NA5CNFSM4KVX62A2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEMV2Q4Q#issuecomment-590063730, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKT6XJK6RDA7VHRUTMZYKETREJT3NANCNFSM4KVX62AQ .

Azzar2 commented 4 years ago

Good day Dave,

Any movement on that front ?

nzain commented 4 years ago

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 commented 4 years ago

Unicode characters (characters > 256) are lost in the call to FontBitMap.DrawText: https://github.com/dwmkerr/sharpgl/blob/523267322be4338a1dd5ab039b222937a1d667f3/source/SharpGL/Core/SharpGL/FontBitmaps.cs#L303

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 commented 4 years ago

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 https://github.com/dwmkerr/sharpgl/blob/523267322be4338a1dd5ab039b222937a1d667f3/source/SharpGL/Core/SharpGL/FontBitmaps.cs#L206 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 commented 4 years ago

Good day Patrick, Dave,

Thank you for the tip. I have tried the following code where the Unicode of the text string to be displayed is converted to either:

none of which gives any better results.

[image: image.png]

Below shows what I get whereas displayed values should be like "1.320 [mm]", etc.

[image: image.png]

Would you have any other suggestion ?

Cordialement / Best regards - Claude Gosselin


Claude Gosselin, Ph.D., P.Eng.Involute Simulation Softwares 1139 des Laurentides Quebec, P. Quebec, Canada G1S-3C2 Email: HyGEARS@HyGEARS.com Web: www.HyGEARS.com


This e-mail message and any attachments may contain legally privileged, confidential or proprietary Information, or information otherwise protected by law of Involute Simulation Softwares Inc., its affiliates, or third parties. This notice serves as marking of its "Confidential" status as defined in any confidentiality agreements concerning the sender and recipient.

If you are not the intended recipient(s), or the employee or agent responsible for delivery of this message to the intended recipient(s), you are hereby notified that any dissemination, distribution or copying of this e-mail message is strictly prohibited. If you have received this message in error, please immediately notify the sender and delete this e-mail message from your computer.

On Tue, Mar 17, 2020 at 9:29 AM Patrick Stalph notifications@github.com wrote:

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

https://github.com/dwmkerr/sharpgl/blob/523267322be4338a1dd5ab039b222937a1d667f3/source/SharpGL/Core/SharpGL/FontBitmaps.cs#L206 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!

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/dwmkerr/sharpgl/issues/168#issuecomment-600071414, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKT6XJJJIKSDFNTHYDAZ2O3RH53LHANCNFSM4KVX62AQ .

EvgeniyKishov commented 4 years ago

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.

Add constant RUSSIAN_CHARSET = 204 (after 870 line)

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);

(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 commented 4 years ago

Good day Mr Kishov,

Thank you very much for the tip. Could you tell me where I can find the CodePage number for English Unicode ? This is what I want to use.

Thank you.

Cordialement / Best regards - Claude Gosselin


Claude Gosselin, Ph.D., P.Eng.Involute Simulation Softwares 1139 des Laurentides Quebec, P. Quebec, Canada G1S-3C2 Email: HyGEARS@HyGEARS.com Web: www.HyGEARS.com


This e-mail message and any attachments may contain legally privileged, confidential or proprietary Information, or information otherwise protected by law of Involute Simulation Softwares Inc., its affiliates, or third parties. This notice serves as marking of its "Confidential" status as defined in any confidentiality agreements concerning the sender and recipient.

If you are not the intended recipient(s), or the employee or agent responsible for delivery of this message to the intended recipient(s), you are hereby notified that any dissemination, distribution or copying of this e-mail message is strictly prohibited. If you have received this message in error, please immediately notify the sender and delete this e-mail message from your computer.

On Tue, Mar 24, 2020 at 4:13 PM EvgeniyKishov notifications@github.com wrote:

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

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/dwmkerr/sharpgl/issues/168#issuecomment-603480848, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKT6XJJEP3S6ZBC3YRKBJBLRJEIAFANCNFSM4KVX62AQ .

nzain commented 4 years ago

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 commented 4 years ago

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 commented 3 years ago

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 commented 3 years ago

Good day Florian,

Thank you for the suggestion. Since I posted this more than 1 year ago, I moved to Wpf with [much] better success.

Cordialement / Best regards - Claude Gosselin


Claude Gosselin, Ph.D., P.Eng.Involute Simulation Softwares 1139 des Laurentides Quebec, P. Quebec, Canada G1S-3C2 Email: HyGEARS@HyGEARS.com Web: www.HyGEARS.com


This e-mail message and any attachments may contain legally privileged, confidential or proprietary Information, or information otherwise protected by law of Involute Simulation Softwares Inc., its affiliates, or third parties. This notice serves as marking of its "Confidential" status as defined in any confidentiality agreements concerning the sender and recipient.

If you are not the intended recipient(s), or the employee or agent responsible for delivery of this message to the intended recipient(s), you are hereby notified that any dissemination, distribution or copying of this e-mail message is strictly prohibited. If you have received this message in error, please immediately notify the sender and delete this e-mail message from your computer.

On Mon, Apr 12, 2021 at 4:41 AM Florian-Krax @.***> wrote:

Hi @Azzar2 https://github.com/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

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/dwmkerr/sharpgl/issues/168#issuecomment-817612994, or unsubscribe https://github.com/notifications/unsubscribe-auth/AKT6XJJTG6EBIJV22BN3JGLTIKW4RANCNFSM4KVX62AQ .