From c276122f60f1858a0e72f423bc3be962c2f23cf1 Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Wed, 20 Mar 2019 18:53:06 +0800 Subject: [PATCH] Start to implement InitBasicShapingEngine --- include/gdi.h | 17 ++- src/newgdi/layoutinfo.c | 89 +++++++++++++- src/newgdi/layoutinfo.h | 28 ++--- src/newgdi/shape-glyphs-basic.c | 201 +++++++++++++------------------- src/newgdi/textrunsinfo.h | 3 +- 5 files changed, 202 insertions(+), 136 deletions(-) diff --git a/include/gdi.h b/include/gdi.h index d1680b2b..366b0c97 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -12176,6 +12176,21 @@ MG_EXPORT int GUIAPI UChars2AChars(LOGFONT* logfont, const Uchar32* ucs, * from their upright orientation. */ #define GRF_TEXT_ORIENTATION_SIDEWAYS 0x01000000 +/** + * The glyphs are individually typeset upside down in + * vertical lines with vertical font metrics. + */ +#define GRF_TEXT_ORIENTATION_UPSIDE_DOWN 0x02000000 +/** + * The glyphs typeset a run rotated 90° counter-clockwise + * from their upright orientation. + */ +#define GRF_TEXT_ORIENTATION_SIDEWAYS_LEFT 0x03000000 +/** + * In vertical writing modes, all typographic character units + * keep in their intrinsic orientation. + */ +#define GRF_TEXT_ORIENTATION_AUTO 0x04000000 /** * In vertical writing modes, typographic character units from * horizontal-only scripts are typeset sideways, i.e. 90° clockwise @@ -12183,7 +12198,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 0x02000000 +#define GRF_TEXT_ORIENTATION_MIXED 0x05000000 #define GRF_OVERFLOW_WRAP_MASK 0x00F00000 /** diff --git a/src/newgdi/layoutinfo.c b/src/newgdi/layoutinfo.c index 251005ba..7cbbedec 100644 --- a/src/newgdi/layoutinfo.c +++ b/src/newgdi/layoutinfo.c @@ -3,7 +3,7 @@ * and Graphics User Interface (GUI) support system for embedded systems * and smart IoT devices. * - * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 2002~2019, Beijing FMSoft Technologies Co., Ltd. * Copyright (C) 1998~2002, WEI Yongming * * This program is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ /* ** layoutinfo.c: The implementation of APIs related LAYOUTINFO ** -** Create by WEI Yongming at 2019/03/14 +** Create by WEI Yongming at 2019/03/20 */ #include @@ -53,6 +53,91 @@ #include "unicode-ops.h" #include "layoutinfo.h" +LAYOUTINFO* GUIAPI CreateLayoutInfo( + const TEXTRUNSINFO* runinfo, Uint32 render_flags, + const BreakOppo* break_oppos, BOOL persist_lines, + int letter_spacing, int word_spacing, int tab_size) +{ + LAYOUTINFO* layoutinfo; + + if (runinfo == NULL || runinfo->sei.inst == NULL) { + return NULL; + } + + layoutinfo = (LAYOUTINFO*)calloc(1, sizeof(LAYOUTINFO)); + if (layoutinfo == NULL) { + return NULL; + } + + layoutinfo->runinfo = runinfo; + layoutinfo->bos = break_oppos; + layoutinfo->rf = render_flags; + layoutinfo->ls = letter_spacing; + layoutinfo->ws = word_spacing; + layoutinfo->ts = tab_size; + + INIT_LIST_HEAD(&layoutinfo->line_head); + layoutinfo->left_ucs = runinfo->nr_ucs; + + layoutinfo->persist = persist_lines ? 1 : 0; + + return layoutinfo; +} + +static void release_glyph_string(GLYPHSTRING* gs) +{ + if (gs->glyphs) + free (gs->glyphs); + if (gs->log_clusters); + free (gs->log_clusters); + + free(gs); +} + +static void release_run(GLYPHRUN* run) +{ + if (run->gs) { + release_glyph_string(run->gs); + } + + free(run); +} + +static void release_line(LAYOUTLINE* line) +{ + while (!list_empty(&line->run_head)) { + GLYPHRUN* run = (GLYPHRUN*)line->run_head.prev; + list_del(line->run_head.prev); + release_run(run); + } + + if (line->log_widths) { + free(line->log_widths); + } + + free(line); +} + +BOOL GUIAPI DestroyLayoutInfo(LAYOUTINFO* info) +{ + while (!list_empty(&info->line_head)) { + LAYOUTLINE* line = (LAYOUTLINE*)info->line_head.prev; + list_del(info->line_head.prev); + release_line(line); + } + + free(info); + return TRUE; +} + +LAYOUTLINE* GUIAPI LayoutNextLine(LAYOUTINFO* info, + LAYOUTLINE* prev_Line, + int* x, int* y, int max_extent, SIZE* line_size, + CB_GLYPH_LAID_OUT cb_laid_out, GHANDLE ctxt) +{ + return NULL; +} + #if 0 int GUIAPI DrawShapedGlyphString(HDC hdc, LOGFONT* logfont_upright, LOGFONT* logfont_sideways, diff --git a/src/newgdi/layoutinfo.h b/src/newgdi/layoutinfo.h index 9648e283..5794a2a5 100644 --- a/src/newgdi/layoutinfo.h +++ b/src/newgdi/layoutinfo.h @@ -3,7 +3,7 @@ * and Graphics User Interface (GUI) support system for embedded systems * and smart IoT devices. * - * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 2002~2019, Beijing FMSoft Technologies Co., Ltd. * Copyright (C) 1998~2002, WEI Yongming * * This program is free software: you can redistribute it and/or modify @@ -57,17 +57,17 @@ struct _SHAPEDGLYPH { }; struct _GLYPHSTRING { - SHAPEDGLYPH* glyphs; - int* log_clusters; + SHAPEDGLYPH* glyphs; + int* log_clusters; - int nr_glyphs; - int reserved; + int nr_glyphs; + int reserved; }; struct _GLYPHRUN { struct list_head list; - TEXTRUN* text_run; // the text run to which this glyph run belongs - GLYPHSTRING* glyphstr; // the glyph string + TEXTRUN* text; // the text run to which this glyph run belongs + GLYPHSTRING* gs; // the glyph string }; struct _LAYOUTLINE { @@ -86,19 +86,21 @@ struct _LAYOUTLINE { Uint8 all_odd:1; // flag indicating all level is odd }; -struct _GLYPHLAYOUTINFO { +struct _LAYOUTINFO { const TEXTRUNSINFO* runinfo; - const BreakOppo* break_oppos; + const BreakOppo* bos; - Uint32 render_flags; - int letter_spacing; - int word_spacing; - int tab_size; + Uint32 rf; + int ls; + int ws; + int ts; struct list_head line_head; // the list head of lines LAYOUTLINE *curr_line; // current line + int left_ucs; // the number of chars not laied out. + Uint32 persist:1; // persist lines? }; #ifdef __cplusplus diff --git a/src/newgdi/shape-glyphs-basic.c b/src/newgdi/shape-glyphs-basic.c index fdbd0b20..e1387d92 100644 --- a/src/newgdi/shape-glyphs-basic.c +++ b/src/newgdi/shape-glyphs-basic.c @@ -55,21 +55,7 @@ #include "window.h" #include "devfont.h" #include "unicode-ops.h" -#include "textrunsinfo.h" - -#if 0 -static void bidi_reverse_shaped_glyphs (void* context, int len, int pos) -{ - int i; - SHAPEDGLYPH* vgs = (SHAPEDGLYPH*)context + pos; - - for (i = 0; i < len / 2; i++) { - SHAPEDGLYPH tmp = vgs[i]; - vgs[i] = vgs[len - 1 - i]; - vgs[len - 1 - i] = tmp; - } -} -#endif +#include "layoutinfo.h" /* Local array size, used for stack-based local arrays */ @@ -79,12 +65,25 @@ static void bidi_reverse_shaped_glyphs (void* context, int len, int pos) # define LOCAL_ARRAY_SIZE 128 #endif -BOOL GUIAPI InitBasicShapingEngine(TEXTRUNSINFO* run_info) + +static void reverse_ucs (Uchar32* ucs, int len) { -#if 0 - int ret_value = 0; - int i, j, nr_reordered; - BidiLevel max_level = 0; + int i; + for (i = 0; i < len / 2; i++) { + Uchar32 tmp = ucs[i]; + ucs[i] = ucs[len - 1 - i]; + ucs[len - 1 - i] = tmp; + } +} + +static BOOL shape_text_run(SEINSTANCE* inst, + const TEXTRUNSINFO* info, const TEXTRUN* run, + GLYPHSTRING* gs) +{ + BOOL ok = FALSE; + int i, j; + const Uchar32* logical_ucs = info->ucs + run->idx; + int nr_ucs = run->len; Uchar32 local_visual_ucs[LOCAL_ARRAY_SIZE]; Uchar32* visual_ucs = NULL; @@ -95,83 +94,48 @@ BOOL GUIAPI InitBasicShapingEngine(TEXTRUNSINFO* run_info) BidiType local_bidi_ts[LOCAL_ARRAY_SIZE]; BidiType *bidi_ts = NULL; - BidiBracketType local_brk_ts[LOCAL_ARRAY_SIZE]; - BidiBracketType *brk_ts = NULL; - BidiLevel local_els[LOCAL_ARRAY_SIZE]; BidiLevel* els = NULL; - int local_indics_map[LOCAL_ARRAY_SIZE]; - int* indics_map = NULL; - - if (nr_ucs == 0 || logical_ucs == NULL || break_oppos == NULL || - visual_glyphs == NULL || nr_glyphs == NULL) { - return 0; - } - - /* TODO: we may re-use visual_glyphs for visual ucs */ if (nr_ucs < LOCAL_ARRAY_SIZE) visual_ucs = local_visual_ucs; else - visual_ucs = malloc (nr_ucs * sizeof(Uchar32)); + visual_ucs = malloc(nr_ucs * sizeof(Uchar32)); if (!visual_ucs) goto out; - if (nr_ucs < LOCAL_ARRAY_SIZE) - indics_map = local_indics_map; - else - indics_map = malloc (nr_ucs * sizeof(int)); - - if (!indics_map) - goto out; - /* TODO: compose logical character here */ memcpy(visual_ucs, logical_ucs, sizeof(Uchar32) * nr_ucs); - if (nr_ucs < LOCAL_ARRAY_SIZE) - bidi_ts = local_bidi_ts; - else - bidi_ts = malloc (nr_ucs * sizeof(BidiType)); - - if (!bidi_ts) - goto out; - - UStrGetBidiTypes(logical_ucs, nr_ucs, bidi_ts); - - if (nr_ucs < LOCAL_ARRAY_SIZE) - brk_ts = local_brk_ts; - else - brk_ts = (BidiBracketType*)malloc (nr_ucs * sizeof(BidiBracketType)); - - if (!brk_ts) - goto out; - - UStrGetBracketTypes (logical_ucs, bidi_ts, nr_ucs, brk_ts); - if (nr_ucs < LOCAL_ARRAY_SIZE) els = local_els; else els = (BidiLevel*)malloc (nr_ucs * sizeof(BidiLevel)); - if (!els) goto out; - max_level = UBidiGetParagraphEmbeddingLevels(bidi_ts, brk_ts, nr_ucs, - paragraph_dir, els) - 1; - if (max_level < 0) - goto out; + // Get the embedding levels from run instead calling + // UBidiGetParagraphEmbeddingLevels + memset(els, run->el, nr_ucs); - /* Set up the ordering array to identity order */ - for (i = 0; i < nr_ucs; i++) - indics_map[i] = i; + if (run->st == SCRIPT_ARABIC) { - if (writing_system == SCRIPT_ARABIC) { - /* Arabic joining */ if (nr_ucs < LOCAL_ARRAY_SIZE) + bidi_ts = local_bidi_ts; + else + bidi_ts = malloc (nr_ucs * sizeof(BidiType)); + + if (!bidi_ts) + goto out; + + UStrGetBidiTypes(logical_ucs, nr_ucs, bidi_ts); + + /* Arabic joining */ + if (run->len < LOCAL_ARRAY_SIZE) ar_props = local_ar_props; else - ar_props = malloc(sizeof(BidiArabicProp) * nr_ucs); + ar_props = malloc(sizeof(BidiArabicProp) * run->len); if (!ar_props) goto out; @@ -181,66 +145,64 @@ BOOL GUIAPI InitBasicShapingEngine(TEXTRUNSINFO* run_info) UBidiShape(BIDI_FLAG_SHAPE_MIRRORING | BIDI_FLAG_SHAPE_ARAB_PRES | BIDI_FLAG_SHAPE_ARAB_LIGA, els, nr_ucs, ar_props, visual_ucs); + + if (bidi_ts && bidi_ts != local_bidi_ts) { + free (bidi_ts); + bidi_ts = NULL; + } + } + else if (BIDI_LEVEL_IS_RTL(run->el)) { + UBidiShapeMirroring(els, nr_ucs, visual_ucs); } - if (UBidiReorderLine(BIDI_FLAGS_DEFAULT, bidi_ts, nr_ucs, 0, - *paragraph_dir, els, visual_ucs, indics_map, NULL, NULL) == 0) + if (els && els != local_els) { + free (els); + els = NULL; + } + + // reorder visual chars + if (BIDI_LEVEL_IS_RTL(run->el)) { + reverse_ucs(visual_ucs, nr_ucs); + } + + // generate the glyphs + gs->glyphs = malloc(sizeof(SHAPEDGLYPH) * nr_ucs); + gs->log_clusters = malloc(sizeof(int) * nr_ucs); + if (gs->glyphs == NULL || gs->log_clusters == NULL) goto out; - // remove the unused characters and get the real length of the visual ucs. j = 0; for (i = 0; i < nr_ucs; i++) { - if (!BIDI_IS_EXPLICIT_OR_BN (bidi_ts[indics_map[i]])) { - visual_ucs[j] = visual_ucs[i]; - j++; - } - } - nr_reordered = j; - - if (break_oppos) { - // The breaking opportunities - if (UStrGetBreaks(writing_system, ctr, wbr, lbp, visual_ucs, nr_reordered, - &break_oppos) == 0) - goto out; - } - - // get shaped glyphs - for (i = 0; i < nr_reordered; i++) { - visual_glyphs[i] = GetGlyphValue(logfont, UCHAR2ACHAR(visual_ucs[i])); + Glyph32 gv; + // check cluster for ligatures and marks if (ar_props) { - BidiArabicProp ar_prop = ar_props[indics_map[i]]; + BidiArabicProp ar_prop = ar_props[i]; if (ar_prop & BIDI_MASK_LIGATURED) { - glyph_shaping_info[i].gt = GLYPH_TYPE_STDLIGATURE; - glyph_shaping_info[i].gp = GLYPH_POS_BASELINE; - } - else if (UCharIsArabicVowel(visual_ucs[i])) { - glyph_shaping_info[i].gt = GLYPH_TYPE_STDMARK; - glyph_shaping_info[i].gp = GLYPH_POS_STDMARK_ABOVE; } else { - glyph_shaping_info[i].gt = GLYPH_TYPE_STANDALONE; - glyph_shaping_info[i].gp = GLYPH_POS_BASELINE; + gv = GetGlyphValue(run->lf, UCHAR2ACHAR(visual_ucs[i])); + gs->glyphs[j].gv = gv; + j++; + + if (UCharIsArabicVowel(logical_ucs[i])) { + // adjust offset + } + else { + } } } - else { - glyph_shaping_info[i].gt = GLYPH_TYPE_STANDALONE; - glyph_shaping_info[i].gp = GLYPH_POS_BASELINE; - } + } + gs->nr_glyphs = j; + + if (ar_props && ar_props != local_ar_props) { + free (ar_props); + ar_props = NULL; } - *nr_glyphs = nr_reordered; - - if (map_v2l) { - memcpy(map_v2l, indics_map, sizeof(int) * nr_reordered); - } - - ret_value = nr_ucs; + ok = TRUE; out: - if (indics_map && indics_map != local_indics_map) - free (indics_map); - if (visual_ucs && visual_ucs != local_visual_ucs) free (visual_ucs); @@ -253,11 +215,12 @@ out: if (bidi_ts && bidi_ts != local_bidi_ts) free (bidi_ts); - if (brk_ts && brk_ts != local_brk_ts) - free (brk_ts); + return ok; +} - return ret_value; -#endif +BOOL GUIAPI InitBasicShapingEngine(TEXTRUNSINFO* info) +{ + info->sei.shape = shape_text_run; return FALSE; } diff --git a/src/newgdi/textrunsinfo.h b/src/newgdi/textrunsinfo.h index 74c56dc5..fe55e7d0 100644 --- a/src/newgdi/textrunsinfo.h +++ b/src/newgdi/textrunsinfo.h @@ -49,7 +49,8 @@ typedef struct _SEINSTANCE SEINSTANCE; typedef struct _TEXTCOLORMAP TEXTCOLORMAP; typedef BOOL (*CB_SHAPE_TEXT_RUN)(SEINSTANCE* instance, - const TEXTRUN* run, GLYPHSTRING* gs); + const TEXTRUNSINFO* info, const TEXTRUN* run, + GLYPHSTRING* gs); typedef BOOL (*CB_DESTROY_INSTANCE)(SEINSTANCE* instance);