Do jednego ze swoich projektów wymyśliłem, że dorobię obsługę Unicode, a tak naprawdę obsługę dwóch pierwszych zestawów zwanymi "Plane".
Dla plane 0 wszystko działa prawidłowo, natomiast z plane 1 jest problem. Pozostałe "plane" od 2 do 16 mnie nie interesują.
Napisałem prosty program w .NET Framework, który wypisuje na konsoli i na bitmapie kilka znaków z plane 0 i plane 1. Jak widać, na konsoli wypisuje prawidłowo za wyjątkiem tego, że zwykły char obsługuje tylko plane 0 (a że niektóre znaki zajmują większy obszar niż jedna komórka to już inny temat i nie jest to problem), a na bitmapie to już nie tylko nie wypisuje znaków z plane 1 (jak widać, próbowałem kilku sposobów znalezionych w Google), ale również coś psuje w obiekcie typu Graphics przy próbie wypisania dowolnego znaku z plane 1, bo jak się przed każdym znakiem nie utworzy nowego obiektu (linie zaznaczone wykrzyknikami), to na bitmapie nie ma ostatniego znaku.
Jak widać, próbowałem kilka różnych fontów i z każdym jest ten sam problem. Natomiast w aplikacji https://andrzejlisek.github.io/Unicode/unicode.htm dla wszystkich wykorzystanych fontów pokazują się wszystkie znaki.
Ja nie oczekuję kolorowych znaków, tylko chociażby niektóre oryginalne znaki lub jakaś kratka lub kropka będąca zamiennikiem znaku, którego ma w danym foncie.
Co z tym zrobić i jak zmusić program do malowania wszystkich znaków Unicode na bitmapie? Jak to jest, że dla tej samej czcionki, w C# jest problem, a w HTML wszystko działa prawidłowo?
Poza tym, dlaczego znak z "plane 1" ma długość 2 znaków, pomimo, że to jest jeden znak? Liczba znaków w napisie, a liczba bajtów to dwie różne sprawy.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestThr
{
class MainClass
{
public static void Main(string[] args)
{
Console.Clear();
List<string> FontNames = new List<string>();
FontNames.Add("Noto Mono");
FontNames.Add("Ubuntu Mono");
FontNames.Add("Consolas");
FontNames.Add("Tlwg Mono");
FontNames.Add("Monospace");
FontNames.Add("Courier");
FontNames.Add("Arial");
FontNames.Add("Times New Roman");
FontNames.Add("Liberation Mono");
List<int> Chars = new List<int>();
Chars.Add(0x37);
Chars.Add(0x41);
Chars.Add(0x25CF);
Chars.Add(0x2592);
Chars.Add(0xC647);
Chars.Add(0xFFFD);
Chars.Add(0x010097);
Chars.Add(0x010133);
Chars.Add(0x010718);
Chars.Add(0x01F6D1);
Chars.Add(0x01F652);
Chars.Add(0x35);
int BmpStep = 60;
Bitmap BmpX = new Bitmap(FontNames.Count * 4 * BmpStep + BmpStep, Chars.Count * BmpStep + BmpStep, PixelFormat.Format24bppRgb);
Graphics BmpG = Graphics.FromImage(BmpX);
string Temp1 = "";
string Temp2 = "";
for (int i = 0; i < Chars.Count; i++)
{
Console.Write(Chars[i].ToString("X"));
Console.Write(" [");
try
{
Console.Write((char)Chars[i]);
}
catch
{
Console.Write("ERROR");
}
Console.Write("] [");
Temp1 = Encoding.UTF32.GetString(new byte[] { (byte)((Chars[i]) & 255), (byte)((Chars[i] >> 8) & 255), (byte)((Chars[i] >> 16) & 255), 0x00 });
Console.Write(Temp1);
Console.Write("]" + Temp1.Length);
Console.Write(" [");
Temp2 = Char.ConvertFromUtf32(Chars[i]);
Console.Write(Temp2);
Console.Write("]" + Temp2.Length + " ");
for (int ii = 0; ii < FontNames.Count; ii++)
{
Font Font_ = new Font(FontNames[ii], 20);
int BmpPos = BmpStep * 4 * ii;
// !!!!!!!!!!!!!!!!
BmpG = Graphics.FromImage(BmpX);
BmpG.DrawString(Temp1, Font_, Brushes.White, BmpPos + BmpStep * 1, BmpStep * i);
// !!!!!!!!!!!!!!!!
BmpG = Graphics.FromImage(BmpX);
BmpG.DrawString(Temp2, Font_, Brushes.White, BmpPos + BmpStep * 2, BmpStep * i);
// !!!!!!!!!!!!!!!!
BmpG = Graphics.FromImage(BmpX);
TextRenderer.DrawText(BmpG, Temp1, Font_, new Point(BmpPos + BmpStep * 3, BmpStep * i), Color.White);
// !!!!!!!!!!!!!!!!
BmpG = Graphics.FromImage(BmpX);
TextRenderer.DrawText(BmpG, Temp2, Font_, new Point(BmpPos + BmpStep * 4, BmpStep * i), Color.White);
}
if (Temp1 == Temp2)
{
Console.Write("OK ");
for (int ii = 0; ii < Temp1.Length; ii++)
{
Console.Write("[");
Console.Write(((int)Temp1[ii]).ToString("X"));
Console.Write("]");
}
}
Console.WriteLine();
}
BmpX.Save("CharTest.png", ImageFormat.Png);
Console.ReadLine();
}
}
}