debug LayoutInfo implementaion

This commit is contained in:
Vincent Wei
2019-03-26 11:24:31 +08:00
parent c890e4296a
commit f5e1144cbe
4 changed files with 215 additions and 70 deletions

View File

@@ -12553,7 +12553,7 @@ typedef struct _TEXTRUNSINFO TEXTRUNSINFO;
/**
* Split a Uchar32 paragraph string in mixed scripts into text runs.
*/
MG_EXPORT TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(Uchar32* ucs, int nr_ucs,
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);

View File

@@ -42,6 +42,8 @@
#include <stdlib.h>
#include <string.h>
#define DEBUG
#include "common.h"
#ifdef _MGCHARSET_UNICODE
@@ -248,12 +250,18 @@ LayoutRun* __mg_layout_run_split(LayoutRun *orig, int split_index)
if (split_index >= orig->len)
return NULL;
_DBG_PRINTF("%s: orig: %d, %d\n",
__FUNCTION__, orig->si, orig->len);
new_run = __mg_layout_run_copy(orig);
new_run->len = split_index;
orig->si += split_index;
orig->len -= split_index;
_DBG_PRINTF("%s: new layout run: %d, %d; orig: %d, %d\n",
__FUNCTION__, new_run->si, new_run->len, orig->si, orig->len);
return new_run;
}
@@ -358,12 +366,9 @@ void __mg_glyph_run_free(GlyphRun* run)
* be at least one byte assigned to each item, you can't create a
* zero-length item).
*
* This function is similar in function to pango_item_split() (and uses
* it internally.)
*
* Return value: the newly allocated item representing text before
* @split_index, which should be freed
* with pango_glyph_run_free().
* with __mg_glyph_run_free().
**/
GlyphRun *__mg_glyph_run_split (GlyphRun *orig, int split_index)
{
@@ -381,6 +386,9 @@ GlyphRun *__mg_glyph_run_split (GlyphRun *orig, int split_index)
if (split_index >= orig->lrun->len)
return NULL;
_DBG_PRINTF("%s: called, orig: %d, %d, split at: %d\n",
__FUNCTION__, orig->lrun->si, orig->lrun->len, split_index);
if (LTR (orig)) {
for (i = 0; i < orig->gstr->nr_glyphs; i++) {
if (orig->gstr->log_clusters[i] >= split_index)

View File

@@ -42,6 +42,8 @@
#include <stdlib.h>
#include <string.h>
#define DEBUG
#include "common.h"
#ifdef _MGCHARSET_UNICODE
@@ -402,15 +404,81 @@ static void free_glyph_run (GlyphRun *grun)
free(grun);
}
static void uninsert_run (LAYOUTLINE *line)
#ifdef DEBUG
static inline void print_line_runs(const LAYOUTLINE* line, const char* func)
{
int j = 0;
struct list_head* i;
_DBG_PRINTF("Runs in line after calling %s (line length: %d):\n",
func, line->len);
list_for_each(i, &line->gruns) {
GlyphRun* run = (GlyphRun*)i;
_DBG_PRINTF("RUN NO.: %d\n", j);
_DBG_PRINTF(" ADDRESS: %p\n", run);
_DBG_PRINTF(" INDEX: %d\n", run->lrun->si);
_DBG_PRINTF(" LENGHT: %d\n", run->lrun->len);
_DBG_PRINTF(" EMBEDDING LEVEL:%d\n", run->lrun->len);
_DBG_PRINTF(" NR GLYPHS: %d\n", run->gstr->nr_glyphs);
j++;
}
}
static inline void print_run(const GlyphRun* run, const char* func)
{
_DBG_PRINTF("Run in %s:\n", func);
_DBG_PRINTF(" ADDRESS: %p\n", run);
_DBG_PRINTF(" INDEX: %d\n", run->lrun->si);
_DBG_PRINTF(" LENGHT: %d\n", run->lrun->len);
_DBG_PRINTF(" EMBEDDING LEVEL:%d\n", run->lrun->len);
_DBG_PRINTF(" NR GLYPHS: %d\n", run->gstr->nr_glyphs);
}
static inline void list_print(struct list_head* head, const char* desc)
{
int i = 0;
struct list_head* e;
printf ("entries in list (%p, next: %p, prev: %p) %s\n",
head, head->next, head->prev, desc);
list_for_each(e, head) {
printf ("%d: %p\n", i, e);
i++;
}
}
#else
static inline void print_line_runs(const LAYOUTLINE* line, const char* func)
{
// do nothing.
}
static inline void print_run(const GlyphRun* run, const char* func)
{
// do nothing.
}
static inline void list_print(struct list_head* head, const char* desc)
{
// do nothing.
}
#endif
static void uninsert_run(LAYOUTLINE *line)
{
GlyphRun *grun;
grun = (GlyphRun*)&line->gruns.next;
grun = (GlyphRun*)line->gruns.next;
list_del(line->gruns.next);
line->len -= grun->lrun->len;
free_glyph_run(grun);
print_line_runs(line, __FUNCTION__);
}
static GlyphRun* insert_run(LAYOUTLINE *line, LayoutState *state,
@@ -436,6 +504,8 @@ static GlyphRun* insert_run(LAYOUTLINE *line, LayoutState *state,
list_add_tail(&glyph_run->list, &line->gruns);
line->len += layout_run->len;
print_line_runs(line, __FUNCTION__);
return glyph_run;
}
@@ -628,10 +698,13 @@ retry_break:
new_lrun = __mg_layout_run_split(lrun, break_num_chars);
state->lrun = new_lrun;
__mg_layout_run_free(lrun);
/* Add the width back, to the line, reshape,
subtract the new width */
state->remaining_width += break_width;
grun = insert_run (line, state, new_lrun, FALSE);
grun = insert_run(line, state, new_lrun, FALSE);
break_width = __mg_glyph_string_get_width(grun->gstr);
state->remaining_width -= break_width;
@@ -714,106 +787,115 @@ static void line_set_resolved_dir(LAYOUTLINE *line, GlyphRunDir direction)
}
}
static struct list_head reorder_runs_recurse (struct list_head* entry,
int n_items)
static void reorder_runs_recurse(struct list_head* result,
GlyphRun** runs, int n_items)
{
struct list_head *tmp, *level_start_node;
GlyphRun **tmp, **level_start_node;
int i, level_start_i;
int min_level = INT_MAX;
struct list_head result;
INIT_LIST_HEAD(&result);
INIT_LIST_HEAD(result);
if (n_items == 0)
return result;
return;
tmp = entry;
for (i = 0; i < n_items; i++) {
GlyphRun *run = (GlyphRun*)tmp;
GlyphRun *run = runs[i];
min_level = MIN (min_level, run->lrun->el);
tmp = tmp->next;
}
level_start_i = 0;
level_start_node = entry;
tmp = entry;
level_start_node = runs;
tmp = runs;
for (i = 0; i < n_items; i++) {
GlyphRun *run = (GlyphRun*)tmp;
GlyphRun* run = runs[i];
if (run->lrun->el == min_level) {
if (min_level % 2) {
if (i > level_start_i) {
struct list_head sub_result;
sub_result = reorder_runs_recurse (level_start_node,
reorder_runs_recurse (&sub_result, level_start_node,
i - level_start_i);
if (!list_empty(&result)) {
list_add_tail(result.next, &sub_result);
}
result = sub_result;
list_concat(&sub_result, result);
list_move(result, &sub_result); // result = sub_result;
}
list_add(&run->list, &result);
list_add(&run->list, result);
}
else {
if (i > level_start_i) {
struct list_head sub_result;
sub_result = reorder_runs_recurse (level_start_node,
reorder_runs_recurse (&sub_result, level_start_node,
i - level_start_i);
if (!list_empty(&sub_result)) {
list_add_tail(sub_result.next, &result);
}
list_concat(result, &sub_result);
}
list_add(&run->list, &result);
list_add_tail(&run->list, result);
}
level_start_i = i + 1;
level_start_node = tmp->next;
level_start_node = tmp + 1;
}
tmp = tmp->next;
tmp++;
}
if (min_level % 2) {
if (i > level_start_i) {
struct list_head sub_result;
sub_result = reorder_runs_recurse (level_start_node,
reorder_runs_recurse(&sub_result, level_start_node,
i - level_start_i);
if (!list_empty(&result)) {
list_add_tail(result.next, &sub_result);
}
result = sub_result;
list_concat(&sub_result, result);
list_move(result, &sub_result); // result = sub_result;
}
}
else {
if (i > level_start_i) {
struct list_head sub_result;
sub_result = reorder_runs_recurse (level_start_node,
reorder_runs_recurse(&sub_result, level_start_node,
i - level_start_i);
if (!list_empty(&sub_result)) {
list_add_tail(sub_result.next, &result);
}
list_concat(result, &sub_result);
}
}
return result;
list_print(result, "returned from reorder_runs_recurse");
return;
}
static void reverse_runs(LAYOUTLINE *line)
static void reverse_runs(struct list_head* result,
GlyphRun** runs, int n_items)
{
int i;
INIT_LIST_HEAD(result);
for (i = n_items - 1; i >= 0; i--) {
GlyphRun* run = runs[i];
list_add_tail(&run->list, result);
}
}
static inline void list_reverse(struct list_head* head)
{
struct list_head tmp_head;
INIT_LIST_HEAD(&tmp_head);
while (!list_empty(&line->gruns)) {
GlyphRun* run = (GlyphRun*)line->gruns.prev;
list_del(line->gruns.prev);
list_add_tail(&run->list, &tmp_head);
while (!list_empty(head)) {
struct list_head* entry = head->prev;
list_del(head->prev);
list_add_tail(entry, &tmp_head);
}
line->gruns = tmp_head;
list_move(head, &tmp_head);
}
/* Local array size, used for stack-based local arrays */
#if SIZEOF_PTR == 8
# define LOCAL_ARRAY_SIZE 256
#else
# define LOCAL_ARRAY_SIZE 128
#endif
static void layout_line_reorder(LAYOUTLINE *line)
{
struct list_head *i;
@@ -821,6 +903,16 @@ static void layout_line_reorder(LAYOUTLINE *line)
Uint8 level_or = 0, level_and = 1;
int length = 0;
GlyphRun** runs = NULL;
GlyphRun* local_runs[LOCAL_ARRAY_SIZE];
if (length > LOCAL_ARRAY_SIZE) {
runs = malloc(sizeof(GlyphRun*) * length);
}
else {
runs = local_runs;
}
/* Check if all gruns are in the same direction, in that case, the
* line does not need modification and we can avoid the expensive
* reorder runs recurse procedure.
@@ -829,6 +921,8 @@ static void layout_line_reorder(LAYOUTLINE *line)
list_for_each(i, &line->gruns) {
GlyphRun *grun = (GlyphRun*)i;
runs[length] = grun;
level_or |= grun->lrun->el;
level_and &= grun->lrun->el;
length++;
@@ -841,10 +935,31 @@ static void layout_line_reorder(LAYOUTLINE *line)
all_odd = (level_and & 0x1) == 1;
if (!all_even && !all_odd) {
line->gruns = reorder_runs_recurse(line->gruns.next, length);
reorder_runs_recurse(&line->gruns, runs, length);
}
else if (all_odd)
reverse_runs(line);
else if (all_odd) {
reverse_runs(&line->gruns, runs, length);
}
print_line_runs(line, __FUNCTION__);
#if 0 /* test code for list_reverse and reverse_runs */
list_reverse(&line->gruns);
print_line_runs(line, "list_reverse");
length = 0;
list_for_each(i, &line->gruns) {
GlyphRun *grun = (GlyphRun*)i;
runs[length] = grun;
length++;
}
reverse_runs(&line->gruns, runs, length);
print_line_runs(line, "reverse_runs");
#endif
if (runs && runs != local_runs)
free(runs);
}
static void zero_line_final_space (LAYOUTLINE *line,
@@ -940,7 +1055,7 @@ static void adjust_line_letter_spacing(LAYOUTLINE *line, LayoutState *state)
if (line->resolved_dir == GLYPH_RUN_DIR_RTL) {
list_for_each(l, &line->gruns) {
if (is_tab_run (layout, (GlyphRun*)l)) {
reverse_runs(line);
list_reverse(&line->gruns);
reversed = TRUE;
break;
}
@@ -1007,7 +1122,7 @@ static void adjust_line_letter_spacing(LAYOUTLINE *line, LayoutState *state)
}
if (reversed)
reverse_runs (line);
list_reverse(&line->gruns);
}
static void justify_clusters (LAYOUTLINE *line, LayoutState *state)
@@ -1265,15 +1380,7 @@ static void layout_line_postprocess (LAYOUTLINE *line,
/* Truncate the logical-final whitespace in the line
* if we broke the line at it */
if (wrapped)
/* The runs are in reverse order at this point,
* since we prepended them to the list.
* So, the first run is the last logical run. */
zero_line_final_space (line, state, (GlyphRun*)&line->gruns.next);
/*
* Reverse the runs
*/
//line->runs = g_slist_reverse (line->runs);
zero_line_final_space (line, state, (GlyphRun*)line->gruns.prev);
/* Ellipsize the line if necessary
*/
@@ -1347,6 +1454,11 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
first_lrun_in_line = list_empty(&line->gruns);
result = process_layout_run(layout, line, state, !have_break, FALSE);
lrun = state->lrun;
_DBG_PRINTF("%s: result of process_layout_run: %d\n",
__FUNCTION__, result);
switch (result) {
case BREAK_ALL_FIT:
if (can_break_in (layout, state->start_offset,
@@ -1368,11 +1480,15 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
goto done;
case BREAK_SOME_FIT:
_DBG_PRINTF("%s: handle BREAK_SOME_FIT: %d\n",
__FUNCTION__, lrun->len);
state->start_offset += old_num_chars - lrun->len;
wrapped = TRUE;
goto done;
case BREAK_NONE_FIT:
_DBG_PRINTF("%s: handle BREAK_NONE_FIT: %d\n",
__FUNCTION__, lrun->len);
/* Back up over unused runs to run where there is a break */
while (!list_empty(&line->gruns) &&
line->gruns.next != break_link) {
@@ -1397,9 +1513,10 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
lrun = state->lrun;
old_num_chars = lrun->len;
result = process_layout_run(layout, line, state, TRUE, TRUE);
assert(result == BREAK_SOME_FIT || result == BREAK_EMPTY_FIT);
state->start_offset += old_num_chars - lrun->len;
state->start_offset += old_num_chars - state->lrun->len;
wrapped = TRUE;
goto done;
@@ -1416,7 +1533,9 @@ static LAYOUTLINE* check_next_line(LAYOUTINFO* layout, LayoutState* state)
}
done:
layout_line_postprocess (line, state, wrapped);
_DBG_PRINTF("%s: calling layout_line_postprocess: %d\n",
__FUNCTION__, line->len);
layout_line_postprocess(line, state, wrapped);
state->line_of_par++;
state->line_start_index += line->len;
return line;
@@ -1425,6 +1544,24 @@ done:
static int traverse_line_glyphs(LAYOUTLINE* line, int x, int y,
CB_GLYPH_LAID_OUT cb_laid_out, GHANDLE ctxt)
{
int j = 0;
struct list_head* i;
int line_adv = 0;
list_for_each(i, &line->gruns) {
GlyphRun* run = (GlyphRun*)i;
for (j = 0; j < run->gstr->nr_glyphs; j++) {
ShapedGlyph* sg = run->gstr->glyphs + j;
GLYPHPOS pos;
pos.x = x + line_adv;
pos.y = y;
pos.x_off = sg->x_off;
pos.y_off = sg->y_off;
line_adv += sg->width;
cb_laid_out(ctxt, run->lrun->lf, 0, run->gstr->glyphs[j].gv, &pos);
}
}
return 0;
}
@@ -1476,7 +1613,7 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
state.line_start_index = 0;
state.start_index_in_trun = 0;
state.trun = (TextRun*)&layout->truninfo->truns.next;
state.trun = (TextRun*)layout->truninfo->truns.next;
}
else {
state.line_start_index = layout->truninfo->nr_ucs - layout->nr_left_ucs;
@@ -1497,7 +1634,7 @@ LAYOUTLINE* GUIAPI LayoutNextLine(
if (layout->persist) {
list_add_tail(&next_line->list, &layout->lines);
}
else {
else if (prev_line) {
release_line(prev_line);
}

View File

@@ -438,7 +438,7 @@ out:
return ok;
}
TEXTRUNSINFO* GUIAPI CreateTextRunsInfo(Uchar32* ucs, int nr_ucs,
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)