diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-01-23 18:39:08 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-01-24 07:46:42 -0500 |
commit | 026bbb125b3302403c6067b22320c4862eb9009f (patch) | |
tree | 0e198d713bbc2d1eeed527e0ab2d24c8c3dca5d0 | |
parent | 04aff39ebcbf43ed4e89d0e00c4b42669dcda0af (diff) | |
download | pango-026bbb125b3302403c6067b22320c4862eb9009f.tar.gz |
Add PangoLayoutRun
Make this a separate type from PangoGlyphItem,
and give it some minimal api.
-rw-r--r-- | pango/meson.build | 2 | ||||
-rw-r--r-- | pango/pango-layout-run-private.h | 14 | ||||
-rw-r--r-- | pango/pango-layout-run.c | 175 | ||||
-rw-r--r-- | pango/pango-layout-run.h | 20 | ||||
-rw-r--r-- | pango/pango.h | 1 |
5 files changed, 212 insertions, 0 deletions
diff --git a/pango/meson.build b/pango/meson.build index 9f4c49be..63a772ea 100644 --- a/pango/meson.build +++ b/pango/meson.build @@ -31,6 +31,7 @@ pango_sources = [ 'serializer.c', 'json/gtkjsonparser.c', 'json/gtkjsonprinter.c', + 'pango-layout-run.c', ] pango_headers = [ @@ -52,6 +53,7 @@ pango_headers = [ 'pango-gravity.h', 'pango-item.h', 'pango-language.h', + 'pango-layout-run.h', 'pango-layout.h', 'pango-matrix.h', 'pango-markup.h', diff --git a/pango/pango-layout-run-private.h b/pango/pango-layout-run-private.h new file mode 100644 index 00000000..4d315da7 --- /dev/null +++ b/pango/pango-layout-run-private.h @@ -0,0 +1,14 @@ +#pragma once + +#include "config.h" + +#include "pango-layout-run.h" +#include "pango-glyph-item.h" +#include "pango-item-private.h" + + +static inline PangoGlyphItem * +pango_layout_run_get_glyph_item (PangoLayoutRun *run) +{ + return (PangoGlyphItem *)run; +} diff --git a/pango/pango-layout-run.c b/pango/pango-layout-run.c new file mode 100644 index 00000000..63965842 --- /dev/null +++ b/pango/pango-layout-run.c @@ -0,0 +1,175 @@ +#include "config.h" + +#include "pango-layout-run-private.h" +#include "pango-item-private.h" +#include "pango-impl-utils.h" + +#include <math.h> + +PangoItem * +pango_layout_run_get_item (PangoLayoutRun *run) +{ + return run->item; +} + +PangoGlyphString * +pango_layout_run_get_glyphs (PangoLayoutRun *run) +{ + return run->glyphs; +} + +/** + * pango_layout_run_get_extents: + * @run: a `PangoLayoutRun` + * @trim: `PangoLeadingTrim` flags + * @ink_rect: (out caller-allocates) (optional): return location + * for the ink extents + * @logical_rect: (out caller-allocates) (optional): return location + * for the logical extents + * + * Gets the extents of a `PangoLayoutRun`. + * + * The @trim flags specify if line-height attributes are taken + * into consideration for determining the logical height. See the + * [CSS inline layout](https://www.w3.org/TR/css-inline-3/#inline-height) + * specification for details. + */ +void +pango_layout_run_get_extents (PangoLayoutRun *run, + PangoLeadingTrim trim, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + PangoGlyphItem *glyph_item = run; + ItemProperties properties; + gboolean has_underline; + gboolean has_overline; + PangoRectangle logical; + PangoFontMetrics *metrics = NULL; + int y_offset; + + pango_item_get_properties (glyph_item->item, &properties); + + has_underline = properties.uline_single || properties.uline_double || + properties.uline_low || properties.uline_error; + has_overline = properties.oline_single; + + if (!logical_rect && (glyph_item->item->analysis.flags & PANGO_ANALYSIS_FLAG_CENTERED_BASELINE)) + logical_rect = &logical; + + if (!logical_rect && (has_underline || has_overline || properties.strikethrough)) + logical_rect = &logical; + + if (properties.shape_set) + _pango_shape_get_extents (glyph_item->item->num_chars, + properties.shape_ink_rect, properties.shape_logical_rect, + ink_rect, logical_rect); + else + pango_glyph_string_extents (glyph_item->glyphs, glyph_item->item->analysis.font, + ink_rect, logical_rect); + + if (ink_rect && (has_underline || has_overline || properties.strikethrough)) + { + int underline_thickness; + int underline_position; + int strikethrough_thickness; + int strikethrough_position; + int new_pos; + + if (!metrics) + metrics = pango_font_get_metrics (glyph_item->item->analysis.font, + glyph_item->item->analysis.language); + + underline_thickness = pango_font_metrics_get_underline_thickness (metrics); + underline_position = pango_font_metrics_get_underline_position (metrics); + strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics); + strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics); + + /* the underline/strikethrough takes x, width of logical_rect. + * Reflect that into ink_rect. + */ + new_pos = MIN (ink_rect->x, logical_rect->x); + ink_rect->width = MAX (ink_rect->x + ink_rect->width, logical_rect->x + logical_rect->width) - new_pos; + ink_rect->x = new_pos; + + /* We should better handle the case of height==0 in the following cases. + * If ink_rect->height == 0, we should adjust ink_rect->y appropriately. + */ + + if (properties.strikethrough) + { + if (ink_rect->height == 0) + { + ink_rect->height = strikethrough_thickness; + ink_rect->y = -strikethrough_position; + } + } + + if (properties.oline_single) + { + ink_rect->y -= underline_thickness; + ink_rect->height += underline_thickness; + } + + if (properties.uline_low) + ink_rect->height += 2 * underline_thickness; + if (properties.uline_single) + ink_rect->height = MAX (ink_rect->height, + underline_thickness - underline_position - ink_rect->y); + if (properties.uline_double) + ink_rect->height = MAX (ink_rect->height, + 3 * underline_thickness - underline_position - ink_rect->y); + if (properties.uline_error) + ink_rect->height = MAX (ink_rect->height, + 3 * underline_thickness - underline_position - ink_rect->y); + } + + y_offset = glyph_item->y_offset; + + if (glyph_item->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; + + if (is_hinted) + adjustment = PANGO_UNITS_ROUND (adjustment); + + y_offset += adjustment; + } + + if (ink_rect) + ink_rect->y -= y_offset; + + if (logical_rect) + logical_rect->y -= y_offset; + + if (logical_rect && trim != PANGO_LEADING_TRIM_BOTH) + { + int leading; + + if (properties.absolute_line_height != 0 || properties.line_height != 0.0) + { + int line_height; + + line_height = MAX (properties.absolute_line_height, ceilf (properties.line_height * logical_rect->height)); + leading = (line_height - logical_rect->height); + } + else + { + /* line-height 'normal' in the CSS inline layout spec */ + if (!metrics) + metrics = pango_font_get_metrics (glyph_item->item->analysis.font, + glyph_item->item->analysis.language); + leading = MAX (metrics->height - (metrics->ascent + metrics->descent), 0); + } + if ((trim & PANGO_LEADING_TRIM_START) == 0) + logical_rect->y -= leading / 2; + if (trim == PANGO_LEADING_TRIM_NONE) + logical_rect->height += leading; + else + logical_rect->height += (leading - leading / 2); + } + + if (metrics) + pango_font_metrics_unref (metrics); +} diff --git a/pango/pango-layout-run.h b/pango/pango-layout-run.h new file mode 100644 index 00000000..b9201071 --- /dev/null +++ b/pango/pango-layout-run.h @@ -0,0 +1,20 @@ +#pragma once + +#include <glib-object.h> +#include <pango/pango-types.h> +#include <pango/pango-item.h> +#include <pango/pango-glyph.h> +#include <pango/pango-layout.h> + + +PANGO_AVAILABLE_IN_ALL +PangoItem * pango_layout_run_get_item (PangoLayoutRun *run); + +PANGO_AVAILABLE_IN_ALL +PangoGlyphString * pango_layout_run_get_glyphs (PangoLayoutRun *run); + +PANGO_AVAILABLE_IN_ALL +void pango_layout_run_get_extents (PangoLayoutRun *run, + PangoLeadingTrim trim, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); diff --git a/pango/pango.h b/pango/pango.h index eca66265..1809296d 100644 --- a/pango/pango.h +++ b/pango/pango.h @@ -42,6 +42,7 @@ #include <pango/pango-item.h> #include <pango/pango-language.h> #include <pango/pango-layout.h> +#include <pango/pango-layout-run.h> #include <pango/pango-matrix.h> #include <pango/pango-markup.h> #include <pango/pango-renderer.h> |