Esempio n. 1
0
static gboolean
ev_page_accessible_set_selection (AtkText *text,
				  gint	   selection_num,
				  gint     start_pos,
				  gint     end_pos)
{
	EvPageAccessible *self = EV_PAGE_ACCESSIBLE (text);
	EvView *view = ev_page_accessible_get_view (self);
	EvRectangle *areas = NULL;
	guint n_areas = 0;
	GdkRectangle start_rect, end_rect;
	GdkPoint start_point, end_point;

	ev_page_cache_get_text_layout (view->page_cache, self->priv->page, &areas, &n_areas);
	if (start_pos < 0 || end_pos >= n_areas)
		return FALSE;

	_ev_view_transform_doc_rect_to_view_rect (view, self->priv->page, areas + start_pos, &start_rect);
	_ev_view_transform_doc_rect_to_view_rect (view, self->priv->page, areas + end_pos - 1, &end_rect);
	start_point.x = start_rect.x;
	start_point.y = start_rect.y;
	end_point.x = end_rect.x + end_rect.width;
	end_point.y = end_rect.y + end_rect.height;
	_ev_view_set_selection (view, &start_point, &end_point);

	return TRUE;
}
Esempio n. 2
0
static gint
ev_page_accessible_get_offset_at_point (AtkText      *text,
					gint         x,
					gint         y,
					AtkCoordType coords)
{
	EvPageAccessible *self = EV_PAGE_ACCESSIBLE (text);
	EvView *view = ev_page_accessible_get_view (self);
	GtkWidget *toplevel;
	EvRectangle *areas = NULL;
	EvRectangle *rect = NULL;
	guint n_areas = 0;
	guint i;
	gint x_widget, y_widget;
	gint offset=-1;
	GdkPoint view_point;
	gdouble doc_x, doc_y;
	GtkBorder border;
	GdkRectangle page_area;

	if (!view->page_cache)
		return -1;

	ev_page_cache_get_text_layout (view->page_cache, self->priv->page, &areas, &n_areas);
	if (!areas)
		return -1;

	view_point.x = x;
	view_point.y = y;
	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
	gtk_widget_translate_coordinates (GTK_WIDGET (self), toplevel, 0, 0, &x_widget, &y_widget);
	view_point.x -= x_widget;
	view_point.y -= y_widget;

	if (coords == ATK_XY_SCREEN) {
		gint x_window, y_window;

		gdk_window_get_origin (gtk_widget_get_window (toplevel), &x_window, &y_window);
		view_point.x -= x_window;
		view_point.y -= y_window;
	}

	ev_view_get_page_extents (view, self->priv->page, &page_area, &border);
	_ev_view_transform_view_point_to_doc_point (view, &view_point, &page_area, &border, &doc_x, &doc_y);

	for (i = 0; i < n_areas; i++) {
		rect = areas + i;
		if (doc_x >= rect->x1 && doc_x <= rect->x2 &&
		    doc_y >= rect->y1 && doc_y <= rect->y2)
			offset = i;
	}

	return offset;
}
Esempio n. 3
0
static void
ev_page_accessible_get_character_extents (AtkText      *text,
					  gint         offset,
					  gint         *x,
					  gint         *y,
					  gint         *width,
					  gint         *height,
					  AtkCoordType coords)
{
	EvPageAccessible *self = EV_PAGE_ACCESSIBLE (text);
	EvView *view = ev_page_accessible_get_view (self);
	GtkWidget *toplevel;
	EvRectangle *areas = NULL;
	EvRectangle *doc_rect;
	guint n_areas = 0;
	gint x_widget, y_widget;
	GdkRectangle view_rect;

	if (!view->page_cache)
		return;

	ev_page_cache_get_text_layout (view->page_cache, self->priv->page, &areas, &n_areas);
	if (!areas || offset >= n_areas)
		return;

	doc_rect = areas + offset;
	_ev_view_transform_doc_rect_to_view_rect (view, self->priv->page, doc_rect, &view_rect);
	view_rect.x -= view->scroll_x;
	view_rect.y -= view->scroll_y;

	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
	gtk_widget_translate_coordinates (GTK_WIDGET (view), toplevel, 0, 0, &x_widget, &y_widget);
	view_rect.x += x_widget;
	view_rect.y += y_widget;

	if (coords == ATK_XY_SCREEN) {
		gint x_window, y_window;

		gdk_window_get_origin (gtk_widget_get_window (toplevel), &x_window, &y_window);
		view_rect.x += x_window;
		view_rect.y += y_window;
	}

	*x = view_rect.x;
	*y = view_rect.y;
	*width = view_rect.width;
	*height = view_rect.height;
}
Esempio n. 4
0
/* ATs expect to be able to identify sentence boundaries based on content. Valid,
 * content-based boundaries may be present at the end of a newline, for instance
 * at the end of a heading within a document. Thus being able to distinguish hard
 * returns from soft returns is necessary. However, the text we get from Poppler
 * for non-tagged PDFs has "\n" inserted at the end of each line resulting in a
 * broken accessibility implementation w.r.t. sentences.
 */
static gboolean
treat_as_soft_return (EvView       *view,
		      gint          page,
		      PangoLogAttr *log_attrs,
		      gint          offset)
{
	EvRectangle *areas = NULL;
	guint n_areas = 0;
	gdouble line_spacing, this_line_height, next_word_width;
	EvRectangle *this_line_start;
	EvRectangle *this_line_end;
	EvRectangle *next_line_start;
	EvRectangle *next_line_end;
	EvRectangle *next_word_end;
	gint prev_offset, next_offset;


	if (!log_attrs[offset].is_white)
		return FALSE;

	ev_page_cache_get_text_layout (view->page_cache, page, &areas, &n_areas);
	if (n_areas <= offset + 1)
		return FALSE;

	prev_offset = offset - 1;
	next_offset = offset + 1;

	/* In wrapped text, the character at the start of the next line starts a word.
	 * Examples where this condition might fail include bullets and images. But it
	 * also includes things like "(", so also check the next character.
	 */
	if (!log_attrs[next_offset].is_word_start &&
	    (next_offset + 1 >= n_areas || !log_attrs[next_offset + 1].is_word_start))
		return FALSE;

	/* In wrapped text, the chars on either side of the newline have very similar heights.
	 * Examples where this condition might fail include a newline at the end of a heading,
	 * and a newline at the end of a paragraph that is followed by a heading.
	 */
	this_line_end = areas + prev_offset;
	next_line_start = areas + next_offset;;

	this_line_height = this_line_end->y2 - this_line_end->y1;
	if (ABS (this_line_height - (next_line_start->y2 - next_line_start->y1)) > 0.25)
		return FALSE;

	/* If there is significant white space between this line and the next, odds are this
	 * is not a soft return in wrapped text. Lines within a typical paragraph are at most
	 * double-spaced. If the spacing is more than that, assume a hard return is present.
	 */
	line_spacing = next_line_start->y1 - this_line_end->y2;
	if (line_spacing - this_line_height > 1)
		return FALSE;

	/* Lines within a typical paragraph have *reasonably* similar x1 coordinates. But
	 * we cannot count on them being nearly identical. Examples where indentation can
	 * be present in wrapped text include indenting the first line of the paragraph,
	 * and hanging indents (e.g. in the works cited within an academic paper). So we'll
	 * be somewhat tolerant here.
	 */
	for ( ; prev_offset > 0 && !log_attrs[prev_offset].is_mandatory_break; prev_offset--);
	this_line_start = areas + prev_offset;
	if (ABS (this_line_start->x1 - next_line_start->x1) > 20)
		return FALSE;

	/* Ditto for x2, but this line might be short due to a wide word on the next line. */
	for ( ; next_offset < n_areas && !log_attrs[next_offset].is_word_end; next_offset++);
	next_word_end = areas + next_offset;
	next_word_width = next_word_end->x2 - next_line_start->x1;

	for ( ; next_offset < n_areas && !log_attrs[next_offset + 1].is_mandatory_break; next_offset++);
	next_line_end = areas + next_offset;
	if (next_line_end->x2 - (this_line_end->x2 + next_word_width) > 20)
		return FALSE;

	return TRUE;
}
Esempio n. 5
0
static gint
ev_view_accessible_get_offset_at_point (AtkText      *text,
					gint         x,
					gint         y,
					AtkCoordType coords)
{
	GtkWidget *widget, *toplevel;
	EvRectangle *areas = NULL;
	EvRectangle *rect = NULL;
	guint n_areas = 0;
	guint i = 0;
	EvPageCache *page_cache;
	gint x_window, y_window, x_widget, y_widget;
	gint offset=-1, rx, ry;
	gdouble scale;
	GtkBorder border;
	GdkRectangle page_area;

	widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
	if (widget == NULL)
		/* State is defunct */
		return -1;

	page_cache = EV_VIEW (widget)->page_cache;
	if (!page_cache)
		return -1;

	ev_view_get_page_extents (EV_VIEW (widget), EV_VIEW (widget)->current_page,
	                          &page_area, &border);

	scale = EV_VIEW (widget)->scale;
	ev_page_cache_get_text_layout (page_cache, EV_VIEW (widget)->current_page, &areas, &n_areas);
	if (!areas)
		return -1;

	rx = x;
	ry = y;

	rx -= page_area.x;
	ry -= page_area.y;

	rx += EV_VIEW (widget)->scroll_x;
	ry += EV_VIEW (widget)->scroll_y;

	toplevel = gtk_widget_get_toplevel (widget);
	gtk_widget_translate_coordinates (widget, toplevel, 0, 0, &x_widget, &y_widget);
	rx -= x_widget;
	ry -= y_widget;

	if (coords == ATK_XY_SCREEN) {
		gdk_window_get_origin (gtk_widget_get_window (toplevel), &x_window, &y_window);
		rx -= x_window;
		ry -= y_window;
	}

	rx /= scale;
	ry /= scale;

	for (i = 0; i < n_areas; i++) {
		rect = areas + i;
		if (rx >= rect->x1 && rx <= rect->x2 &&
		    ry >= rect->y1 && ry <= rect->y2)
			offset = i;
	}

	return offset;
}
Esempio n. 6
0
static void
ev_view_accessible_get_character_extents (AtkText      *text,
					  gint         offset,
					  gint         *x,
					  gint         *y,
					  gint         *width,
					  gint         *height,
					  AtkCoordType coords)
{
	GtkWidget *widget, *toplevel;
	EvRectangle *areas = NULL;
	EvRectangle *rect = NULL;
	guint n_areas = 0;
	EvPageCache *page_cache;
	gint x_widget, y_widget, x_window, y_window;
	gdouble scale;
	GtkBorder border;
	GdkRectangle page_area;

	widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
	if (widget == NULL)
		/* State is defunct */
		return;

	page_cache = EV_VIEW (widget)->page_cache;
	if (!page_cache)
		return;

	ev_view_get_page_extents (EV_VIEW (widget), EV_VIEW (widget)->current_page,
	                          &page_area, &border);

	scale = EV_VIEW (widget)->scale;
	ev_page_cache_get_text_layout (page_cache, EV_VIEW (widget)->current_page, &areas, &n_areas);
	if (!areas)
		return;

	if (offset >= n_areas)
		return;

	rect = areas + offset;
	*x = (int)(rect->x1 * scale);
	*y = (int)(rect->y1 * scale);

	*width = (int)(fabs (rect->x2 - rect->x1) * scale);
	*height = (int)(fabs (rect->y2 - rect->y1) * scale);

	toplevel = gtk_widget_get_toplevel (widget);
	gtk_widget_translate_coordinates (widget, toplevel, 0, 0, &x_widget, &y_widget);
	*x += x_widget;
	*y += y_widget;

	if (coords == ATK_XY_SCREEN) {
		gdk_window_get_origin (gtk_widget_get_window (toplevel), &x_window, &y_window);
		*x += x_window;
		*y += y_window;
	}

	*x -= EV_VIEW (widget)->scroll_x;
	*y -= EV_VIEW (widget)->scroll_y;

	*x += page_area.x;
	*y += page_area.y;
}