📄 dw_page.c
字号:
/* * Standard Dw function */static void Dw_page_add (DwContainer *container, DwWidget *widget){ /* todo */}/* * Standard Dw function */static void Dw_page_remove (DwContainer *container, DwWidget *widget){ /* todo */}/* * Standard Dw function */static void Dw_page_forall (DwContainer *container, DwCallback callback, gpointer callback_data){ DwPage *page; int word_index; DwPageWord *word; page = DW_PAGE (container); for (word_index = 0; word_index < page->num_words; word_index++) { word = &page->words[word_index]; if (word->content.type == DW_CONTENT_WIDGET) (*callback) (word->content.data.widget, callback_data); }}/* * ... * * avail_line is passed from Dw_page_real_word_wrap, to avoid calculating * it twice. */static void Dw_page_justify_line (DwPage *page, DwPageLine *line, gint32 avail_width){ /* To avoid rounding errors, the calculation is based on accumulated * values (*_cum). */ gint i; gint32 orig_space_sum, orig_space_cum; gint32 eff_space_diff_cum, last_eff_space_diff_cum; gint32 diff; diff = avail_width - page->last_line_width; if (diff > 0) { orig_space_sum = 0; for (i = line->first_word; i < line->last_word - 1; i++) orig_space_sum += page->words[i].orig_space; orig_space_cum = 0; last_eff_space_diff_cum = 0; for (i = line->first_word; i < line->last_word - 1; i++) { orig_space_cum += page->words[i].orig_space; if (orig_space_cum == 0) eff_space_diff_cum = last_eff_space_diff_cum; else eff_space_diff_cum = diff * orig_space_cum / orig_space_sum; page->words[i].eff_space = page->words[i].orig_space + (eff_space_diff_cum - last_eff_space_diff_cum); DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", i, page->words[i].eff_space); last_eff_space_diff_cum = eff_space_diff_cum; } }}/* * ... */static void Dw_page_add_line (DwPage *page, gint word_ind, gboolean new_par){ DwPageLine *last_line, *plast_line; DBG_MSG (page, "wrap", 0, "Dw_page_add_line"); DBG_MSG_START (page); page->num_lines++; a_List_add (page->lines, page->num_lines, page->num_lines_max); DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines); DEBUG_MSG (DEBUG_REWRAP_LEVEL, "--- new line %d in %p, with word %d of %d" "\n", page->num_lines - 1, page, word_ind, page->num_words); last_line = &page->lines[page->num_lines - 1]; if (page->num_lines == 1) plast_line = NULL; else plast_line = &page->lines[page->num_lines - 2]; if (plast_line) { /* second or more lines: copy values of last line */ last_line->top = plast_line->top + plast_line->ascent + plast_line->descent + plast_line->break_space; last_line->max_line_width = plast_line->max_line_width; last_line->max_word_min = plast_line->max_word_min; last_line->max_par_max = plast_line->max_par_max; last_line->par_min = plast_line->par_min; last_line->par_max = plast_line->par_max; } else { /* first line: initialize values */ last_line->top = 0; last_line->max_line_width = page->line1_offset_eff; last_line->max_word_min = 0; last_line->max_par_max = 0; last_line->par_min = page->line1_offset_eff; last_line->par_max = page->line1_offset_eff; } DBG_OBJ_ARRSET_NUM (page, "lines.%d.top", page->num_lines - 1, last_line->top); DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_line_width", page->num_lines - 1, last_line->max_line_width); DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_word_min", page->num_lines - 1, last_line->max_word_min); DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_par_max", page->num_lines - 1, last_line->max_par_max); DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_min", page->num_lines - 1, last_line->par_min); DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_max", page->num_lines - 1, last_line->par_max); last_line->first_word = word_ind; last_line->ascent = 0; last_line->descent = 0; last_line->margin_descent = 0; last_line->break_space = 0; last_line->left_offset = 0; DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1, last_line->ascent); DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1, last_line->descent); /* update values in line */ last_line->max_line_width = MAX (last_line->max_line_width, page->last_line_width); if (page->num_lines > 1) page->last_line_width = 0; else page->last_line_width = page->line1_offset_eff; if (new_par) { last_line->max_par_max = MAX (last_line->max_par_max, page->last_line_par_max); DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_par_max", page->num_lines - 1, last_line->max_par_max); if (page->num_lines > 1) { last_line->par_min = 0; last_line->par_max = 0; } else { last_line->par_min = page->line1_offset_eff; last_line->par_max = page->line1_offset_eff; } page->last_line_par_min = 0; page->last_line_par_max = 0; DBG_OBJ_SET_NUM(page, "last_line_par_min", page->last_line_par_min); DBG_OBJ_SET_NUM(page, "last_line_par_max", page->last_line_par_max); } last_line->par_min = page->last_line_par_min; last_line->par_max = page->last_line_par_max; DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_min", page->num_lines - 1, last_line->par_min); DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_max", page->num_lines - 1, last_line->par_max); DBG_MSG_END (page);}/* * This function is called in two cases: (i) when a word is added (by * Dw_page_add_word), and (ii) when a page has to be (partially) * rewrapped. It does word wrap, and adds new lines, if necesary. */static void Dw_page_real_word_wrap (DwPage *page, gint word_ind){ DwPageLine *last_line; DwPageWord *word, *prev_word; gint32 avail_width, last_space, left_offset; gboolean new_line = FALSE, new_par = FALSE; DwWidget *widget = DW_WIDGET (page); DwExtremes word_extremes; DBG_MSGF (page, "wrap", 0, "Dw_page_real_word_wrap (%d): %s, width = %d", word_ind, a_Dw_content_html (&page->words[word_ind].content), page->words[word_ind].size.width); DBG_MSG_START (page); avail_width = page->avail_width - p_Dw_style_box_diff_width (widget->style) - page->inner_padding; if (prefs.limit_text_width && avail_width > widget->viewport->allocation.width - 10) avail_width = widget->viewport->allocation.width - 10; word = &page->words[word_ind]; if (page->num_lines == 0) { DBG_MSG (page, "wrap", 0, "first line"); new_line = TRUE; new_par = TRUE; last_line = NULL; } else { last_line = &page->lines[page->num_lines - 1]; if (page->num_words > 0) { prev_word = &page->words[word_ind - 1]; if (prev_word->content.type == DW_CONTENT_BREAK) { DBG_MSG (page, "wrap", 0, "after a break"); /* previous word is a break */ new_line = TRUE; new_par = TRUE; } else if (word->style->white_space != DW_STYLE_WHITE_SPACE_NORMAL) { DBG_MSGF (page, "wrap", 0, "no wrap (white_space = %d)", word->style->white_space); new_line = FALSE; new_par = FALSE; } else { if (last_line->first_word != word_ind) { /* Does new word fit into the last line? */ DBG_MSGF (page, "wrap", 0, "word %d (%s) fits? (%d + %d + %d <= %d)...", word_ind, a_Dw_content_html (&word->content), page->last_line_width, prev_word->orig_space, word->size.width, avail_width); new_line = (page->last_line_width + prev_word->orig_space + word->size.width > avail_width); DBG_MSGF (page, "wrap", 0, "... %s.", new_line ? "No" : "Yes"); } } } } /* Has sometimes the wrong value. */ word->eff_space = word->orig_space; DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", word_ind, word->eff_space); /* Test, whether line1_offset can be used. */ if (word_ind == 0) { if (page->ignore_line1_offset_sometimes) { if (page->line1_offset + word->size.width > avail_width) page->line1_offset_eff = 0; else page->line1_offset_eff = page->line1_offset; } else page->line1_offset_eff = page->line1_offset; } if (last_line != NULL && new_line && !new_par && word->style->text_align == DW_STYLE_TEXT_ALIGN_JUSTIFY) Dw_page_justify_line (page, last_line, avail_width); if (new_line) { Dw_page_add_line (page, word_ind, new_par); last_line = &page->lines[page->num_lines - 1]; } last_line->last_word = word_ind + 1; last_line->ascent = MAX (last_line->ascent, word->size.ascent); last_line->descent = MAX (last_line->descent, word->size.descent); DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1, last_line->ascent); DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1, last_line->descent); if (word->content.type == DW_CONTENT_WIDGET) { last_line->margin_descent = MAX (last_line->margin_descent, word->size.descent + word->content.data.widget->style->margin.bottom); DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1, last_line->descent); /* If the widget is not in the first line of the paragraph, its top * margin may make the line higher. */ if (page->num_lines > 1) { /* Here, we know already what the break and the bottom margin * contributed to the space before this line. */ last_line->ascent = MAX (last_line->ascent, word->size.ascent + word->content.data.widget->style->margin.top); DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1, last_line->ascent); } } else last_line->margin_descent = MAX (last_line->margin_descent, last_line->descent); Dw_page_get_word_extremes (word, &word_extremes); last_space = (word_ind > 0) ? page->words[word_ind - 1].orig_space : 0; if (word->content.type == DW_CONTENT_BREAK) last_line->break_space = MAX3 (word->content.data.break_space, last_line->margin_descent - last_line->descent, last_line->break_space); page->last_line_width += word->size.width; if (!new_line) page->last_line_width += last_space; page->last_line_par_min += word_extremes.max_width; page->last_line_par_max += word_extremes.max_width; if (!new_par) { page->last_line_par_min += last_space; page->last_line_par_max += last_space; } if (word->style->white_space != DW_STYLE_WHITE_SPACE_NORMAL) { last_line->par_min += word_extremes.min_width + last_space; /* This may also increase the accumulated minimum word width. */ last_line->max_word_min = MAX (last_line->max_word_min, last_line->par_min); /* NOTE: Most code relies on that all values of nowrap are equal for all * words within one line. */ } else /* Simple case. */ last_line->max_word_min = MAX (last_line->max_word_min, word_extremes.min_width); DBG_OBJ_SET_NUM(page, "last_line_par_min", page->last_line_par_min); DBG_OBJ_SET_NUM(page, "last_line_par_max", page->last_line_par_max); DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_min", page->num_lines - 1, last_line->par_min); DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_max", page->num_lines - 1, last_line->par_max); DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_word_min", page->num_lines - 1, last_line->max_word_min); /* Finally, justify the line. Breaks are ignored, since the HTML * parser sometimes assignes the wrong style to them. (todo: ) */ if (word->content.type != DW_CONTENT_BREAK) { switch (word->style->text_align) { case DW_STYLE_TEXT_ALIGN_LEFT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -