📄 pango-layout.c
字号:
if (layout_line->start_index + layout_line->length > index) break; if (!pango_layout_iter_next_line (iter)) { index = layout_line->start_index + layout_line->length; break; } } pos->y = logical_rect.y; pos->height = logical_rect.height; pango_layout_line_index_to_x (layout_line, index, 0, &x_pos); pos->x = logical_rect.x + x_pos; if (index < layout_line->start_index + layout_line->length) { pango_layout_line_index_to_x (layout_line, index, 1, &x_pos); pos->width = (logical_rect.x + x_pos) - pos->x; } else pos->width = 0; } pango_layout_iter_free (iter);}static voidpango_layout_line_get_range (PangoLayoutLine *line, char **start, char **end){ char *p; p = line->layout->text + line->start_index; if (start) *start = p; if (end) *end = p + line->length;}static int *pango_layout_line_get_vis2log_map (PangoLayoutLine *line, gboolean strong){ PangoLayout *layout = line->layout; PangoDirection prev_dir; PangoDirection cursor_dir; GSList *tmp_list; gchar *start, *end; int *result; int pos; int n_chars; pango_layout_line_get_range (line, &start, &end); n_chars = g_utf8_strlen (start, end - start); result = g_new (int, n_chars + 1); if (strong) cursor_dir = line->resolved_dir; else cursor_dir = (line->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; /* Handle the first visual position */ if (line->resolved_dir == cursor_dir) result[0] = line->resolved_dir == PANGO_DIRECTION_LTR ? 0 : end - start; prev_dir = line->resolved_dir; pos = 0; tmp_list = line->runs; while (tmp_list) { PangoLayoutRun *run = tmp_list->data; int run_n_chars = run->item->num_chars; PangoDirection run_dir = (run->item->analysis.level % 2) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; char *p = layout->text + run->item->offset; int i; /* pos is the visual position at the start of the run */ /* p is the logical byte index at the start of the run */ if (run_dir == PANGO_DIRECTION_LTR) { if ((cursor_dir == PANGO_DIRECTION_LTR) || (prev_dir == run_dir)) result[pos] = p - start; p = g_utf8_next_char (p); for (i = 1; i < run_n_chars; i++) { result[pos + i] = p - start; p = g_utf8_next_char (p); } if (cursor_dir == PANGO_DIRECTION_LTR) result[pos + run_n_chars] = p - start; } else { if (cursor_dir == PANGO_DIRECTION_RTL) result[pos + run_n_chars] = p - start; p = g_utf8_next_char (p); for (i = 1; i < run_n_chars; i++) { result[pos + run_n_chars - i] = p - start; p = g_utf8_next_char (p); } if ((cursor_dir == PANGO_DIRECTION_RTL) || (prev_dir == run_dir)) result[pos] = p - start; } pos += run_n_chars; prev_dir = run_dir; tmp_list = tmp_list->next; } /* And the last visual position */ if ((cursor_dir == line->resolved_dir) || (prev_dir == line->resolved_dir)) result[pos] = line->resolved_dir == PANGO_DIRECTION_LTR ? end - start : 0; return result;}static int *pango_layout_line_get_log2vis_map (PangoLayoutLine *line, gboolean strong){ gchar *start, *end; int *reverse_map; int *result; int i; int n_chars; pango_layout_line_get_range (line, &start, &end); n_chars = g_utf8_strlen (start, end - start); result = g_new0 (int, end - start + 1); reverse_map = pango_layout_line_get_vis2log_map (line, strong); for (i=0; i <= n_chars; i++) result[reverse_map[i]] = i; g_free (reverse_map); return result;}static PangoDirectionpango_layout_line_get_char_direction (PangoLayoutLine *layout_line, int index){ GSList *run_list; run_list = layout_line->runs; while (run_list) { PangoLayoutRun *run = run_list->data; if (run->item->offset <= index && run->item->offset + run->item->length > index) return run->item->analysis.level % 2 ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; run_list = run_list->next; } g_assert_not_reached (); return PANGO_DIRECTION_LTR;}/** * pango_layout_get_cursor_pos: * @layout: a #PangoLayout * @index_: the byte index of the cursor * @strong_pos: location to store the strong cursor position (may be %NULL) * @weak_pos: location to store the weak cursor position (may be %NULL) * * Given an index within a layout, determines the positions that of the * strong and weak cursors if the insertion point is at that * index. The position of each cursor is stored as a zero-width * rectangle. The strong cursor location is the location where * characters of the directionality equal to the base direction of the * layout are inserted. The weak cursor location is the location * where characters of the directionality opposite to the base * direction of the layout are inserted. **/voidpango_layout_get_cursor_pos (PangoLayout *layout, int index, PangoRectangle *strong_pos, PangoRectangle *weak_pos){ PangoDirection dir1; PangoRectangle line_rect; PangoLayoutLine *layout_line = NULL; /* Quiet GCC */ int x1_trailing; int x2; g_return_if_fail (layout != NULL); g_return_if_fail (index >= 0 && index <= layout->length); layout_line = pango_layout_index_to_line_and_extents (layout, index, &line_rect); g_assert (index >= layout_line->start_index); /* Examine the trailing edge of the character before the cursor */ if (index == layout_line->start_index) { dir1 = layout_line->resolved_dir; if (layout_line->resolved_dir == PANGO_DIRECTION_LTR) x1_trailing = 0; else x1_trailing = line_rect.width; } else { gint prev_index = g_utf8_prev_char (layout->text + index) - layout->text; dir1 = pango_layout_line_get_char_direction (layout_line, prev_index); pango_layout_line_index_to_x (layout_line, prev_index, TRUE, &x1_trailing); } /* Examine the leading edge of the character after the cursor */ if (index >= layout_line->start_index + layout_line->length) { if (layout_line->resolved_dir == PANGO_DIRECTION_LTR) x2 = line_rect.width; else x2 = 0; } else { pango_layout_line_index_to_x (layout_line, index, FALSE, &x2); } if (strong_pos) { strong_pos->x = line_rect.x; if (dir1 == layout_line->resolved_dir) strong_pos->x += x1_trailing; else strong_pos->x += x2; strong_pos->y = line_rect.y; strong_pos->width = 0; strong_pos->height = line_rect.height; } if (weak_pos) { weak_pos->x = line_rect.x; if (dir1 == layout_line->resolved_dir) weak_pos->x += x2; else weak_pos->x += x1_trailing; weak_pos->y = line_rect.y; weak_pos->width = 0; weak_pos->height = line_rect.height; }}static inline intdirection_simple (PangoDirection d){ switch (d) { case PANGO_DIRECTION_LTR : case PANGO_DIRECTION_WEAK_LTR : case PANGO_DIRECTION_TTB_RTL : return 1; case PANGO_DIRECTION_RTL : case PANGO_DIRECTION_WEAK_RTL : case PANGO_DIRECTION_TTB_LTR : return -1; case PANGO_DIRECTION_NEUTRAL : return 0; /* no default, compiler should complain if a new values is added */ } /* not reached */ return 0;}static PangoAlignmentget_alignment (PangoLayout *layout, PangoLayoutLine *line){ PangoAlignment alignment = layout->alignment; if (alignment != PANGO_ALIGN_CENTER && line->layout->auto_dir && direction_simple (line->resolved_dir) == -direction_simple (pango_context_get_base_dir (layout->context))) { if (alignment == PANGO_ALIGN_LEFT) alignment = PANGO_ALIGN_RIGHT; else if (alignment == PANGO_ALIGN_RIGHT) alignment = PANGO_ALIGN_LEFT; } return alignment;}static voidget_x_offset (PangoLayout *layout, PangoLayoutLine *line, int layout_width, int line_width, int *x_offset){ PangoAlignment alignment = get_alignment (layout, line); /* Alignment */ if (layout_width == 0) *x_offset = 0; else if (alignment == PANGO_ALIGN_RIGHT) *x_offset = layout_width - line_width; else if (alignment == PANGO_ALIGN_CENTER) *x_offset = (layout_width - line_width) / 2; else *x_offset = 0; /* Indentation */ /* For center, we ignore indentation; I think I've seen word * processors that still do the indentation here as if it were * indented left/right, though we can't sensibly do that without * knowing whether left/right is the "normal" thing for this text */ if (alignment == PANGO_ALIGN_CENTER) return; if (line->is_paragraph_start) { if (layout->indent > 0) { if (alignment == PANGO_ALIGN_LEFT) *x_offset += layout->indent; else *x_offset -= layout->indent; } } else { if (layout->indent < 0) { if (alignment == PANGO_ALIGN_LEFT) *x_offset -= layout->indent; else *x_offset += layout->indent; } }}static voidget_line_extents_layout_coords (PangoLayout *layout, PangoLayoutLine *line, int layout_width, int y_offset, int *baseline, PangoRectangle *line_ink_layout, PangoRectangle *line_logical_layout){ int x_offset; /* Line extents in line coords (origin at line baseline) */ PangoRectangle line_ink; PangoRectangle line_logical; pango_layout_line_get_extents (line, line_ink_layout ? &line_ink : NULL, &line_logical); get_x_offset (layout, line, layout_width, line_logical.width, &x_offset); /* Convert the line's extents into layout coordinates */ if (line_ink_layout) { *line_ink_layout = line_ink; line_ink_layout->x = line_ink.x + x_offset; line_ink_layout->y = y_offset - line_logical.y + line_ink.y; } if (line_logical_layout) { *line_logical_layout = line_logical; line_logical_layout->x = line_logical.x + x_offset; line_logical_layout->y = y_offset; } if (baseline) *baseline = y_offset - line_logical.y;}/* if non-NULL line_extents returns a list of line extents * in layout coordinates */static voidpango_layout_get_extents_internal (PangoLayout *layout, PangoRectangle *ink_rect, PangoRectangle *logical_rect, GSList **line_extents){ GSList *line_list; int y_offset = 0; int width; gboolean need_width = FALSE; g_return_if_fail (layout != NULL); if (ink_rect && layout->ink_rect_cached) { *ink_rect = layout->ink_rect; ink_rect = NULL; } if (logical_rect && layout->logical_rect_cached) { *logical_rect = layout->logical_rect; logical_rect = NULL; } if (!ink_rect && !logical_rect && !line_extents) return; pango_layout_check_lines (layout); /* When we are not wrapping, we need the overall width of the layout to * figure out the x_offsets of each line. However, we only need the * x_offsets if we are computing the ink_rect or individual line extents. */ width = layout->width; if (layout->auto_dir) { /* If one of the lines of the layout is not left aligned, then we need * the width of the layout to calculate line x-offsets; this requires * looping through the lines for layout->auto_dir. */ line_list = layout->lines; while (line_list && !need_width) { PangoLayoutLine *line = line_list->data; if (get_alignment (layout, line) != PANGO_ALIGN_LEFT) need_width = TRUE; line_list = line_list->next; } } else if (layout->alignment != PANGO_ALIGN_LEFT) need_width = TRUE; if (width == -1 && need_width && (ink_rect || line_extents)) { PangoRectangle overall_logical; pango_layout_get_extents_internal (layout, NULL, &overall_logical, NULL); width = overall_logical.width; } if (logical_rect) { logical_rect->x = 0; logical_rect->y = 0; logical_rect->width = 0; logical_rect->height = 0; } line_list = layout->lines; while (line_list) { PangoLayoutLine *line = line_list->data; /* Line extents in layout coords (origin at 0,0 of the layout) */ PangoRectangle line_ink_layout; PangoRectangle line_logical_layout; int new_pos; /* This block gets the line extents in layout coords */ { int baseli
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -