summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-06-22 23:22:32 -0400
committerMatthias Clasen <mclasen@redhat.com>2022-07-04 11:17:21 -0400
commit509d24d0359bc7c30028a7408b781d803c665959 (patch)
treec75fd87e19d96209c8ed64262bb4fa0cafcf1a00
parent4cfc401b7c4fd45d980ffd5f9e8b7bf3e4c26702 (diff)
downloadpango-509d24d0359bc7c30028a7408b781d803c665959.tar.gz
Implement all the line styles
-rw-r--r--pango/pango-renderer.c127
-rw-r--r--pango/pango-renderer.h27
-rw-r--r--pango/pangocairo-render.c188
-rw-r--r--pango/pangocairo-render.h21
4 files changed, 211 insertions, 152 deletions
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 03e24bb6..3bd2b7ea 100644
--- a/pango/pango-renderer.c
+++ b/pango/pango-renderer.c
@@ -96,7 +96,9 @@ static void pango_renderer_default_draw_rectangle (PangoRenderer *rende
int y,
int width,
int height);
-static void pango_renderer_default_draw_error_underline (PangoRenderer *renderer,
+static void pango_renderer_default_draw_styled_line (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoLineStyle style,
int x,
int y,
int width,
@@ -136,7 +138,7 @@ pango_renderer_class_init (PangoRendererClass *klass)
klass->draw_glyphs = pango_renderer_default_draw_glyphs;
klass->draw_run = pango_renderer_default_draw_run;
klass->draw_rectangle = pango_renderer_default_draw_rectangle;
- klass->draw_error_underline = pango_renderer_default_draw_error_underline;
+ klass->draw_styled_line = pango_renderer_default_draw_styled_line;
klass->prepare_run = pango_renderer_default_prepare_run;
gobject_class->finalize = pango_renderer_finalize;
@@ -200,8 +202,6 @@ draw_underline (PangoRenderer *renderer,
rect->height);
G_GNUC_FALLTHROUGH;
case PANGO_LINE_STYLE_SOLID:
- case PANGO_LINE_STYLE_DOTTED:
- case PANGO_LINE_STYLE_DASHED:
pango_renderer_draw_rectangle (renderer,
PANGO_RENDER_PART_UNDERLINE,
rect->x,
@@ -209,12 +209,24 @@ draw_underline (PangoRenderer *renderer,
rect->width,
rect->height);
break;
+ case PANGO_LINE_STYLE_DOTTED:
+ case PANGO_LINE_STYLE_DASHED:
+ pango_renderer_draw_styled_line (renderer,
+ PANGO_RENDER_PART_UNDERLINE,
+ underline,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+ break;
case PANGO_LINE_STYLE_WAVY:
- pango_renderer_draw_error_underline (renderer,
- rect->x,
- rect->y,
- rect->width,
- 3 * rect->height);
+ pango_renderer_draw_styled_line (renderer,
+ PANGO_RENDER_PART_UNDERLINE,
+ underline,
+ rect->x,
+ rect->y,
+ rect->width,
+ 3 * rect->height);
break;
default:
break;
@@ -243,9 +255,6 @@ draw_overline (PangoRenderer *renderer,
rect->height);
G_GNUC_FALLTHROUGH;
case PANGO_LINE_STYLE_SOLID:
- case PANGO_LINE_STYLE_DOTTED:
- case PANGO_LINE_STYLE_DASHED:
- case PANGO_LINE_STYLE_WAVY:
pango_renderer_draw_rectangle (renderer,
PANGO_RENDER_PART_OVERLINE,
rect->x,
@@ -253,6 +262,25 @@ draw_overline (PangoRenderer *renderer,
rect->width,
rect->height);
break;
+ case PANGO_LINE_STYLE_DOTTED:
+ case PANGO_LINE_STYLE_DASHED:
+ pango_renderer_draw_styled_line (renderer,
+ PANGO_RENDER_PART_OVERLINE,
+ overline,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+ break;
+ case PANGO_LINE_STYLE_WAVY:
+ pango_renderer_draw_styled_line (renderer,
+ PANGO_RENDER_PART_OVERLINE,
+ overline,
+ rect->x,
+ rect->y,
+ rect->width,
+ 3 * rect->height);
+ break;
default:
break;
}
@@ -283,9 +311,6 @@ draw_strikethrough (PangoRenderer *renderer,
rect->y += rect->height;
G_GNUC_FALLTHROUGH;
case PANGO_LINE_STYLE_SOLID:
- case PANGO_LINE_STYLE_DOTTED:
- case PANGO_LINE_STYLE_DASHED:
- case PANGO_LINE_STYLE_WAVY:
pango_renderer_draw_rectangle (renderer,
PANGO_RENDER_PART_STRIKETHROUGH,
rect->x,
@@ -293,6 +318,25 @@ draw_strikethrough (PangoRenderer *renderer,
rect->width,
rect->height);
break;
+ case PANGO_LINE_STYLE_DOTTED:
+ case PANGO_LINE_STYLE_DASHED:
+ pango_renderer_draw_styled_line (renderer,
+ PANGO_RENDER_PART_STRIKETHROUGH,
+ state->strikethrough,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+ break;
+ case PANGO_LINE_STYLE_WAVY:
+ pango_renderer_draw_styled_line (renderer,
+ PANGO_RENDER_PART_STRIKETHROUGH,
+ state->strikethrough,
+ rect->x,
+ rect->y,
+ rect->width,
+ 3 * rect->height);
+ break;
default:
break;
}
@@ -1090,15 +1134,20 @@ pango_renderer_default_draw_rectangle (PangoRenderer *renderer,
}
/**
- * pango_renderer_draw_error_underline:
+ * pango_renderer_draw_styled_line:
* @renderer: a `PangoRenderer`
- * @x: X coordinate of underline, in Pango units in user coordinate system
- * @y: Y coordinate of underline, in Pango units in user coordinate system
- * @width: width of underline, in Pango units in user coordinate system
- * @height: height of underline, in Pango units in user coordinate system
+ * @part: type of object this rectangle is part of
+ * @style: the line style
+ * @x: X coordinate of line, in Pango units in user coordinate system
+ * @y: Y coordinate of line, in Pango units in user coordinate system
+ * @width: width of line, in Pango units in user coordinate system
+ * @height: height of line, in Pango units in user coordinate system
+ *
+ * Draw a line in the given style.
*
- * Draw a squiggly line that approximately covers the given rectangle
- * in the style of an underline used to indicate a spelling error.
+ * For `PANGO_LINE_STYLE_WAVY`, this should draw a squiggly line that
+ * approximately covers the given rectangle in the style of an underline
+ * used to indicate a spelling error.
*
* The width of the underline is rounded to an integer number
* of up/down segments and the resulting rectangle is centered
@@ -1108,18 +1157,21 @@ pango_renderer_default_draw_rectangle (PangoRenderer *renderer,
* Use [method@Pango.Renderer.activate] to activate a renderer.
*/
void
-pango_renderer_draw_error_underline (PangoRenderer *renderer,
- int x,
- int y,
- int width,
- int height)
+pango_renderer_draw_styled_line (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoLineStyle style,
+ int x,
+ int y,
+ int width,
+ int height)
{
PangoRendererPrivate *priv = pango_renderer_get_instance_private (renderer);
g_return_if_fail (PANGO_IS_RENDERER (renderer));
+ g_return_if_fail (IS_VALID_PART (part));
g_return_if_fail (priv->active_count > 0);
- PANGO_RENDERER_GET_CLASS (renderer)->draw_error_underline (renderer, x, y, width, height);
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_styled_line (renderer, part, style, x, y, width, height);
}
/* We are drawing an error underline that looks like one of:
@@ -1189,11 +1241,13 @@ get_total_matrix (PangoMatrix *total,
}
static void
-pango_renderer_default_draw_error_underline (PangoRenderer *renderer,
- int x,
- int y,
- int width,
- int height)
+pango_renderer_default_draw_styled_line (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoLineStyle style,
+ int x,
+ int y,
+ int width,
+ int height)
{
PangoRendererPrivate *priv = pango_renderer_get_instance_private (renderer);
int square;
@@ -1208,6 +1262,13 @@ pango_renderer_default_draw_error_underline (PangoRenderer *renderer,
if (width <= 0 || height <= 0)
return;
+ if (style != PANGO_LINE_STYLE_WAVY)
+ {
+ /* subclasses can do better */
+ pango_renderer_draw_rectangle (renderer, part, x, y, width, height);
+ return;
+ }
+
square = height / HEIGHT_SQUARES;
unit_width = (HEIGHT_SQUARES - 1) * square;
width_units = (width + unit_width / 2) / unit_width;
diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h
index dfde0167..d75c6db1 100644
--- a/pango/pango-renderer.h
+++ b/pango/pango-renderer.h
@@ -75,13 +75,12 @@ struct _PangoRenderer
* PangoRendererClass:
* @draw_glyphs: draws a `PangoGlyphString`
* @draw_rectangle: draws a rectangle
- * @draw_error_underline: draws a squiggly line that approximately
- * covers the given rectangle in the style of an underline used to
- * indicate a spelling error.
+ * @draw_line: draws a line in the given style that approximately
+ * covers the given rectangle
* @draw_trapezoid: draws a trapezoidal filled area
* @draw_glyph: draws a single glyph
* @part_changed: do renderer specific processing when rendering
- * attributes change
+ * attributes change
* @begin: Do renderer-specific initialization before drawing
* @end: Do renderer-specific cleanup after drawing
* @prepare_run: updates the renderer for a new run
@@ -93,7 +92,7 @@ struct _PangoRenderer
* and have default implementations:
* - draw_glyphs
* - draw_rectangle
- * - draw_error_underline
+ * - draw_styled_line
* - draw_shape
* - draw_glyph_item
*
@@ -122,7 +121,15 @@ struct _PangoRendererClass
int y,
int width,
int height);
- void (*draw_error_underline) (PangoRenderer *renderer,
+ void (*draw_styled_line) (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoLineStyle style,
+ int x,
+ int y,
+ int width,
+ int height);
+ void (*draw_line) (PangoRenderer *renderer,
+ PangoLineStyle style,
int x,
int y,
int width,
@@ -202,6 +209,14 @@ void pango_renderer_draw_rectangle (PangoRenderer *renderer,
int width,
int height);
PANGO_AVAILABLE_IN_ALL
+void pango_renderer_draw_styled_line (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoLineStyle style,
+ int x,
+ int y,
+ int width,
+ int height);
+PANGO_AVAILABLE_IN_ALL
void pango_renderer_draw_error_underline (PangoRenderer *renderer,
int x,
int y,
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index 2a76a161..533cf638 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -689,11 +689,11 @@ pango_cairo_renderer_draw_trapezoid (PangoRenderer *renderer,
#define HEIGHT_SQUARES 2.5
static void
-draw_error_underline (cairo_t *cr,
- double x,
- double y,
- double width,
- double height)
+draw_wavy_line (cairo_t *cr,
+ double x,
+ double y,
+ double width,
+ double height)
{
double square = height / HEIGHT_SQUARES;
double unit_width = (HEIGHT_SQUARES - 1) * square;
@@ -742,11 +742,13 @@ draw_error_underline (cairo_t *cr,
}
static void
-pango_cairo_renderer_draw_error_underline (PangoRenderer *renderer,
- int x,
- int y,
- int width,
- int height)
+pango_cairo_renderer_draw_styled_line (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoLineStyle style,
+ int x,
+ int y,
+ int width,
+ int height)
{
PangoCairoRenderer *crenderer = (PangoCairoRenderer *) (renderer);
cairo_t *cr = crenderer->cr;
@@ -755,15 +757,68 @@ pango_cairo_renderer_draw_error_underline (PangoRenderer *renderer,
{
cairo_save (cr);
- set_color (crenderer, PANGO_RENDER_PART_UNDERLINE);
+ set_color (crenderer, part);
cairo_new_path (cr);
}
- draw_error_underline (cr,
- crenderer->x_offset + (double)x / PANGO_SCALE,
- crenderer->y_offset + (double)y / PANGO_SCALE,
- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+ switch (style)
+ {
+ case PANGO_LINE_STYLE_NONE:
+ break;
+
+ case PANGO_LINE_STYLE_DOTTED:
+ case PANGO_LINE_STYLE_DASHED:
+ cairo_save (cr);
+ cairo_set_line_width (cr, (double)height / PANGO_SCALE);
+ if (style == PANGO_LINE_STYLE_DOTTED)
+ {
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_dash (cr, (const double []){0., (double)(2 * height) / PANGO_SCALE}, 2, 0.);
+ }
+ else
+ {
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
+ cairo_set_dash (cr, (const double []){(double)(3 * height) / PANGO_SCALE, (double)(3 * height) / PANGO_SCALE}, 2, 0.);
+ }
+ cairo_move_to (cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE + (double)height / (2 * PANGO_SCALE),
+ crenderer->y_offset + (double)y / PANGO_SCALE + (double)height / (2 * PANGO_SCALE));
+ cairo_line_to (cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE + (double)width / PANGO_SCALE - (double)height / PANGO_SCALE,
+ crenderer->y_offset + (double)y / PANGO_SCALE + (double)height / (2 * PANGO_SCALE));
+ cairo_stroke (cr);
+ cairo_restore (cr);
+ break;
+
+ case PANGO_LINE_STYLE_SOLID:
+ cairo_rectangle (cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE,
+ crenderer->y_offset + (double)y / PANGO_SCALE,
+ (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+ break;
+
+ case PANGO_LINE_STYLE_DOUBLE:
+ cairo_rectangle (cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE,
+ crenderer->y_offset + (double)y / PANGO_SCALE,
+ (double)width / PANGO_SCALE, (double)height / (3 * PANGO_SCALE));
+ cairo_rectangle (cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE,
+ crenderer->y_offset + (double)y / PANGO_SCALE + (double)(2 * height) / (3 * PANGO_SCALE),
+ (double)width / PANGO_SCALE, (double)height / (3 * PANGO_SCALE));
+ break;
+
+
+ case PANGO_LINE_STYLE_WAVY:
+ draw_wavy_line (cr,
+ crenderer->x_offset + (double)x / PANGO_SCALE,
+ crenderer->y_offset + (double)y / PANGO_SCALE,
+ (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
if (!crenderer->do_path)
{
@@ -786,8 +841,8 @@ pango_cairo_renderer_class_init (PangoCairoRendererClass *klass)
renderer_class->draw_glyphs = pango_cairo_renderer_draw_glyphs;
renderer_class->draw_run = pango_cairo_renderer_draw_run;
renderer_class->draw_rectangle = pango_cairo_renderer_draw_rectangle;
+ renderer_class->draw_styled_line = pango_cairo_renderer_draw_styled_line;
renderer_class->draw_trapezoid = pango_cairo_renderer_draw_trapezoid;
- renderer_class->draw_error_underline = pango_cairo_renderer_draw_error_underline;
}
static PangoCairoRenderer *cached_renderer = NULL; /* MT-safe */
@@ -992,30 +1047,6 @@ _pango_cairo_do_layout (cairo_t *cr,
release_renderer (crenderer);
}
-static void
-_pango_cairo_do_error_underline (cairo_t *cr,
- double x,
- double y,
- double width,
- double height,
- gboolean do_path)
-{
- /* We don't use a renderer here, for a simple reason:
- * the only renderer we can get is the default renderer, that
- * is all implemented here, so we shortcircuit and make our
- * life way easier.
- */
-
- if (!do_path)
- cairo_new_path (cr);
-
- draw_error_underline (cr, x, y, width, height);
-
- if (!do_path)
- cairo_fill (cr);
-}
-
-
/* public wrapper of above to show or append path */
@@ -1132,35 +1163,6 @@ pango_cairo_show_layout (cairo_t *cr,
}
/**
- * pango_cairo_show_error_underline:
- * @cr: a Cairo context
- * @x: The X coordinate of one corner of the rectangle
- * @y: The Y coordinate of one corner of the rectangle
- * @width: Non-negative width of the rectangle
- * @height: Non-negative height of the rectangle
- *
- * Draw a squiggly line in the specified cairo context that approximately
- * covers the given rectangle in the style of an underline used to indicate a
- * spelling error.
- *
- * The width of the underline is rounded to an integer
- * number of up/down segments and the resulting rectangle is centered in the
- * original rectangle.
- */
-void
-pango_cairo_show_error_underline (cairo_t *cr,
- double x,
- double y,
- double width,
- double height)
-{
- g_return_if_fail (cr != NULL);
- g_return_if_fail ((width >= 0) && (height >= 0));
-
- _pango_cairo_do_error_underline (cr, x, y, width, height, FALSE);
-}
-
-/**
* pango_cairo_glyph_string_path:
* @cr: a Cairo context
* @font: a `PangoFont` from a `PangoCairoFontMap`
@@ -1184,6 +1186,26 @@ pango_cairo_glyph_string_path (cairo_t *cr,
}
/**
+ * pango_cairo_run_path:
+ * @cr: a Cairo context
+ * @text: the UTF-8 text that @run refers to
+ * @run: a `PangoRun`
+ *
+ * Adds the text in `PangoRun` to the current path in the
+ * specified cairo context.
+ *
+ * The origin of the glyphs (the left edge of the line) will be
+ * at the current point of the cairo context.
+ */
+void
+pango_cairo_run_path (cairo_t *cr,
+ const char *text,
+ PangoRun *run)
+{
+ _pango_cairo_do_run (cr, text, run, TRUE);
+}
+
+/**
* pango_cairo_line_path:
* @cr: a Cairo context
* @line: a `PangoLine`
@@ -1244,31 +1266,3 @@ pango_cairo_lines_path (cairo_t *cr,
_pango_cairo_do_lines (cr, lines, TRUE);
}
-
-/**
- * pango_cairo_error_underline_path:
- * @cr: a Cairo context
- * @x: The X coordinate of one corner of the rectangle
- * @y: The Y coordinate of one corner of the rectangle
- * @width: Non-negative width of the rectangle
- * @height: Non-negative height of the rectangle
- *
- * Add a squiggly line to the current path in the specified cairo context that
- * approximately covers the given rectangle in the style of an underline used
- * to indicate a spelling error.
- *
- * The width of the underline is rounded to an integer number of up/down
- * segments and the resulting rectangle is centered in the original rectangle.
- */
-void
-pango_cairo_error_underline_path (cairo_t *cr,
- double x,
- double y,
- double width,
- double height)
-{
- g_return_if_fail (cr != NULL);
- g_return_if_fail ((width >= 0) && (height >= 0));
-
- _pango_cairo_do_error_underline (cr, x, y, width, height, TRUE);
-}
diff --git a/pango/pangocairo-render.h b/pango/pangocairo-render.h
index 45ca44ae..b9386142 100644
--- a/pango/pangocairo-render.h
+++ b/pango/pangocairo-render.h
@@ -42,33 +42,22 @@ void pango_cairo_show_lines (cairo_t *cr,
PANGO_AVAILABLE_IN_ALL
void pango_cairo_show_layout (cairo_t *cr,
PangoLayout *layout);
-
-PANGO_AVAILABLE_IN_ALL
-void pango_cairo_show_error_underline (cairo_t *cr,
- double x,
- double y,
- double width,
- double height);
-
PANGO_AVAILABLE_IN_ALL
void pango_cairo_glyph_string_path (cairo_t *cr,
PangoFont *font,
PangoGlyphString *glyphs);
PANGO_AVAILABLE_IN_ALL
-void pango_cairo_layout_path (cairo_t *cr,
- PangoLayout *layout);
+void pango_cairo_run_path (cairo_t *cr,
+ const char *text,
+ PangoRun *run);
PANGO_AVAILABLE_IN_ALL
void pango_cairo_line_path (cairo_t *cr,
PangoLine *line);
PANGO_AVAILABLE_IN_ALL
void pango_cairo_lines_path (cairo_t *cr,
PangoLines *lines);
-
PANGO_AVAILABLE_IN_ALL
-void pango_cairo_error_underline_path (cairo_t *cr,
- double x,
- double y,
- double width,
- double height);
+void pango_cairo_layout_path (cairo_t *cr,
+ PangoLayout *layout);
G_END_DECLS