diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-06-22 23:22:32 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-07-04 11:17:21 -0400 |
commit | 509d24d0359bc7c30028a7408b781d803c665959 (patch) | |
tree | c75fd87e19d96209c8ed64262bb4fa0cafcf1a00 | |
parent | 4cfc401b7c4fd45d980ffd5f9e8b7bf3e4c26702 (diff) | |
download | pango-509d24d0359bc7c30028a7408b781d803c665959.tar.gz |
Implement all the line styles
-rw-r--r-- | pango/pango-renderer.c | 127 | ||||
-rw-r--r-- | pango/pango-renderer.h | 27 | ||||
-rw-r--r-- | pango/pangocairo-render.c | 188 | ||||
-rw-r--r-- | pango/pangocairo-render.h | 21 |
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 |