在Delphi中,泰语UTF-8编码字符串的实际长度是多少?

4
Thai是一种非常特殊的语言。你可以像其他任何语言一样在辅音后面、前面、上面或下面(好吧,只有短长“u”的音可以放在下面,但无论如何...)书写元音(共32个)。
此外,还有其他修饰符(4个声调标记、ga-ran、mai-tai-ku和其他修饰符)可以放在已有元音的上方!
例如:
 ที่ดีที่สุด (the best)

如您所见,如果我尝试使用等宽字体打印它,则“实际长度”将为5个字符,但所有UTF-8 strlen例程都会给我返回11个字符 - 这是完全正确的,但我需要知道当等宽字体打印时字符串将使用的“实际空间”,无论是在屏幕上还是在打印机上。
当然,一个简单的解决方案是列出所有可以放在单词顶部或底部的特殊字符,并从总计中删除它们。
由于我不确定是否能找到所有特殊字符,因此是否已经有任何语言中的例程可以让我将其翻译成Delphi?
谢谢。

9
您所要求的是字体在处理Unicode组合代码点后呈现的字素大小。在Delphi RTL中,您无法找到任何有关此的信息。由于其直接与字体使用相关,因此您需要像VCL的TCanvas.TextExtent()或FMX的TCanvas.Text(Width|Height)()方法一样的东西,并且需要在TCanvas.Font中加载一个Unicode字体(或直接使用Win32GetTextExtentPoint32()函数)。 - Remy Lebeau
1
谢谢,我只是担心模拟写字体会是一个相当漫长的过程,但我会去做的。顺便问一下,你为什么没有回答呢?我无法接受评论 :) - ZioBit
2
当你想向除了提问者或回答者之外的其他人发表评论时,请在被称呼者的名字前加上“@”字符,例如:@RemyLebeau 我认为您的评论很适合作为答案输入。 - Tom Brunberg
如果您所说的“实际空间”是指像素宽度和高度,@RemyLebeau已经通过GetTextExtentPoint32给出了解决方案,该函数表示(使用您使用的大小为20的CordialUPC字体)字符串在默认96像素每英寸的窗体上的宽度为57像素,高度为37像素。将其缩放到打印机.Canvas尺寸只需要使用Printer.Canvas.Handle而不是窗体的Canvas.Handle作为HDC参数即可。 - Ken White
被设计为与基本字符一起呈现的代码点称为“组合字符”。然而,这也不是一个确切的解决方案,因为还有其他排版字符不会呈现为字形,例如换行符和零宽度空格。此外,对于某些变音符号,它们会与某些拉丁字母组成单个代码点。请参阅Unicode FAQ - Tom Blodget
1个回答

1
在C++中:
    /*---------------------------------------------------------------------------*/
    /*                              thai_tcslen                                  */
    /*---------------------------------------------------------------------------*/
    long thai_tcslen(_TCHAR *buff)
    {
      long bufpos = 0;
      long normal_length = _tcslen(buff);
      long thai_length = 0;

      for (bufpos = 0; bufpos < normal_length; ++bufpos) {
        if (   *(buff+bufpos) != _T('Ñ')/*mai han na kaad*//*-047*/
            && *(buff+bufpos) != _T('Ô')/*sara ee        *//*-044*/
            && *(buff+bufpos) != _T('Õ')/*sara eeeee     *//*-043*/
            && *(buff+bufpos) != _T('Ö')/*sara uu        *//*-042*/
            && *(buff+bufpos) != _T('×')/*sara uuuuu     *//*-041*/
            && *(buff+bufpos) != _T('Ø')/*sara oo        *//*-040*/
            && *(buff+bufpos) != _T('Ù')/*sara ooooo     *//*-039*/
            && *(buff+bufpos) != _T('ç')/*mai tai khoo   *//*-025*/
            && *(buff+bufpos) != _T('è')/*mai aek        *//*-024*/
            && *(buff+bufpos) != _T('é')/*mai toe        *//*-023*/
            && *(buff+bufpos) != _T('ê')/*mai cha ta wah *//*-022*/
            && *(buff+bufpos) != _T('ë')/*mai tree       *//*-021*/
            && *(buff+bufpos) != _T('ì')/*ka ran         *//*-020*/
            ) {
          ++thai_length;
        }
      }

      return thai_length;
    } /* thai_tcslen */

在VB6中:
    Public Function ThaiStringLength(ByRef ThaiString As String) As Long
      Dim b As String, noLengthChars(13) As Byte
      b = ThaiString

      noLengthChars(0) = 209
      noLengthChars(1) = 212
      noLengthChars(2) = 213
      noLengthChars(3) = 214
      noLengthChars(4) = 215
      noLengthChars(5) = 216
      noLengthChars(6) = 217
      noLengthChars(7) = 231
      noLengthChars(8) = 232
      noLengthChars(9) = 233
      noLengthChars(10) = 234
      noLengthChars(11) = 235
      noLengthChars(12) = 236

      Dim o As Long
      For o = 0 To 12
        If InStr(b, Chr(noLengthChars(o))) > 0 Then
          b = Replace(b, Chr(noLengthChars(o)), "")
        End If
      Next
      ThaiStringLength = Len(b)
    End Function

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接