【问题标题】:Converting LTR to RTL?将 LTR 转换为 RTL?
【发布时间】:2012-02-13 04:21:12
【问题描述】:

你知道很多 ui 组件和开发工具不支持 rtl ,我们可以称之为 flipping text ,因为结果是相同的例子:

LTR

سلام salam متن راهنما word

RTL

word متن راهنما salam  سلام

无论如何要将此 LTR 转换为 RTL,我没有任何想法,语言无关紧要

实际上,我正在寻找一种解决方案来在 RAD Studio Firemonkey Application 中完成这项工作,因为您可能知道 firemonkey 应用程序不支持 rtl,它在 rad studio 的路线图中但尚未实施

【问题讨论】:

  • 我认为您将修复程序移植到 FMX 上来完成这项工作并不容易。也许它可以用于文本输出,但我想象中的编辑工作将是一个挑战。您可能需要等到 FMX 完成。
  • 相关的 Mac OS X API 是“ATSUI”或 Apple Type Services for Unicode Imaging,Win32 API 是 UNISCRIBE。在 FMX 提供一个包含通用 API 的库之前,祝你好运。我确信 QT 已经有了它,所以任何实现它的人都可以研究他们在 QT 中是如何做到的。

标签: c++ regex delphi uniscribe


【解决方案1】:

如果您使用MFC,这里是如何设置翻正方向和对齐方式。假设您的 CEdit 控件名为 m_TextEdit

void MyDialog::SetLangDirection(bool RTL)
{
    DWORD w_dwStyle;

    w_dwStyle = GetWindowLong(m_TextEdit.GetSafeHwnd(), GWL_EXSTYLE);

    if (RTL)
    {
        w_dwStyle -= WS_EX_LEFT | WS_EX_LTRREADING;
        w_dwStyle |= WS_EX_RIGHT | WS_EX_RTLREADING;
    }
    else
    {
        w_dwStyle -= WS_EX_RIGHT | WS_EX_RTLREADING;
        w_dwStyle |= WS_EX_LEFT | WS_EX_LTRREADING;
    }

    SetWindowLong(m_TextEdit.GetSafeHwnd(), GWL_EXSTYLE, w_dwStyle);
}

my tip

【讨论】:

    【解决方案2】:

    在 Windows 下,您可以通过 UniScribe API 来实现。

    我已经使用它来将 Unicode 文本转换为一组字形,用于我们的 Open Source PDF writer

    您有SynPdf.pas 单元中的源代码示例。见TPdfWrite.AddUnicodeHexTextUniScribe方法:

    function TPdfWrite.AddUnicodeHexTextUniScribe(PW: PWideChar;
      WinAnsiTTF: TPdfFontTrueType; NextLine: boolean; Canvas: TPdfCanvas): boolean;
    var L, i,j: integer;
        res: HRESULT;
        max, count, numSp: integer;
        Sp: PScriptPropertiesArray;
        W: PWideChar;
        items: array of TScriptItem;
        level: array of byte;
        VisualToLogical: array of integer;
        psc: pointer; // opaque Uniscribe font metric cache
        complex,R2L: boolean;
        complexs: array of byte;
        glyphs: array of TScriptVisAttr;
        glyphsCount: integer;
        OutGlyphs, LogClust: array of word;
    procedure Append(i: Integer);
    // local procedure used to add glyphs from items[i] to the PDF content stream
    var L: integer;
        W: PWideChar;
    procedure DefaultAppend;
    var tmpU: array of WideChar;
    begin
      SetLength(tmpU,L+1); // we need the text to be ending with #0
      move(W^,tmpU[0],L*2);
      AddUnicodeHexTextNoUniScribe(pointer(tmpU),WinAnsiTTF,false,Canvas);
    end;
    begin
      L := items[i+1].iCharPos-items[i].iCharPos; // length of this shapeable item
      if L=0 then
        exit; // nothing to append
      W := PW+items[i].iCharPos;
      if not GetBit(complexs[0],i) then begin
        // not complex items are rendered as fast as possible
        DefaultAppend;
        exit;
      end;
      res := ScriptShape(0,psc,W,L,max,@items[i].a,
        pointer(OutGlyphs),pointer(LogClust),pointer(glyphs),glyphsCount);
      case res of
        E_OUTOFMEMORY: begin // max was not big enough (should never happen)
          DefaultAppend;
          exit;
        end;
        E_PENDING, USP_E_SCRIPT_NOT_IN_FONT: begin // need HDC and a selected font object
          res := ScriptShape(Canvas.FDoc.GetDCWithFont(WinAnsiTTF),
            psc,W,L,max,@items[i].a,
            pointer(OutGlyphs),pointer(LogClust),pointer(glyphs),glyphsCount);
          if res<>0 then begin // we won't change font if necessary, sorry
            // we shall implement the complex technic as stated by
            // http://msdn.microsoft.com/en-us/library/dd374105(v=VS.85).aspx
            DefaultAppend;
            exit;
          end;
        end;
        0: ; // success -> will add glyphs just below
        else exit;
      end;
      // add glyphs to the PDF content
      // (NextLine has already been handled: not needed here)
      AddGlyphs(pointer(OutGlyphs),glyphsCount,Canvas);
    end;
    begin
      result := false; // on UniScribe error, handle as Unicode
      // 1. Breaks a Unicode string into individually shapeable items
      L := StrLenW(PW)+1; // include last #0
      max := L+2; // should be big enough
      SetLength(items,max);
      count := 0;
      if ScriptItemize(PW,L,max,nil,nil,pointer(items),count)<>0 then
        exit; // error trying processing Glyph Shaping -> fast return
      // 2. guess if requiring glyph shaping or layout
      SetLength(complexs,(count shr 3)+1);
      ScriptGetProperties(sP,numSp);
      complex := false;
      R2L := false;
      for i := 0 to Count-2 do // don't need Count-1 = Terminator
        if fComplex in sP^[items[i].a.eScript and (1 shl 10-1)]^.fFlags then begin
          complex := true;
          SetBit(complexs[0],i);
        end else
          if fRTL in items[i].a.fFlags then
            R2L := true;
      if not complex then begin
        // no glyph shaping -> fast append as normal Unicode Text
        if R2L then begin
          // handle Right To Left but not Complex text
          W := pointer(items); // there is enough temp space in items[]
          W[L] := #0;
          dec(L);
          for i := 0 to L do
            W[i] := PW[L-i];
          AddUnicodeHexTextNoUniScribe(W,WinAnsiTTF,NextLine,Canvas);
          result := true; // mark handled here
        end;
        exit;
      end;
      // 3. get Visual Order, i.e. how to render the content from left to right
      SetLength(level,count);
      for i := 0 to Count-1 do
        level[i] := items[i].a.s.uBidiLevel;
      SetLength(VisualToLogical,count);
      if ScriptLayout(Count,pointer(level),pointer(VisualToLogical),nil)<>0 then
        exit;
      // 4. now we have enough information to start drawing
      result := true;
      if NextLine then
        Canvas.MoveToNextLine; // manual NextLine handling
      // 5. add glyphs for all shapeable items
      max := (L*3)shr 1+32; // should be big enough - allocate only once
      SetLength(glyphs,max);
      SetLength(OutGlyphs,max);
      SetLength(LogClust,max);
      psc := nil; // cached for the same character style used
      if Canvas.RightToLeftText then
        // append from right to left visual order
        for j := Count-2 downto 0 do // Count-2: ignore last ending item
          Append(VisualToLogical[j]) else
        // append from left to right visual order
        for j := 0 to Count-2 do // Count-2: ignore last ending item
          Append(VisualToLogical[j]);
    end;
    

    当然,这仅适用于 Windows。所以它不能在 Mac OS X 上运行。你必须在 Mac OS X 下使用另一个库...

    【讨论】:

      【解决方案3】:

      这很复杂。如果你想正确地做到这一点,你必须使用International Components for Unicode中的Bidi Library

      【讨论】:

      • 你有类似的例子吗?
      • 例如,FMX 可以包裹 ICU。这甚至可能是 FMX 团队的计划。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-18
      • 2014-04-25
      • 1970-01-01
      • 1970-01-01
      • 2014-01-04
      • 1970-01-01
      相关资源
      最近更新 更多