📄 pango-layout.c
字号:
} pango_glyph_string_index_to_x (run->glyphs, layout->text + run->item->offset, run->item->length, &run->item->analysis, index - run->item->offset, trailing, x_pos); if (x_pos) *x_pos += width; return; } width += pango_glyph_string_get_width (run->glyphs); run_list = run_list->next; } if (x_pos) *x_pos = width;}static PangoLayoutLine *pango_layout_index_to_line (PangoLayout *layout, int index, int *line_nr, PangoLayoutLine **line_before, PangoLayoutLine **line_after){ GSList *tmp_list; GSList *line_list; PangoLayoutLine *line = NULL; PangoLayoutLine *prev_line = NULL; int i = -1; line_list = tmp_list = layout->lines; while (tmp_list) { PangoLayoutLine *tmp_line = tmp_list->data; if (tmp_line->start_index > index) break; /* index was in paragraph delimiters */ prev_line = line; line = tmp_line; line_list = tmp_list; i++; if (line->start_index + line->length > index) break; tmp_list = tmp_list->next; } if (line_nr) *line_nr = i; if (line_before) *line_before = prev_line; if (line_after) *line_after = (line_list && line_list->next) ? line_list->next->data : NULL; return line;}static PangoLayoutLine *pango_layout_index_to_line_and_extents (PangoLayout *layout, int index, PangoRectangle *line_rect){ PangoLayoutIter *iter; PangoLayoutLine *line = NULL; iter = pango_layout_get_iter (layout); if (!ITER_IS_INVALID (iter)) while (TRUE) { PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (iter); if (tmp_line->start_index > index) break; /* index was in paragraph delimiters */ line = tmp_line; pango_layout_iter_get_line_extents (iter, NULL, line_rect); if (line->start_index + line->length > index) break; if (!pango_layout_iter_next_line (iter)) break; /* Use end of last line */ } pango_layout_iter_free (iter); return line;}/** * pango_layout_index_to_line_x: * @layout: a #PangoLayout * @index_: the byte index of a grapheme within the layout. * @trailing: an integer indicating the edge of the grapheme to retrieve the * position of. If 0, the trailing edge of the grapheme, if > 0, * the leading of the grapheme. * @line: location to store resulting line index. (which will * between 0 and pango_layout_get_line_count(layout) - 1) * @x_pos: location to store resulting position within line * (%PANGO_SCALE units per device unit) * * Converts from byte @index_ within the @layout to line and X position. * (X position is measured from the left edge of the line) */voidpango_layout_index_to_line_x (PangoLayout *layout, int index, gboolean trailing, int *line, int *x_pos){ int line_num; PangoLayoutLine *layout_line = NULL; g_return_if_fail (layout != NULL); g_return_if_fail (index >= 0); g_return_if_fail (index <= layout->length); pango_layout_check_lines (layout); layout_line = pango_layout_index_to_line (layout, index, &line_num, NULL, NULL); if (layout_line) { /* use end of line if index was in the paragraph delimiters */ if (index > layout_line->start_index + layout_line->length) index = layout_line->start_index + layout_line->length; if (line) *line = line_num; pango_layout_line_index_to_x (layout_line, index, trailing, x_pos); } else { if (line) *line = -1; if (x_pos) *x_pos = -1; }}/** * pango_layout_move_cursor_visually: * @layout: a #PangoLayout. * @strong: whether the moving cursor is the strong cursor or the * weak cursor. The strong cursor is the cursor corresponding * to text insertion in the base direction for the layout. * @old_index: the byte index of the grapheme for the old index * @old_trailing: if 0, the cursor was at the trailing edge of the * grapheme indicated by @old_index, if > 0, the cursor * was at the leading edge. * @direction: direction to move cursor. A negative * value indicates motion to the left. * @new_index: location to store the new cursor byte index. A value of -1 * indicates that the cursor has been moved off the beginning * of the layout. A value of %G_MAXINT indicates that * the cursor has been moved off the end of the layout. * @new_trailing: number of characters to move forward from the location returned * for @new_index to get the position where the cursor should * be displayed. This allows distinguishing the position at * the beginning of one line from the position at the end * of the preceding line. @new_index is always on the line * where the cursor should be displayed. * * Computes a new cursor position from an old position and * a count of positions to move visually. If @direction is positive, * then the new strong cursor position will be one position * to the right of the old cursor position. If @direction is negative, * then the new strong cursor position will be one position * to the left of the old cursor position. * * In the presence of bidirectional text, the correspondence * between logical and visual order will depend on the direction * of the current run, and there may be jumps when the cursor * is moved off of the end of a run. * * Motion here is in cursor positions, not in characters, so a * single call to pango_layout_move_cursor_visually() may move the * cursor over multiple characters when multiple characters combine * to form a single grapheme. **/voidpango_layout_move_cursor_visually (PangoLayout *layout, gboolean strong, int old_index, int old_trailing, int direction, int *new_index, int *new_trailing){ PangoLayoutLine *line = NULL; PangoLayoutLine *prev_line; PangoLayoutLine *next_line; int *log2vis_map; int *vis2log_map; int n_vis; int vis_pos, vis_pos_old, log_pos; int start_offset; gboolean off_start = FALSE; gboolean off_end = FALSE; g_return_if_fail (layout != NULL); g_return_if_fail (old_index >= 0 && old_index <= layout->length); g_return_if_fail (old_index < layout->length || old_trailing == 0); g_return_if_fail (new_index != NULL); g_return_if_fail (new_trailing != NULL); direction = (direction >= 0 ? 1 : -1); pango_layout_check_lines (layout); /* Find the line the old cursor is on */ line = pango_layout_index_to_line (layout, old_index, NULL, &prev_line, &next_line); start_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index); while (old_trailing--) old_index = g_utf8_next_char (layout->text + old_index) - layout->text; log2vis_map = pango_layout_line_get_log2vis_map (line, strong); n_vis = g_utf8_strlen (layout->text + line->start_index, line->length); /* Clamp old_index to fit on the line */ if (old_index > (line->start_index + line->length)) old_index = line->start_index + line->length; vis_pos = log2vis_map[old_index - line->start_index]; g_free (log2vis_map); /* Handling movement between lines */ if (vis_pos == 0 && direction < 0) { if (line->resolved_dir == PANGO_DIRECTION_LTR) off_start = TRUE; else off_end = TRUE; } else if (vis_pos == n_vis && direction > 0) { if (line->resolved_dir == PANGO_DIRECTION_LTR) off_end = TRUE; else off_start = TRUE; } if (off_start || off_end) { /* If we move over a paragraph boundary, count that as * an extra position in the motion */ gboolean paragraph_boundary; if (off_start) { if (!prev_line) { *new_index = -1; *new_trailing = 0; return; } line = prev_line; paragraph_boundary = (line->start_index + line->length != old_index); } else { if (!next_line) { *new_index = G_MAXINT; *new_trailing = 0; return; } line = next_line; paragraph_boundary = (line->start_index != old_index); } n_vis = g_utf8_strlen (layout->text + line->start_index, line->length); start_offset = g_utf8_pointer_to_offset (layout->text, layout->text + line->start_index); if (vis_pos == 0 && direction < 0) { vis_pos = n_vis; if (paragraph_boundary) vis_pos++; } else /* (vis_pos == n_vis && direction > 0) */ { vis_pos = 0; if (paragraph_boundary) vis_pos--; } } vis2log_map = pango_layout_line_get_vis2log_map (line, strong); vis_pos_old = vis_pos + direction; log_pos = g_utf8_pointer_to_offset (layout->text + line->start_index, layout->text + line->start_index + vis2log_map[vis_pos_old]); do { vis_pos += direction; log_pos += g_utf8_pointer_to_offset (layout->text + line->start_index + vis2log_map[vis_pos_old], layout->text + line->start_index + vis2log_map[vis_pos]); vis_pos_old = vis_pos; } while (vis_pos > 0 && vis_pos < n_vis && !layout->log_attrs[start_offset + log_pos].is_cursor_position); *new_index = line->start_index + vis2log_map[vis_pos]; g_free (vis2log_map); *new_trailing = 0; if (*new_index == line->start_index + line->length && line->length > 0) { do { log_pos--; *new_index = g_utf8_prev_char (layout->text + *new_index) - layout->text; (*new_trailing)++; } while (log_pos > 0 && !layout->log_attrs[start_offset + log_pos].is_cursor_position); }}/** * pango_layout_xy_to_index: * @layout: a #PangoLayout * @x: the X offset (in Pango units) * from the left edge of the layout. * @y: the Y offset (in Pango units) * from the top edge of the layout * @index_: location to store calculated byte index * @trailing: location to store a integer indicating where * in the grapheme the user clicked. It will either * be zero, or the number of characters in the * grapheme. 0 represents the trailing edge of the grapheme. * * Converts from X and Y position within a layout to the byte * index to the character at that logical position. If the * Y position is not inside the layout, the closest position is chosen * (the position will be clamped inside the layout). If the * X position is not within the layout, then the start or the * end of the line is chosen as described for pango_layout_x_to_index(). * If either the X or Y positions were not inside the layout, then the * function returns %FALSE; on an exact hit, it returns %TRUE. * * Return value: %TRUE if the coordinates were inside text, %FALSE otherwise. **/gbooleanpango_layout_xy_to_index (PangoLayout *layout, int x, int y, int *index, gint *trailing){ PangoLayoutIter *iter; PangoLayoutLine *prev_line = NULL; PangoLayoutLine *found = NULL; int found_line_x = 0; int prev_last = 0; int prev_line_x = 0; gboolean retval = FALSE; gboolean outside = FALSE; g_return_val_if_fail (PANGO_IS_LAYOUT (layout), FALSE); iter = pango_layout_get_iter (layout); do { PangoRectangle line_logical; int first_y, last_y; pango_layout_iter_get_line_extents (iter, NULL, &line_logical); pango_layout_iter_get_line_yrange (iter, &first_y, &last_y); if (y < first_y) { if (prev_line && y < (prev_last + (first_y - prev_last) / 2)) { found = prev_line; found_line_x = prev_line_x; } else { if (prev_line == NULL) outside = TRUE; /* off the top */ found = _pango_layout_iter_get_line (iter); found_line_x = x - line_logical.x; } } else if (y >= first_y && y < last_y) { found = _pango_layout_iter_get_line (iter); found_line_x = x - line_logical.x; } prev_line = _pango_layout_iter_get_line (iter); prev_last = last_y; prev_line_x = x - line_logical.x; if (found != NULL) break; } while (pango_layout_iter_next_line (iter)); pango_layout_iter_free (iter); if (found == NULL) { /* Off the bottom of the layout */ outside = TRUE; found = prev_line; found_line_x = prev_line_x; } retval = pango_layout_line_x_to_index (found, found_line_x, index, trailing); if (outside) retval = FALSE; return retval;}/** * pango_layout_index_to_pos: * @layout: a #PangoLayout * @index_: byte index within @layout * @pos: rectangle in which to store the position of the grapheme * * Converts from an index within a #PangoLayout to the onscreen position * corresponding to the grapheme at that index, which is represented * as rectangle. Note that <literal>pos->x</literal> is always the leading * edge of the grapheme and <literal>pos->x + pos->width</literal> the trailing * edge of the grapheme. If the directionality of the grapheme is right-to-left, * then <literal>pos->width</literal> will be negative. **/voidpango_layout_index_to_pos (PangoLayout *layout, int index, PangoRectangle *pos){ PangoRectangle logical_rect; PangoLayoutIter *iter; PangoLayoutLine *layout_line = NULL; int x_pos; g_return_if_fail (layout != NULL); g_return_if_fail (index >= 0); g_return_if_fail (pos != NULL); iter = pango_layout_get_iter (layout); if (!ITER_IS_INVALID (iter)) { while (TRUE) { PangoLayoutLine *tmp_line = _pango_layout_iter_get_line (iter); if (tmp_line->start_index > index) { /* index is in the paragraph delimiters, move to * end of previous line */ index = layout_line->start_index + layout_line->length; break; } layout_line = tmp_line; pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -