📄 pango-layout.c
字号:
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 (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 baseline; get_line_extents_layout_coords (layout, line, width, y_offset, &baseline, ink_rect ? &line_ink_layout : NULL, &line_logical_layout); if (line_extents) { Extents *ext = g_slice_new (Extents); ext->baseline = baseline; ext->ink_rect = line_ink_layout; ext->logical_rect = line_logical_layout; *line_extents = g_slist_prepend (*line_extents, ext); } } if (ink_rect) { /* Compute the union of the current ink_rect with * line_ink_layout */ if (line_list == layout->lines) { *ink_rect = line_ink_layout; } else { new_pos = MIN (ink_rect->x, line_ink_layout.x); ink_rect->width = MAX (ink_rect->x + ink_rect->width, line_ink_layout.x + line_ink_layout.width) - new_pos; ink_rect->x = new_pos; new_pos = MIN (ink_rect->y, line_ink_layout.y); ink_rect->height = MAX (ink_rect->y + ink_rect->height, line_ink_layout.y + line_ink_layout.height) - new_pos; ink_rect->y = new_pos; } } if (logical_rect) { if (layout->width == -1) { /* When no width is set on layout, we can just compute the max of the * line lengths to get the horizontal extents ... logical_rect.x = 0. */ logical_rect->width = MAX (logical_rect->width, line_logical_layout.width); } else { /* When a width is set, we have to compute the union of the horizontal * extents of all the lines. */ if (line_list == layout->lines) { logical_rect->x = line_logical_layout.x; logical_rect->width = line_logical_layout.width; } else { new_pos = MIN (logical_rect->x, line_logical_layout.x); logical_rect->width = MAX (logical_rect->x + logical_rect->width, line_logical_layout.x + line_logical_layout.width) - new_pos; logical_rect->x = new_pos; } } logical_rect->height += line_logical_layout.height; /* No space after the last line, of course. */ if (line_list->next != NULL) logical_rect->height += layout->spacing; } y_offset += line_logical_layout.height + layout->spacing; line_list = line_list->next; } if (ink_rect) { layout->ink_rect = *ink_rect; layout->ink_rect_cached = TRUE; } if (logical_rect) { layout->logical_rect = *logical_rect; layout->logical_rect_cached = TRUE; } if (line_extents) *line_extents = g_slist_reverse (*line_extents);}/** * pango_layout_get_extents: * @layout: a #PangoLayout * @ink_rect: rectangle used to store the extents of the layout as drawn * or %NULL to indicate that the result is not needed. * @logical_rect: rectangle used to store the logical extents of the layout or %NULL to indicate that the result is not needed. * * Computes the logical and ink extents of @layout. Logical extents * are usually what you want for positioning things. Note that both extents * may have non-zero x and y. You may want to use those to offset where you * render the layout. Not doing that is a very typical bug that shows up as * right-to-left layouts not being correctly positioned in a layout with * a set width. * * The extents are given in layout coordinates and in Pango units; layout * coordinates begin at the top left corner of the layout. */voidpango_layout_get_extents (PangoLayout *layout, PangoRectangle *ink_rect, PangoRectangle *logical_rect){ g_return_if_fail (layout != NULL); pango_layout_get_extents_internal (layout, ink_rect, logical_rect, NULL);}/** * pango_layout_get_pixel_extents: * @layout: a #PangoLayout
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -