Конвертировать LTR в RTL?

1

Как вы знаете, многие компоненты ui и инструменты dev не поддерживают rtl, мы можем назвать это flipping text, потому что результат такой же:

LTR

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

РТЛ

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

есть все равно, чтобы преобразовать этот LTR в RTL, у меня нет никакой идеи, и язык не имеет значения

На самом деле я ищу решение для этого сделать в приложении RAD Studio Firemonkey, так как вы можете знать, что приложения firemonkey не поддерживают rtl в дорожной карте студии Rad, но еще не реализованы

  • 2
    Я не думаю, что вам будет легко внедрить исправление в FMX, чтобы сделать эту работу. Возможно, это можно было бы сделать для текста, но я думаю, это будет проблемой, чтобы заставить редактирование работать. Возможно, вам придется подождать, пока FMX не будет сделано.
  • 0
    Соответствующим API Mac OS X является «ATSUI» или Apple Type Services для Unicode Imaging, а Win32 API - UNISCRIBE. Пока FMX не предоставляет библиотеку с общим API, который объединяет оба, удачи. Я уверен, что QT уже имеет это, так что, кто бы ни реализовывал это, мог изучить, как они сделали это в QT.
Теги:
uniscribe

2 ответа

4
Лучший ответ

В Windows вы можете сделать это через API UniScribe.

Я использовал это, чтобы преобразовать текст Unicode в набор глифов, для нашего автора PDF с открытым исходным кодом.

У вас есть образец исходного кода в модуле 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...

  • 0
    +1. Я понятия не имел, как это сделать, это хорошо иметь это на SO.
0

Это сложно. Если вы хотите сделать это правильно, вы должны использовать библиотеку Bidi из международных компонентов для Unicode.

  • 0
    У вас есть что-то вроде примера?
  • 0
    Таким образом, FMX может обернуть ICU, например. Это может быть даже план команды FMX.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню