From 1c79cf510fbb1dc7124e8a07cd93e16ea8a2b175 Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Thu, 28 Mar 2019 17:47:12 +0800 Subject: [PATCH] Tune the TextRunsInfo and LayoutInfo related APIs --- include/common.h | 24 +- include/gdi.h | 225 ++++++++--------- src/font/unicode-script.c | 76 +++--- src/newgdi/Makefile.am | 2 +- src/newgdi/glyph-shaped.c | 2 +- src/newgdi/layout-ellipsize.c | 4 +- src/newgdi/layout-utils.c | 94 ++++++- src/newgdi/layoutinfo.c | 77 ++++-- src/newgdi/layoutinfo.h | 26 +- src/newgdi/simple-glyph-renderer.c | 12 +- src/newgdi/textrunsinfo.c | 391 +++++++++++++++++++++-------- src/newgdi/textrunsinfo.h | 58 ++--- 12 files changed, 645 insertions(+), 346 deletions(-) diff --git a/include/common.h b/include/common.h index 5eaa1521..c5a4e83c 100644 --- a/include/common.h +++ b/include/common.h @@ -846,25 +846,28 @@ typedef DWORD32 RGBCOLOR; * \brief Makes a RGBA triple value from red \a r, green \a g, * blue \a b and alpha \a components. * - * \note The red, green, blue and alpha components are all ranged from 0 to 255, - * and the returned value will be a double word. + * \note The red, green, blue, and alpha components are all ranged + * from 0 to 255, and the returned value will be a 32-bit double word. * * \sa GetRValue, GetGValue, GetBValue, GetAValue */ -#define MakeRGBA(r, g, b, a) (((DWORD32)((BYTE)(r))) | ((DWORD32)((BYTE)(g)) << 8) \ - | ((DWORD32)((BYTE)(b)) << 16) | ((DWORD32)((BYTE)(a)) << 24)) +#define MakeRGBA(r, g, b, a) \ + (((DWORD32)((BYTE)(r))) \ + | ((DWORD32)((BYTE)(g)) << 8) \ + | ((DWORD32)((BYTE)(b)) << 16) \ + | ((DWORD32)((BYTE)(a)) << 24)) /** * \def MakeRGB(r, g, b) - * \brief Makes a RGB triple value from red \a r, green \a g, and blue \a b components. + * \brief Makes a RGB triple value from red \a r, green \a g, + * and blue \a b components. * * \note The red, green, and blue components are all ranged from 0 to 255, - * and the returned value will be a double word. + * and the returned value will be a 32-bit double word. * - * \sa GetRValue, GetGValue, GetBValue + * \sa GetRValue, GetGValue, GetBValue, GetAValue */ -#define MakeRGB(r, g, b) (((DWORD32)((BYTE)(r))) | ((DWORD32)((BYTE)(g)) << 8) \ - | ((DWORD32)((BYTE)(b)) << 16)) +#define MakeRGB(r, g, b) MakeRGBA((r), (g), (b), 255) /** * A rectangle defined by coordinates of corners. @@ -875,8 +878,7 @@ typedef DWORD32 RGBCOLOR; * * \sa PRECT, GAL_Rect */ -typedef struct _RECT -{ +typedef struct _RECT { /** * The x coordinate of the upper-left corner of the rectangle. */ diff --git a/include/gdi.h b/include/gdi.h index d26d8147..4873a8b0 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -9075,94 +9075,79 @@ typedef enum { GLYPH_RUN_DIR_RTL, GLYPH_RUN_DIR_TTB, GLYPH_RUN_DIR_BTT, - - GLYPH_RUN_DIR_NEUTRAL, - GLYPH_RUN_DIR_WEAK_LTR, - GLYPH_RUN_DIR_WEAK_RTL, } GlyphRunDir; typedef enum { - WRITING_MODE_HORIZONTAL_TTB = 0, - WRITING_MODE_HORIZONTAL_BTT, - WRITING_MODE_VERTICAL_RL, - WRITING_MODE_VERTICAL_LR, -} ParagraphWritingMode; - -#define GLYPH_GRAVITY_SOUTH 0 -#define GLYPH_GRAVITY_EAST 1 -#define GLYPH_GRAVITY_NORTH 2 -#define GLYPH_GRAVITY_WEST 3 -#define GLYPH_GRAVITY_AUTO 4 + LAYOUT_GRAVITY_SOUTH = 0, + LAYOUT_GRAVITY_EAST, + LAYOUT_GRAVITY_NORTH, + LAYOUT_GRAVITY_WEST, + LAYOUT_GRAVITY_AUTO, +} LayoutGravity; typedef enum { - GLYPH_ORIENT_UPRIGHT = GLYPH_GRAVITY_SOUTH, - GLYPH_ORIENT_SIDEWAYS = GLYPH_GRAVITY_EAST, - GLYPH_ORIENT_UPSIDE_DOWN = GLYPH_GRAVITY_NORTH, - GLYPH_ORIENT_SIDEWAYS_LEFT = GLYPH_GRAVITY_WEST, - GLYPH_ORIENT_AUTO = GLYPH_GRAVITY_AUTO, -} GlyphOrient; + LAYOUT_GRAVITY_POLICY_NATURAL, + LAYOUT_GRAVITY_POLICY_STRONG, + LAYOUT_GRAVITY_POLICY_LINE, +} LayoutGravityPolicy; -typedef enum { - GLYPH_ORIENT_POLICY_NATURAL, - GLYPH_ORIENT_POLICY_STRONG, - GLYPH_ORIENT_POLICY_LINE, -} GlyphOrientPolicy; - -#define GLYPH_ORIENT_IS_VERTICAL(orient) \ - ((orient) == GLYPH_ORIENT_SIDEWAYS || (orient) == GLYPH_ORIENT_SIDEWAYS_LEFT) +#define LAYOUT_GRAVITY_IS_VERTICAL(gravity) \ + ((gravity) == LAYOUT_GRAVITY_EAST || (gravity) == LAYOUT_GRAVITY_WEST) /** Get the vertical orientation property of a Unicode character */ MG_EXPORT UVerticalOrient GUIAPI UCharGetVerticalOrientation(Uchar32 uc); /** - * ScriptGetGlyphOrientation: - * @script: #ScriptType to query - * @base_orient: base orientation of the paragraph - * @policy: orientation policy + * \fn LayoutGravity GUIAPI ScriptGetLayoutGravity(ScriptType script, + * LayoutGravity base_gravity, LayoutGravityPolicy policy) + * \brief Based on the script, base gravity, and policy, returns actual gravity + * to use in laying out a single glyph run. * - * Based on the script, base orientation, and policy, returns actual orientation - * to use in laying out a single glyph run. - * - * If @base_orient is %GLYPH_ORIENT_AUTO, it is first replaced with the + * If @base_orient is %LAYOUT_GRAVITY_AUTO, it is first replaced with the * preferred orientation of @script. To get the preferred orientation of a script, - * pass %GLYPH_ORIENT_AUTO and %GLYPH_ORIENT_POLICY_STRONG in. + * pass %LAYOUT_GRAVITY_AUTO and %LAYOUT_GRAVITY_POLICY_STRONG in. * - * Return value: resolved orientation suitable to use for a run of text + * \param script The script type to query + * \param base_gravity The base gravity of the paragraph/layout + * \param policy The gravity policy + * + * \param The resolved gravity suitable to use for a layout run of text * with @script. * * Since: 3.4.0 */ -MG_EXPORT GlyphOrient GUIAPI ScriptGetGlyphOrientation (ScriptType script, - GlyphOrient base_orient, GlyphOrientPolicy policy); +MG_EXPORT LayoutGravity GUIAPI ScriptGetLayoutGravity(ScriptType script, + LayoutGravity base_gravity, LayoutGravityPolicy policy); /** - * GetWideGlyphOrientationForScript: - * @script: #ScriptType to query - * @wide: %TRUE for wide characters as returned by IsUCharWide() - * @base_orient: base orientation of the paragraph - * @policy: orientation policy + * \fn LayoutGravity GUIAPI ScriptGetLayoutGravityForWide (ScriptType script, + * BOOL wide, LayoutGravity base_gravity, LayoutGravityPolicy policy) + * \brief Based on the script, East Asian width, base gravity, and policy, + * returns the actual gravity to use in laying out a single character + * or a run of text. * - * Based on the script, East Asian width, base orientation, and policy, - * returns actual orientation to use in laying out a single character - * or a run of glyph. - * - * This function is similar to ScriptGetGlyphOrientation() except + * This function is similar to ScriptGetLayoutGravity() except * that this function makes a distinction between narrow/half-width and * wide/full-width characters also. Wide/full-width characters always - * stand upright, that is, they always take the - * base orientation, whereas narrow/full-width characters are always + * stand upright, that is, they always take the + * base gravity, whereas narrow/half-width characters are always * rotated in vertical context. * - * If @base_orient is %GLYPH_ORIENT_AUTO, it is first replaced with the - * preferred orientation of @script. + * If @base_orient is %LAYOUT_GRAVITY_AUTO, it is first replaced with the + * preferred gravity of @script. * - * Return value: resolved orientation suitable to use for a run of text - * with @script and @wide. + * \param script The script type to query + * \param wide TRUE for wide characters as returned by IsUCharWide() + * \param base_gravity The base gravity of the paragraph + * \param policy The gravity policy + * + * \return The resolved gravity suitable to use for a run of text + * with \a script and \a wide. * * Since: 3.4.0 */ -GlyphOrient GetWideGlyphOrientationForScript (ScriptType script, - BOOL wide, GlyphOrient base_orient, GlyphOrientPolicy policy); +LayoutGravity ScriptGetLayoutGravityForWide (ScriptType script, + BOOL wide, LayoutGravity base_gravity, LayoutGravityPolicy policy); /** @} end of unicode_ops */ @@ -12196,32 +12181,40 @@ MG_EXPORT int GUIAPI UChars2AChars(LOGFONT* logfont, const Uchar32* ucs, #define GRF_WRITING_MODE_MASK 0xF0000000 /** - * Top-to-bottom direction. + * Top-to-bottom horizontal direction. * Both the writing mode and the typographic mode are horizontal. */ #define GRF_WRITING_MODE_HORIZONTAL_TB 0x00000000 /** - * Right-to-left direction. - * Both the writing mode and the typographic mode are vertical. + * Bottom-to-top horizontal direction. + * Both the writing mode and the typographic mode are horizontal, + * but lines are generated from bottom to top. */ -#define GRF_WRITING_MODE_VERTICAL_RL 0x10000000 +#define GRF_WRITING_MODE_HORIZONTAL_BT 0x10000000 /** - * Left-to-right direction. - * Both the writing mode and the typographic mode are vertical. + * Right-to-left vertical direction. + * Both the writing mode and the typographic mode are vertical, + * but the lines are generated from right to left. */ -#define GRF_WRITING_MODE_VERTICAL_LR 0x20000000 +#define GRF_WRITING_MODE_VERTICAL_RL 0x20000000 +/** + * Left-to-right vertical direction. + * Both the writing mode and the typographic mode are vertical. + * but the lines are generated from left to right. + */ +#define GRF_WRITING_MODE_VERTICAL_LR 0x30000000 -#define GRF_TEXT_ORIENTATION_MASK 0x0F000000 +#define GRF_TEXT_ORIENTATION_MASK 0x0F000000 /** * The glyphs are individually typeset upright in * vertical lines with vertical font metrics. */ -#define GRF_TEXT_ORIENTATION_UPRIGHT 0x00000000 +#define GRF_TEXT_ORIENTATION_UPRIGHT 0x00000000 /** * The glyphs typeset a run rotated 90° clockwise * from their upright orientation. */ -#define GRF_TEXT_ORIENTATION_SIDEWAYS 0x01000000 +#define GRF_TEXT_ORIENTATION_SIDEWAYS 0x01000000 /** * The glyphs are individually typeset upside down in * vertical lines with vertical font metrics. @@ -12236,7 +12229,7 @@ MG_EXPORT int GUIAPI UChars2AChars(LOGFONT* logfont, const Uchar32* ucs, * In vertical writing modes, all typographic character units * keep in their intrinsic orientation. */ -#define GRF_TEXT_ORIENTATION_AUTO 0x04000000 +#define GRF_TEXT_ORIENTATION_AUTO 0x04000000 /** * In vertical writing modes, typographic character units from * horizontal-only scripts are typeset sideways, i.e. 90° clockwise @@ -12244,7 +12237,7 @@ MG_EXPORT int GUIAPI UChars2AChars(LOGFONT* logfont, const Uchar32* ucs, * Typographic character units from vertical scripts are * typeset with their intrinsic orientation. */ -#define GRF_TEXT_ORIENTATION_MIXED 0x05000000 +#define GRF_TEXT_ORIENTATION_MIXED 0x05000000 #define GRF_OVERFLOW_WRAP_MASK 0x00F00000 /** @@ -12384,10 +12377,12 @@ MG_EXPORT int GUIAPI UChars2AChars(LOGFONT* logfont, const Uchar32* ucs, /** @} end of glyph_render_flags */ -#define GLYPH_ORIENTATION_UPRIGHT GLYPH_GRAVITY_SOUTH -#define GLYPH_ORIENTATION_SIDEWAYS GLYPH_GRAVITY_EAST -#define GLYPH_ORIENTATION_UPSIDE_DOWN GLYPH_GRAVITY_NORTH -#define GLYPH_ORIENTATION_SIDEWAYS_LEFT GLYPH_GRAVITY_WEST +typedef enum { + GLYPH_ORIENT_UPRIGHT, + GLYPH_ORIENT_SIDEWAYS, + GLYPH_ORIENT_UPSIDE_DOWN, + GLYPH_ORIENT_SIDEWAYS_LEFT, +} GlyphOrient; #define GLYPH_HANGED_NONE 0 #define GLYPH_HANGED_START 1 @@ -12415,13 +12410,13 @@ typedef struct _GLYPHEXTINFO { Uint8 whitespace:1; /** * The orientation of the glyph; can be one of the following values: - * - GLYPH_ORIENTATION_UPRIGHT\n + * - GLYPH_ORIENT_UPRIGHT\n * the glyph is in the standard horizontal orientation. - * - GLYPH_ORIENTATION_SIDEWAYS\n + * - GLYPH_ORIENT_SIDEWAYS\n * the glyph rotates 90° clockwise from horizontal. - * - GLYPH_ORIENTATION_SIDEWAYS_LEFT\n + * - GLYPH_ORIENT_SIDEWAYS_LEFT\n * the glyph rotates 90° counter-clockwise from horizontal. - * - GLYPH_ORIENTATION_INVERTED\n + * - GLYPH_ORIENT_UPSIDE_DOWN\n * the glyph is in the inverted horizontal orientation. */ Uint8 orientation:2; @@ -12465,13 +12460,13 @@ typedef struct _GLYPHPOS { Uint8 ellipsis:1; /** * The orientation of the glyph; can be one of the following values: - * - GLYPH_ORIENTATION_UPRIGHT\n + * - GLYPH_ORIENT_UPRIGHT\n * the glyph is in the standard horizontal orientation. - * - GLYPH_ORIENTATION_SIDEWAYS\n + * - GLYPH_ORIENT_SIDEWAYS\n * the glyph rotates 90° clockwise from horizontal. - * - GLYPH_ORIENTATION_SIDEWAYS_LEFT\n + * - GLYPH_ORIENT_SIDEWAYS_LEFT\n * the glyph rotates 90° counter-clockwise from horizontal. - * - GLYPH_ORIENTATION_UPSIDE_DOWN\n + * - GLYPH_ORIENT_UPSIDE_DOWN\n * the glyph is upside down. */ Uint8 orientation:2; @@ -12607,9 +12602,8 @@ typedef struct _TEXTRUNSINFO TEXTRUNSINFO; /** * \fn TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(const Uchar32* ucs, int nr_ucs, - * LanguageCode lang_code, ParagraphDir base_dir, GlyphRunDir run_dir, - * GlyphOrient glyph_orient, GlyphOrientPolicy orient_policy, - * const char* logfont_name, RGBCOLOR color, + * LanguageCode lang_code, ParagraphDir base_dir, + * const char* logfont_name, RGBCOLOR color, RGBCOLOR bg_color, * BreakOppo* break_oppos) * * \brief Split a Uchar32 paragraph string in mixed scripts into text runs. @@ -12619,16 +12613,16 @@ typedef struct _TEXTRUNSINFO TEXTRUNSINFO; * * \param ucs The Uchar32 string returned by \a GetUCharsUntilParagraphBoundary. * \param nr_ucs The length of the Uchar32 string. - * \param * \param lang_code The language code. * \param base_dir The base direction of the paragraph. - * \param run_dir The writing direction of the paragraph. - * \param glyph_orient The glyph orientation. - * \param orient_policy THe glyph orientation policy of the paragraph. * \param logfont_name The default logfont name. You can change the font * of some text in the paragraph by calling \a SetFontInTextRuns. * \param color The default text color. You can change the text color - * of some text in the paragraph by calling \a SetTextColorInTextRuns + * of some text in the paragraph by calling \a SetTextColorInTextRuns. + * \param bg_color The default background color. You can change the background + * color of some text in the paragraph by calling + * \a SetBackgroundColorInTextRuns. If the background is transparent, + * please pass MakeRGBA(0,0,0,0) for this argument. * \param break_oppos If not NULL, the break opportunities will be tailored * according to the script type of every text run. Please skip the first * entry when you pass the pointer. @@ -12644,35 +12638,35 @@ typedef struct _TEXTRUNSINFO TEXTRUNSINFO; * \sa GetUCharsUntilParagraphBoundary, UStrGetBreaks, * SetFontInTextRuns, SetTextColorInTextRuns */ -MG_EXPORT TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(const Uchar32* ucs, int nr_ucs, - LanguageCode lang_code, ParagraphDir base_dir, GlyphRunDir run_dir, - GlyphOrient glyph_orient, GlyphOrientPolicy orient_policy, - const char* logfont_name, RGBCOLOR color, +MG_EXPORT TEXTRUNSINFO* GUIAPI CreateTextRunsInfo( + const Uchar32* ucs, int nr_ucs, + LanguageCode lang_code, ParagraphDir base_dir, + const char* logfont_name, RGBCOLOR color, RGBCOLOR bg_color, BreakOppo* break_oppos); /** - * Set logfont of text runs + * Set logfont name of text runs */ -MG_EXPORT BOOL GUIAPI SetFontInTextRuns(TEXTRUNSINFO* truninfo, - int start_index, int length, const char* logfont_name); +MG_EXPORT BOOL GUIAPI SetFontNameInTextRuns(TEXTRUNSINFO* truninfo, + int start_index, int length, const char* logfont_name); + +/** + * Get logfont name of a specific character in text runs + */ +MG_EXPORT const char* GUIAPI GetFontNameInTextRuns( + const TEXTRUNSINFO* truninfo, int index); /** * Set text olor in text runs. */ MG_EXPORT BOOL GUIAPI SetTextColorInTextRuns(TEXTRUNSINFO* truninfo, - int start_index, int length, RGBCOLOR color); + int start_index, int length, RGBCOLOR color); /** - * Set underline color in text runs. + * Get text color of a specific character in text runs */ -MG_EXPORT BOOL GUIAPI SetUnderlineColorInTextRuns(TEXTRUNSINFO* truninfo, - int start_index, int length, RGBCOLOR color); - -/** - * Set strikethrough color in text runs. - */ -MG_EXPORT BOOL GUIAPI SetStrikethroughColorInTextRuns(TEXTRUNSINFO* truninfo, - int start_index, int length, RGBCOLOR color); +MG_EXPORT RGBCOLOR GUIAPI GetTextColorInTextRuns( + const TEXTRUNSINFO* truninfo, int index); /** * Set background color in text runs. @@ -12681,10 +12675,10 @@ MG_EXPORT BOOL GUIAPI SetBackgroundColorInTextRuns(TEXTRUNSINFO* truninfo, int start_index, int length, RGBCOLOR color); /** - * Set outline color in text runs. + * Get background color of a specific character in text runs */ -MG_EXPORT BOOL GUIAPI SetOutlineColorInTextRuns(TEXTRUNSINFO* truninfo, - int start_index, int length, RGBCOLOR color); +MG_EXPORT RGBCOLOR GUIAPI GetBackgroundColorInTextRuns( + const TEXTRUNSINFO* truninfo, int index); /** * \fn BOOL GUIAPI DestroyTextRunsInfo(TEXTRUNSINFO* truninfo) @@ -12886,12 +12880,13 @@ MG_EXPORT int DrawLayoutLine(HDC hdc, LAYOUTLINE* line, int x, int y, RECT* rc_bouding); #ifdef _MGDEVEL_MODE -void* GetNextTextRunInfo(TEXTRUNSINFO* runinfo, - void* prev, +typedef struct _TextRun TEXTRUN; + +MG_EXPORT TEXTRUN* GetNextTextRunInfo(TEXTRUNSINFO* runinfo, + TEXTRUN* prev, const char** fontname, int* start_index, int* length, LanguageCode* lang_code, ScriptType* script, - BidiLevel* embedding_level, GlyphRunDir* run_dir, - GlyphOrient* orient, Uint8* flags); + BidiLevel* embedding_level, Uint8* flags); /* Get layout line information */ MG_EXPORT BOOL GUIAPI GetLayoutLineInfo(LAYOUTLINE* line, diff --git a/src/font/unicode-script.c b/src/font/unicode-script.c index 92b0c309..1b37ba1b 100644 --- a/src/font/unicode-script.c +++ b/src/font/unicode-script.c @@ -386,21 +386,27 @@ ScriptType GUIAPI NormalizeScriptType(LanguageCode cl, return ws; } +typedef enum { + HORIZONTAL_DIRECTION_LTR, + HORIZONTAL_DIRECTION_RTL, + HORIZONTAL_DIRECTION_WEAK, +} HorizontalDirection; + typedef enum { VERTICAL_DIRECTION_NONE, VERTICAL_DIRECTION_TTB, - VERTICAL_DIRECTION_BTT + VERTICAL_DIRECTION_BTT, } VerticalDirection; typedef struct { /* GlyphRunDir */ Uint8 horiz_dir; /* Orientation in horizontal context */ - /* PangoVerticalDirection */ + /* VerticalDirection */ Uint8 vert_dir; /* Orientation in vertical context */ - /* GlyphOrient */ - Uint8 preferred_orient; /* Preferred context orientation */ + /* LayoutGravity */ + Uint8 preferred_gravity; /* Preferred context gravity */ /* BOOL */ Uint8 wide; /* Whether script is mostly wide. @@ -412,13 +418,13 @@ typedef struct { #define TTB VERTICAL_DIRECTION_TTB #define BTT VERTICAL_DIRECTION_BTT -#define LTR GLYPH_RUN_DIR_LTR -#define RTL GLYPH_RUN_DIR_RTL -#define WEAK GLYPH_RUN_DIR_WEAK_LTR +#define LTR HORIZONTAL_DIRECTION_LTR +#define RTL HORIZONTAL_DIRECTION_RTL +#define WEAK HORIZONTAL_DIRECTION_WEAK -#define S GLYPH_ORIENT_UPRIGHT -#define E GLYPH_ORIENT_SIDEWAYS -#define W GLYPH_ORIENT_SIDEWAYS_LEFT +#define S LAYOUT_GRAVITY_SOUTH +#define E LAYOUT_GRAVITY_EAST +#define W LAYOUT_GRAVITY_WEST #define UNKNOWN_SCRIPT_PROPERTY \ {LTR, NONE, S, FALSE} @@ -627,61 +633,61 @@ static inline ScriptTypeProperties get_script_properties (ScriptType script) return script_properties[script]; } -GlyphOrient ScriptGetGlyphOrientation (ScriptType script, - GlyphOrient base_orient, GlyphOrientPolicy hint) +LayoutGravity ScriptGetLayoutGravity (ScriptType script, + LayoutGravity base_gravity, LayoutGravityPolicy hint) { ScriptTypeProperties props = get_script_properties (script); - if (base_orient == GLYPH_ORIENT_AUTO) - base_orient = props.preferred_orient; + if (base_gravity == LAYOUT_GRAVITY_AUTO) + base_gravity = props.preferred_gravity; - return GetWideGlyphOrientationForScript (script, props.wide, - base_orient, hint); + return ScriptGetLayoutGravityForWide (script, props.wide, + base_gravity, hint); } -GlyphOrient GetWideGlyphOrientationForScript (ScriptType script, - BOOL wide, GlyphOrient base_orient, GlyphOrientPolicy hint) +LayoutGravity ScriptGetLayoutGravityForWide (ScriptType script, + BOOL wide, LayoutGravity base_gravity, LayoutGravityPolicy hint) { ScriptTypeProperties props = get_script_properties (script); BOOL vertical; - if (base_orient == GLYPH_ORIENT_AUTO) - base_orient = props.preferred_orient; + if (base_gravity == LAYOUT_GRAVITY_AUTO) + base_gravity = props.preferred_gravity; - vertical = GLYPH_ORIENT_IS_VERTICAL(base_orient); + vertical = LAYOUT_GRAVITY_IS_VERTICAL(base_gravity); /* Everything is designed such that a system with no vertical support * renders everything correctly horizontally. So, if not in a vertical - * orientation, base and resolved gravities are always the same. + * gravity, base and resolved gravities are always the same. * * Wide characters are always upright. */ if (!vertical || wide) - return base_orient; + return base_gravity; - /* If here, we have a narrow character in a vertical orientation setting. + /* If here, we have a narrow character in a vertical gravity setting. * Resolve depending on the hint. */ switch (hint) { default: - case GLYPH_ORIENT_POLICY_NATURAL: + case LAYOUT_GRAVITY_POLICY_NATURAL: if (props.vert_dir == VERTICAL_DIRECTION_NONE) - return GLYPH_ORIENT_UPRIGHT; - if ((base_orient == GLYPH_ORIENT_SIDEWAYS) ^ + return LAYOUT_GRAVITY_SOUTH; + if ((base_gravity == LAYOUT_GRAVITY_EAST) ^ (props.vert_dir == VERTICAL_DIRECTION_BTT)) - return GLYPH_ORIENT_UPRIGHT; + return LAYOUT_GRAVITY_SOUTH; else - return GLYPH_ORIENT_UPSIDE_DOWN; + return LAYOUT_GRAVITY_NORTH; - case GLYPH_ORIENT_POLICY_STRONG: - return base_orient; + case LAYOUT_GRAVITY_POLICY_STRONG: + return base_gravity; - case GLYPH_ORIENT_POLICY_LINE: - if ((base_orient == GLYPH_ORIENT_SIDEWAYS) ^ + case LAYOUT_GRAVITY_POLICY_LINE: + if ((base_gravity == LAYOUT_GRAVITY_EAST) ^ (props.horiz_dir == GLYPH_RUN_DIR_RTL)) - return GLYPH_ORIENT_UPRIGHT; + return LAYOUT_GRAVITY_SOUTH; else - return GLYPH_ORIENT_UPSIDE_DOWN; + return LAYOUT_GRAVITY_NORTH; } } #endif /* _MGCHARSET_UNICODE */ diff --git a/src/newgdi/Makefile.am b/src/newgdi/Makefile.am index 0994bedd..480182c0 100644 --- a/src/newgdi/Makefile.am +++ b/src/newgdi/Makefile.am @@ -19,7 +19,7 @@ SRC_FILES = gdi.c attr.c clip.c map.c coor.c rect.c \ simple-glyph-renderer.c glyph-shaped.c \ textrunsinfo.c \ shape-glyphs-basic.c shape-glyphs-complex.c \ - layout-utils.c layout-ellipsize.c layoutinfo.c + layoutinfo.c layout-utils.c layout-ellipsize.c endif HDR_FILES = glyph.h drawtext.h mi.h midc.h mistruct.h miwideline.h \ diff --git a/src/newgdi/glyph-shaped.c b/src/newgdi/glyph-shaped.c index 269ccf03..e5f2f56e 100644 --- a/src/newgdi/glyph-shaped.c +++ b/src/newgdi/glyph-shaped.c @@ -93,7 +93,7 @@ int GUIAPI DrawShapedGlyphString(HDC hdc, Glyph32 gv = shaped_glyphs->cb_get_glyph_info( shaped_glyphs->shaping_engine, shaped_glyphs->glyph_infos, i, NULL); - if (glyph_pos[i].orientation == GLYPH_ORIENTATION_UPRIGHT) { + if (glyph_pos[i].orientation == GLYPH_ORIENT_UPRIGHT) { if (logfont_upright) SelectFont(hdc, logfont_upright); else diff --git a/src/newgdi/layout-ellipsize.c b/src/newgdi/layout-ellipsize.c index 4a499ac8..50949ef1 100644 --- a/src/newgdi/layout-ellipsize.c +++ b/src/newgdi/layout-ellipsize.c @@ -339,7 +339,7 @@ static void shape_ellipsis (EllipsizeState *state) ellipsis_ucs = _ellipsis_baseline; } - text_run = __mg_text_run_get_by_offset(state->layout->truninfo, + text_run = __mg_text_run_get_by_offset_const(state->layout->truninfo, state->gap_start_iter.run_iter.start_index, NULL); layout_run = __mg_layout_run_new_ellipsis (state->layout, text_run, @@ -384,7 +384,7 @@ static void update_ellipsis_shape (EllipsizeState *state) BOOL is_cjk; const TextRun* text_run; - text_run = __mg_text_run_get_by_offset(state->layout->truninfo, + text_run = __mg_text_run_get_by_offset_const(state->layout->truninfo, state->gap_start_iter.run_iter.start_index, NULL); if (state->fontname != text_run->fontname) { diff --git a/src/newgdi/layout-utils.c b/src/newgdi/layout-utils.c index d467891f..a2c5b647 100644 --- a/src/newgdi/layout-utils.c +++ b/src/newgdi/layout-utils.c @@ -124,6 +124,72 @@ void __mg_release_logfont_for_layout(const LAYOUTINFO* layout, ReleaseRes(Str2Key(my_fontname)); } +static GlyphOrient resolve_glyph_orient(const LAYOUTINFO* layout, + const TextRun* trun) +{ + LayoutGravity gravity; + + if (layout->grv_plc == LAYOUT_GRAVITY_POLICY_STRONG) { + return layout->orient; + } + + gravity = ScriptGetLayoutGravityForWide(trun->st, + trun->flags & TEXTRUN_FLAG_UPRIGHT, + layout->grv_base, layout->grv_plc); + switch (gravity) { + case LAYOUT_GRAVITY_SOUTH: + return GLYPH_ORIENT_UPRIGHT; + case LAYOUT_GRAVITY_EAST: + return GLYPH_ORIENT_SIDEWAYS; + case LAYOUT_GRAVITY_NORTH: + return GLYPH_ORIENT_SIDEWAYS_LEFT; + case LAYOUT_GRAVITY_WEST: + return GLYPH_ORIENT_UPSIDE_DOWN; + default: + break; + } + + return GLYPH_ORIENT_UPRIGHT; +} + +static void resolve_layout_run_dir(const LAYOUTINFO* layout, + LayoutRun* lrun) +{ + /* The level vs. gravity dance: + * If gravity is SOUTH, leave level untouched. + * If gravity is NORTH, step level one up, to + * not get mirrored upside-down text. + * If gravity is EAST, step up to an even level, as + * it's a clockwise-rotated layout, so the rotated + * top is unrotated left. + * If gravity is WEST, step up to an odd level, as + * it's a counter-clockwise-rotated layout, so the rotated + * top is unrotated right. + */ + switch (layout->grv_base) { + case LAYOUT_GRAVITY_SOUTH: + default: + lrun->dir = (lrun->el & 1) ? GLYPH_RUN_DIR_RTL : GLYPH_RUN_DIR_LTR; + break; + case LAYOUT_GRAVITY_NORTH: + lrun->el++; + lrun->dir = (lrun->el & 1) ? GLYPH_RUN_DIR_RTL : GLYPH_RUN_DIR_LTR; + break; + case LAYOUT_GRAVITY_EAST: + lrun->el += 1; + lrun->el &= ~1; + lrun->dir = (lrun->el & 1) ? GLYPH_RUN_DIR_TTB : GLYPH_RUN_DIR_BTT; + break; + case LAYOUT_GRAVITY_WEST: + lrun->el |= 1; + lrun->dir = (lrun->el & 1) ? GLYPH_RUN_DIR_TTB : GLYPH_RUN_DIR_BTT; + break; + } + + if (LAYOUT_GRAVITY_IS_VERTICAL(layout->grv_base)) + lrun->flags |= LAYOUTRUN_FLAG_CENTERED_BASELINE; +} + /* * Not like Pango, we simply use the properties of the referenced TextRun * for the new orphan LayoutRun, including the direction, the orientation, @@ -136,10 +202,12 @@ void __mg_release_logfont_for_layout(const LAYOUTINFO* layout, LayoutRun* __mg_layout_run_new_ellipsis(const LAYOUTINFO* layout, const TextRun* trun, const Uchar32* ucs, int nr_ucs) { + GlyphOrient ort; LOGFONT* lf; LayoutRun* lrun; - lf = __mg_create_logfont_for_layout(layout, trun->fontname, trun->ort); + ort = resolve_glyph_orient(layout, trun); + lf = __mg_create_logfont_for_layout(layout, trun->fontname, ort); if (lf == NULL) return NULL; @@ -151,20 +219,22 @@ LayoutRun* __mg_layout_run_new_ellipsis(const LAYOUTINFO* layout, lrun->lc = trun->lc; lrun->st = UCharGetScriptType(ucs[0]); lrun->el = trun->el; - lrun->dir = trun->dir; - lrun->ort = trun->ort; + lrun->ort = ort; lrun->flags = trun->flags | LAYOUTRUN_FLAG_ELLIPSIS; + resolve_layout_run_dir(layout, lrun); return lrun; } LayoutRun* __mg_layout_run_new_from(const LAYOUTINFO* layout, const TextRun* trun) { + GlyphOrient ort; LOGFONT* lf; LayoutRun* lrun; - lf = __mg_create_logfont_for_layout(layout, trun->fontname, trun->ort); + ort = resolve_glyph_orient(layout, trun); + lf = __mg_create_logfont_for_layout(layout, trun->fontname, ort); if (lf == NULL) return NULL; @@ -176,26 +246,28 @@ LayoutRun* __mg_layout_run_new_from(const LAYOUTINFO* layout, lrun->lc = trun->lc; lrun->st = trun->st; lrun->el = trun->el; - lrun->dir = trun->dir; - lrun->ort = trun->ort; + lrun->ort = ort; lrun->flags = trun->flags; + resolve_layout_run_dir(layout, lrun); return lrun; } LayoutRun* __mg_layout_run_new_from_offset(const LAYOUTINFO* layout, const TextRun* trun, int offset) { + GlyphOrient ort; LOGFONT* lf; LayoutRun* lrun; if (offset >= trun->len) { - _DBG_PRINTF("%s: offset(%d) >= trun->len(%p, %d)\n", - __FUNCTION__, offset, trun, trun->len); + _WRN_PRINTF("offset(%d) >= trun->len(%p, %d)", + offset, trun, trun->len); return NULL; } - lf = __mg_create_logfont_for_layout(layout, trun->fontname, trun->ort); + ort = resolve_glyph_orient(layout, trun); + lf = __mg_create_logfont_for_layout(layout, trun->fontname, ort); if (lf == NULL) return NULL; @@ -208,10 +280,10 @@ LayoutRun* __mg_layout_run_new_from_offset(const LAYOUTINFO* layout, lrun->lc = trun->lc; lrun->st = trun->st; lrun->el = trun->el; - lrun->dir = trun->dir; - lrun->ort = trun->ort; + lrun->ort = ort; lrun->flags = trun->flags; + resolve_layout_run_dir(layout, lrun); return lrun; } diff --git a/src/newgdi/layoutinfo.c b/src/newgdi/layoutinfo.c index 43ed8eaa..96c364ec 100644 --- a/src/newgdi/layoutinfo.c +++ b/src/newgdi/layoutinfo.c @@ -106,6 +106,49 @@ LAYOUTINFO* GUIAPI CreateLayoutInfo( INIT_LIST_HEAD(&layout->lines); layout->nr_left_ucs = truninfo->nr_ucs; + switch (render_flags & GRF_WRITING_MODE_MASK) { + default: + case GRF_WRITING_MODE_HORIZONTAL_TB: + layout->grv_base = LAYOUT_GRAVITY_SOUTH; + break; + case GRF_WRITING_MODE_HORIZONTAL_BT: + layout->grv_base = LAYOUT_GRAVITY_NORTH; + break; + case GRF_WRITING_MODE_VERTICAL_RL: + layout->grv_base = LAYOUT_GRAVITY_WEST; + break; + case GRF_WRITING_MODE_VERTICAL_LR: + layout->grv_base = LAYOUT_GRAVITY_EAST; + break; + } + + switch (render_flags & GRF_TEXT_ORIENTATION_MASK) { + case GRF_TEXT_ORIENTATION_AUTO: + layout->grv_plc = LAYOUT_GRAVITY_POLICY_NATURAL; + layout->orient = GLYPH_ORIENT_UPRIGHT; + break; + case GRF_TEXT_ORIENTATION_MIXED: + layout->grv_plc = LAYOUT_GRAVITY_POLICY_LINE; + layout->orient = GLYPH_ORIENT_UPRIGHT; + break; + case GRF_TEXT_ORIENTATION_UPRIGHT: + layout->grv_plc = LAYOUT_GRAVITY_POLICY_STRONG; + layout->orient = GLYPH_ORIENT_UPRIGHT; + break; + case GRF_TEXT_ORIENTATION_SIDEWAYS: + layout->grv_plc = LAYOUT_GRAVITY_POLICY_STRONG; + layout->orient = GLYPH_ORIENT_SIDEWAYS; + break; + case GRF_TEXT_ORIENTATION_UPSIDE_DOWN: + layout->grv_plc = LAYOUT_GRAVITY_POLICY_STRONG; + layout->orient = GLYPH_ORIENT_UPSIDE_DOWN; + break; + case GRF_TEXT_ORIENTATION_SIDEWAYS_LEFT: + layout->grv_plc = LAYOUT_GRAVITY_POLICY_STRONG; + layout->orient = GLYPH_ORIENT_SIDEWAYS_LEFT; + break; + } + layout->persist = persist_lines ? 1 : 0; return layout; @@ -165,7 +208,7 @@ struct _LayoutState { /* maintained per paragraph */ // Current resolved base direction - GlyphRunDir base_dir; + ParagraphDir base_dir; // Line of the paragraph, starting at 1 for first line int line_of_par; // Glyphs for the current glyph run @@ -536,7 +579,7 @@ static inline void print_line_runs(const LAYOUTLINE* line, const char* func) _DBG_PRINTF(" LENGHT: %d\n", run->lrun->len); _DBG_PRINTF(" EMBEDDING LEVEL:%d\n", run->lrun->el); _DBG_PRINTF(" NO SHAPING :%s\n", - (run->lrun->flags & LAYOUTRUN_FLAG_NO_SHAPING) ? "YES" : "NO"); + (run->lrun->noshape) ? "YES" : "NO"); _DBG_PRINTF(" NR GLYPHS: %d\n", run->gstr->nr_glyphs); j++; } @@ -861,17 +904,17 @@ static LAYOUTLINE *layout_line_new(LAYOUTINFO *layout) /* The resolved direction for the line is always one * of LTR/RTL; not a week or neutral directions */ -static void line_set_resolved_dir(LAYOUTLINE *line, GlyphRunDir direction) +static void line_set_resolved_dir(LAYOUTLINE *line, ParagraphDir direction) { switch (direction) { default: - case GLYPH_RUN_DIR_LTR: - case GLYPH_RUN_DIR_WEAK_LTR: - case GLYPH_RUN_DIR_NEUTRAL: + case BIDI_PGDIR_LTR: + case BIDI_PGDIR_WLTR: + case BIDI_PGDIR_ON: line->resolved_dir = GLYPH_RUN_DIR_LTR; break; - case GLYPH_RUN_DIR_RTL: - case GLYPH_RUN_DIR_WEAK_RTL: + case BIDI_PGDIR_RTL: + case BIDI_PGDIR_WRTL: line->resolved_dir = GLYPH_RUN_DIR_RTL; break; } @@ -889,20 +932,20 @@ static void line_set_resolved_dir(LAYOUTLINE *line, GlyphRunDir direction) * A similar dance is performed in textrunsinfo.c: * state_add_character(). Keep in sync. */ - switch (line->layout->truninfo->ort_rsv) { + switch (line->layout->grv_base) { default: - case GLYPH_GRAVITY_AUTO: - case GLYPH_GRAVITY_SOUTH: + case LAYOUT_GRAVITY_AUTO: + case LAYOUT_GRAVITY_SOUTH: break; - case GLYPH_GRAVITY_NORTH: + case LAYOUT_GRAVITY_NORTH: line->resolved_dir = GLYPH_RUN_DIR_LTR + GLYPH_RUN_DIR_RTL - line->resolved_dir; break; - case GLYPH_GRAVITY_EAST: + case LAYOUT_GRAVITY_EAST: line->resolved_dir = GLYPH_RUN_DIR_LTR; break; - case GLYPH_GRAVITY_WEST: + case LAYOUT_GRAVITY_WEST: line->resolved_dir = GLYPH_RUN_DIR_RTL; break; } @@ -1609,7 +1652,7 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state) state->remaining_width = break_remaining_width; /* determine start text run again */ - state->trun = __mg_text_run_get_by_offset(layout->truninfo, + state->trun = __mg_text_run_get_by_offset_const(layout->truninfo, state->start_offset, &state->start_index_in_trun); if (state->start_index_in_trun > 0) { state->lrun = __mg_layout_run_new_from_offset(layout, @@ -1744,7 +1787,7 @@ LAYOUTLINE* GUIAPI LayoutNextLine( //state.shape_ink_rect; //state.shape_logical_rect; - state.base_dir = layout->truninfo->run_dir; + state.base_dir = layout->truninfo->base_dir; state.line_of_par = 1; state.glyphs = NULL; state.log_widths = NULL; @@ -1766,7 +1809,7 @@ LAYOUTLINE* GUIAPI LayoutNextLine( state.line_start_index = layout->truninfo->nr_ucs - layout->nr_left_ucs; state.start_offset = state.line_start_index; state.start_index_in_trun = 0; - state.trun = __mg_text_run_get_by_offset(layout->truninfo, + state.trun = __mg_text_run_get_by_offset_const(layout->truninfo, state.line_start_index, &state.start_index_in_trun); _DBG_PRINTF("%s: line_start_index: %d, start_index_in_trun: %d(%p)\n", diff --git a/src/newgdi/layoutinfo.h b/src/newgdi/layoutinfo.h index 52434149..f726fab3 100644 --- a/src/newgdi/layoutinfo.h +++ b/src/newgdi/layoutinfo.h @@ -65,22 +65,23 @@ struct _GlyphString { unsigned int space; }; -#define LAYOUTRUN_FLAG_CENTERED_BASELINE TEXTRUN_FLAG_CENTERED_BASELINE #define LAYOUTRUN_FLAG_NO_SHAPING TEXTRUN_FLAG_NO_SHAPING +#define LAYOUTRUN_FLAG_UPRIGHT TEXTRUN_FLAG_UPRIGHT #define LAYOUTRUN_FLAG_ELLIPSIS 0x04 +#define LAYOUTRUN_FLAG_CENTERED_BASELINE 0x08 struct _LayoutRun { - LOGFONT* lf; // the logfont for this run - const Uchar32* ucs; // the uchar string + LOGFONT* lf; // the logfont for this run + const Uchar32* ucs; // the uchar string - int si; // the start index of this run - int len; // the length of the uchar string - Uint32 lc:8; // language code - Uint32 st:8; // script type - Uint32 el:8; // the bidi embedding level - Uint32 dir:2; // the run direction; value rage: [0, 3] - Uint32 ort:2; // the glyph orientation; value range: [0, 3] - Uint32 flags:4;// other flags + int si; // the start index of this run + int len; // the length of the uchar string + Uint32 lc:8; // language code + Uint32 st:8; // script type + Uint32 el:8; // the bidi embedding level + Uint32 dir:2; // the run direction; value rage: [0, 3] + Uint32 ort:2; // the glyph orientation; value range: [0, 3] + Uint32 flags:4; // other flags }; struct _GlyphRun { @@ -127,6 +128,9 @@ struct _LAYOUTINFO { int nr_left_ucs;// the number of chars not laied out int nr_lines; // the number of lines + Uint32 grv_base:4; // the base gravity + Uint32 grv_plc:2; // the gravity policy specified + Uint32 orient:2; // the glyph orientation specified Uint32 persist:1; // persist lines? Uint32 single_paragraph:1; }; diff --git a/src/newgdi/simple-glyph-renderer.c b/src/newgdi/simple-glyph-renderer.c index 304e93c4..1df57d95 100644 --- a/src/newgdi/simple-glyph-renderer.c +++ b/src/newgdi/simple-glyph-renderer.c @@ -536,14 +536,14 @@ static void adjust_glyph_position(MYGLYPHARGS* args, { switch (args->rf & GRF_WRITING_MODE_MASK) { case GRF_WRITING_MODE_VERTICAL_RL: - if (gi->orientation == GLYPH_ORIENTATION_UPRIGHT) { + if (gi->orientation == GLYPH_ORIENT_UPRIGHT) { x -= (args->lw + ge->bbox_w) / 2; x -= ge->bbox_x; } break; case GRF_WRITING_MODE_VERTICAL_LR: - if (gi->orientation == GLYPH_ORIENTATION_SIDEWAYS) { + if (gi->orientation == GLYPH_ORIENT_SIDEWAYS) { x += args->lfsw->size; } else { @@ -858,7 +858,7 @@ static void init_glyph_info(MYGLYPHARGS* args, int i, gi->whitespace = 0; gi->suppressed = 0; gi->hanged = GLYPH_HANGED_NONE; - gi->orientation = GLYPH_ORIENTATION_UPRIGHT; + gi->orientation = GLYPH_ORIENT_UPRIGHT; } static inline int shrink_total_extent(MYGLYPHARGS* args, int total_extent, @@ -899,13 +899,13 @@ static int get_glyph_extent_info(MYGLYPHARGS* args, Glyph32 gv, == GRF_TEXT_ORIENTATION_MIXED) { if (is_horizontal_only_script(gi->uc)) { logfont = args->lfsw; - gi->orientation = GLYPH_ORIENTATION_SIDEWAYS; + gi->orientation = GLYPH_ORIENT_SIDEWAYS; } } else if ((args->rf & GRF_TEXT_ORIENTATION_MASK) == GRF_TEXT_ORIENTATION_SIDEWAYS) { logfont = args->lfsw; - gi->orientation = GLYPH_ORIENTATION_SIDEWAYS; + gi->orientation = GLYPH_ORIENT_SIDEWAYS; } } @@ -1364,7 +1364,7 @@ int GUIAPI DrawGlyphStringEx(HDC hdc, for (i = 0; i < nr_glyphs; i++) { if (glyph_pos[i].suppressed == 0 && glyph_pos[i].whitespace == 0) { - if (glyph_pos[i].orientation == GLYPH_ORIENTATION_UPRIGHT) { + if (glyph_pos[i].orientation == GLYPH_ORIENT_UPRIGHT) { if (logfont_upright) SelectFont(hdc, logfont_upright); else diff --git a/src/newgdi/textrunsinfo.c b/src/newgdi/textrunsinfo.c index 8e19563d..a7f908b2 100644 --- a/src/newgdi/textrunsinfo.c +++ b/src/newgdi/textrunsinfo.c @@ -84,9 +84,11 @@ typedef struct _TextRunState { const Uchar32* emb_end; int emb_end_offset; BidiLevel emb_level; - - GlyphOrient ort_rsv; + Uint8 upright; +#if 0 + LayoutGravity grv_rsv; BOOL centered_baseline; +#endif Uint8 changed; @@ -144,15 +146,18 @@ static LanguageCode compute_derived_language (LanguageCode lang, static void state_update_for_new_run (TextRunState *state) { if (state->changed & (SCRIPT_CHANGED | WIDTH_CHANGED)) { - GlyphOrient orient = state->runinfo->ort_base; - GlyphOrientPolicy orient_policy = state->runinfo->ort_plc; + state->upright = state->width_iter.upright; +#if 0 + LayoutGravity gravity = state->runinfo->grv_base; + LayoutGravityPolicy gravity_policy = state->runinfo->grv_plc; - if (orient == GLYPH_ORIENT_AUTO) - orient = state->runinfo->ort_rsv; + if (gravity == LAYOUT_GRAVITY_AUTO) + gravity = state->runinfo->grv_rsv; - state->ort_rsv = GetWideGlyphOrientationForScript( + state->grv_rsv = ScriptGetLayoutGravityForWide( state->script_iter.script, state->width_iter.upright, - orient, orient_policy); + gravity, gravity_policy); +#endif } if (state->changed & (SCRIPT_CHANGED | LANG_CHANGED)) { @@ -179,19 +184,23 @@ static void state_add_character(TextRunState *state, state->run = malloc(sizeof(TextRun)); state->run->fontname = NULL; - state->run->si = pos - state->text; - state->run->len = 1; - state->run->lc = state->derived_lang; - state->run->st = state->script_iter.script; - state->run->el = state->emb_level; - state->run->dir = state->runinfo->run_dir; - state->run->ort = state->ort_rsv; - state->run->flags = 0; + state->run->si = pos - state->text; + state->run->len = 1; + state->run->lc = state->derived_lang; + state->run->st = state->script_iter.script; + state->run->el = state->emb_level; + state->run->flags = 0; if (no_shaping) { state->run->flags |= TEXTRUN_FLAG_NO_SHAPING; } + if (state->upright) { + state->run->flags |= TEXTRUN_FLAG_UPRIGHT; + } + //state->run->dir = state->runinfo->run_dir; + //state->run->ort = state->grv_rsv; +#if 0 /* The level vs. gravity dance: * If gravity is SOUTH, leave level untouched. * If gravity is NORTH, step level one up, to @@ -204,23 +213,24 @@ static void state_add_character(TextRunState *state, * top is unrotated right. */ switch (state->run->ort) { - case GLYPH_GRAVITY_SOUTH: + case LAYOUT_GRAVITY_SOUTH: default: break; - case GLYPH_GRAVITY_NORTH: + case LAYOUT_GRAVITY_NORTH: state->run->el++; break; - case GLYPH_GRAVITY_EAST: + case LAYOUT_GRAVITY_EAST: state->run->el += 1; state->run->el &= ~1; break; - case GLYPH_GRAVITY_WEST: + case LAYOUT_GRAVITY_WEST: state->run->el |= 1; break; } state->run->flags |= state->centered_baseline ? TEXTRUN_FLAG_CENTERED_BASELINE : 0; +#endif list_add_tail(&state->run->list, &state->runinfo->truns); state->runinfo->nr_runs++; @@ -307,10 +317,11 @@ static BOOL create_text_runs(TEXTRUNSINFO* runinfo, BidiLevel* els) state.end = runinfo->ucs + runinfo->nr_ucs; state.run = NULL; state.els = els; - state.ort_rsv = runinfo->ort_rsv; - - /* check font gravity here */ - state.centered_baseline = GLYPH_ORIENT_IS_VERTICAL(runinfo->ort_rsv); + state.upright = 0; +#if 0 + state.grv_rsv = runinfo->ort_rsv; + state.centered_baseline = LAYOUT_GRAVITY_IS_VERTICAL(runinfo->grv_rsv); +#endif state.run_start = state.text; state.changed = 0; @@ -349,31 +360,30 @@ out: return ok; } -static inline Uint8 get_glyph_orient_from_fontname (const char* fontname) +static inline Uint8 get_gravity_from_fontname (const char* fontname) { switch (fontGetOrientFromName (fontname)) { case FONT_ORIENT_SIDEWAYS: - return GLYPH_ORIENT_SIDEWAYS; + return LAYOUT_GRAVITY_EAST; case FONT_ORIENT_UPSIDE_DOWN: - return GLYPH_ORIENT_UPSIDE_DOWN; + return LAYOUT_GRAVITY_NORTH; case FONT_ORIENT_SIDEWAYS_LEFT: - return GLYPH_ORIENT_SIDEWAYS_LEFT; + return LAYOUT_GRAVITY_WEST; case FONT_ORIENT_UPRIGHT: default: - return GLYPH_ORIENT_UPRIGHT; + return LAYOUT_GRAVITY_SOUTH; } } #ifdef _MGDEVEL_MODE -void* GetNextTextRunInfo(TEXTRUNSINFO* runinfo, - void* prev, +TEXTRUN* GetNextTextRunInfo(TEXTRUNSINFO* runinfo, + TEXTRUN* prev, const char** fontname, int* start_index, int* length, LanguageCode* lang_code, ScriptType* script, - BidiLevel* embedding_level, GlyphRunDir* run_dir, - GlyphOrient* orient, Uint8* flags) + BidiLevel* embedding_level, Uint8* flags) { TextRun* run = NULL; @@ -396,25 +406,24 @@ void* GetNextTextRunInfo(TEXTRUNSINFO* runinfo, if (lang_code) *lang_code = run->lc; if (script) *script = run->st; if (embedding_level) *embedding_level = run->el; - if (run_dir) *run_dir = run->dir; - if (orient) *orient = run->ort; +#if 0 + if (gravity) *orient = run->ort; +#endif if (flags) *flags = run->flags; return run; } #endif /* _MGDEVEL_MODE */ -static BOOL is_fontname_conformed(const char* fontname, - GlyphOrient glyph_orient, GlyphOrientPolicy orient_policy) +static BOOL is_fontname_conformed(const char* fontname) { LOGFONT* lf; - DEVFONT *sbc_devfont, *mbc_devfont; + DEVFONT *mbc_devfont; BOOL ok = FALSE; if ((lf = CreateLogFontByName(fontname)) == NULL) return FALSE; - sbc_devfont = lf->devfonts[0]; mbc_devfont = lf->devfonts[1]; if (mbc_devfont == NULL) goto out; @@ -422,15 +431,6 @@ static BOOL is_fontname_conformed(const char* fontname, if (mbc_devfont->charset_ops->conv_to_uc32) goto out; - /* TODO: check more */ - if (glyph_orient != GLYPH_ORIENT_UPRIGHT) { - - if (sbc_devfont->font_ops->is_rotatable(lf, sbc_devfont, 100) != 100 - || mbc_devfont->font_ops->is_rotatable(lf, mbc_devfont, 100) - != 100) - goto out; - } - ok = TRUE; out: @@ -439,9 +439,8 @@ out: } TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(const Uchar32* ucs, int nr_ucs, - LanguageCode lang_code, ParagraphDir base_dir, GlyphRunDir run_dir, - GlyphOrient glyph_orient, GlyphOrientPolicy orient_policy, - const char* logfont_name, RGBCOLOR color, + LanguageCode lang_code, ParagraphDir base_dir, + const char* logfont_name, RGBCOLOR color, RGBCOLOR bg_color, BreakOppo* break_oppos) { BOOL ok = FALSE; @@ -454,8 +453,8 @@ TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(const Uchar32* ucs, int nr_ucs, return NULL; } - if (!is_fontname_conformed(logfont_name, glyph_orient, orient_policy)) { - _WRN_PRINTF("Please check your fontname; it must conform to the glyph orientation specified."); + if (!is_fontname_conformed(logfont_name)) { + _WRN_PRINTF("Please check your fontname; it must in Unicode charset."); return NULL; } @@ -477,16 +476,6 @@ TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(const Uchar32* ucs, int nr_ucs, UBidiGetParagraphEmbeddingLevelsAlt(ucs, nr_ucs, &base_dir, els); - /* the breaking opportunities should be passed to the layout function. - // Calculate the breaking opportunities - if (UStrGetBreaks(script_type, ctr, wbr, lbp, - ucs, nr_ucs, &bos) == 0) { - _ERR_PRINTF("%s: failed to get breaking opportunities.\n", - __FUNCTION__); - goto out; - } - */ - // Initialize other fields runinfo->ucs = ucs; runinfo->fontname = strdup(logfont_name); @@ -495,20 +484,27 @@ TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(const Uchar32* ucs, int nr_ucs, runinfo->lc = LANGCODE_en; // fallback to English else runinfo->lc = lang_code; - runinfo->base_level = (base_dir == BIDI_PGDIR_LTR) ? 0 : 1; - runinfo->run_dir = run_dir; - runinfo->ort_base = glyph_orient; - runinfo->ort_plc = orient_policy; - if (runinfo->ort_base == GLYPH_ORIENT_AUTO) - runinfo->ort_rsv = get_glyph_orient_from_fontname (runinfo->fontname); - else - runinfo->ort_rsv = runinfo->ort_base; + runinfo->base_dir = base_dir; - INIT_LIST_HEAD(&runinfo->attrs.list); - runinfo->attrs.si = 0; - runinfo->attrs.len = nr_ucs; - runinfo->attrs.type = TEXT_ATTR_TEXT_COLOR; - runinfo->attrs.value = color; +#if 0 + runinfo->base_level = (base_dir == BIDI_PGDIR_LTR) ? 0 : 1; + runinfo->grv_base = glyph_orient; + runinfo->grv_plc = gravity_policy; + if (runinfo->grv_base == LAYOUT_GRAVITY_AUTO) + runinfo->grv_rsv = get_gravity_from_fontname (runinfo->fontname); + else + runinfo->grv_rsv = runinfo->ort_base; +#endif + + INIT_LIST_HEAD(&runinfo->fg_colors.list); + runinfo->fg_colors.si = 0; + runinfo->fg_colors.len = nr_ucs; + runinfo->fg_colors.value = color; + + INIT_LIST_HEAD(&runinfo->bg_colors.list); + runinfo->bg_colors.si = 0; + runinfo->bg_colors.len = nr_ucs; + runinfo->bg_colors.value = bg_color; INIT_LIST_HEAD(&runinfo->truns); runinfo->nr_runs = 0; @@ -542,39 +538,30 @@ out: return NULL; } -BOOL GUIAPI SetFontInTextRuns(TEXTRUNSINFO* runinfo, - int start_index, int length, const char* logfont_name) -{ - if (runinfo == NULL) - return FALSE; - - // can not change font for empty runs - if (list_empty(&runinfo->truns)) - return FALSE; - - // TODO - return FALSE; -} - -RGBCOLOR __mg_textruns_get_text_color(const TEXTRUNSINFO* runinfo, int index) +TextRun* __mg_text_run_get_by_offset(TEXTRUNSINFO* runinfo, + int index, int *start_offset) { struct list_head *i; + TextRun* found = NULL; - list_for_each(i, &runinfo->attrs.list) { - TextAttrMap* color_entry; - color_entry = (TextAttrMap*)i; - if (index >= color_entry->si && - (index < color_entry->si + color_entry->len) && - color_entry->type == TEXT_ATTR_TEXT_COLOR) { - return color_entry->value; + list_for_each(i, &runinfo->truns) { + TextRun* trun = (TextRun*)i; + if (index >= trun->si && + (index < trun->si + trun->len)) { + found = trun; + if (start_offset) { + *start_offset = index - trun->si; + } + + break; } } - return runinfo->attrs.value; + return found; } -const TextRun* __mg_text_run_get_by_offset(const TEXTRUNSINFO* runinfo, - int index, int *start_offset) +const TextRun* __mg_text_run_get_by_offset_const( + const TEXTRUNSINFO* runinfo, int index, int *start_offset) { struct list_head *i; const TextRun* found = NULL; @@ -595,10 +582,133 @@ const TextRun* __mg_text_run_get_by_offset(const TEXTRUNSINFO* runinfo, return found; } +TextRun* __mg_text_run_copy(const TextRun *trun) +{ + TextRun *result; + + if (trun == NULL) + return NULL; + + result = malloc(sizeof(TextRun)); + memcpy(result, trun, sizeof(TextRun)); + + return result; +} + +TextRun* __mg_text_run_split(TextRun *orig, int split_index) +{ + TextRun *new_run; + + if (orig == NULL) + return NULL; + if (split_index <= 0) + return NULL; + if (split_index >= orig->len) + return NULL; + + new_run = __mg_text_run_copy(orig); + new_run->len = split_index; + + orig->si += split_index; + orig->len -= split_index; + + return new_run; +} + +BOOL GUIAPI SetFontNameInTextRuns(TEXTRUNSINFO* runinfo, + int start_index, int length, const char* logfont_name) +{ + TextRun* run; + int start_offset; + int left_ucs;; + + if (runinfo == NULL || logfont_name == NULL || + start_index < 0 || (start_index + length) > runinfo->nr_ucs) + return FALSE; + + if (strcmp(logfont_name, runinfo->fontname) == 0) + return TRUE; + + // can not change font for empty runs + if (list_empty(&runinfo->truns)) + return FALSE; + + if (start_index == 0 && length == runinfo->nr_ucs) { + // change the default fontname + if (!is_fontname_conformed(logfont_name)) { + return FALSE; + } + + free(runinfo->fontname); + runinfo->fontname = strdup(logfont_name); + return TRUE; + } + + left_ucs = length; + while (left_ucs > 0) { + run = __mg_text_run_get_by_offset(runinfo, start_index, &start_offset); + + if (run == NULL) + return FALSE; + + if (start_offset == 0) { + if (left_ucs >= run->len) { + // change the fontname of current run + if (run->fontname) { + free(run->fontname); + } + run->fontname = strdup(logfont_name); + + start_index += run->len; + left_ucs -= run->len; + } + else { + TextRun* new_run; + + new_run = __mg_text_run_split(run, run->len - left_ucs); + new_run->fontname = strdup(logfont_name); + // insert the new run to the list. + __list_add(&new_run->list, run->list.prev, &run->list); + + left_ucs = 0; + } + } + else { + TextRun* new_run; + + new_run = __mg_text_run_split(run, start_offset); + // insert the new run to the list. + __list_add(&new_run->list, run->list.prev, &run->list); + } + } + + return TRUE; +} + +const char* GUIAPI GetFontNameInTextRuns(const TEXTRUNSINFO* runinfo, int index) +{ + struct list_head *i; + + if (runinfo == NULL) + return NULL; + + list_for_each(i, &runinfo->truns) { + TextRun* run = (TextRun*)i; + if (index >= run->si && (index < run->si + run->len)) { + if (run->fontname == NULL) + goto out; + return run->fontname; + } + } + +out: + return runinfo->fontname; +} + BOOL GUIAPI SetTextColorInTextRuns(TEXTRUNSINFO* runinfo, int start_index, int length, RGBCOLOR color) { - TextAttrMap* color_entry = NULL; + TextColorMap* color_entry = NULL; if (runinfo == NULL || start_index < 0 || length < 0 || start_index > runinfo->nr_ucs || @@ -606,17 +716,16 @@ BOOL GUIAPI SetTextColorInTextRuns(TEXTRUNSINFO* runinfo, goto error; } - color_entry = calloc(1, sizeof(TextAttrMap)); + color_entry = calloc(1, sizeof(TextColorMap)); if (color_entry == NULL) { goto error; } color_entry->si = start_index; color_entry->len = length; - color_entry->type = TEXT_ATTR_TEXT_COLOR; color_entry->value = color; - list_add(&color_entry->list, &runinfo->attrs.list); + list_add(&color_entry->list, &runinfo->fg_colors.list); return TRUE; @@ -624,14 +733,80 @@ error: return FALSE; } +RGBCOLOR GetTextColorInTextRuns(const TEXTRUNSINFO* runinfo, int index) +{ + struct list_head *i; + + list_for_each(i, &runinfo->fg_colors.list) { + TextColorMap* color_entry; + color_entry = (TextColorMap*)i; + if (index >= color_entry->si && + (index < color_entry->si + color_entry->len)) { + return color_entry->value; + } + } + + return runinfo->fg_colors.value; +} + +BOOL GUIAPI SetBackgroundColorInTextRuns(TEXTRUNSINFO* runinfo, + int start_index, int length, RGBCOLOR color) +{ + TextColorMap* color_entry = NULL; + + if (runinfo == NULL || start_index < 0 || length < 0 || + start_index > runinfo->nr_ucs || + (start_index + length) > runinfo->nr_ucs) { + goto error; + } + + color_entry = calloc(1, sizeof(TextColorMap)); + if (color_entry == NULL) { + goto error; + } + + color_entry->si = start_index; + color_entry->len = length; + color_entry->value = color; + + list_add(&color_entry->list, &runinfo->bg_colors.list); + + return TRUE; + +error: + return FALSE; +} + +RGBCOLOR GetBackgroundColorInTextRuns(const TEXTRUNSINFO* runinfo, int index) +{ + struct list_head *i; + + list_for_each(i, &runinfo->bg_colors.list) { + TextColorMap* color_entry; + color_entry = (TextColorMap*)i; + if (index >= color_entry->si && + (index < color_entry->si + color_entry->len)) { + return color_entry->value; + } + } + + return runinfo->bg_colors.value; +} + BOOL GUIAPI DestroyTextRunsInfo(TEXTRUNSINFO* runinfo) { if (runinfo == NULL) return FALSE; - while (!list_empty(&runinfo->attrs.list)) { - TextAttrMap* entry = (TextAttrMap*)runinfo->attrs.list.prev; - list_del(runinfo->attrs.list.prev); + while (!list_empty(&runinfo->bg_colors.list)) { + TextColorMap* entry = (TextColorMap*)runinfo->bg_colors.list.prev; + list_del(runinfo->bg_colors.list.prev); + free(entry); + } + + while (!list_empty(&runinfo->fg_colors.list)) { + TextColorMap* entry = (TextColorMap*)runinfo->fg_colors.list.prev; + list_del(runinfo->fg_colors.list.prev); free(entry); } diff --git a/src/newgdi/textrunsinfo.h b/src/newgdi/textrunsinfo.h index 0c24b2a5..636fb705 100644 --- a/src/newgdi/textrunsinfo.h +++ b/src/newgdi/textrunsinfo.h @@ -47,7 +47,7 @@ typedef struct _LayoutRun LayoutRun; typedef struct _TextRun TextRun; typedef struct _GlyphString GlyphString; typedef struct _SEInstance SEInstance; -typedef struct _TextAttrMap TextAttrMap; +typedef struct _TextColorMap TextColorMap; typedef BOOL (*CB_SHAPE_LAYOUT_RUN)(SEInstance* instance, const TEXTRUNSINFO* info, const LayoutRun* run, @@ -68,36 +68,31 @@ struct _ShapingEngineInfo { CB_DESTROY_INSTANCE free; }; -#define TEXTRUN_FLAG_CENTERED_BASELINE 0x01 -#define TEXTRUN_FLAG_NO_SHAPING 0x02 +#define TEXTRUN_FLAG_NO_SHAPING 0x01 +#define TEXTRUN_FLAG_UPRIGHT 0x02 struct _TextRun { struct list_head list; char* fontname; // the logfont name for this run; NULL for default - int si; // start index in the uchar string - int len; // the length in uchars + int si; // start index in the uchar string + int len; // the length in uchars - Uint32 lc:8; // language code - Uint32 st:8; // script type - Uint32 el:8; // the bidi embedding level + Uint32 lc:8; // language code + Uint32 st:8; // script type + Uint32 el:8; // the bidi embedding level + Uint32 flags:2; // other flags +#if 0 Uint32 dir:2; // the run direction; value range: [0, 3] Uint32 ort:2; // the glyph orientation; value range: [0, 3] - Uint32 flags:4;// other flags +#endif }; -#define TEXT_ATTR_TEXT_COLOR 0x00 -#define TEXT_ATTR_UNDERLINE_COLOR 0x01 -#define TEXT_ATTR_STRIKETHROUGH_COLOR 0x02 -#define TEXT_ATTR_OUTLINE_COLOR 0x03 -#define TEXT_ATTR_BACKGROUND_COLOR 0x04 - -struct _TextAttrMap { +struct _TextColorMap { struct list_head list; int si; int len; - int type; // attribute type - Uint32 value; // attribute value + RGBCOLOR value; // attribute value }; struct _TEXTRUNSINFO { @@ -105,17 +100,22 @@ struct _TEXTRUNSINFO { const Uchar32* ucs; // the uchars char* fontname; // the default logfont name specified - TextAttrMap attrs; // the head of color map (list) + TextColorMap fg_colors; // the head of foreground color map (list) + TextColorMap bg_colors; // the head of background color map (list) struct list_head truns; // the head of text runs (list) - int nr_ucs; // number of uchars - int nr_runs; // number of runs + int nr_ucs; // number of uchars + int nr_runs; // number of runs + LanguageCode lc; // language code specified + ParagraphDir base_dir; // paragraph base direction + +#if 0 Uint32 lc:8; // language code specified - Uint32 ort_base:3; // the glyph orientation specified - Uint32 ort_rsv:3; // the glyph orientation resolved - Uint32 ort_plc:2; // the glyph orientation policy specified - Uint32 run_dir:4; // the run direction specified + Uint32 grv_base:4; // the gravity specified + Uint32 grv_plc:2; // the gravity policy specified + Uint32 grv_rsv:4; // the gravity resolved Uint32 base_level:1; // the paragraph direction; 0 for LTR, 1 for RTL +#endif /* The following fields will be initialized by the shaping engine. */ ShapingEngineInfo sei; // the shaping engine information @@ -125,9 +125,11 @@ struct _TEXTRUNSINFO { extern "C" { #endif /* __cplusplus */ -RGBCOLOR __mg_textruns_get_text_color(const TEXTRUNSINFO* runinfo, int index); - -const TextRun* __mg_text_run_get_by_offset(const TEXTRUNSINFO* runinfo, +TextRun* __mg_text_run_copy(const TextRun *orig); +TextRun* __mg_text_run_split(TextRun *orig, int split_index); +TextRun* __mg_text_run_get_by_offset(TEXTRUNSINFO* runinfo, + int index, int *start_offset); +const TextRun* __mg_text_run_get_by_offset_const(const TEXTRUNSINFO* runinfo, int index, int *start_offset); #ifdef __cplusplus