From a049e387e0d0660111d5e04493dcb73ed97ec926 Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Fri, 22 Mar 2019 09:40:05 +0800 Subject: [PATCH] some code for layout --- src/newgdi/layout-utils.c | 20 ++-- src/newgdi/layoutinfo.c | 163 ++++++++++++++++++++------------ src/newgdi/layoutinfo.h | 14 +-- src/newgdi/shape-glyphs-basic.c | 2 +- src/newgdi/textrunsinfo.c | 4 +- src/newgdi/textrunsinfo.h | 2 +- 6 files changed, 125 insertions(+), 80 deletions(-) diff --git a/src/newgdi/layout-utils.c b/src/newgdi/layout-utils.c index 4672d142..2caf530d 100644 --- a/src/newgdi/layout-utils.c +++ b/src/newgdi/layout-utils.c @@ -144,13 +144,13 @@ BOOL __mg_glyph_item_iter_next_cluster (GlyphItemIter *iter) glyph_index++; if (glyph_index == glyphs->nr_glyphs) { - iter->end_index = item->idx + item->len; + iter->end_index = item->si + item->len; iter->end_char = item->len; break; } if (glyphs->log_clusters[glyph_index] > cluster) { - iter->end_index = item->idx + glyphs->log_clusters[glyph_index]; + iter->end_index = item->si + glyphs->log_clusters[glyph_index]; iter->end_char += iter->end_index - iter->start_index; break; } @@ -162,13 +162,13 @@ BOOL __mg_glyph_item_iter_next_cluster (GlyphItemIter *iter) glyph_index--; if (glyph_index < 0) { - iter->end_index = item->idx + item->len; + iter->end_index = item->si + item->len; iter->end_char = item->len; break; } if (glyphs->log_clusters[glyph_index] > cluster) { - iter->end_index = item->idx + glyphs->log_clusters[glyph_index]; + iter->end_index = item->si + glyphs->log_clusters[glyph_index]; iter->end_char += iter->end_index - iter->start_index; break; } @@ -207,7 +207,7 @@ BOOL __mg_glyph_item_iter_prev_cluster (GlyphItemIter *iter) cluster = glyphs->log_clusters[glyph_index - 1]; while (TRUE) { if (glyph_index == 0) { - iter->start_index = item->idx; + iter->start_index = item->si; iter->start_char = 0; break; } @@ -216,7 +216,7 @@ BOOL __mg_glyph_item_iter_prev_cluster (GlyphItemIter *iter) if (glyphs->log_clusters[glyph_index] < cluster) { glyph_index++; - iter->start_index = item->idx + glyphs->log_clusters[glyph_index]; + iter->start_index = item->si + glyphs->log_clusters[glyph_index]; iter->start_char -= iter->end_index - iter->start_index; break; } @@ -227,7 +227,7 @@ BOOL __mg_glyph_item_iter_prev_cluster (GlyphItemIter *iter) cluster = glyphs->log_clusters[glyph_index + 1]; while (TRUE) { if (glyph_index == glyphs->nr_glyphs - 1) { - iter->start_index = item->idx; + iter->start_index = item->si; iter->start_char = 0; break; } @@ -236,7 +236,7 @@ BOOL __mg_glyph_item_iter_prev_cluster (GlyphItemIter *iter) if (glyphs->log_clusters[glyph_index] < cluster) { glyph_index--; - iter->start_index = item->idx + glyphs->log_clusters[glyph_index]; + iter->start_index = item->si + glyphs->log_clusters[glyph_index]; iter->start_char -= iter->end_index - iter->start_index; break; } @@ -262,7 +262,7 @@ BOOL __mg_glyph_item_iter_init_start (GlyphItemIter *iter, else iter->end_glyph = glyph_item->glyphs->nr_glyphs - 1; - iter->end_index = glyph_item->item->idx; + iter->end_index = glyph_item->item->si; iter->end_char = 0; iter->start_glyph = iter->end_glyph; @@ -284,7 +284,7 @@ BOOL __mg_glyph_item_iter_init_end (GlyphItemIter *iter, else iter->start_glyph = -1; - iter->start_index = glyph_item->item->idx + glyph_item->item->len; + iter->start_index = glyph_item->item->si + glyph_item->item->len; iter->start_char = glyph_item->item->len; iter->end_glyph = iter->start_glyph; diff --git a/src/newgdi/layoutinfo.c b/src/newgdi/layoutinfo.c index 75ef6b23..c8b8c9f2 100644 --- a/src/newgdi/layoutinfo.c +++ b/src/newgdi/layoutinfo.c @@ -54,34 +54,34 @@ #include "layoutinfo.h" LAYOUTINFO* GUIAPI CreateLayoutInfo( - const TEXTRUNSINFO* runinfo, Uint32 render_flags, + const TEXTRUNSINFO* truninfo, Uint32 render_flags, const BreakOppo* break_oppos, BOOL persist_lines, int letter_spacing, int word_spacing, int tab_size) { - LAYOUTINFO* layoutinfo; + LAYOUTINFO* layout; - if (runinfo == NULL || runinfo->sei.inst == NULL) { + if (truninfo == NULL || truninfo->sei.inst == NULL) { return NULL; } - layoutinfo = (LAYOUTINFO*)calloc(1, sizeof(LAYOUTINFO)); - if (layoutinfo == NULL) { + layout = (LAYOUTINFO*)calloc(1, sizeof(LAYOUTINFO)); + if (layout == 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; + layout->truninfo = truninfo; + layout->bos = break_oppos; + layout->rf = render_flags; + layout->ls = letter_spacing; + layout->ws = word_spacing; + layout->ts = tab_size; - INIT_LIST_HEAD(&layoutinfo->line_head); - layoutinfo->left_ucs = runinfo->nr_ucs; + INIT_LIST_HEAD(&layout->line_head); + layout->left_ucs = truninfo->nr_ucs; - layoutinfo->persist = persist_lines ? 1 : 0; + layout->persist = persist_lines ? 1 : 0; - return layoutinfo; + return layout; } static void release_glyph_string(GLYPHSTRING* gs) @@ -105,9 +105,9 @@ static void release_run(GLYPHRUN* 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); + while (!list_empty(&line->grun_head)) { + GLYPHRUN* run = (GLYPHRUN*)line->grun_head.prev; + list_del(line->grun_head.prev); release_run(run); } @@ -162,7 +162,7 @@ struct _LayoutState { /* Glyphs for the current text run */ GLYPHSTRING* glyphs; - /* Character offset of first item in state->item in layout->runinfo->ucs */ + /* Character offset of first item in state->item in layout->truninfo->ucs */ int start_offset; /* Logical widths for the current text run */ @@ -172,7 +172,7 @@ struct _LayoutState { * to the remaining portion of the first item */ int log_widths_offset; - /* Start index of line in layout->runinfo->ucs */ + /* Start index of line in layout->truninfo->ucs */ int line_start_index; /* maintained per line */ @@ -221,7 +221,7 @@ static void shape_shape(const Uchar32* ucs, int nr_ucs, static void shape_full(const Uchar32* item_ucs, int nr_item_ucs, const Uchar32* para_ucs, int nr_para_ucs, - const TEXTRUNSINFO* runinfo, const TEXTRUN* textrun, + const TEXTRUNSINFO* truninfo, const TEXTRUN* textrun, GLYPHSTRING* glyphs) { } @@ -244,17 +244,17 @@ static GLYPHSTRING* shape_run(LAYOUTLINE *line, LayoutState *state, LAYOUTINFO *layout = line->layout; GLYPHSTRING *glyphs = __mg_glyph_string_new (); - if (layout->runinfo->ucs[item->idx] == '\t') + if (layout->truninfo->ucs[item->si] == '\t') shape_tab(line, glyphs); else { if (state->shape_set) - shape_shape(layout->runinfo->ucs + item->idx, item->len, + shape_shape(layout->truninfo->ucs + item->si, item->len, &state->shape_ink_rect, &state->shape_logical_rect, glyphs); else - shape_full(layout->runinfo->ucs + item->idx, item->len, - layout->runinfo->ucs, layout->runinfo->nr_ucs, - layout->runinfo, item, glyphs); + shape_full(layout->truninfo->ucs + item->si, item->len, + layout->truninfo->ucs, layout->truninfo->nr_ucs, + layout->truninfo, item, glyphs); if (layout->ls) { GlyphItem glyph_item; @@ -264,7 +264,7 @@ static GLYPHSTRING* shape_run(LAYOUTLINE *line, LayoutState *state, glyph_item.glyphs = glyphs; __mg_glyph_item_letter_space (&glyph_item, - layout->runinfo->ucs, + layout->truninfo->ucs, layout->bos + state->start_offset, layout->ls); @@ -279,6 +279,58 @@ static GLYPHSTRING* shape_run(LAYOUTLINE *line, LayoutState *state, return glyphs; } +static GLYPHRUN* insert_run (LAYOUTLINE *line, LayoutState *state, + TEXTRUN *text_run, int si, int len, BOOL last_run) +{ + GLYPHRUN *glyph_run = malloc (sizeof(GLYPHRUN)); + + glyph_run->trun = text_run; + + if (last_run && state->log_widths_offset == 0) + glyph_run->gs = state->glyphs; + else + glyph_run->gs = shape_run (line, state, text_run); + + if (last_run) { + if (state->log_widths_offset > 0) + __mg_glyph_string_free (state->glyphs); + state->glyphs = NULL; + free (state->log_widths); + state->log_widths = NULL; + } + + glyph_run->si = si; + glyph_run->len = len; + + list_add_tail(&glyph_run->list, &line->grun_head); + line->len += text_run->len; + + return glyph_run; +} + +static inline BOOL can_break_at (LAYOUTINFO *layout, + int offset, BOOL always_wrap_char) +{ + Uint32 wrap = layout->rf & GRF_OVERFLOW_WRAP_MASK; + + if (offset == layout->truninfo->nr_ucs) + return TRUE; + + if (wrap == GRF_OVERFLOW_WRAP_NORMAL) + wrap = always_wrap_char ? GRF_OVERFLOW_WRAP_ANYWHERE : + GRF_OVERFLOW_WRAP_BREAK_WORD; + + else if (wrap == GRF_OVERFLOW_WRAP_BREAK_WORD) + return layout->bos[offset] & BOV_LB_BREAK_FLAG; + else if (wrap == GRF_OVERFLOW_WRAP_ANYWHERE) + return layout->bos[offset] & BOV_GB_CHAR_BREAK; + else { + _WRN_PRINTF ("broken LayoutInfo\n"); + } + + return TRUE; +} + /* * Tries to insert as much as possible of the text runs at the head of * state->items onto @line. Five results are possible: @@ -299,14 +351,13 @@ static GLYPHSTRING* shape_run(LAYOUTLINE *line, LayoutState *state, * or %BREAK_NONE_FIT returned. This is used when the end of the * run is not a break position. */ -static BreakResult process_one_text_run(LAYOUTINFO *layout, +BreakResult process_one_text_run(LAYOUTINFO *layout, LAYOUTLINE *line, LayoutState *state, BOOL force_fit, BOOL no_break_at_end) { TEXTRUN *item = state->item; BOOL shape_set = FALSE; int width; - int length; int i; BOOL processing_new_item = FALSE; @@ -315,7 +366,6 @@ static BreakResult process_one_text_run(LAYOUTINFO *layout, #define LINE_SEPARATOR 0x2028 if (!state->glyphs) { - pango_layout_get_item_properties (item, &state->properties); state->glyphs = shape_run (line, state, item); state->log_widths = NULL; @@ -325,16 +375,16 @@ static BreakResult process_one_text_run(LAYOUTINFO *layout, } if (!layout->single_paragraph && - layout->runinfo->text[item->idx] == LINE_SEPARATOR && + layout->truninfo->ucs[item->si] == LINE_SEPARATOR && !should_ellipsize_current_line (layout, state)) { - insert_run (line, state, item, TRUE); + insert_run (line, state, item, 0, item->len, TRUE); state->log_widths_offset += item->len; return BREAK_LINE_SEPARATOR; } if (state->remaining_width < 0 && !no_break_at_end) /* Wrapping off */ { - insert_run (line, state, item, TRUE); + insert_run (line, state, item, 0, item->len, TRUE); return BREAK_ALL_FIT; } @@ -349,11 +399,11 @@ static BreakResult process_one_text_run(LAYOUTINFO *layout, } if ((width <= state->remaining_width || - (item->len == 1 && !line->runs)) && + (item->len == 1 && list_empty(&line->grun_head))) && !no_break_at_end) { state->remaining_width -= width; state->remaining_width = MAX (state->remaining_width, 0); - insert_run (line, state, item, TRUE); + insert_run (line, state, item, 0, item->len, TRUE); return BREAK_ALL_FIT; } @@ -367,7 +417,7 @@ static BreakResult process_one_text_run(LAYOUTINFO *layout, if (processing_new_item) { GlyphItem glyph_item = {item, state->glyphs}; state->log_widths = malloc (sizeof (int) * item->len); - __mg_glyph_item_get_logical_widths(&glyph_item, layout->runinfo->ucs, + __mg_glyph_item_get_logical_widths(&glyph_item, layout->truninfo->ucs, state->log_widths); } @@ -380,8 +430,9 @@ retry_break: break; /* If there are no previous runs we have to take care to grab at least one char. */ - if (can_break_at (layout, state->start_offset + num_chars, retrying_with_char_breaks) && - (num_chars > 0 || line->runs)) + if (can_break_at (layout, state->start_offset + num_chars, + retrying_with_char_breaks) && + (num_chars > 0 || !list_empty(&line->grun_head))) { break_num_chars = num_chars; break_width = width; @@ -395,13 +446,15 @@ retry_break: * XXX Currently it doesn't quite match the logic there. We don't check * the cluster here. But should be fine in practice. */ if (break_num_chars > 0 && break_num_chars < item->len && - layout->log_attrs[state->start_offset + break_num_chars - 1].is_white) + layout->bos[state->start_offset + break_num_chars - 1] & BOV_WHITESPACE) { break_width -= state->log_widths[state->log_widths_offset + break_num_chars - 1]; } - if (layout->wrap == PANGO_WRAP_WORD_CHAR && force_fit && break_width > state->remaining_width && !retrying_with_char_breaks) - { + if ((layout->rf & GRF_OVERFLOW_WRAP_MASK) == GRF_OVERFLOW_WRAP_NORMAL + && force_fit + && break_width > state->remaining_width + && !retrying_with_char_breaks) { retrying_with_char_breaks = TRUE; num_chars = item->len; width = orig_width; @@ -412,34 +465,26 @@ retry_break: if (force_fit || break_width <= state->remaining_width) /* Successfully broke the item */ { - if (state->remaining_width >= 0) - { + if (state->remaining_width >= 0) { state->remaining_width -= break_width; state->remaining_width = MAX (state->remaining_width, 0); } - if (break_num_chars == item->len) - { - insert_run (line, state, item, TRUE); - + if (break_num_chars == item->len) { + insert_run (line, state, item, 0, item->len, TRUE); return BREAK_ALL_FIT; } - else if (break_num_chars == 0) - { + else if (break_num_chars == 0) { return BREAK_EMPTY_FIT; } - else - { - TEXTRUN *new_item; + else { + GLYPHRUN *grun; - length = g_utf8_offset_to_pointer (layout->runinfo->ucs + item->idx, break_num_chars) - (layout->runinfo->ucs + item->idx); - - new_item = pango_item_split (item, length, break_num_chars); - - /* Add the width back, to the line, reshape, subtract the new width */ + /* Add the width back, to the line, reshape, + subtract the new width */ state->remaining_width += break_width; - insert_run (line, state, new_item, FALSE); - break_width = __mg_glyph_string_get_width (NULL /*((GlyphItem *)(line->runs->data))->glyphs*/); + grun = insert_run (line, state, item, 0, break_num_chars, FALSE); + break_width = __mg_glyph_string_get_width (grun->gs); state->remaining_width -= break_width; state->log_widths_offset += break_num_chars; diff --git a/src/newgdi/layoutinfo.h b/src/newgdi/layoutinfo.h index 21b44031..19c33a49 100644 --- a/src/newgdi/layoutinfo.h +++ b/src/newgdi/layoutinfo.h @@ -66,10 +66,10 @@ struct _GLYPHSTRING { struct _GLYPHRUN { struct list_head list; - TEXTRUN* text; // the text run to which this glyph run belongs + TEXTRUN* trun; // the text run to which this glyph run belongs GLYPHSTRING* gs; // the glyph string - int offset; // the offset of the first uchar in the text run - int nr_ucs; // the number of the uchars + int si; // the start index in the text run + int len; // the number of the uchars }; struct _LAYOUTLINE { @@ -77,10 +77,10 @@ struct _LAYOUTLINE { LAYOUTINFO* layout; int* log_widths; // the widths of the logical chars - struct list_head run_head; // the list head for glyph runs + struct list_head grun_head; // the list head for glyph runs - int idx; // the index in the uchar string - int nr_ucs; // the number of the uchars + int si; // the start index in the uchar string + int len; // the length of line (number of uchars) Uint8 first_line:1; // is first line of the paragraph? Uint8 resolved_dir:3; // resolved direction of the line @@ -89,7 +89,7 @@ struct _LAYOUTLINE { }; struct _LAYOUTINFO { - const TEXTRUNSINFO* runinfo; + const TEXTRUNSINFO* truninfo; const BreakOppo* bos; Uint32 rf; diff --git a/src/newgdi/shape-glyphs-basic.c b/src/newgdi/shape-glyphs-basic.c index bf7af69f..7de0c726 100644 --- a/src/newgdi/shape-glyphs-basic.c +++ b/src/newgdi/shape-glyphs-basic.c @@ -83,7 +83,7 @@ static BOOL shape_text_run(SEINSTANCE* inst, { BOOL ok = FALSE; int i, j; - const Uchar32* logical_ucs = info->ucs + run->idx; + const Uchar32* logical_ucs = info->ucs + run->si; int nr_ucs = run->len; Uchar32 local_shaped_ucs[LOCAL_ARRAY_SIZE]; diff --git a/src/newgdi/textrunsinfo.c b/src/newgdi/textrunsinfo.c index 1f4d3f28..7cbbf04d 100644 --- a/src/newgdi/textrunsinfo.c +++ b/src/newgdi/textrunsinfo.c @@ -257,7 +257,7 @@ static void state_add_character(TEXTRUNSTATE *state, state->run->lf = NULL; else state->run->lf = create_logfont_for_ort(state->runinfo, state->ort_rsv); - state->run->idx = pos - state->text; + state->run->si = pos - state->text; state->run->len = 1; state->run->lc = state->derived_lang; state->run->st = state->script_iter.script; @@ -468,7 +468,7 @@ void* GetNextTextRunInfo(TEXTRUNSINFO* runinfo, } if (logfont) *logfont = run->lf; - if (start_index) *start_index = run->idx; + if (start_index) *start_index = run->si; if (length) *length = run->len; if (lang_code) *lang_code = run->lc; if (script) *script = run->st; diff --git a/src/newgdi/textrunsinfo.h b/src/newgdi/textrunsinfo.h index 4a5eadf7..fb587a69 100644 --- a/src/newgdi/textrunsinfo.h +++ b/src/newgdi/textrunsinfo.h @@ -73,7 +73,7 @@ struct _TEXTRUN { struct list_head list; LOGFONT* lf; // the logfont for this run - int idx; // start index in the Unicode string + int si; // start index in the Unicode string int len; // the number of Unicode characters Uint32 lc:8; // language code