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.
ThePangoItem
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.
ThePangoAnalysis
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
- ABC width 반환.
Uniscribe Glossary 참조.
- ABC width 반환.
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 등등.