Uniscribe vs Pango

기본적인 과정

  • Itemize (item 분리)
  • Shape (item 별 glyph 추출)
  • Place (?)
  • Render

1. Itemize

a. Uniscribe
HRESULT ScriptItemize(
_In_     const WCHAR          *pwcInChars,
_In_           int            cInChars,
_In_           int            cMaxItems,
_In_opt_ const SCRIPT_CONTROL *psControl,
_In_opt_ const SCRIPT_STATE   *psState,
_Out_          SCRIPT_ITEM    *pItems,
_Out_          int            *pcItems
);

pItems 이 떨어지는 Item 들이고,
반환해주는 정보들인 SCRIPT_ITEM , SCRIPT_ANALYSIS, SCRIPT_STATE 은 아래와 같다.

typedef struct tag_SCRIPT_ITEM {
  int             iCharPos;
  SCRIPT_ANALYSIS a;
} SCRIPT_ITEM;
typedef struct tag_SCRIPT_ANALYSIS {
  WORD         eScript  :10;
  WORD         fRTL  :1;
  WORD         fLayoutRTL  :1;
  WORD         fLinkBefore  :1;
  WORD         fLinkAfter  :1;
  WORD         fLogicalOrder  :1;
  WORD         fNoGlyphIndex  :1;
  SCRIPT_STATE s;
} SCRIPT_ANALYSIS;
typedef struct tag_SCRIPT_STATE {
  WORD uBidiLevel  :5;
  WORD fOverrideDirection  :1;
  WORD fInhibitSymSwap  :1;
  WORD fCharShape  :1;
  WORD fDigitSubstitute  :1;
  WORD fInhibitLigate  :1;
  WORD fDisplayZWG  :1;
  WORD fArabicNumContext  :1;
  WORD fGcpClusters  :1;
  WORD fReserved  :1;
  WORD fEngineReserved  :2;
} SCRIPT_STATE;
b. Pango
GList *pango_itemize                (PangoContext      *context,
                                      const char        *text,
                                      int                start_index,
                                      int                length,
                                      PangoAttrList     *attrs,
                                      PangoAttrIterator *cached_iter);

return 값이 PangoItem 으로 떨어지고, GList 를 상속받은 놈임.

struct _PangoItem
{
  gint offset;
  gint length;
  gint num_chars;
  PangoAnalysis analysis;
};
  • PangoItem
  • @offset: byte offset of the start of this item in text.
  • @length: length of this item in bytes.
  • @num_chars: number of Unicode characters in the item.
  • @analysis: analysis results for the item.
    The PangoItem structure stores information about a segment of text.
struct _PangoAnalysis
{
  PangoEngineShape *shape_engine;
  PangoEngineLang  *lang_engine;
  PangoFont *font;

  guint8 level;
  guint8 gravity; /* PangoGravity */
  guint8 flags;

  guint8 script; /* PangoScript */
  PangoLanguage *language;

  GSList *extra_attrs;
};
  • PangoAnalysis
  • @shape_engine: the engine for doing rendering-system-dependent processing.
  • @lang_engine: the engine for doing rendering-system-independent processing.
  • @font: the font for this segment.
  • @level: the bidirectional level for this segment.
  • @gravity: the glyph orientation for this segment (A #PangoGravity).
  • @flags: boolean flags for this segment (currently only one) (Since: 1.16).
  • @script: the detected script for this segment (A #PangoScript) (Since: 1.18).
  • @language: the detected language for this segment.
  • @extra_attrs: extra attributes for this segment.
    The PangoAnalysis structure stores information about the properties of a segment of text.
c. Mapping 여부
  • escript -> script (pango script 가 1024개 보다 적어서 mapping 가능)
  • fRTL -> level을 이해하면 될듯?
  • fLayoutRTL -> 숫자의 rtl 인데 이것도 level을 이해하면 가능하려나..
  • fLinkBefore & fLinkAfter -> 불가능: item의 처음이나 마지막 글자가 이어진 item과 linking 이 되는지. pango에 정보가 없고, 어떤 언어에서 발생하는지도 모르겟음.
  • fLogicalOrder -> glyphString을 만들 때(shaping)에서 logical order로 할껀지, visual order로 할껀지. pango에서는 테스트 필요.
  • fNoGlyphIndex -> use of glyph 켜기/끄기. true면 complex script shaping도 꺼짐. bitmap, vector and device font에 사용됨. pango 에서 불가능한듯?? pangofont에서 속성을 알아보자.
  • uBidiLevel -> level
  • fOverrideDirection -> script 가 override 하는 경우도 있나보네.... 하...
  • fInhibitSymSwap -> unicode mirrored glyphs "" 이런거?
    그 외, 몇개 더 있음. 추가 할 것!
    msdn - SCRIPT_STATE 참조.
d. wine은?

분기를 엄청 태우면서, unicode 에 따라 하드코딩이 되어있는 것으로 보임. 참고 가능할 듯.

2. Shape

a. uniscribe
HRESULT ScriptShape(
  _In_          HDC             hdc,
  _Inout_       SCRIPT_CACHE    *psc,
  _In_    const WCHAR           *pwcChars,
  _In_          int             cChars,
  _In_          int             cMaxGlyphs,
  _Inout_       SCRIPT_ANALYSIS *psa,
  _Out_         WORD            *pwOutGlyphs,
  _Out_         WORD            *pwLogClust,
  _Out_         SCRIPT_VISATTR  *psva,
  _Out_         int             *pcGlyphs
);
  • script cache
  • font metric cache,
    msdn - uniscribe cache 참조
  • hdc가 없어도 cache 로 동작. ScriptShape, ScriptPlace, ScriptTextOut 에 해당 하는 내용.
  • script analysis
    • 구조는 위에 있음. 이게 어케 out 이 될 수 있는가. shape 에서 어떤걸 건드리길래?
  • Glyphs
    • 이게 주 목적이고.
  • logical clust
    • 주변 unicode character 에 따라 glyph 가 영향 받을 수 있는 것들.
    • application이 cluster 만보고도 그런 것들을 처리 할수 있게 함.
  • script visual attribute
typedef struct tag_SCRIPT_VISATTR {
  WORD uJustification  :4;
  WORD fClusterStart  :1;
  WORD fDiacritic  :1;
  WORD fZeroWidth  :1;
  WORD fReserved  :1;
  WORD fShapeReserved  :8;
} SCRIPT_VISATTR;
typedef enum tag_SCRIPT_JUSTIFY { 
  SCRIPT_JUSTIFY_NONE            = 0,
  SCRIPT_JUSTIFY_ARABIC_BLANK    = 1,
  SCRIPT_JUSTIFY_CHARACTER       = 2,
  SCRIPT_JUSTIFY_RESERVED1       = 3,
  SCRIPT_JUSTIFY_BLANK           = 4,
  SCRIPT_JUSTIFY_RESERVED2       = 5,
  SCRIPT_JUSTIFY_RESERVED3       = 6,
  SCRIPT_JUSTIFY_ARABIC_NORMAL   = 7,
  SCRIPT_JUSTIFY_ARABIC_KASHIDA  = 8,
  SCRIPT_JUSTIFY_ARABIC_ALEF     = 9,
  SCRIPT_JUSTIFY_ARABIC_HA       = 10,
  SCRIPT_JUSTIFY_ARABIC_RA       = 11,
  SCRIPT_JUSTIFY_ARABIC_BA       = 12,
  SCRIPT_JUSTIFY_ARABIC_BARA     = 13,
  SCRIPT_JUSTIFY_ARABIC_SEEN     = 14,
  SCRIPT_JUSTIFY_ARABIC_SEEN_M   = 15
} SCRIPT_JUSTIFY;
b. pango
void pango_shape (const gchar      *text,
                  gint              length,
                  const PangoAnalysis *analysis,
                  PangoGlyphString *glyphs);

3. Place

a. uniscribe
HRESULT ScriptPlace(
  _In_          HDC             hdc,
  _Inout_       SCRIPT_CACHE    *psc,
  _In_    const WORD            *pwGlyphs,
  _In_          int             cGlyphs,
  _In_    const SCRIPT_VISATTR  *psva,
  _Inout_       SCRIPT_ANALYSIS *psa,
  _Out_         int             *piAdvance,
  _Out_         GOFFSET         *pGoffset,
  _Out_         ABC             *pABC
);
  • SCRIPT_ANALYSIS
    • psa 는 ScriptPlace 에서 일부 정보를 채워주는 것 같음. 어떤 놈들을?? 실제 ms 에서 한글과 영어 테스트 결과 변화가 없는 걸 보니, 특정 언어에 필요한 정보들인 것으로 파악 됨.
  • Advance
    • advance width: glyph의 rendering 시작부터 다음 glyph의 rendering 시작점
  • GOFFSET
    • 실제로 돌려보니, du, dv 모두 0 나오는데... 뭐지. 설명에는 "x, y offset of combining glyphs"라고 되어있음
  • ABC
b. pango
void   pango_glyph_string_extents  (PangoGlyphString *glyphs,
                                     PangoFont        *font,
                                     PangoRectangle   *ink_rect,
                                     PangoRectangle   *logical_rect);

ink_rect와 logical_rect 들로 ABCwidth, advance width랑 비슷한 개념일 듯?
설명이 없어서 파악이 잘 안됨.. ㅠ

4. Rendering

a. uniscribe
HRESULT ScriptTextOut(
  _In_     const HDC             hdc,
  _Inout_        SCRIPT_CACHE    *psc,
  _In_           int             x,
  _In_           int             y,
  _In_           UINT            fuOptions,
  _In_opt_ const RECT            *lprc,
  _In_     const SCRIPT_ANALYSIS *psa,
  _In_     const WCHAR           *pwcReserved,
  _In_           int             iReserved,
  _In_     const WORD            *pwGlyphs,
  _In_           int             cGlyphs,
  _In_     const int             *piAdvance,
  _In_opt_ const int             *piJustify,
  _In_     const GOFFSET         *pGoffset
);
b. pango

pango는 여러 backend를 사용 가능함. freetype / cairo 등등.