static uint32_t text_entry_try_invoke_preedit_action(struct text_entry *entry, int32_t x, int32_t y, uint32_t button, enum wl_pointer_button_state state) { int index, trailing; uint32_t cursor; const char *text; if (!entry->preedit.text) return 0; pango_layout_xy_to_index(entry->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); text = pango_layout_get_text(entry->layout); cursor = g_utf8_offset_to_pointer(text + index, trailing) - text; if (cursor < entry->cursor || cursor > entry->cursor + strlen(entry->preedit.text)) { return 0; } if (state == WL_POINTER_BUTTON_STATE_RELEASED) wl_text_input_invoke_action(entry->text_input, button, cursor - entry->cursor); return 1; }
std::string ttext::get_token(const gui2::tpoint & position, const char * delim) const { recalculate(); // Get the index of the character. int index, trailing; if (!pango_layout_xy_to_index(layout_, position.x * PANGO_SCALE, position.y * PANGO_SCALE, &index, &trailing)) { return ""; } std::string txt = pango_layout_get_text(layout_); std::string d(delim); if (index < 0 || (static_cast<size_t>(index) >= txt.size()) || d.find(txt.at(index)) != std::string::npos) { return ""; // if the index is out of bounds, or the index character is a delimiter, return nothing } size_t l = index; while (l > 0 && (d.find(txt.at(l-1)) == std::string::npos)) { --l; } size_t r = index + 1; while (r < txt.size() && (d.find(txt.at(r)) == std::string::npos)) { ++r; } return txt.substr(l,r-l); }
gui2::tpoint ttext::get_column_line(const gui2::tpoint& position) const { recalculate(); // Get the index of the character. int index, trailing; pango_layout_xy_to_index(layout_, position.x * PANGO_SCALE, position.y * PANGO_SCALE, &index, &trailing); // Extract the line and the offset in pixels in that line. int line, offset; pango_layout_index_to_line_x(layout_, index, trailing, &line, &offset); offset = PANGO_PIXELS(offset); // Now convert this offset to a column, this way is a bit hacky but haven't // found a better solution yet. /** * @todo There's still a bug left. When you select a text which is in the * ellipses on the right side the text gets reformatted with ellipses on * the left and the selected character is not the one under the cursor. * Other widget toolkits don't show ellipses and have no indication more * text is available. Haven't found what the best thing to do would be. * Until that time leave it as is. */ for(size_t i = 0; ; ++i) { const int pos = get_cursor_position(i, line).x; if(pos == offset) { return gui2::tpoint(i, line); } } }
static int get_layout_index (MateIconTextItem *iti, int x, int y) { int index; int trailing; const char *cluster; const char *cluster_end; MateIconTextItemPrivate *priv; PangoRectangle extents; trailing = 0; index = 0; priv = iti->_priv; pango_layout_get_extents (priv->layout, NULL, &extents); x = (x * PANGO_SCALE) + extents.x; y = (y * PANGO_SCALE) + extents.y; pango_layout_xy_to_index (priv->layout, x, y, &index, &trailing); cluster = gtk_entry_get_text (GTK_ENTRY (priv->entry)) + index; cluster_end = cluster; while (trailing) { cluster_end = g_utf8_next_char (cluster_end); --trailing; } index += (cluster_end - cluster); return index; }
/* Given an x-y position, return the paragraph and offset * within the paragraph of the click. */ gboolean xy_to_cp (int width, int x, int y, Paragraph **para_return, int *index) { GList *para_list; int height = 0; *para_return = NULL; para_list = paragraphs; while (para_list && height < y) { Paragraph *para = para_list->data; if (height + para->height >= y) { gboolean result = pango_layout_xy_to_index (para->layout, x * PANGO_SCALE, (y - height) * PANGO_SCALE, index, NULL); if (result && para_return) *para_return = para; return result; } height += para->height; para_list = para_list->next; } return FALSE; }
static void gimp_text_tool_xy_to_iter (GimpTextTool *text_tool, gdouble x, gdouble y, GtkTextIter *iter) { PangoLayout *layout; gint offset_x; gint offset_y; gint index; gint trailing; gimp_text_tool_ensure_layout (text_tool); gimp_text_layout_untransform_point (text_tool->layout, &x, &y); gimp_text_layout_get_offsets (text_tool->layout, &offset_x, &offset_y); x -= offset_x; y -= offset_y; layout = gimp_text_layout_get_pango_layout (text_tool->layout); pango_layout_xy_to_index (layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); gimp_text_buffer_get_iter_at_index (text_tool->buffer, iter, index, TRUE); if (trailing) gtk_text_iter_forward_char (iter); }
int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { #if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) return offsetForPositionForSimpleText(run, xFloat, includePartialGlyphs); #endif // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. int x = static_cast<int>(xFloat); PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); int index, trailing; pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing); glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index); if (includePartialGlyphs) offset += trailing; g_free(utf8); g_object_unref(layout); return offset; }
/** * Find the position in a string where an x coordinate falls. * * \param[in] fstyle style for this text * \param[in] string UTF-8 string to measure * \param[in] length length of string, in bytes * \param[in] x coordinate to search for * \param[out] char_offset updated to offset in string of actual_x, [0..length] * \param[out] actual_x updated to x coordinate of character closest to x * \return NSERROR_OK and char_offset and actual_x updated or appropriate * error code on faliure */ static nserror nsfont_position_in_string(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { int index; PangoFontDescription *desc; PangoRectangle pos; nsfont_pango_check(); desc = nsfont_style_to_description(fstyle); pango_layout_set_font_description(nsfont_pango_layout, desc); pango_font_description_free(desc); pango_layout_set_text(nsfont_pango_layout, string, length); if (pango_layout_xy_to_index(nsfont_pango_layout, x * PANGO_SCALE, 0, &index, 0) == FALSE) { index = length; } pango_layout_index_to_pos(nsfont_pango_layout, index, &pos); *char_offset = index; *actual_x = PANGO_PIXELS(pos.x); return NSERROR_OK; }
static gint gtk_label_accessible_get_offset_at_point (AtkText *atk_text, gint x, gint y, AtkCoordType coords) { GtkWidget *widget; GtkLabel *label; const gchar *text; gint index, x_layout, y_layout; gint x_window, y_window; gint x_local, y_local; GdkWindow *window; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text)); if (widget == NULL) return -1; label = GTK_LABEL (widget); gtk_label_get_layout_offsets (label, &x_layout, &y_layout); window = gtk_widget_get_window (widget); gdk_window_get_origin (window, &x_window, &y_window); x_local = x - x_layout - x_window; y_local = y - y_layout - y_window; if (coords == ATK_XY_WINDOW) { window = gdk_window_get_toplevel (window); gdk_window_get_origin (window, &x_window, &y_window); x_local += x_window; y_local += y_window; } if (!pango_layout_xy_to_index (gtk_label_get_layout (label), x_local * PANGO_SCALE, y_local * PANGO_SCALE, &index, NULL)) { if (x_local < 0 || y_local < 0) index = 0; else index = -1; } if (index != -1) { text = gtk_label_get_text (label); return g_utf8_pointer_to_offset (text, text + index); } return -1; }
static VALUE rg_xy_to_index(VALUE self, VALUE x, VALUE y) { int index, trailing; gboolean ret = pango_layout_xy_to_index(_SELF(self), NUM2INT(x), NUM2INT(y), &index, &trailing); return rb_ary_new3(3, CBOOL2RVAL(ret), INT2NUM(index), INT2NUM(trailing)); }
static gint gtk_icon_view_item_accessible_get_offset_at_point (AtkText *text, gint x, gint y, AtkCoordType coord_type) { GtkIconViewItemAccessible *item; gint offset = 0; #if 0 GtkIconView *icon_view; const gchar *item_text; gint index; gint l_x, l_y; #endif item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text); if (!GTK_IS_ICON_VIEW (item->widget)) return -1; if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT)) return -1; #if 0 icon_view = GTK_ICON_VIEW (item->widget); /* FIXME we probably have to use GailTextCell to salvage this */ gtk_icon_view_update_item_text (icon_view, item->item); atk_component_get_position (ATK_COMPONENT (text), &l_x, &l_y, coord_type); x -= l_x + item->item->layout_x - item->item->x; x += ((item->item->width - item->item->layout_width) / 2) + (MAX (item->item->pixbuf_width, icon_view->priv->item_width) - item->item->width) / 2, y -= l_y + item->item->layout_y - item->item->y; item_text = pango_layout_get_text (icon_view->priv->layout); if (!pango_layout_xy_to_index (icon_view->priv->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, NULL)) { if (x < 0 || y < 0) index = 0; else index = -1; } if (index == -1) offset = g_utf8_strlen (item_text, -1); else offset = g_utf8_pointer_to_offset (item_text, item_text + index); #endif return offset; }
int Font::offsetForPositionForComplexText(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const { PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout, style.rtl()); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); int index, trailing; pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing); glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index); g_object_unref(layout); g_free(utf8); return offset; }
static int _get_string_index (GtkEntry *entry, gint x, gint y) { //Declarations int layout_index; int entry_index; int trailing; PangoLayout *layout; //Initalizations layout = gtk_entry_get_layout (GTK_ENTRY (entry)); if (pango_layout_xy_to_index (layout, x * PANGO_SCALE, y * PANGO_SCALE, &layout_index, &trailing)) entry_index = gtk_entry_layout_index_to_text_index (GTK_ENTRY (entry), layout_index); else entry_index = -1; return entry_index; }
static void text_entry_set_anchor_position(struct text_entry *entry, int32_t x, int32_t y) { int index, trailing; const char *text; pango_layout_xy_to_index(entry->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); text = pango_layout_get_text(entry->layout); entry->anchor = g_utf8_offset_to_pointer(text + index, trailing) - text; text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); text_entry_update(entry); }
/** * gail_misc_get_index_at_point_in_layout: * @widget: A #GtkWidget * @layout: The #PangoLayout from which to get the index at the * specified point. * @x_layout: The x-offset at which the widget displays the * #PangoLayout, relative to @widget * @y_layout: The y-offset at which the widget displays the * #PangoLayout, relative to @widget * @x: The x-coordinate relative to @coords at which to * calculate the index * @y: The y-coordinate relative to @coords at which to * calculate the index * @coords: An #AtkCoordType enumeration * * Gets the byte offset at the specified @x and @y in a #PangoLayout. * * Returns: the byte offset at the specified @x and @y in a * #PangoLayout **/ gint gail_misc_get_index_at_point_in_layout (GtkWidget *widget, PangoLayout *layout, gint x_layout, gint y_layout, gint x, gint y, AtkCoordType coords) { gint index, x_window, y_window, x_toplevel, y_toplevel; gint x_temp, y_temp; gboolean ret; gail_misc_get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel); x_temp = x - x_layout - x_window; y_temp = y - y_layout - y_window; if (coords == ATK_XY_WINDOW) { x_temp += x_toplevel; y_temp += y_toplevel; } else if (coords != ATK_XY_SCREEN) return -1; ret = pango_layout_xy_to_index (layout, x_temp * PANGO_SCALE, y_temp * PANGO_SCALE, &index, NULL); if (!ret) { if (x_temp < 0 || y_temp < 0) index = 0; else index = -1; } return index; }
static void text_entry_set_cursor_position(struct text_entry *entry, int32_t x, int32_t y, bool move_anchor) { int index, trailing; const char *text; uint32_t cursor; pango_layout_xy_to_index(entry->layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); text = pango_layout_get_text(entry->layout); cursor = g_utf8_offset_to_pointer(text + index, trailing) - text; if (move_anchor) entry->anchor = cursor; if (text_entry_has_preedit(entry)) { text_entry_commit_and_reset(entry); assert(!text_entry_has_preedit(entry)); } if (entry->cursor == cursor) return; entry->cursor = cursor; text_entry_update_layout(entry); widget_schedule_redraw(entry->widget); text_entry_update(entry); }
static gint gtk_text_cell_accessible_get_offset_at_point (AtkText *text, gint x, gint y, AtkCoordType coords) { AtkObject *parent; GtkRendererCellAccessible *gail_renderer; GtkCellRendererText *gtk_renderer; GtkRequisition min_size; GtkWidget *widget; GdkRectangle rendered_rect; PangoLayout *layout; gchar *renderer_text; gfloat xalign, yalign; gint x_offset, y_offset, index; gint xpad, ypad; gint x_window, y_window, x_toplevel, y_toplevel; gint x_temp, y_temp; gboolean ret; if (!GTK_TEXT_CELL_ACCESSIBLE (text)->cell_text) return -1; gail_renderer = GTK_RENDERER_CELL_ACCESSIBLE (text); gtk_renderer = GTK_CELL_RENDERER_TEXT (gail_renderer->renderer); parent = atk_object_get_parent (ATK_OBJECT (text)); g_object_get (gtk_renderer, "text", &renderer_text, NULL); if (text == NULL) { g_free (renderer_text); return -1; } if (GTK_IS_CONTAINER_CELL_ACCESSIBLE (parent)) parent = atk_object_get_parent (parent); widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent)); g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), -1); _gtk_cell_accessible_parent_get_cell_area (GTK_CELL_ACCESSIBLE_PARENT (parent), GTK_CELL_ACCESSIBLE (text), &rendered_rect); gtk_cell_renderer_get_preferred_size (GTK_CELL_RENDERER (gtk_renderer), widget, &min_size, NULL); gtk_cell_renderer_get_alignment (GTK_CELL_RENDERER (gtk_renderer), &xalign, &yalign); if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) xalign = 1.0 - xalign; x_offset = MAX (0, xalign * (rendered_rect.width - min_size.width)); y_offset = MAX (0, yalign * (rendered_rect.height - min_size.height)); layout = create_pango_layout (GTK_TEXT_CELL_ACCESSIBLE (text)); gtk_cell_renderer_get_padding (gail_renderer->renderer, &xpad, &ypad); get_origins (widget, &x_window, &y_window, &x_toplevel, &y_toplevel); x_temp = x - (x_offset + rendered_rect.x + xpad) - x_window; y_temp = y - (y_offset + rendered_rect.y + ypad) - y_window; if (coords == ATK_XY_WINDOW) { x_temp += x_toplevel; y_temp += y_toplevel; } else if (coords != ATK_XY_SCREEN) index = -1; ret = pango_layout_xy_to_index (layout, x_temp * PANGO_SCALE, y_temp * PANGO_SCALE, &index, NULL); if (!ret) { if (x_temp < 0 || y_temp < 0) index = 0; else index = -1; } g_object_unref (layout); if (index == -1) { if (coords == ATK_XY_WINDOW || coords == ATK_XY_SCREEN) { glong length; length = g_utf8_strlen (renderer_text, -1); g_free (renderer_text); return length; } g_free (renderer_text); return index; } else { glong offset; offset = g_utf8_pointer_to_offset (renderer_text, renderer_text + index); g_free (renderer_text); return offset; } }
/* split a text buffer into chunks using the passed Pango layout */ GList * split_for_layout(PangoLayout * layout, const gchar * text, PangoAttrList * attributes, BalsaPrintSetup * psetup, gboolean is_header, GArray ** offsets) { GList *split_list = NULL; PangoLayoutIter *iter; const gchar *start; gint p_offset; gboolean add_tab; gint p_y0; gint p_y1; gint p_y_pos; gint p_height; /* set the text and its attributes, then get an iter */ pango_layout_set_text(layout, text, -1); if (attributes) pango_layout_set_attributes(layout, attributes); if (offsets) *offsets = g_array_new(FALSE, FALSE, sizeof(guint)); iter = pango_layout_get_iter(layout); /* loop over lines */ start = text; p_offset = 0; add_tab = FALSE; p_y_pos = C_TO_P(psetup->c_y_pos); p_height = C_TO_P(psetup->c_height); do { pango_layout_iter_get_line_yrange(iter, &p_y0, &p_y1); if (p_y_pos + p_y1 - p_offset > p_height) { gint index; gint tr; gchar *chunk; gboolean ends_with_nl; if (offsets) { guint offs = start - text; *offsets = g_array_append_val(*offsets, offs); } pango_layout_xy_to_index(layout, 0, p_y0, &index, &tr); ends_with_nl = text[index - 1] == '\n'; if (ends_with_nl) index--; chunk = g_strndup(start, text + index - start); if (add_tab) split_list = g_list_append(split_list, g_strconcat("\t", chunk, NULL)); else split_list = g_list_append(split_list, g_strdup(chunk)); add_tab = is_header && !ends_with_nl; g_free(chunk); start = text + index; if (ends_with_nl) start++; if (*start == '\0') p_y_pos = p_height; else { p_y_pos = 0; psetup->page_count++; } p_offset = p_y0; } } while (pango_layout_iter_next_line(iter)); pango_layout_iter_free(iter); /* append any remaining stuff */ if (*start != '\0') { p_y_pos += p_y1 - p_offset; if (offsets) { guint offs = start - text; *offsets = g_array_append_val(*offsets, offs); } if (add_tab) split_list = g_list_append(split_list, g_strconcat("\t", start, NULL)); else split_list = g_list_append(split_list, g_strdup(start)); } /* remember the new y position in cairo units */ psetup->c_y_pos = P_TO_C(p_y_pos); /* return the list */ return split_list; }