Implement sloped caret drawing

Prepare for Pango to return slope information for carets.

While we are at it, improve the shape of our carets a bit.
This commit is contained in:
Matthias Clasen 2021-08-23 17:39:04 -04:00
parent ad71f454bd
commit f90e9b26f8

View File

@ -972,6 +972,7 @@ draw_insertion_cursor (GtkStyleContext *context,
cairo_t *cr,
double x,
double y,
double width,
double height,
double aspect_ratio,
gboolean is_primary,
@ -981,7 +982,8 @@ draw_insertion_cursor (GtkStyleContext *context,
GdkRGBA primary_color;
GdkRGBA secondary_color;
int stem_width;
int offset;
double angle;
double dx, dy;
cairo_save (cr);
cairo_new_path (cr);
@ -990,107 +992,104 @@ draw_insertion_cursor (GtkStyleContext *context,
gdk_cairo_set_source_rgba (cr, is_primary ? &primary_color : &secondary_color);
stem_width = height * aspect_ratio + 1;
if (width < 0)
stem_width = - stem_width;
/* put (stem_width % 2) on the proper side of the cursor */
if (direction == PANGO_DIRECTION_LTR)
offset = stem_width / 2;
else
offset = stem_width - stem_width / 2;
angle = atan (height / width);
cairo_rectangle (cr, x - offset, y, stem_width, height);
cairo_fill (cr);
dx = (stem_width/2.0) * cos (M_PI/2 - angle);
dy = (stem_width/2.0) * sin (M_PI/2 - angle);
if (draw_arrow)
{
int arrow_width;
int ax, ay;
arrow_width = stem_width + 1;
if (direction == PANGO_DIRECTION_RTL)
{
ax = x - offset - 1;
ay = y + height - arrow_width * 2 - arrow_width + 1;
double x0, y0, x1, y1, x2, y2;
cairo_move_to (cr, ax, ay + 1);
cairo_line_to (cr, ax - arrow_width, ay + arrow_width);
cairo_line_to (cr, ax, ay + 2 * arrow_width);
cairo_fill (cr);
x0 = x - dx + 2 * dy;
y0 = y + height - dy - 2 * dx;
x1 = x0 + 4 * dy;
y1 = y0 - 4 * dx;
x2 = x0 + 2 * dy - 3 * dx;
y2 = y0 - 2 * dx - 3 * dy;
cairo_move_to (cr, x + width + dx, y + dy);
cairo_line_to (cr, x + dx, y + height + dy);
cairo_line_to (cr, x2, y2);
cairo_line_to (cr, x1, y1);
cairo_line_to (cr, x + width - dx, y - dy);
}
else if (direction == PANGO_DIRECTION_LTR)
{
ax = x + stem_width - offset;
ay = y + height - arrow_width * 2 - arrow_width + 1;
double x0, y0, x1, y1, x2, y2;
cairo_move_to (cr, ax, ay + 1);
cairo_line_to (cr, ax + arrow_width, ay + arrow_width);
cairo_line_to (cr, ax, ay + 2 * arrow_width);
cairo_fill (cr);
x0 = x + dx + 2 * dy;
y0 = y + height + dy - 2 * dx;
x1 = x0 + 4 * dy;
y1 = y0 - 4 * dx;
x2 = x0 + 2 * dy + 3 * dx;
y2 = y0 - 2 * dx + 3 * dy;
cairo_move_to (cr, x + width - dx, y - dy);
cairo_line_to (cr, x - dx, y + height - dy);
cairo_line_to (cr, x2, y2);
cairo_line_to (cr, x1, y1);
cairo_line_to (cr, x + width + dx, y + dy);
}
else
g_assert_not_reached();
}
else
{
cairo_move_to (cr, x + width + dx, y + dy);
cairo_line_to (cr, x + dx, y + height + dy);
cairo_line_to (cr, x - dx, y + height - dy);
cairo_line_to (cr, x + width - dx, y - dy);
}
cairo_fill (cr);
cairo_restore (cr);
}
static void
get_insertion_cursor_bounds (double height,
get_insertion_cursor_bounds (double width,
double height,
double aspect_ratio,
PangoDirection direction,
gboolean draw_arrow,
graphene_rect_t *bounds)
{
int stem_width;
int offset;
stem_width = height * aspect_ratio + 1;
if (direction == PANGO_DIRECTION_LTR)
offset = stem_width / 2;
else
offset = stem_width - stem_width / 2;
if (draw_arrow)
{
if (direction == PANGO_DIRECTION_LTR)
{
graphene_rect_init (bounds,
- offset, 0,
2 * stem_width + 1, height);
}
else
{
graphene_rect_init (bounds,
- offset - stem_width - 2, 0,
2 * stem_width + 2, height);
}
}
else
{
graphene_rect_init (bounds,
- offset, 0,
stem_width, height);
}
graphene_rect_init (bounds,
- 2 * stem_width, - stem_width,
width + 4 * stem_width, height + 2 * stem_width);
}
static void
snapshot_insertion_cursor (GtkSnapshot *snapshot,
GtkStyleContext *context,
double width,
double height,
double aspect_ratio,
gboolean is_primary,
PangoDirection direction,
gboolean draw_arrow)
{
if (draw_arrow)
if (width != 0 || draw_arrow)
{
cairo_t *cr;
graphene_rect_t bounds;
get_insertion_cursor_bounds (height, aspect_ratio, direction, draw_arrow, &bounds);
get_insertion_cursor_bounds (width, height, aspect_ratio, direction, draw_arrow, &bounds);
cr = gtk_snapshot_append_cairo (snapshot, &bounds);
draw_insertion_cursor (context, cr, 0, 0, height, aspect_ratio, is_primary, direction, draw_arrow);
draw_insertion_cursor (context, cr, 0, 0, width, height, aspect_ratio, is_primary, direction, draw_arrow);
cairo_destroy (cr);
}
@ -1193,6 +1192,7 @@ gtk_snapshot_render_insertion_cursor (GtkSnapshot *snapshot,
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x + PANGO_PIXELS (cursor1->x), y + PANGO_PIXELS (cursor1->y)));
snapshot_insertion_cursor (snapshot,
context,
PANGO_PIXELS (cursor1->width),
PANGO_PIXELS (cursor1->height),
aspect_ratio,
TRUE,
@ -1206,6 +1206,7 @@ gtk_snapshot_render_insertion_cursor (GtkSnapshot *snapshot,
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x + PANGO_PIXELS (cursor2->x), y + PANGO_PIXELS (cursor2->y)));
snapshot_insertion_cursor (snapshot,
context,
PANGO_PIXELS (cursor2->width),
PANGO_PIXELS (cursor2->height),
aspect_ratio,
FALSE,