summaryrefslogtreecommitdiff
path: root/pango/pango-renderer.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-01-14 22:11:15 -0500
committerMatthias Clasen <mclasen@redhat.com>2022-01-24 10:58:17 -0500
commit65bf6b818579ff3d5c072814d10260a324ffd01e (patch)
tree5f1f5c50bac8eca5b267641d1a5c259e20c452ed /pango/pango-renderer.c
parent1f655e6b71096ff32a9e479bdcc702ed24131923 (diff)
downloadpango-65bf6b818579ff3d5c072814d10260a324ffd01e.tar.gz
Implement rendering for PangoLine
Diffstat (limited to 'pango/pango-renderer.c')
-rw-r--r--pango/pango-renderer.c260
1 files changed, 187 insertions, 73 deletions
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
index 311c28cd..afb9b360 100644
--- a/pango/pango-renderer.c
+++ b/pango/pango-renderer.c
@@ -25,6 +25,8 @@
#include "pango-renderer.h"
#include "pango-impl-utils.h"
#include "pango-layout-private.h"
+#include "pango-line-private.h"
+#include "pango-layout-run-private.h"
#define N_RENDER_PARTS 5
@@ -56,6 +58,8 @@ struct _LineState
struct _PangoRendererPrivate
{
+ PangoContext *context;
+
PangoColor color[N_RENDER_PARTS];
gboolean color_set[N_RENDER_PARTS];
guint16 alpha[N_RENDER_PARTS];
@@ -146,6 +150,20 @@ pango_renderer_finalize (GObject *gobject)
G_OBJECT_CLASS (pango_renderer_parent_class)->finalize (gobject);
}
+static void
+pango_renderer_activate_with_context (PangoRenderer *renderer,
+ PangoContext *context)
+{
+ /* We only change the matrix if the renderer isn't already active. */
+ if (!renderer->active_count)
+ {
+ pango_renderer_set_matrix (renderer, context ? pango_context_get_matrix (context) : NULL);
+ renderer->priv->context = context;
+ }
+
+ pango_renderer_activate (renderer);
+}
+
/**
* pango_renderer_draw_layout:
* @renderer: a `PangoRenderer`
@@ -173,17 +191,7 @@ pango_renderer_draw_layout (PangoRenderer *renderer,
g_return_if_fail (PANGO_IS_RENDERER (renderer));
g_return_if_fail (PANGO_IS_LAYOUT (layout));
- /* We only change the matrix if the renderer isn't already
- * active.
- */
- if (!renderer->active_count)
- {
- PangoContext *context = pango_layout_get_context (layout);
- pango_renderer_set_matrix (renderer,
- pango_context_get_matrix (context));
- }
-
- pango_renderer_activate (renderer);
+ pango_renderer_activate_with_context (renderer, pango_layout_get_context (layout));
_pango_layout_get_iter (layout, &iter);
@@ -549,6 +557,11 @@ draw_shaped_glyphs (PangoRenderer *renderer,
}
}
+static void pango_renderer_draw_runs (PangoRenderer *renderer,
+ GSList *runs,
+ const char *text,
+ int x,
+ int y);
/**
* pango_renderer_draw_layout_line:
@@ -573,27 +586,13 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
int x,
int y)
{
- int x_off = 0;
- int glyph_string_width;
LineState state = { 0, };
- GSList *l;
- gboolean got_overall = FALSE;
- PangoRectangle overall_rect;
const char *text;
g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
- /* We only change the matrix if the renderer isn't already
- * active.
- */
- if (!renderer->active_count)
- pango_renderer_set_matrix (renderer,
- G_LIKELY (line->layout) ?
- pango_context_get_matrix
- (pango_layout_get_context (line->layout)) :
- NULL);
-
- pango_renderer_activate (renderer);
+ pango_renderer_activate_with_context (renderer,
+ line->layout ? pango_layout_get_context (line->layout) : NULL);
renderer->priv->line = line;
renderer->priv->line_state = &state;
@@ -604,27 +603,143 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
text = G_LIKELY (line->layout) ? pango_layout_get_text (line->layout) : NULL;
- for (l = line->runs; l; l = l->next)
+ pango_renderer_draw_runs (renderer, line->runs, text, x, y);
+
+ /* Finish off any remaining underlines */
+ draw_underline (renderer, &state);
+ draw_overline (renderer, &state);
+ draw_strikethrough (renderer, &state);
+
+ renderer->priv->line_state = NULL;
+ renderer->priv->line = NULL;
+
+ pango_renderer_deactivate (renderer);
+}
+
+/**
+ * pango_renderer_draw_line:
+ * @renderer: a `PangoRenderer`
+ * @line: a `PangoLine`
+ * @x: X position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: Y position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws @line with the specified `PangoRenderer`.
+ *
+ * This draws the glyph items that make up the line, as well as
+ * shapes, backgrounds and lines that are specified by the attributes
+ * of those items.
+ */
+void
+pango_renderer_draw_line (PangoRenderer *renderer,
+ PangoLine *line,
+ int x,
+ int y)
+{
+ LineState state = { 0, };
+
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+ pango_renderer_activate_with_context (renderer, line->context);
+
+ renderer->priv->line = NULL;
+ renderer->priv->line_state = &state;
+
+ state.underline = PANGO_UNDERLINE_NONE;
+ state.overline = PANGO_OVERLINE_NONE;
+ state.strikethrough = FALSE;
+
+ pango_renderer_draw_runs (renderer, line->runs, line->data->text, x, y);
+
+ /* Finish off any remaining underlines */
+ draw_underline (renderer, &state);
+ draw_overline (renderer, &state);
+ draw_strikethrough (renderer, &state);
+
+ renderer->priv->line_state = NULL;
+ renderer->priv->line = NULL;
+
+ pango_renderer_deactivate (renderer);
+}
+
+/**
+ * pango_renderer_draw_lines:
+ * @renderer: a `PangoRenderer`
+ * @lines: a `PangoLines` object
+ * @x: X position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: Y position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws @lines with the specified `PangoRenderer`.
+ */
+void
+pango_renderer_draw_lines (PangoRenderer *renderer,
+ PangoLines *lines,
+ int x,
+ int y)
+{
+ int n;
+ PangoLine *line;
+ int line_x, line_y;
+
+ g_return_if_fail (PANGO_IS_RENDERER_FAST (renderer));
+
+ renderer->priv->lines = lines;
+
+ n = 0;
+ while ((line = pango_lines_get_line (lines, n, &line_x, &line_y)) != NULL)
+ {
+ if (n == 0)
+ pango_renderer_activate_with_context (renderer, line->context);
+
+ pango_renderer_draw_line (renderer, line, x + line_x, y + line_y);
+
+ n++;
+ }
+
+ if (n > 0)
+ pango_renderer_deactivate (renderer);
+}
+
+static void
+pango_renderer_draw_runs (PangoRenderer *renderer,
+ GSList *runs,
+ const char *text,
+ int x,
+ int y)
+{
+ GSList *l;
+ int x_off = 0;
+ int glyph_string_width;
+ gboolean got_overall = FALSE;
+ PangoRectangle overall_rect;
+
+ for (l = runs; l; l = l->next)
{
PangoFontMetrics *metrics;
PangoLayoutRun *run = l->data;
+ PangoGlyphItem *glyph_item = l->data;
+ PangoItem *item = glyph_item->item;
+ PangoGlyphString *glyphs = glyph_item->glyphs;
PangoAttrShape *shape_attr;
PangoRectangle ink_rect, *ink = NULL;
PangoRectangle logical_rect, *logical = NULL;
int y_off;
- if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ if (glyph_item->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
logical = &logical_rect;
pango_renderer_prepare_run (renderer, run);
- get_item_properties (run->item, &shape_attr);
+ get_item_properties (item, &shape_attr);
if (shape_attr)
{
ink = &ink_rect;
logical = &logical_rect;
- _pango_shape_get_extents (run->glyphs->num_glyphs,
+ _pango_shape_get_extents (glyphs->num_glyphs,
&shape_attr->ink_rect,
&shape_attr->logical_rect,
ink,
@@ -641,20 +756,19 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
logical = &logical_rect;
}
if (G_UNLIKELY (ink || logical))
- pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
- ink, logical);
+ pango_glyph_string_extents (glyphs, item->analysis.font, ink, logical);
if (logical)
glyph_string_width = logical_rect.width;
else
- glyph_string_width = pango_glyph_string_get_width (run->glyphs);
+ glyph_string_width = pango_glyph_string_get_width (glyphs);
}
- state.logical_rect_end = x + x_off + glyph_string_width;
+ renderer->priv->line_state->logical_rect_end = x + x_off + glyph_string_width;
- x_off += run->start_x_offset;
- y_off = run->y_offset;
+ x_off += glyph_item->start_x_offset;
+ y_off = glyph_item->y_offset;
- if (run->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
+ if (item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)
{
gboolean is_hinted = ((logical_rect.y | logical_rect.height) & (PANGO_SCALE - 1)) == 0;
int adjustment = logical_rect.y + logical_rect.height / 2;
@@ -665,12 +779,13 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
y_off += adjustment;
}
-
if (renderer->priv->color_set[PANGO_RENDER_PART_BACKGROUND])
{
if (!got_overall)
{
+#ifdef EXTENTS
pango_layout_line_get_extents (line, NULL, &overall_rect);
+#endif
got_overall = TRUE;
}
@@ -683,67 +798,49 @@ pango_renderer_draw_layout_line (PangoRenderer *renderer,
}
if (shape_attr)
- {
- draw_shaped_glyphs (renderer, run->glyphs, shape_attr, x + x_off, y - y_off);
- }
+ draw_shaped_glyphs (renderer, glyphs, shape_attr, x + x_off, y - y_off);
else
- {
- pango_renderer_draw_glyph_item (renderer,
- text,
- run,
- x + x_off, y - y_off);
- }
+ pango_renderer_draw_glyph_item (renderer, text, glyph_item, x + x_off, y - y_off);
if (renderer->underline != PANGO_UNDERLINE_NONE ||
renderer->priv->overline != PANGO_OVERLINE_NONE ||
renderer->strikethrough)
{
- metrics = pango_font_get_metrics (run->item->analysis.font,
- run->item->analysis.language);
+ metrics = pango_font_get_metrics (item->analysis.font,
+ item->analysis.language);
if (renderer->underline != PANGO_UNDERLINE_NONE)
- add_underline (renderer, &state,metrics,
+ add_underline (renderer, renderer->priv->line_state, metrics,
x + x_off, y - y_off,
ink, logical);
if (renderer->priv->overline != PANGO_OVERLINE_NONE)
- add_overline (renderer, &state,metrics,
+ add_overline (renderer, renderer->priv->line_state, metrics,
x + x_off, y - y_off,
ink, logical);
if (renderer->strikethrough)
- add_strikethrough (renderer, &state, metrics,
+ add_strikethrough (renderer, renderer->priv->line_state, metrics,
x + x_off, y - y_off,
- ink, logical, run->glyphs->num_glyphs);
+ ink, logical, glyphs->num_glyphs);
pango_font_metrics_unref (metrics);
}
if (renderer->underline == PANGO_UNDERLINE_NONE &&
- state.underline != PANGO_UNDERLINE_NONE)
- draw_underline (renderer, &state);
+ renderer->priv->line_state->underline != PANGO_UNDERLINE_NONE)
+ draw_underline (renderer, renderer->priv->line_state);
if (renderer->priv->overline == PANGO_OVERLINE_NONE &&
- state.overline != PANGO_OVERLINE_NONE)
- draw_overline (renderer, &state);
+ renderer->priv->line_state->overline != PANGO_OVERLINE_NONE)
+ draw_overline (renderer, renderer->priv->line_state);
- if (!renderer->strikethrough && state.strikethrough)
- draw_strikethrough (renderer, &state);
+ if (!renderer->strikethrough && renderer->priv->line_state->strikethrough)
+ draw_strikethrough (renderer, renderer->priv->line_state);
x_off += glyph_string_width;
- x_off += run->end_x_offset;
+ x_off += glyph_item->end_x_offset;
}
-
- /* Finish off any remaining underlines
- */
- draw_underline (renderer, &state);
- draw_overline (renderer, &state);
- draw_strikethrough (renderer, &state);
-
- renderer->priv->line_state = NULL;
- renderer->priv->line = NULL;
-
- pango_renderer_deactivate (renderer);
}
/**
@@ -1476,12 +1573,15 @@ pango_renderer_default_prepare_run (PangoRenderer *renderer,
guint16 fg_alpha = 0;
guint16 bg_alpha = 0;
GSList *l;
+ PangoGlyphItem *glyph_item;
+
+ glyph_item = pango_layout_run_get_glyph_item (run);
renderer->underline = PANGO_UNDERLINE_NONE;
renderer->priv->overline = PANGO_OVERLINE_NONE;
renderer->strikethrough = FALSE;
- for (l = run->item->analysis.extra_attrs; l; l = l->next)
+ for (l = glyph_item->item->analysis.extra_attrs; l; l = l->next)
{
PangoAttribute *attr = l->data;
@@ -1645,3 +1745,17 @@ pango_renderer_get_layout_line (PangoRenderer *renderer)
{
return renderer->priv->line;
}
+
+/**
+ * pango_renderer_get_context:
+ * @renderer: a `PangoRenderer`
+ *
+ * Gets the current context in which @renderer operates.
+ *
+ * Returns: (nullable) (transfer none): the `PangoContext`
+ */
+PangoContext *
+pango_renderer_get_context (PangoRenderer *renderer)
+{
+ return renderer->priv->context;
+}