【问题标题】:Real length of a Thai UTF-8 encoded string in DelphiDelphi中泰语UTF-8编码字符串的实际长度
【发布时间】:2017-10-05 04:59:27
【问题描述】:

泰语是一种非常特殊的语言。您可以在辅音之后,或在它的前面,或在它的顶部,或在它的底部(好吧,只是短和长的“u”音可以放在底部,但无论如何......)。

此外,还有其他修饰语(4 个声调标记、ga-ran、mai-tai-ku 和其他修饰语)可以在已经存在的元音之上!

例如:

 ที่ดีที่สุด (the best)

如您所见,如果我尝试使用等宽字体打印,“实际长度”将为 5 个字符,但所有 UTF-8 strlen 例程都会返回 11 个字符 - 这是完全正确的,但是我需要知道当等宽打印时,字符串将在屏幕/打印机上使用的“实际空间”。

当然,一个简单的解决方案是列出所有可以出现在单词顶部或底部的特殊字符,并将它们从总数中删除。

由于我不确定我是否能找到所有特殊字符,是否已经有一个用任何语言制作的例程以便我可以在 Delphi 中翻译它?

谢谢

【问题讨论】:

  • 您要求的是字体在处理 Unicode 组合代码点后视觉呈现的字形大小。你不会在 Delphi RTL 中找到任何东西。而且由于它与字体使用直接相关,因此您需要类似 VCL 的 TCanvas.TextExtent() 或 FMX 的 TCanvas.Text(Width|Height)() 方法,并在 TCanvas.Font 中加载 Unicode 字体(或直接使用 Win32 GetTextExtentPoint32() 函数)。
  • 谢谢,我只是担心模拟写字体会是一个相当长的过程,但我会这样做。顺便说一句,你为什么不回答?我不能接受评论:)
  • 当您想向提问者或响应者以外的其他人发表评论时,请在收件人姓名前加上 at (@) 字符,例如:@RemyLebeau 我认为您的评论会很好输入作为答案
  • 如果 实际空间 是指像素宽度和高度,@RemyLebeau 为您提供了GetTextExtentPoint32 的解决方案,它表示(使用大小为 20 的 CordialUPC 字体您已经使用过)该字符串为 57 像素宽 x 37 像素高,默认为每英寸 96 像素的表单。缩放到 Printer.Canvas 维度是使用 Printer.Canvas.Handle 而不是表单的 Canvas.Handle 作为 HDC 参数。
  • 旨在使用基本字符呈现的代码点称为“组合字符”。但是,这也不是一个精确的解决方案,因为还有其他排版字符不会呈现为字素,例如换行和零宽度空格。此外,对于某些变音符号,由一些拉丁字母组成的单数代码点。请参阅Unicode FAQ

标签: delphi utf-8 thai


【解决方案1】:

在 C++ 中:

    /*---------------------------------------------------------------------------*/
    /*                              thai_tcslen                                  */
    /*---------------------------------------------------------------------------*/
    short thai_tcslen(_TCHAR *buff)
    {
      short bufpos;
      short normal_length;
      short thai_length;

      thai_length=0;
      normal_length = _tcslen(buff);
      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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 2011-05-03
    • 2016-02-09
    • 1970-01-01
    • 2011-10-06
    • 2010-12-17
    相关资源
    最近更新 更多